cadrumo.core.optional_extras module

Capability-gated optional package extras and their import guard.

The shipped package is lean: a bare pip install cadrumo omits the optional integration stacks (Google export, the live-AEAT browser, the Anthropic-API LLM provider). Each maps to a [project.optional-dependencies] extra and is imported lazily, so the core CLI builds and runs without it.

This module is the single source of truth for those extras. It lives in core — the innermost layer — so an adapter can guard its own external-library import without importing the application layer, and the application doctor can probe the same OPTIONAL_EXTRAS registry through application.provisioning.probe_optional_extra(). require_optional_extra() is the seam every feature boundary calls before its lazy import so a missing extra becomes one instructive MissingOptionalExtraError naming pip install cadrumo[<extra>] instead of a raw deep-stack ModuleNotFoundError.

These records describe package availability only. They do not decide whether an operator has opted into Google export, browser automation, or hosted LLM usage; that consent surface is represented separately by ServiceCapability.

class OptionalExtra(**data)[source]

Bases: BaseModel

A capability-gated optional package extra and how to probe/install it.

Variables:
  • extra – The [project.optional-dependencies] key.

  • import_name – Importable package/module name used by the spec-only probe.

  • feature – Human-readable feature label used in refusals and doctor rows.

Parameters:
  • extra (str)

  • import_name (str)

  • feature (str)

extra: str
import_name: str
feature: str
exception MissingOptionalExtraError(extra)[source]

Bases: CoreError

Raised when a feature is reached but its optional extra is not installed.

Descends from CoreError so the project-wide CadrumoError boundary sees the refusal. Application probes report the same missing package as a application.provisioning.DependencyStatus; feature guards raise this exception only when the operator reaches the guarded boundary.

Carries the extra’s machine identity and nothing else. The operator-facing text is the registered error code’s own translation key, so this refusal renders through the same catalogue every other registered error does, and the recovery is resolved downstream from the facts rather than rendered here as an install command.

Variables:

extra – Optional-extra registry record that failed the spec-only probe.

Parameters:

extra (OptionalExtra)

Return type:

None

code
optional_extra_available(extra)[source]

Return whether extra’s package is importable, without importing it.

A spec-only check (importlib.util.find_spec()) — no side effects, no heavy module load. Never raises: a missing parent package resolves to False. This helper intentionally does not call require_optional_extra(); probes should report dependency status, not raise feature-boundary refusals.

Parameters:

extra (OptionalExtra) – The OptionalExtra registry record to probe.

Return type:

bool

Returns:

True when extra.import_name has an import spec; otherwise False.

optional_extra_for_module(module_name)[source]

Return the registered extra that owns module_name, or None.

Answers the classification question “is this missing module a capability package the operator may legitimately not have installed?” against OPTIONAL_EXTRAS — the declared inventory of optionally-absent packages. Any module outside that inventory is a required dependency (or a first-party module), so its absence is a broken installation rather than a configuration choice.

Matching is on the top-level package so a failed deep import (playwright.async_api) attributes to its owning extra. The match is deliberately one-way: a ModuleNotFoundError raised from inside an installed optional package names that package’s own missing dependency, does not match the registry, and is therefore classified as a real failure.

Parameters:

module_name (str) – The dotted module name that failed to import.

Return type:

OptionalExtra | None

Returns:

The owning OptionalExtra, or None when module_name belongs to no registered extra.

require_optional_extra(extra)[source]

Raise MissingOptionalExtraError when extra is absent; a no-op when present.

Call this at a feature boundary, immediately before the lazy import of the extra’s package, so a missing extra becomes a single actionable message instead of a raw deep-stack ModuleNotFoundError.

Parameters:

extra (OptionalExtra) – The OptionalExtra required by the feature boundary.

Raises:

MissingOptionalExtraError – If extra.import_name is not importable.

Return type:

None