plugins.registry
plugins.registry
Which component plays which cadjoint kind, and where it runs.
This is the part that is genuinely cadjoint’s: a name -> spec table, a kind -> name default, and three places a spec can come from, later ones winning:
- Built-ins — the Tesseract packages in this repository (:data:
BUILTIN_PACKAGES), aslocalspecs. Nothing shipped here fills the private tier’s five in-process kinds; thediff-brepdistribution registers those through the entry-point group below, and :mod:cadjoint.tiersays so in one sentence when it is absent. - Entry points — the
cadjoint.pluginsgroup. A distribution registers a component by exposing a :class:~cadjoint.plugins.PluginSpec, a mapping in theplugins.tomltable form, or a callable returning either. - The config file —
plugins.toml, found at$CADJOINT_PLUGINS(a file, or a directory holding one) or else$XDG_CONFIG_HOME/cadjoint/plugins.toml(default~/.config/cadjoint/plugins.toml). A table whose name matches an existing plugin replaces its spec — that is how the thermal solver moves from this process to a cluster URL without a line of code changing.
The file has two tables::
[defaults] # which plugin fills each slot
elastic_solver = "elastic_calculix"
[plugins.thermal_jaxfem] # where a plugin runs
kind = "thermal_solver"
transport = "remote"
url = "http://thermal.cadjoint.svc.cluster.local:8000"
schema_hash = "sha256:2a1f..."
Seeing the public tier. CADJOINT_PUBLIC_TIER=1 leaves the private tier’s kinds (:data:cadjoint.tier.KINDS) out of the process-wide registry wherever they come from — what a public install sees, on a machine that has diff-brep installed. Child processes inherit it, so a playground started with it answers every request as the public tier does.
Callers ask by name (:func:get_plugin) for one specific component, or by kind (:func:plugin_for_kind) for whatever currently fills a slot — which is what :mod:cadjoint.fem.tesseracts.chain and :mod:cadjoint.fem.backends do, so neither imports a tesseract_api module. Instances are cached, so a local plugin imports its API module once and a remote one holds a single warm session.
Classes
| Name | Description |
|---|---|
| PluginRegistry | The plugins this process knows about, and the instances it has open. |
PluginRegistry
plugins.registry.PluginRegistry(specs=None, defaults=None, *, source=None)
The plugins this process knows about, and the instances it has open.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| specs | Mapping[str, PluginSpec] | None | Name -> spec. | None |
| defaults | Mapping[str, str] | None | Kind -> plugin name. | None |
| source | Path | None | Where the config came from, for error messages. | None |
Methods
| Name | Description |
|---|---|
| close | Close every open instance (tearing down spawned containers). |
| default_for | The plugin name filling kind. |
| for_kind | The (cached) plugin instance currently filling kind. |
| kinds | Registered plugin names grouped by kind. |
| names | Registered plugin names, sorted. |
| plugin | The (cached) plugin instance registered under name. |
| register | Add or replace a spec, closing any open instance under that name. |
| spec | The spec registered under name. |
| unregister | Remove a spec (and its default, and any open instance). |
| without | A copy of this registry with every plugin of kinds left out. |
close
plugins.registry.PluginRegistry.close()
Close every open instance (tearing down spawned containers).
default_for
plugins.registry.PluginRegistry.default_for(kind)
The plugin name filling kind.
Raises
| Name | Type | Description |
|---|---|---|
| KeyError | If no plugin declares that kind, if several do with no default set, or if the default names something unregistered. |
for_kind
plugins.registry.PluginRegistry.for_kind(kind)
The (cached) plugin instance currently filling kind.
kinds
plugins.registry.PluginRegistry.kinds()
Registered plugin names grouped by kind.
names
plugins.registry.PluginRegistry.names()
Registered plugin names, sorted.
plugin
plugins.registry.PluginRegistry.plugin(name)
The (cached) plugin instance registered under name.
register
plugins.registry.PluginRegistry.register(spec, *, default=None)
Add or replace a spec, closing any open instance under that name.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| spec | PluginSpec | The spec to register. | required |
| default | bool | None | Make it the default for its kind (None: only when nothing else fills that kind yet). |
None |
spec
plugins.registry.PluginRegistry.spec(name)
The spec registered under name.
Raises
| Name | Type | Description |
|---|---|---|
| KeyError | If nothing is registered under that name. |
unregister
plugins.registry.PluginRegistry.unregister(name)
Remove a spec (and its default, and any open instance).
Returns
| Name | Type | Description |
|---|---|---|
| PluginSpec | None | The removed spec, or None if nothing was registered under |
|
| PluginSpec | None | name. |
without
plugins.registry.PluginRegistry.without(kinds)
A copy of this registry with every plugin of kinds left out.
What :func:cadjoint.tier.absent installs so the public tier’s degraded behaviour can be exercised with the private providers still present in the process.
Functions
| Name | Description |
|---|---|
| available_plugins | Names registered in the process-wide registry. |
| build_registry | Assemble a registry from built-ins, entry points and the config file. |
| builtin_specs | Specs for every component shipped in this checkout. |
| config_path | The plugins.toml in effect, or None when there is none. |
| entry_point_specs | Specs contributed by installed distributions. |
| get_plugin | The plugin registered under name in the process-wide registry. |
| load_config | Load the plugins config in effect. |
| parse_config | Split a parsed config document into specs and per-kind defaults. |
| plugin_for_kind | The plugin currently filling kind in the process-wide registry. |
| public_tier_forced | Whether $CADJOINT_PUBLIC_TIER asks for the public tier only. |
| register_plugin | Register spec in the process-wide registry. |
| registry | The process-wide registry, assembled on first use. |
| set_registry | Install new as the process-wide registry, returning the old one. |
available_plugins
plugins.registry.available_plugins()
Names registered in the process-wide registry.
build_registry
plugins.registry.build_registry(config=None, use_entry_points=True)
Assemble a registry from built-ins, entry points and the config file.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| config | Path | None | An explicit plugins.toml; None resolves it the usual way. |
None |
| use_entry_points | bool | Include installed cadjoint.plugins entry points (tests turn this off to stay hermetic). |
True |
Returns
| Name | Type | Description |
|---|---|---|
| PluginRegistry | The assembled registry. |
builtin_specs
plugins.registry.builtin_specs()
Specs for every component shipped in this checkout.
local specs for the Tesseract packages present, and nothing else. The private tier’s in-process kinds arrive through the entry-point group, never from here.
config_path
plugins.registry.config_path()
The plugins.toml in effect, or None when there is none.
Returns
| Name | Type | Description |
|---|---|---|
| Path | None | The resolved path. |
Raises
| Name | Type | Description |
|---|---|---|
| PluginConfigError | If $CADJOINT_PLUGINS names something unreadable — silently falling back to the built-ins would hide a deployment bug. |
entry_point_specs
plugins.registry.entry_point_specs()
Specs contributed by installed distributions.
A broken entry point raises a :class:PluginConfigError naming it rather than being skipped: a plugin that silently fails to register is the hardest kind of deployment bug to see.
get_plugin
plugins.registry.get_plugin(name)
The plugin registered under name in the process-wide registry.
load_config
plugins.registry.load_config(path=None)
Load the plugins config in effect.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| path | Path | None | An explicit file to read; None resolves via :func:config_path. |
None |
Returns
| Name | Type | Description |
|---|---|---|
| dict | (specs, defaults, path); the first two are empty and path is |
|
| dict | None when no config file exists. |
Raises
| Name | Type | Description |
|---|---|---|
| PluginConfigError | Before Python 3.11 without tomli installed. |
parse_config
plugins.registry.parse_config(document, *, source)
Split a parsed config document into specs and per-kind defaults.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| document | Mapping[str, Any] | The parsed TOML mapping. | required |
| source | str | What to name in error messages (a path, usually). | required |
Returns
| Name | Type | Description |
|---|---|---|
| dict | (specs, defaults) — {name: PluginSpec} and |
|
| dict | {kind: plugin name}. |
Raises
| Name | Type | Description |
|---|---|---|
| PluginConfigError | On an unknown top-level table or a malformed plugin table. |
plugin_for_kind
plugins.registry.plugin_for_kind(kind)
The plugin currently filling kind in the process-wide registry.
public_tier_forced
plugins.registry.public_tier_forced()
Whether $CADJOINT_PUBLIC_TIER asks for the public tier only.
register_plugin
plugins.registry.register_plugin(spec, *, default=None)
Register spec in the process-wide registry.
registry
plugins.registry.registry()
The process-wide registry, assembled on first use.
set_registry
plugins.registry.set_registry(new)
Install new as the process-wide registry, returning the old one.
None clears it, so the next :func:registry call rebuilds from the environment. Tests use this to point cadjoint at a served plugin without touching the user’s config.