mineproductivity.registry¶
Auto-generated API reference for the Registry package, rendered from the package's own docstrings. For the narrative overview, dependency rules, and extension guide, see Packages -> Registry.
registry ¶
mineproductivity.registry -- the plugin-first backbone of
MineProductivity: the single, generic discovery-and-lookup mechanism
that lets KPIs, connectors, ontology entity types, and analytics models
be added to the platform as separate, installable packages, with zero
change to the core.
Implements docs/architecture/03_Registry_Framework_Design_Specification.md
exactly. registry depends only on core -- see README.md for
the full set of architectural rules this package must satisfy.
Everything documented here is part of the public API and can be imported
directly from mineproductivity.registry, e.g.::
from mineproductivity.registry import Registry, EntryPointDiscovery
DiscoveryCache ¶
Memoizes :meth:EntryPointDiscovery.discover results per
:class:EntryPointSpec for the lifetime of the process --
entry-point scanning touches the filesystem/importlib metadata and
is not free to repeat on every lookup (design spec §22).
Invalidated only by an explicit call to :meth:invalidate, never
implicitly -- e.g. a test harness that installs a plugin mid-process
must call invalidate() itself to see it.
A single lock serializes get_or_discover calls, so concurrent
calls for the same spec are guaranteed to trigger exactly one
underlying discovery pass (design spec §25); the public contract
only guarantees that result, not this specific locking strategy.
EntryPointDiscovery ¶
Scans installed packages' entry-points (via :mod:importlib.metadata)
and imports each one, running whatever @register-decorated side
effects the imported module contains.
An exception raised while importing any one entry-point's target module is caught, logged, and skipped -- it MUST NOT prevent discovery of the remaining entry-points in the same group (design spec §11, §26, the isolation rule: "a mine with 30 installed KPI packs cannot have its whole platform go down because pack #17 has a typo").
discover ¶
Import every entry-point in spec.group.
Returns:
| Type | Description |
|---|---|
Result[Sequence[str]]
|
|
EntryPointSpec
dataclass
¶
Bases: BaseValueObject
One discoverable entry-point group, e.g.
EntryPointSpec(group="mineproductivity.connectors", target_registry="connectors").
DuplicateRegistrationError ¶
Bases: RegistrationError
Registry.register() called with a key that already exists.
Registration is add-only (design spec AD-RG-04) -- re-registering an existing key is always rejected, never silently accepted as an update.
RegistrationError ¶
UnregisteredLookupError ¶
VersionIncompatibleError ¶
Bases: RegistrationError
A plugin's declared core_version_range excludes the installed
core version.
Registry ¶
Bases: Generic[TKey, TItem]
A generic, type-safe, metadata-aware registration container.
Every domain-specific registry (KPIRegistry, ConnectorRegistry,
EntityTypeRegistry, AnalyticsRegistry) is a type alias over
this class, not a subclass with new behavior -- composition over
inheritance, and one implementation to trust platform-wide (design
spec AD-RG-01).
A deliberate structural echo of
:class:~mineproductivity.core.repository.BaseRepository: a registry
is, conceptually, a repository whose entities are types/classes/
callables instead of domain entities. Registry does not subclass
BaseRepository, since its keys are typically strings/codes rather
than BaseEntity ids.
Examples:
>>> registry: Registry[str, type] = Registry(name="widgets")
>>> class Widget: pass
>>> registry.register("widget", Widget).is_ok
True
>>> registry.get("widget") is Widget
True
>>> registry.register("widget", Widget).is_ok
False
name
property
¶
The domain-facing name this registry was constructed with
(e.g. "kpis", "connectors") -- used in log messages and
error details.
register ¶
Register item under key.
Registration is add-only (design spec §19, AD-RG-04): re- registering an existing key -- even with the exact same item -- is always rejected, never silently accepted as an update.
Returns:
| Type | Description |
|---|---|
Result[None]
|
|
get ¶
Raising lookup of key.
Raises:
| Type | Description |
|---|---|
UnregisteredLookupError
|
If no item is registered under |
list ¶
All registered items, optionally filtered by specification --
mirrors :meth:~mineproductivity.core.repository.BaseRepository.list's
shape deliberately.
metadata_for ¶
Non-raising lookup of the metadata attached to key at
registration time, if any.
VersionCompatibility ¶
Stateless version-range compatibility checks.
VersionRange
dataclass
¶
Bases: BaseValueObject
A half-open version range: [min_version, max_version_exclusive),
e.g. mineproductivity>=1.0,<2.0 (Cookbook Part I, Ch. 9).
registered_in ¶
Build a decorator that registers the decorated item into
registry, deriving its key (and, optionally, its metadata) from
the item itself.
Suitable whenever registration needs nothing beyond "derive a key,
reject a duplicate" -- mineproductivity.connectors.register_connector
is exactly this, a thin, partially-applied wrapper around
registered_in(). A domain package that needs additional
registration-time validation implements its own @register
instead, calling Registry.register() directly:
mineproductivity.kpis.register does this to also raise
KPICircularDependencyError at registration time (never deferred
to first use). mineproductivity.ontology.register_equipment is
unrelated to this mechanism entirely -- ontology sits below
registry in the dependency stack (core -> ontology -> events ->
registry) and cannot import it; its entity-type registry is a
separate, internal mechanism. "One discovery pattern for the whole
ecosystem" (Cookbook Part I, Ch. 9) means every domain package builds
its @register the same shape -- decorator + typed registry +
raising lookup -- not that every one is literally built from this
one function.
Examples: