API¶
Runtime support library for projects built with pyrig.
core ¶
Foundational utilities shared across the project.
constants ¶
Constants used throughout the project.
dependencies ¶
Installed package dependency graph and the cross-package discovery it enables.
discovery ¶
Subclass and module discovery scoped across installed package dependents.
dependency_graph
cached
¶
dependency_graph() -> DependencyGraph
Return the dependency graph of pyrig_runtime and its dependents.
Built once and cached. Pruned to pyrig_runtime and every package that
depends on it, directly or transitively; packages it depends on are not
included.
Returns:
| Type | Description |
|---|---|
DependencyGraph
|
Directed graph rooted at |
DependencyGraph
|
ancestors. |
Note
The returned instance is shared across all callers. Do not mutate it.
Source code in src/pyrig_runtime/core/dependencies/discovery.py
dependent_packages
cached
¶
dependent_packages(
package: ModuleType,
) -> tuple[ModuleType, ...]
Return every installed package that depends on package.
The result is cached per unique package argument.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
package
|
ModuleType
|
Package whose dependents should be discovered. |
required |
Returns:
| Type | Description |
|---|---|
ModuleType
|
Tuple of imported module objects for every package that depends on |
...
|
|
tuple[ModuleType, ...]
|
(dependencies before dependents). Does not include |
tuple[ModuleType, ...]
|
itself. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
Source code in src/pyrig_runtime/core/dependencies/discovery.py
equivalent_modules_across_dependencies ¶
equivalent_modules_across_dependencies(
module: ModuleType,
) -> Iterator[ModuleType]
Yield the equivalent module from every dependent of module's root package.
For each installed package that depends on the root of module,
locates the module at the same sub-path within that dependent and
yields it if the import succeeds. The root package itself is excluded
from results.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
ModuleType
|
Module whose root determines which dependents to search and whose sub-path within that root locates the corresponding module in each dependent. |
required |
Yields:
| Type | Description |
|---|---|
ModuleType
|
Successfully imported module objects, in dependency order. |
ModuleType
|
Dependents are silently skipped whenever importing the equivalent |
ModuleType
|
module fails, whether because no module exists at that sub-path |
ModuleType
|
or because the import itself raises. |
Source code in src/pyrig_runtime/core/dependencies/discovery.py
subclasses_across_dependencies ¶
subclasses_across_dependencies[T](
cls: type[T], module: ModuleType
) -> Iterator[type[T]]
Yield subclasses of cls defined at the same sub-path as module.
The search covers module itself, every sub-module if module is a
package, and the equivalently-located module (and its own sub-modules,
if a package) in every installed package that depends on module's
root package.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type[T]
|
Base class whose subclasses should be discovered. |
required |
module
|
ModuleType
|
Module or package that scopes the search, and whose root package determines which dependents are searched. |
required |
Yields:
| Type | Description |
|---|---|
type[T]
|
Subclass types of |
type[T]
|
order is stable across calls but reflects discovery order, not |
type[T]
|
any deliberate priority. |
Note
Every module within the search scope is imported as a side effect, executing any module-level code it contains.
Source code in src/pyrig_runtime/core/dependencies/discovery.py
distribution ¶
Utilities for parsing metadata text from installed Python distributions.
distribution_header ¶
Return the header portion of a distribution's metadata.
The header is the metadata content before the first blank line,
containing the single-line RFC 822 header fields (e.g. Name,
Requires-Dist). If no blank line is found, the entire metadata
text is returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metadata
|
str
|
The full metadata of an installed distribution. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The header portion of the distribution's metadata. |
Source code in src/pyrig_runtime/core/dependencies/distribution.py
distribution_header_value_pattern ¶
Compile a regex that matches a single-line metadata header field.
Matches lines of the form field_name: value. Use findall on the
result to collect every value when the header repeats.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
field_name
|
str
|
Name of the header field to match, exactly as it
appears in the metadata (e.g. |
required |
Returns:
| Type | Description |
|---|---|
Pattern[str]
|
A case-sensitive pattern with each match's value captured in the |
Pattern[str]
|
first group. |
Source code in src/pyrig_runtime/core/dependencies/distribution.py
distribution_metadata ¶
distribution_metadata(dist: Distribution) -> str | None
Return the full metadata text of a distribution, or None if it has none.
distribution_name ¶
distribution_requirement_as_module_name ¶
Extract the importable module name from a dependency requirement string.
Version specifiers, extras, and anything else after the package name are discarded. Hyphens are normalized to underscores; dots are kept, so namespace packages remain dotted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
req
|
str
|
A dependency requirement string, e.g. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The package name in snake_case, e.g. |
Example
distribution_requirement_as_module_name("my-package[extra]>=1.0.0") 'my_package'
Source code in src/pyrig_runtime/core/dependencies/distribution.py
distribution_requirements ¶
Return the list of dependency requirements from a distribution's metadata.
distribution_summary ¶
Return the summary recorded in an installed distribution's metadata.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metadata
|
str
|
The full metadata of an installed distribution. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The distribution's summary description. |
Raises:
| Type | Description |
|---|---|
LookupError
|
If the metadata has no |
Source code in src/pyrig_runtime/core/dependencies/distribution.py
graph ¶
Directed graph of installed Python package dependency relationships.
DependencyGraph ¶
Bases: DiGraph
Directed graph of installed Python package dependencies.
Nodes are package names normalized to their importable module form (hyphens become underscores); an edge A → B means "A depends on B". The graph is built at instantiation by scanning every installed distribution.
Source code in src/pyrig_runtime/core/graph.py
build ¶
Build the graph from installed Python distributions.
Distributions whose metadata cannot be read are skipped and do not become nodes.
Source code in src/pyrig_runtime/core/dependencies/graph.py
parse_name_and_deps ¶
parse_name_and_deps(
dist: Distribution,
) -> tuple[str, Iterator[str]]
Extract the package name and dependencies from a distribution.
The name and every dependency name are normalized to an importable
module name; dots are preserved for namespace packages (e.g.
zope.interface remains zope.interface).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dist
|
Distribution
|
Distribution to extract metadata from. |
required |
Returns:
| Type | Description |
|---|---|
str
|
A two-tuple |
Iterator[str]
|
normalized name of each dependency the distribution declares. If |
tuple[str, Iterator[str]]
|
the distribution's metadata cannot be read, |
tuple[str, Iterator[str]]
|
string and |
Raises:
| Type | Description |
|---|---|
LookupError
|
If the distribution's metadata can be read but does
not declare a |
Source code in src/pyrig_runtime/core/dependencies/graph.py
subclass ¶
Abstract base for cross-package subclass discovery without explicit registration.
DependencySubclass ¶
Abstract base enabling plugin-style subclass discovery across installed packages.
Subclasses declare a discovery scope by overriding the discovery hook, and the base class automatically finds every subclass defined at that scope, both within its root package and across every installed package that depends on it. The scope may be a single module, to keep discovery narrow, or a whole sub-package, to widen it to a full module hierarchy. No explicit registration is required.
concrete_leaves
classmethod
¶
discovery_module
abstractmethod
classmethod
¶
discovery_module() -> ModuleType
Return the module or package that scopes discovery of this class.
Used by subclasses() to scope cross-package discovery to the correct
namespace. Every concrete subclass must override this to declare where its
own implementation classes live: returning a package widens discovery to
that package's whole module hierarchy, while returning a plain module
keeps discovery narrow to that single module.
The base implementation returns pyrig_runtime.rig.
Returns:
| Type | Description |
|---|---|
ModuleType
|
The module or package that scopes the search for this class's |
ModuleType
|
subclasses. |
Note
The returned module's root package must be pyrig_runtime itself
or one of its installed dependents; otherwise discovery fails.
Source code in src/pyrig_runtime/core/dependencies/subclass.py
leaf
classmethod
¶
Return the leaf subclass for this class's discovery scope.
Returns the class itself if no subclasses are discovered. Otherwise
returns the first value leaves() yields for this class: if every
discovered leaf shares one merge key, that is this class's one
true leaf; if leaves span more than one merge key, every group but
the first encountered is silently discarded, so leaf() is only
meaningful for hierarchies that resolve to a single merge key.
Returns:
| Type | Description |
|---|---|
type[Self]
|
The first leaf subclass type |
type[Self]
|
itself if none are found. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the leaves in the first merge-key group cannot be combined into a single class. |
Note
Discovery runs fresh on every call, and merging generates a
new type each time, so two calls do not return the identical
object when leaves are merged — only L caches a stable
result. Which merged leaf's behavior wins for any method
they both define should not be relied upon.
Source code in src/pyrig_runtime/core/dependencies/subclass.py
leaves
classmethod
¶
Yield leaf subclasses discovered within the declared discovery scope.
Only leaf-level subclasses are considered; any intermediate parent
classes that also appear in the result are omitted. The remaining leaves
are grouped by merge_key(): a group with a single leaf is yielded as-is,
while a group with several leaves is combined into one newly generated subclass
inheriting from every leaf in that group, letting independently-installed
packages cooperatively extend the same class by sharing a merge key.
Yields:
| Type | Description |
|---|---|
type[Self]
|
Leaf subclass types, one per distinct |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the leaves within a merge key group cannot be combined into a single class. |
Source code in src/pyrig_runtime/core/dependencies/subclass.py
merge_key
classmethod
¶
merge_key() -> Hashable
Return the key that decides which leaf subclasses get merged together.
Leaf subclasses that return an equal merge key are combined into
one generated subclass by leaves(); those with different keys
stay apart. Override to group cooperating implementations under a
shared key. The default returns the class name, so same-named
leaf overrides across dependent packages merge automatically.
Returns:
| Type | Description |
|---|---|
Hashable
|
A value comparable with |
Hashable
|
subclasses. |
Source code in src/pyrig_runtime/core/dependencies/subclass.py
sort_key
classmethod
¶
Return the sort key used to order this class relative to peer subclasses.
Used by sorted_subclasses() to order a collection of subclasses.
Override to sort by priority, numeric position, or any other criterion.
The default returns the class name, giving alphabetical ordering.
Returns:
| Type | Description |
|---|---|
SupportsRichComparison
|
A value comparable with |
SupportsRichComparison
|
subclasses. |
Source code in src/pyrig_runtime/core/dependencies/subclass.py
sorted_subclasses
classmethod
¶
Sort the given subclasses using each subclass's sort_key().
Does not perform any discovery.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
subclasses
|
Iterable[type[Self]]
|
Subclass types to sort. |
required |
Returns:
| Type | Description |
|---|---|
list[type[Self]]
|
The same subclass types sorted by their |
Source code in src/pyrig_runtime/core/dependencies/subclass.py
subclasses
classmethod
¶
Yield every subclass discovered within the declared discovery scope.
Includes intermediate parent classes; unlike leaves(), the
result is not filtered down to leaves.
Yields:
| Type | Description |
|---|---|
type[Self]
|
Subclass types found anywhere in the discovery scope. The |
type[Self]
|
order is stable across calls but reflects discovery order, |
type[Self]
|
not any deliberate priority. |
Source code in src/pyrig_runtime/core/dependencies/subclass.py
DependencySubclassMeta ¶
Bases: ABCMeta
Metaclass backing DependencySubclass with the cached I/L properties.
I
property
¶
Return a cached instance of L.
The instance is created once per class and reused on every subsequent access.
Returns:
| Type | Description |
|---|---|
C
|
An instance of |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
graph ¶
Abstract directed graph foundation with forward and reverse edge traversal.
DiGraph ¶
Bases: ABC
Abstract directed graph with forward and reverse adjacency tracking.
Subclasses implement build to populate nodes and edges.
Attributes:
| Name | Type | Description |
|---|---|---|
nodes |
set[str]
|
Set of all node identifiers currently in the graph. |
edges |
dict[str, set[str]]
|
Forward adjacency map from each node to its outgoing neighbors. |
reverse_edges |
dict[str, set[str]]
|
Reverse adjacency map from each node to its incoming neighbors. |
Source code in src/pyrig_runtime/core/graph.py
add_edge ¶
Add a directed edge from source to target.
Creates both nodes if they do not already exist.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
str
|
Edge origin node. |
required |
target
|
str
|
Edge destination node. |
required |
Source code in src/pyrig_runtime/core/graph.py
ancestors ¶
Find all nodes that have a directed path to the target node.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str
|
Node to find ancestors for. |
required |
Returns:
| Type | Description |
|---|---|
set[str]
|
Set of nodes with a directed path to the target. The target |
set[str]
|
itself is included only if the graph has a cycle back to it. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the target node is not in the graph. |
Source code in src/pyrig_runtime/core/graph.py
build
abstractmethod
¶
Populate the graph with nodes and edges.
Called during construction. Subclasses must add every node and edge that belongs to the graph.
prune ¶
prune(root: str) -> None
Remove every node except root and its ancestors.
Edges to or from a removed node are removed along with it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
str
|
Node whose ancestors are kept. |
required |
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
Source code in src/pyrig_runtime/core/graph.py
sorted_ancestors ¶
Return the ancestors of target in topological order.
Each ancestor appears after every ancestor it has an outgoing edge to.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str
|
Node to find ancestors of. |
required |
Yields:
| Type | Description |
|---|---|
Iterable[str]
|
Each ancestor of |
Iterable[str]
|
if |
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
CycleError
|
If the ancestor subgraph contains a cycle, making topological sorting impossible. |
Source code in src/pyrig_runtime/core/graph.py
topological_sort_subgraph ¶
Sort a subset of nodes in topological order.
If there is an edge from A to B, B appears before A in the result. Nodes with no dependency relationship between them may appear in any relative order.
Only edges whose both endpoints are in nodes are considered; edges
to or from nodes outside the subset are ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
nodes
|
set[str]
|
The subset of nodes to sort. |
required |
Yields:
| Type | Description |
|---|---|
Iterable[str]
|
Each node in |
Raises:
| Type | Description |
|---|---|
KeyError
|
If any node in |
CycleError
|
If the subgraph contains a cycle, making topological sorting impossible. |
Source code in src/pyrig_runtime/core/graph.py
introspection ¶
Runtime introspection primitives for classes, callables, modules, and packages.
classes ¶
Utilities for Python classes.
discover_subclasses ¶
Discover all transitive subclasses of cls currently loaded in memory.
Each subclass appears exactly once, even when reachable through multiple inheritance paths. Does not trigger any imports, so only subclasses from already-imported modules are included in the result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type[T]
|
Base class to find subclasses of. |
required |
Returns:
| Type | Description |
|---|---|
tuple[type[T], ...]
|
Tuple of all transitive subclass types, excluding |
Source code in src/pyrig_runtime/core/introspection/classes.py
filter_concrete_classes ¶
Filter out abstract classes from a collection.
A class is considered abstract when it has one or more unimplemented abstract methods and therefore cannot be instantiated directly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
classes
|
Iterable[type[T]]
|
Iterable of class types to filter. |
required |
Yields:
| Type | Description |
|---|---|
type[T]
|
Concrete (non-abstract) classes from the input, in the same order |
type[T]
|
as |
Source code in src/pyrig_runtime/core/introspection/classes.py
filter_leaf_classes ¶
Yield only leaf classes, removing any ancestors present in the collection.
A class is kept only when no other class in the collection is a strict subclass of it. The original iterable is not modified.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
classes
|
Iterable[type[T]]
|
Iterable of class types to filter. |
required |
Yields:
| Type | Description |
|---|---|
type[T]
|
Classes that have no subclasses present in the same collection, in |
type[T]
|
the same order as |
Source code in src/pyrig_runtime/core/introspection/classes.py
generate_class ¶
generate_class[T](
name: str,
bases: tuple[type[T], ...],
methods: Iterable[FunctionType] = (),
namespace: dict[str, Any] | None = None,
) -> type[T]
Dynamically create a class from base classes, methods, and attributes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Name of the new class, used as its |
required |
bases
|
tuple[type[T], ...]
|
Base classes the new class inherits from. |
required |
methods
|
Iterable[FunctionType]
|
Functions to add to the class, each under its own |
()
|
namespace
|
dict[str, Any] | None
|
Extra attributes for the class body, keyed by name. Mutated
in place with the |
None
|
Returns:
| Type | Description |
|---|---|
type[T]
|
The newly created class. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Note
The generated class's __module__ is whatever the underlying
type() call infers from the calling context, which is not
necessarily the caller's own module. Pass "__module__" in
namespace to set it explicitly.
Source code in src/pyrig_runtime/core/introspection/classes.py
functions ¶
Utilities for Python functions.
filter_module_functions ¶
filter_module_functions(
module: ModuleType, members: Iterable[Any]
) -> Iterator[Callable[..., Any]]
Yield functions from members defined directly in module.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
ModuleType
|
Module to filter functions for. |
required |
members
|
Iterable[Any]
|
Iterable of candidate members to filter. |
required |
Yields:
| Type | Description |
|---|---|
Callable[..., Any]
|
Each function defined in |
Source code in src/pyrig_runtime/core/introspection/functions.py
module_functions ¶
module_functions(
module: ModuleType,
) -> Iterator[Callable[..., Any]]
Yield all functions defined directly in a module.
Excludes objects imported from other modules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
ModuleType
|
Module to inspect. |
required |
Yields:
| Type | Description |
|---|---|
Callable[..., Any]
|
Each function defined in |
Source code in src/pyrig_runtime/core/introspection/functions.py
inspection ¶
Utilities for inspecting Python objects.
obj_members ¶
Yield the values of an object's members without invoking descriptors.
Members are read statically, so properties with side effects are not
triggered. __annotate__ and __annotate_func__ are always excluded
from the result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
object
|
Object to inspect (class, module, or any Python object). |
required |
predicate
|
Callable[[Any], bool] | None
|
Optional filter. When given, only members for which it
returns |
None
|
Yields:
| Type | Description |
|---|---|
Any
|
Each matching member's value. |
Source code in src/pyrig_runtime/core/introspection/inspection.py
unwrap_obj ¶
unwrap_obj(obj: Callable[..., Any]) -> FunctionType | type
unwrap_obj(obj: property) -> FunctionType
Unwrap a Python object to its innermost underlying object.
Recognizes properties, bound methods, classmethods, staticmethods, and
functools.wraps-style decorator chains. All layers are removed, not just
the outermost one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
Any
|
Python object to unwrap. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
The innermost Python object after all wrapping layers have been removed. |
Source code in src/pyrig_runtime/core/introspection/inspection.py
modules ¶
Utilities for Python modules.
import_modules ¶
import_modules(
module_names: Iterable[str],
) -> Iterator[ModuleType]
Import multiple modules by name, lazily.
Modules are imported on demand as the result is iterated, not eagerly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module_names
|
Iterable[str]
|
Dotted module names to import. |
required |
Yields:
| Type | Description |
|---|---|
ModuleType
|
Each imported module, in the order the names are iterated. |
Source code in src/pyrig_runtime/core/introspection/modules.py
iter_modules ¶
iter_modules(
package: ModuleType,
) -> Iterator[tuple[ModuleType, bool]]
Import and yield each direct child of a package, in discovery order.
Only the immediate children are visited; nested sub-packages are not recursed into.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
package
|
ModuleType
|
Package to iterate. Must have a |
required |
Yields:
| Type | Description |
|---|---|
ModuleType
|
|
bool
|
|
Note
Importing each child is a deliberate side effect — any module-level code in those children executes on demand as the iterator is consumed.
Source code in src/pyrig_runtime/core/introspection/modules.py
replace_root_module ¶
replace_root_module(
module: ModuleType, root: str
) -> ModuleType
replace_root_module[T](
module: ModuleType, root: str, default: T
) -> ModuleType | T
replace_root_module(
module: ModuleType, root: str, default: Any = MISSING
) -> ModuleType | Any
Import the equivalent module under a different root package.
Replaces the first dotted segment of module's name with root and
attempts to import the resulting module name. Later segments are left
untouched even if they happen to share the old root's name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
ModuleType
|
Module whose root segment should be swapped. |
required |
root
|
str
|
Root package name to substitute in. |
required |
default
|
Any
|
Value to return if the import fails. If not provided, the exception propagates unchanged. |
MISSING
|
Returns:
| Type | Description |
|---|---|
ModuleType | Any
|
The imported module at the equivalent sub-path under |
ModuleType | Any
|
|
Source code in src/pyrig_runtime/core/introspection/modules.py
replace_root_module_name ¶
Return the equivalent module name under a different root package.
Replaces the first dotted segment of name with root. Later segments
are left untouched even if they happen to share the old root's name.
For a top-level name with no dots, the entire string is replaced and
root alone is returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Dotted module name (e.g., |
required |
root
|
str
|
Root package name to substitute in. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The equivalent dotted module name under |
Example
replace_root_module_name("some_package.subpackage.module", "other_package") 'other_package.subpackage.module'
Source code in src/pyrig_runtime/core/introspection/modules.py
root_module ¶
root_module(module: ModuleType) -> ModuleType
Import and return the top-level package of the given module.
For a module named "package.subpackage.module", the module corresponding
to "package" is returned. For a top-level module with no dots in its name,
the module for that same name is returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
ModuleType
|
Module to resolve the root package for. |
required |
Returns:
| Type | Description |
|---|---|
ModuleType
|
The module corresponding to the first segment of the dotted name. |
Source code in src/pyrig_runtime/core/introspection/modules.py
root_module_name ¶
Return the name of the top-level package of the given module.
For a module named "package.subpackage.module", the string "package"
is returned. For a top-level module with no dots in its name, that same
name is returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Dotted module name (e.g., |
required |
Returns:
| Type | Description |
|---|---|
str
|
The first segment of the dotted module name. |
Example
root_module_name("some_package.subpackage.module") 'some_package'
Source code in src/pyrig_runtime/core/introspection/modules.py
safe_import_module ¶
safe_import_module(
module_name: str,
package: str | None = ...,
*,
exceptions: tuple[type[BaseException], ...] = ...,
) -> ModuleType
safe_import_module[T](
module_name: str,
package: str | None = ...,
*,
default: T,
exceptions: tuple[type[BaseException], ...] = ...,
) -> ModuleType | T
safe_import_module(
module_name: str,
package: str | None = None,
*,
default: Any = MISSING,
exceptions: tuple[type[BaseException], ...] = (
Exception,
),
) -> ModuleType | Any
Import a module by name, with an optional fallback on failure.
By default, catches any Exception raised during import — not just
ImportError — so an error from the module's own top-level code (e.g.,
a stray ValueError) is caught too. Pass exceptions to narrow what
gets caught.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module_name
|
str
|
Dotted module name (e.g., |
required |
package
|
str | None
|
Anchor package for relative imports, forwarded to
|
None
|
default
|
Any
|
Value to return if the import raises a caught exception. If not provided, the exception propagates unchanged. |
MISSING
|
exceptions
|
tuple[type[BaseException], ...]
|
Exception types to catch. Defaults to |
(Exception,)
|
Returns:
| Type | Description |
|---|---|
ModuleType | Any
|
The imported module, or |
ModuleType | Any
|
and |
Source code in src/pyrig_runtime/core/introspection/modules.py
packages ¶
Utilities for Python packages.
is_package ¶
is_package(module: ModuleType) -> bool
register_package_modules
cached
¶
register_package_modules(package: ModuleType) -> None
Ensure all modules in a package hierarchy are imported.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
package
|
ModuleType
|
Root package whose entire module hierarchy will be imported. |
required |
Note
Cached per package — subsequent calls with the same package do nothing.
Source code in src/pyrig_runtime/core/introspection/packages.py
walk_package ¶
walk_package(
package: ModuleType,
) -> Iterator[tuple[ModuleType, bool]]
Walk all modules in a package hierarchy, recursing into sub-packages.
Importing each visited module is a side effect of iteration. The root
package itself is not yielded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
package
|
ModuleType
|
Root package to start traversal from. |
required |
Yields:
| Type | Description |
|---|---|
ModuleType
|
|
bool
|
|
Source code in src/pyrig_runtime/core/introspection/packages.py
strings ¶
Utilities for working with strings.
fully_qualified_name ¶
fully_qualified_name(
obj: MethodType | FunctionType | type,
) -> str
Return the fully qualified name of a callable.
The returned name consists of the callable's module and qualified name,
preserving any enclosing classes or functions.
E.g., for a method foo in class Bar in module baz, the fully qualified
name is "baz.Bar.foo".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
MethodType | FunctionType | type
|
The callable (function, method, or class). |
required |
Returns:
| Type | Description |
|---|---|
str
|
The callable's fully qualified name. |
Source code in src/pyrig_runtime/core/strings.py
kebab_to_snake_case ¶
regex_find ¶
Return the first captured group from a regex search on the given text.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pattern
|
Pattern[str]
|
A compiled regex pattern with at least one capturing group. |
required |
text
|
str
|
The text to search within. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The first captured group from the regex search. |
Raises:
| Type | Description |
|---|---|
LookupError
|
If no match is found for the pattern in the text. |
Source code in src/pyrig_runtime/core/strings.py
snake_to_kebab_case ¶
wrappers ¶
Utilities for wrapping callables.
safe_call ¶
safe_call(
func: Callable[..., Any],
*,
args: tuple[Any, ...] = (),
kwargs: dict[str, Any] | None = None,
default: Any = MISSING,
exceptions: tuple[type[BaseException], ...] = (
Exception,
),
) -> Any
Call func, returning default if a caught exception is raised.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
Callable[..., Any]
|
Callable to invoke. |
required |
args
|
tuple[Any, ...]
|
Positional arguments forwarded to |
()
|
kwargs
|
dict[str, Any] | None
|
Keyword arguments forwarded to |
None
|
default
|
Any
|
Value to return when a caught exception is raised. If omitted, the exception propagates instead. |
MISSING
|
exceptions
|
tuple[type[BaseException], ...]
|
Exception types to catch. Defaults to |
(Exception,)
|
Returns:
| Type | Description |
|---|---|
Any
|
The return value of |
Any
|
caught exception is raised and |
Source code in src/pyrig_runtime/core/wrappers.py
rig ¶
Convention-based namespace that dependent projects mirror to extend behavior.
cli ¶
CLI subsystem for pyrig-runtime-based projects.
Dependent projects inherit a runnable CLI entry point and can extend it with project-specific commands alongside shared built-in commands.
cli ¶
Typer CLI application builder with cross-package command discovery.
CLI ¶
Bases: DependencySubclass
Typer application builder for pyrig-runtime-based projects.
Builds and runs the command-line application for any project that depends on
pyrig-runtime. A dependent project may subclass CLI to override any step of
the build to fit its needs.
app ¶
base_app ¶
Create an empty base Typer application.
Returns:
| Type | Description |
|---|---|
Typer
|
A new Typer app configured to show help when invoked without |
Typer
|
arguments. |
base_app_kwargs ¶
Return keyword arguments for creating the base Typer application.
This base configuration makes sure that calling the CLI without any arguments will display the help message, and that the help text is the same as the description of the invoking project.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A dictionary of keyword arguments to pass to |
Source code in src/pyrig_runtime/rig/cli/cli.py
build_app ¶
Register the callback and all commands onto the given app.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
Typer
|
The Typer app to populate. |
required |
Returns:
| Type | Description |
|---|---|
Typer
|
The same app instance, now fully configured. |
Source code in src/pyrig_runtime/rig/cli/cli.py
callback ¶
callback(
verbose: Annotated[
int,
Option(
--verbose,
-v,
count=True,
help="Increase verbosity: -v (DEBUG), -vv (modules), -vvv (timestamps)",
),
] = 0,
quiet: Annotated[
int,
Option(
--quiet,
-q,
count=True,
help="Decrease verbosity: -q (WARNING), -qq (ERROR), -qqq (CRITICAL)",
),
] = 0,
) -> None
Apply the verbosity options for the current invocation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
verbose
|
Annotated[int, Option(--verbose, -v, count=True, help='Increase verbosity: -v (DEBUG), -vv (modules), -vvv (timestamps)')]
|
Number of times verbosity was increased (e.g. via |
0
|
quiet
|
Annotated[int, Option(--quiet, -q, count=True, help='Decrease verbosity: -q (WARNING), -qq (ERROR), -qqq (CRITICAL)')]
|
Number of times verbosity was decreased (e.g. via |
0
|
Source code in src/pyrig_runtime/rig/cli/cli.py
configure_logging ¶
Configure the logging level and format for the current invocation.
Each increment of verbose lowers the log level by one step (toward
DEBUG); each increment of quiet raises it by one step (toward
CRITICAL). The message format also expands as verbose increases:
the level name is added first, then the module name, then a
timestamp.
The resulting level is not clamped to the standard range, so a high
enough verbose or quiet count can push it below DEBUG or above
CRITICAL.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
verbose
|
int
|
Number of times verbosity was increased (e.g. via |
required |
quiet
|
int
|
Number of times verbosity was decreased (e.g. via |
required |
Note
Uses logging.basicConfig with force=True to ensure that the
configuration is applied even if logging has already been configured
by the calling project or other dependencies.
Source code in src/pyrig_runtime/rig/cli/cli.py
discovery_module
classmethod
¶
discovery_module() -> ModuleType
help_text ¶
help_text() -> str
Return the help text for the invoking project.
Returns:
| Type | Description |
|---|---|
str
|
The project's distribution summary, or an empty string if no |
str
|
metadata is available for it. |
Source code in src/pyrig_runtime/rig/cli/cli.py
merge_key
classmethod
¶
merge_key() -> Hashable
Return a constant merge key.
There is only one CLI so different subclasses should converge into
a single subclass
Returns:
The name of this class: CLI.
Source code in src/pyrig_runtime/rig/cli/cli.py
module_subcommand_groups ¶
module_subcommand_groups(
module: ModuleType,
) -> dict[str, Typer]
Return the Typer command groups found in a subcommands module.
Scans the module's namespace for typer.Typer instances. Both natively
defined and imported instances are included. The key for each entry is
the kebab-case form of the attribute name it is bound to.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
ModuleType
|
The subcommands module to scan. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Typer]
|
Mapping of kebab-case attribute name to the |
dict[str, Typer]
|
bound to it. |
Source code in src/pyrig_runtime/rig/cli/cli.py
package_name ¶
package_name() -> str
Return the snake_case package name of the invoking project.
For example, if the project is invoked as uv run my-project, the
package name is my_project.
Source code in src/pyrig_runtime/rig/cli/cli.py
project_name ¶
project_name() -> str
Return the stem of sys.argv[0] as the invoking project name.
When a project is invoked through a registered console-script entry point
(e.g. uv run my-project), sys.argv[0] is the path to that script, so
its stem is the project name as it was registered.
Source code in src/pyrig_runtime/rig/cli/cli.py
register_callback ¶
Attach the verbosity callback to the given app.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
Typer
|
The Typer app to attach the callback to. |
required |
register_direct_subcommands ¶
register_direct_subcommands(
app: Typer, module: ModuleType
) -> None
Register every function defined in a module as a top-level command.
Adds each function found directly in module to app as a flat Typer
command. Imported functions are excluded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
Typer
|
The Typer app to register the commands onto. |
required |
module
|
ModuleType
|
The subcommands module to scan for command functions. |
required |
Source code in src/pyrig_runtime/rig/cli/cli.py
register_shared_subcommands ¶
Discover and register shared commands from pyrig-runtime and its dependents.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
Typer
|
The Typer app to register the commands onto. |
required |
Note
Commands are registered in dependency order (pyrig-runtime first, then dependent packages in topological order). When two packages define a command with the same name, the last registration takes precedence.
Source code in src/pyrig_runtime/rig/cli/cli.py
register_subcommand_groups ¶
register_subcommand_groups(
app: Typer, module: ModuleType
) -> None
Register every typer.Typer instance in a module as a named command group.
Attaches each typer.Typer found in the module's namespace to app,
using the kebab-case form of the attribute name as the group name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
Typer
|
The Typer app to register the command groups onto. |
required |
module
|
ModuleType
|
The subcommands module to scan for group instances. |
required |
Source code in src/pyrig_runtime/rig/cli/cli.py
register_subcommands ¶
Discover and register project-specific commands for the invoking project.
Any dependent project can define its own CLI commands by adding
functions or typer.Typer groups to <package>.rig.cli.subcommands.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
Typer
|
The Typer app to register the commands onto. |
required |
Note
If the invoking project's subcommands module cannot be imported, registration is silently skipped.
Source code in src/pyrig_runtime/rig/cli/cli.py
commands ¶
Implementations of CLI command actions for pyrig-runtime-based projects.
version ¶
Version display command for pyrig-runtime-based project CLIs.
project_version ¶
Print the name and installed version of the project running this CLI.
Reports the version of the project whose CLI is currently running. The project must be installed for its version to be available.
Source code in src/pyrig_runtime/rig/cli/commands/version.py
main ¶
shared_subcommands ¶
Shared CLI commands for all dependent packages.
In every installed pyrig-runtime based package functions defined directly in this
module are registered as top-level CLI commands and module-level typer.Typer instances
are registered as command groups, with each group's name derived from the kebab-case
form of the variable name.
version ¶
Print the name and installed version.
Reports the version of whichever project's CLI entry point was used to invoke this command. The project must be installed.
Source code in src/pyrig_runtime/rig/cli/shared_subcommands.py
subcommands ¶
Project-specific CLI commands.
Functions defined directly in this module are registered as top-level CLI
commands. Module-level typer.Typer instances are registered as command
groups, with each group's name derived from the kebab-case form of the
variable name.