Releases: beanbaginc/python-registries
Registries 1.0
Welcome to Registries
Many projects need to deal with managing multiple implementations of a concept. A command line tool might have a class for every subcommand. A web application might have classes that talk to different backend services (databases, search engines, queues, etc.). You may parse or generate multiple file formats, API payloads. You may need factory methods, or want to support plugins.
Somewhere, these concepts, these implementations need to be registered and tracked, validated, made easily accessible to other parts of the code. We've made that easy with Registries.
Registries is an implementation of the Registry Pattern. Each registry fronts a concept (such as available command classes) and provides default items, registration and validation for new ones, easy and fast lookup of items based on attribute values, and full inspection of all available items. Registries are typed, thread-safe, performant, customizable, and trivial to use.
Here's a basic example:
from registries import Registry
# Let's define the item type we'll track, and some implementations.
class BaseItem:
my_attr: str
class FooItem(BaseItem):
my_attr = 'foo'
class BarItem(BaseItem):
my_attr = 'bar'
# Let's build our registry.
class MyRegistry(Registry[Type[BaseItem]]):
lookup_attrs = ['my_attr']
def get_defaults():
return [FooItem, BarItem]
registry = MyRegistry()
# Now we can look things up.
assert registry.get('foo') is FooItem
assert registry.get('bar') is BarItem
# Register a new item.
class BazItem(BaseItem):
my_attr = 'baz'
registry.register(BazItem)
assert BazItem in registry
assert registry.get('baz') is BazItem
# And unregister it again.
registry.unregister(BazItem)
assert BazItem not in registry
More detailed examples can be found in our documentation.
We've been using this for many years in Review Board, our open source code review product, and finally split it into its own package to make it more generally available.
The code is under the MIT license, and supports Python 3.8 through 3.13.
Target Audience
Registries is built for Python developers who are building production-quality projects. If you've had to deal with any of the above requirements in your code, then this was built for you.
Comparison
Many projects build in-house solutions, classes or functions that store items in a dictionary. This is how we started, and it can work perfectly fine. What you'd get from Registries over this is the thread-safety, consistency in behavior, less code to manage, and optional features like built-in Entry Point management or ordered tracking.
We've found a few projects that offer some similar functionality to Registries with different approaches and tradeoffs, including:
- autoregistry: Same basic idea, but ties the registered object to the registry more directly, rather than keeping them independent concepts. No typing on our level, or thread-safety, but has some neat ideas in it.
- class-registry: Offers a lot of the same functionality, with some neat additions like an auto-register metaclass, but without the extensibility hooks offered in our custom registries or the typing or thread-safety. Last updated in 2017.
- registry-factory: A more involved approach to the Registry Pattern. Includes an optional single central registry, object versioning, and certain forms of purpose-specific metadata. No typing, thread-safety, or Entry Point management. More opinionated design and more complex to get going.
All are worth checking out. The typing and thread-safety are key elements we wanted to focus on, as well as customization via hooks and registry-defined error classes in order to better cover unforeseen needs in a project.
Links
Documentation: https://registries.readthedocs.io/
PyPI: https://pypi.org/project/registries/
GitHub: https://github.com/beanbaginc/python-registries
Feature Overview for 1.0
- Dynamic Registration and Unregistration: Add and remove objects from your registry easily, with validation, conflict control, and thread-safety.
- Flexible Lookups: Look up objects by registered attribute values, or iterate through all registered objects.
- Thread-Safety: A central registry can be manipulated across threads without any issues.
- Extensibility: Registration, unregistration, initial population, and lookup behavior can all be customized in subclasses by defining pre/post hooks.
- Type Hints: Registries are typed as Generics, helping ensure registration and lookup reflects the correct item types.
- Custom Errors: Registries can define their own error classes, providing custom messaging or state that may be useful to callers.
- Useful Built-In Registries:
OrderedRegistry
ensures objects remain in registration order, andEntryPointRegistry
auto-populates based on Python Entry Points.