Skip to content

Conversation

@cvanelteren
Copy link
Collaborator

@cvanelteren cvanelteren commented Oct 25, 2025

This PR makes our configuration system thread-safe and adds support for thread-local storage. This is particularly important when running tests in parallel (e.g., with pytest-xdist), where each test thread needs to modify configuration parameters without affecting other threads.

I started playing around with a recent PR that would be merged in the future(matplotlib/pytest-mpl#242 (comment)). This PR would prep for making it threadsafe -- speeding up local development. GHA has 2 threads per worker so it could be beneficial there, and otherwise not hurt.

The Problem

Currently, when multiple threads try to access or modify configuration parameters at the same time, we can get race conditions and data corruption. Also, there's no way for a thread to make temporary changes that are automatically cleaned up when the thread exits.

Proposed fix

The PR implements a thread-safe version of _RcParams that:

  1. Uses a reentrant lock (threading.RLock) to prevent race conditions
  2. Adds thread-local storage so each thread can have its own temporary configuration changes
  3. Implements a context manager interface for clean management of thread-local changes
  4. Properly merges thread-local changes back into the main configuration

Added tests

  • test_rcparams_thread_safety

@codecov
Copy link

codecov bot commented Oct 25, 2025

Codecov Report

❌ Patch coverage is 92.36641% with 10 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
ultraplot/internals/rcsetup.py 82.50% 3 Missing and 4 partials ⚠️
ultraplot/tests/test_config.py 96.70% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

@cvanelteren
Copy link
Collaborator Author

Need to do some final checks to see how this interacts with the Configurator class. Furthermore, we need to override the default MPL rc params as it is not threadsafe currently. Perhaps it is easier to control this in Configurator in general. Will get back to this when I have the time.

Copy link
Collaborator

@beckermr beckermr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there may be a bug in the logic.

Comment on lines 638 to 641
if key is not None:
# Store in both thread-local storage and main dictionary
self._local.changes[key] = value
dict.__setitem__(self, key, value)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block doesn't make sense to me. I think we need to test if we're in the context manager block and then only make a local change if we are. Otherwise threads will make changes to the global settings which could interfere with each other.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am leaning towards moving this logic (thread safety) inside the Configurator we both need to control ultraplot's rc and matplotlib's rc making this PR a bit moot and #384 an essential step in this direction.

@cvanelteren
Copy link
Collaborator Author

I think there may be a bug in the logic.

Think you are right. I believe I fixed it now. I updated the docstring to reflect the intent of the block. The idea is that we have a main thread which contains the correct information, but threads can locally modify the rc params without affecting the main thread. I will document this as we are not resolving any conflicting settings that happens on the threads themselves, the main thread contains the "correct" information.

@cvanelteren
Copy link
Collaborator Author

hmm the threadsafety wrapping broke something -- will address this when I have more time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants