Resolvers API

The s3dgraphy.resolvers package implements property propagation: given a node and a property name, the resolver walks the graph and returns the value (and the source level it came from — node, swimlane, graph) without forcing the caller to know which edges to traverse.

Property resolver

Generic 3-level property resolver (DP-32 Layer A).

class s3dgraphy.resolvers.property_resolver.PropagationRule(id: str, label: str = '', node_getter: ~typing.Callable[[~typing.Any, ~typing.Any], ~typing.Any] = <function _noop_node>, swimlane_getter: ~typing.Callable[[~typing.Any, ~typing.Any], ~typing.Any] = <function _noop_swimlane>, graph_getter: ~typing.Callable[[~typing.Any], ~typing.Any] = <function _noop_graph>, swimlane_aggregate: ~typing.Callable[[~typing.List[~typing.Any]], ~typing.Any] | None = None)[source]

Bases: object

Declarative description of how to resolve a propagative property.

The resolver walks three levels and returns the first non-null value:

  1. node: node_getter(graph, node)

  2. swimlane: for every EpochNode connected via has_first_epoch or survive_in_epoch, call swimlane_getter(graph, epoch); if swimlane_aggregate is provided, it is applied to the list of non-null values (e.g. min or max). Otherwise the first non-null value wins.

  3. graph: graph_getter(graph)

Any getter that returns None signals “no value at this level” and delegates to the next one. A getter may raise to signal a hard error.

id: str
label: str = ''

Optional human-readable label (used in warnings and debug output).

node_getter(node)
swimlane_getter(epoch_node)
graph_getter()
swimlane_aggregate: Callable[[List[Any]], Any] | None = None

If set, applied to the list of non-null swimlane values. Typical values: min for start dates, max for end dates, or a custom combiner. When None, the first non-null value wins.

__init__(id: str, label: str = '', node_getter: ~typing.Callable[[~typing.Any, ~typing.Any], ~typing.Any] = <function _noop_node>, swimlane_getter: ~typing.Callable[[~typing.Any, ~typing.Any], ~typing.Any] = <function _noop_swimlane>, graph_getter: ~typing.Callable[[~typing.Any], ~typing.Any] = <function _noop_graph>, swimlane_aggregate: ~typing.Callable[[~typing.List[~typing.Any]], ~typing.Any] | None = None) → None
s3dgraphy.resolvers.property_resolver.resolve(graph, node, rule: PropagationRule, default=None)[source]

Return the resolved value for node following rule.

Falls back to default if no level yields a non-null value.

s3dgraphy.resolvers.property_resolver.resolve_with_source(graph, node, rule: PropagationRule, default=None) → Tuple[Any, str | None][source]

Like resolve(), but also returns the source level.

Returns a (value, source) tuple where source is one of "node", "swimlane", "graph" or None (when the default was used).

EpochNode query semantics. When node is itself an EpochNode, the node- and swimlane-level collapse to the same lookup: a value declared on the Epoch is the swimlane value. To match the user mental model (and the Epoch Manager UI, which thinks of the Epoch as a swimlane), the node-level call is skipped for Epochs and the returned source is always "swimlane" (or "graph") — never "node".

s3dgraphy.resolvers.property_resolver.register_rule(rule: PropagationRule) → None[source]

Register a rule. Replaces any existing rule with the same id.

s3dgraphy.resolvers.property_resolver.unregister_rule(rule_id: str) → None[source]

Remove a rule from the registry (silent if absent).

s3dgraphy.resolvers.property_resolver.get_rule(rule_id: str) → PropagationRule[source]

Fetch a registered rule by id. Raises KeyError if not found.

s3dgraphy.resolvers.property_resolver.list_rules() → List[str][source]

Return the ids of all registered rules, sorted.

Builtin rules

Built-in PropagationRules registered at import time.

  • absolute_time_start / absolute_time_end: feed Layer B (TPQ/TAQ closure) and reproduce the behavior of the previous hardcoded Graph._calculate_base_chronology.

  • author: declaration of the authorship property. Node-level and swimlane-level getters return None until DP-51 formalizes AuthorNode and has_author edges in yEd. Graph-level already works today: the Canvas Header loader (DP-40) populates graph.attributes['author_name' | ...].

See Property Propagation for the conceptual model (node-level → swimlane-level → graph-level fallback) and the list of canonical PropagationRule instances shipped with 1.5.