orchestrata_ultimate.refactor.codemod.analysis.protocol

Reference › orchestrata_ultimate › refactor › codemod › analysis › protocol

The contract that every analysis pass follows, plus the helper that finds a target. AnalysisPass is a protocol with one method, analyze(target, **params), returning a result object; the daemon server, scripts.codemod and most analyzers import this module. resolve_node_id(cig, target) maps a module path or dotted name to a node id in the graph: it tries the key module:<path>, then the raw key, then the dotted form with a leading src., scripts. or tests. removed, and returns None when nothing matches.

At a glance

Source src/orchestrata_ultimate/refactor/codemod/analysis/protocol.py
Lines of code 56
Classes 1
Functions 1
Imports (internal) orchestrata_ultimate.core.base.traces, orchestrata_ultimate.refactor.codemod._cig
Imported by orchestrata_ultimate.refactor.codemod.analysis, orchestrata_ultimate.refactor.codemod.analysis.abstraction, orchestrata_ultimate.refactor.codemod.analysis.blast_radius, orchestrata_ultimate.refactor.codemod.analysis.complexity, orchestrata_ultimate.refactor.codemod.analysis.coupling, orchestrata_ultimate.refactor.codemod.analysis.dead_code, orchestrata_ultimate.refactor.codemod.analysis.test_coverage, orchestrata_ultimate.refactor.codemod.server, scripts.codemod
Tests that import it tests/refactor/codemod/analysis/test_protocol.py

Class diagram

Class diagram orchestrata_ultimate.refactor.codemod.analysis.protocol

Dependency diagram

Dependency diagram orchestrata_ultimate.refactor.codemod.analysis.protocol

API

Classes

AnalysisPass (protocol)

Bases: Protocol · Decorators: traces(spec='110', story='US-110-006', reqs=['REQ-110-031', 'REQ-110-032']), runtime_checkable · Line 23

A read-only analysis over one loaded workspace.

Attribute Type Default
name str
Method Signature Summary
analyze analyze(target: str | None = None, ****params: Any) -> object Run the analysis; target is a module path (or None for all).

Functions

Function Signature Summary
resolve_node_id traces resolve_node_id(cig: CodeIntelligenceGraph, target: str) -> int | None Resolve a module path or dotted name to its CIG node id.

Source

Permalink: https://gitlab.com/MSamy/orchestrata-ultimate-architecture/-/blob/a4cbc2bdf/src/orchestrata_ultimate/refactor/codemod/analysis/protocol.py

"""The AnalysisPass protocol and the shared target resolver (SPEC-110 FR-011).

An analysis pass is a read-only query over a loaded workspace: it takes the
workspace's ``CodeIntelligenceGraph`` (and, where the graph cannot answer,
the forest's ``ast`` overlay) and returns a frozen dataclass. It never
writes the workspace (REQ-110-032).
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable

from orchestrata_ultimate.core.base.traces import traces

if TYPE_CHECKING:
    from orchestrata_ultimate.refactor.codemod._cig import CodeIntelligenceGraph

__all__ = ["AnalysisPass", "resolve_node_id"]


@traces(spec="110", story="US-110-006", reqs=["REQ-110-031", "REQ-110-032"])
@runtime_checkable
class AnalysisPass(Protocol):
    """A read-only analysis over one loaded workspace."""

    name: str

    def analyze(self, target: str | None = None, **params: Any) -> object:
        """Run the analysis; ``target`` is a module path (or None for all)."""
        ...


@traces(spec="110", story="US-110-006", reqs=["REQ-110-031"])
def resolve_node_id(cig: CodeIntelligenceGraph, target: str) -> int | None:
    """Resolve a module path or dotted name to its CIG node id.

    Tries ``module:<path>``, the raw key, then the dotted form with a
    ``src.``/``scripts.``/``tests.`` prefix stripped (the strategies the
    ``scripts/codemod.py analyze`` command has always used).

    Returns:
        The node id, or None when no strategy matches.
    """
    key = f"module:{target}"
    if key in cig.key_to_id:
        return cig.key_to_id[key]
    if target in cig.key_to_id:
        return cig.key_to_id[target]
    dotted = target.replace("/", ".").replace(".py", "")
    for prefix in ("src.", "scripts.", "tests."):
        if dotted.startswith(prefix):
            dotted = dotted[len(prefix) :]
            break
    if dotted in cig.key_to_id:
        return cig.key_to_id[dotted]
    return None