A tiny thread-safe registry mapping for simple plugin/registry use-cases.
Project description
mnemoreg
mnemoreg is a tiny, dependency-free, thread-safe registry mapping useful for registering callables and other values by string keys. It's intentionally small and suitable for embedding in other projects. It uses only the Python standard library and aims to provide a predictable, easy-to-use interface for shared, named objects.
Table of Contents
- Highlights
- Installation
- Quick start
- API summary
- Thread-safety and testing notes
- Serialization
- Development and testing
- Contributing
- Troubleshooting
- License
Highlights
- Small, single-file registry implementation (see
mnemoreg/core.py). - Thread-safe operations using
threading.RLockand explicitbulk()context. - Decorator-based registration for callables.
- Snapshot and (de)serialization helpers.
- Configurable overwrite behaviour (forbid / allow / warn).
Installation
Install from PyPI:
pip install mnemoreg
Or install from source:
git clone https://github.com/i3iorn/mnemoreg.git
cd mnemoreg
pip install .
Quick start
from mnemoreg import Registry
# Create a registry typed for string keys and int values
r = Registry[str, int]()
r["one"] = 1
print(r["one"]) # 1
# Register a callable under an explicit key
@r.register("plus")
def plus(x):
return x + 1
print(r["plus"](4)) # 5
# Register using the function name as the key
@r.register()
def multiply(x, y):
return x * y
print(r["multiply"](3, 4)) # 12
# Use the bulk context manager to perform multiple operations under the same lock
with r.bulk():
r["a"] = 1
r["b"] = 2
# Create a shallow snapshot
snap = r.snapshot()
print(snap)
See the tests/ directory for many additional examples and edge cases.
API summary
This is a concise summary — see mnemoreg/core.py docstrings for full details.
Registry(*, lock: Optional[RLock]=None, log_level: int=logging.WARNING, overwrite_policy: int=OverwritePolicy.FORBID)— constructor.- Mapping-like methods:
__getitem__,__setitem__,__delitem__,__iter__,__len__,__contains__. register(key: Optional[str] = None)— decorator to register callables/objects.get(key, default=None),snapshot(),to_dict().from_dict(mapping),from_json(s)— classmethods to build from serialized data.to_json(**kwargs)— serialize to JSON string.bulk()— context manager that acquires the registry lock for batched operations.update(mapping),clear(),unregister(key),remove(key).
Exceptions raised:
AlreadyRegisteredError— when a key must not already exist but does.NotRegisteredError— when accessing/deleting a key that does not exist.
Overwrite behaviour is controlled by OverwritePolicy enum (FORBID=0, ALLOW=1, WARN=2).
Thread-safety and testing notes
mnemoreg is guarded by a threading.RLock for mutating operations. Iteration and
snapshot() return shallow copies to avoid exposing internal state to concurrent
mutation.
If you write tests that intentionally start background threads which raise
exceptions (for example, tests that exercise concurrency failure modes), pytest
will surface a PytestUnhandledThreadExceptionWarning for uncaught exceptions
in threads. To hide that specific warning only for the threaded test module,
add this module-level filter to tests/test_registry_threaded.py:
# tests/test_registry_threaded.py
import pytest
# suppress only the thread-unhandled warning for this module
pytestmark = pytest.mark.filterwarnings(
"ignore::pytest.PytestUnhandledThreadExceptionWarning"
)
For the pytest-asyncio deprecation warning shown by newer versions:
configure the default fixture loop scope in your pytest configuration. For
example, in pyproject.toml:
[tool.pytest.ini_options]
asyncio_mode = "strict"
asyncio_default_fixture_loop_scope = "function"
This sets the asyncio fixture loop scope explicitly and avoids the
PytestDeprecationWarning about the unset asyncio_default_fixture_loop_scope.
Serialization
The registry supports basic JSON-friendly (de)serialization via to_dict,
from_dict, to_json, and from_json. These operate on shallow copies of the
internal store, so custom objects will need their own serialization logic before
being stored if you need to persist them as JSON.
Example:
r = Registry[str, int]()
r["one"] = 1
s = r.to_json()
new_r = Registry.from_json(s)
Development and testing
Run tests with:
python -m pytest -vv
The test suite covers single-threaded and concurrent scenarios. If you see spurious warnings from async fixtures or thread exceptions while developing, use the options described above to configure pytest or narrow the warning filters to the affected test modules.
Contributing
Contributions are welcome. A suggested workflow:
- Open an issue to discuss larger changes.
- Branch from
main(ormaster) for new work. - Add tests for new behaviour or bug fixes.
- Run the test suite and make sure everything passes.
- Create a pull request with a clear description of the changes.
Coding style: keep changes small and well-tested. Prefer plain stdlib implementations unless there is a clear productivity win from a dependency.
Troubleshooting
- AlreadyRegisteredError during concurrent writes: your test or production
logic may be attempting to re-register a key; consider
OverwritePolicy.ALLOWor adjust the test flow to avoid races. PytestUnhandledThreadExceptionWarning: see the module-levelpytestmarkexample above to suppress the warning only in the threaded test module.pytest-asynciodeprecation warnings: setasyncio_default_fixture_loop_scopein pytest config as shown above.
If you hit something not covered here, please open an issue with a small reproduction.
License
mnemoreg is licensed under the MIT License — see the LICENSE file for
details.
Maintainers: i3iorn
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mnemoreg-0.3.2.tar.gz.
File metadata
- Download URL: mnemoreg-0.3.2.tar.gz
- Upload date:
- Size: 22.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c2447e6703ae5db7e1fd4576e91f1fab2c03e80c542fde93bb305309b8b5cff8
|
|
| MD5 |
fb28cd8d2b332bb2c7b28d77c94d3395
|
|
| BLAKE2b-256 |
4dcb00b0f0980e5e3440b3256a4efe5e25733643c4093ad980bc86eff8a1ba65
|
File details
Details for the file mnemoreg-0.3.2-py3-none-any.whl.
File metadata
- Download URL: mnemoreg-0.3.2-py3-none-any.whl
- Upload date:
- Size: 10.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6008d42e9e9e0097f3c69ada52cc2f6a1e1646c7fd3bfb26ab38de0b6a96ea48
|
|
| MD5 |
140a4fce01c568247620acd485be1764
|
|
| BLAKE2b-256 |
27b8e582bab8f6ed0e0b95c5a593b808e7e21f9cdc39bd72e906b8f6df72090d
|