Property Propagation
Added in version 1.5.0.
The s3dgraphy.resolvers package implements the 3-level property
resolver introduced in s3dgraphy 1.5 (DP-32 Layer A). Given a node and
a property name, the resolver walks the graph and returns the value plus
the source level it came from, so callers no longer need to know which
edges to traverse.
Conceptually
For every propagative property — author, license, embargo,
absolute_time_start, absolute_time_end — the resolver tries
three lookups in order and returns the first non-null result:
Node-level
PropagationRule.node_getter()reads a value attached directly to the input node (typically aPropertyNodereachable viahas_propertyor anAuthorNodereachable viahas_author).Swimlane-level For every
EpochNodeconnected to the input node viahas_first_epochorsurvive_in_epoch, the resolver callsPropagationRule.swimlane_getter(). IfPropagationRule.swimlane_aggregateis provided (minfor start dates,maxfor end dates), it is applied to the non-null values; otherwise the first non-null value wins.Graph-level
PropagationRule.graph_getter()reads a value from the canvas header (graph.attributes['author_name'|'license'|'embargo'], populated by the DP-40 Canvas Header loader).
When the input itself is an EpochNode, the resolver
short-circuits to the swimlane-level lookup — for an epoch, “node level”
and “swimlane level” are the same thing.
PropagationRule
Every propagative property is declared once as a
PropagationRule:
from s3dgraphy.resolvers import PropagationRule, register_rule
AUTHOR_RULE = PropagationRule(
id="author",
label="Author",
node_getter=_author_node_level,
swimlane_getter=_author_swimlane_level,
graph_getter=_author_graph_level,
)
register_rule(AUTHOR_RULE)
The four ship-standard rules are registered at module-import time in
s3dgraphy.resolvers.builtin_rules:
Rule id |
What it returns |
Aggregate |
|---|---|---|
|
TPQ — earliest year |
|
|
TAQ — latest year |
|
|
joined display string |
none |
|
license string |
none |
|
embargo end date |
none |
The author rule follows every has_author edge (not just the
first one) and joins the display values with " ; ". Duplicates are
de-duplicated while preserving edge order.
The author display string is read from
AuthorNode.description (1.5 dev9 yEd palette convention:
AuthorNode.name = "A.01",
AuthorNode.description = "Giulia Rossi | ORCID:… | affiliation"),
falling back to data["name"] + data["surname"] and lastly to the
short code in AuthorNode.name.
resolve() / resolve_with_source()
Two entry points:
from s3dgraphy.resolvers import resolve, resolve_with_source
val = resolve(graph, node, AUTHOR_RULE) # → "Giulia Rossi ; AI Tool"
val, src = resolve_with_source(graph, node, AUTHOR_RULE) # → ("Giulia Rossi", "swimlane")
src is one of "node" / "swimlane" / "graph" /
"none". Use it to tag UI labels (em-graph paints node-level values
black, swimlane-level grey, graph-level grey-italic).
Custom rules
Add a project-specific propagative property without touching s3dgraphy core:
MATERIAL_RULE = PropagationRule(
id="material",
label="Material",
node_getter=lambda g, n: _read_prop(g, n, "material_type"),
swimlane_getter=lambda g, e: _read_prop(g, e, "material_type"),
graph_getter=lambda g: g.attributes.get("project_material"),
)
register_rule(MATERIAL_RULE)
val = resolve(graph, node, MATERIAL_RULE)
Use register_rule() / unregister_rule() / get_rule() /
list_rules() from s3dgraphy.resolvers to manage the
registry.
See also
Temporal Inference Engine — the Temporal Inference Engine (Layer B) that uses the temporal rules registered here to seed TPQ/TAQ closure through stratigraphic relations.
Transforms — the
compacttransform that promotes per-node declarations to swimlane-level once the resolver reports they are redundant.Diagnostics API —
attribute_property_node/attribute_temporal_claimwalk the same provenance chain to attribute a value to who asserted it.
API Reference
- s3dgraphy.resolvers.PropagationRule[source]
Declarative description of how to resolve a propagative property.
The resolver walks three levels and returns the first non-null value:
node:
node_getter(graph, node)swimlane: for every EpochNode connected via
has_first_epochorsurvive_in_epoch, callswimlane_getter(graph, epoch); ifswimlane_aggregateis provided, it is applied to the list of non-null values (e.g.minormax). Otherwise the first non-null value wins.graph:
graph_getter(graph)
Any getter that returns
Nonesignals “no value at this level” and delegates to the next one. A getter may raise to signal a hard error.
See Resolvers API for the full autodoc of
s3dgraphy.resolvers.property_resolver and
s3dgraphy.resolvers.builtin_rules.