calute.extensions.dependency#

Dependency resolution for Calute plugins and skills.

Provides version constraint parsing, dependency specification, and topological sorting with circular dependency detection for local plugin/skill dependency graphs.

exception calute.extensions.dependency.CircularDependencyError(cycle: list[str])[source]#

Bases: Exception

Raised when a circular dependency is detected during topological sorting.

cycle#

An ordered list of node names that form the cycle. The first and last elements are identical, illustrating the loop (e.g., ["A", "B", "C", "A"]).

class calute.extensions.dependency.DependencyResolver[source]#

Bases: object

Resolve a dependency graph, detecting missing deps, version conflicts, and circular dependencies, and produce a topological load order.

The resolver provides two main operations:

  • resolve() – checks that a flat list of DependencySpec requirements are met by a set of available packages with known versions.

  • topological_sort() – orders nodes in a directed acyclic graph so that every dependency appears before the nodes that depend on it.

Example

>>> resolver = DependencyResolver()
>>> available = {"A": "1.0.0", "B": "2.0.0"}
>>> reqs = [DependencySpec("A", ">=1.0")]
>>> result = resolver.resolve(available, reqs)
>>> result.satisfied
True
resolve(available: dict[str, str], requirements: list[calute.extensions.dependency.DependencySpec]) ResolveResult[source]#

Check that all requirements are met by available packages.

Parameters
  • available – Mapping of package name to version string.

  • requirements – List of dependency specifications to check.

Returns

A ResolveResult with satisfaction status and details.

topological_sort(graph: dict[str, list[str]]) list[str][source]#

Topological sort of a dependency graph.

Parameters

graph – Mapping of node -> list of nodes it depends on.

Returns

List of node names in dependency-safe order (dependencies first).

Raises

CircularDependencyError – If a cycle is detected.

class calute.extensions.dependency.DependencySpec(name: str, version_constraint: str | None = None)[source]#

Bases: object

A single dependency requirement consisting of a name and optional version constraint.

name#

The identifier of the required dependency (e.g., "my_plugin").

Type

str

version_constraint#

An optional version constraint string such as ">=1.0.0" or "~=2.1". None means any version is acceptable.

Type

str | None

Example

>>> spec = DependencySpec(name="my_plugin", version_constraint=">=1.0")
>>> spec.to_version_constraint().satisfies("1.5.0")
True
name: str#
to_version_constraint() VersionConstraint[source]#

Convert the version constraint string into a VersionConstraint object.

Returns

A VersionConstraint parsed from version_constraint. If version_constraint is None, an unconstrained (always-satisfied) VersionConstraint is returned.

version_constraint: str | None = None#
class calute.extensions.dependency.ResolveResult(satisfied: bool, missing: list[str] = <factory>, conflicts: list[str] = <factory>, resolution_order: list[str] = <factory>)[source]#

Bases: object

Result of a dependency resolution pass.

satisfied#

True when all requirements are met with no missing dependencies and no version conflicts.

Type

bool

missing#

Names of required packages that were not found in the available set.

Type

list[str]

conflicts#

Human-readable descriptions of version mismatches (e.g., "foo: requires >=2.0, found 1.3.0").

Type

list[str]

resolution_order#

An ordered list of package names representing a safe loading sequence (populated when topological sorting is performed separately).

Type

list[str]

conflicts: list[str]#
missing: list[str]#
resolution_order: list[str]#
satisfied: bool#
class calute.extensions.dependency.VersionConstraint(constraint_str: str)[source]#

Bases: object

Parse and evaluate PEP 440-style version constraint strings.

A VersionConstraint encapsulates one or more comparison operators applied to version strings. Supported operators are ==, !=, >=, <=, >, <, and ~= (compatible release). Multiple constraints can be combined with commas (e.g., ">=1.0,<2.0"), in which case all constraints must be satisfied.

raw#

The original constraint string passed to the constructor.

Example

>>> vc = VersionConstraint(">=1.0.0")
>>> vc.satisfies("1.2.3")
True
>>> vc = VersionConstraint(">=1.0,<2.0")
>>> vc.satisfies("2.0.0")
False
>>> vc = VersionConstraint("~=1.2")
>>> vc.satisfies("1.3.0")
True
satisfies(version: str) bool[source]#

Check whether version satisfies every constraint.

If no constraints were parsed (e.g., the constraint string was empty), any version is considered satisfying.

Parameters

version – A dotted version string to test (e.g., "1.2.3").

Returns

True if version satisfies all individual constraints, False otherwise.

calute.extensions.dependency.parse_dependency(dep_str: str) DependencySpec[source]#

Parse a dependency string into a DependencySpec.

The string is expected to start with an alphanumeric-plus-hyphens/underscores name, optionally followed by a version constraint expression. If no constraint is present, version_constraint on the returned spec will be None.

Parameters

dep_str – A dependency declaration such as "my_plugin>=1.0.0" or plain "my_plugin".

Returns

A DependencySpec with the parsed name and optional version_constraint.

Example

>>> parse_dependency("my_plugin>=1.0.0")
DependencySpec(name='my_plugin', version_constraint='>=1.0.0')
>>> parse_dependency("my_plugin")
DependencySpec(name='my_plugin', version_constraint=None)