graflo.architecture.contract.ingestion.resource¶
Declarative resource configuration (YAML/manifest contract).
Attributes¶
Resource = ResourceConfig
module-attribute
¶
logger = logging.getLogger(__name__)
module-attribute
¶
Classes¶
EdgeInferSpec
¶
Bases: ConfigBaseModel
Selector for controlling inferred edge emission.
Source code in graflo/architecture/contract/ingestion/resource.py
Attributes¶
edge_id
property
¶
relation = PydanticField(default=None, description='Optional relation discriminator. If omitted, selector applies to all relations for (source, target).')
class-attribute
instance-attribute
¶
source = PydanticField(..., description='Edge source vertex name.')
class-attribute
instance-attribute
¶
target = PydanticField(..., description='Edge target vertex name.')
class-attribute
instance-attribute
¶
Methods:¶
matches(edge_id)
¶
ResourceConfig
¶
Bases: ConfigBaseModel
Declarative resource definition (serializable contract).
Source code in graflo/architecture/contract/ingestion/resource.py
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 | |
Attributes¶
drop_trivial_input_fields = PydanticField(default=False, description='If True, remove top-level input keys whose value is None or the empty string before the actor pipeline runs.')
class-attribute
instance-attribute
¶
encoding = PydanticField(default=EncodingType.UTF_8, description='Character encoding for input/output (e.g. utf-8, ISO-8859-1).')
class-attribute
instance-attribute
¶
extra_weights = PydanticField(default_factory=list, description='Additional edge attribute / vertex-weight enrichment for this resource.')
class-attribute
instance-attribute
¶
fail_fast = PydanticField(default=False, description='If True, a transform step fails when required input keys are missing in the current document (rename: all source keys must be present; call: all input keys). If False (default), rename applies only to keys present in the document and functional transforms skip the step when inputs are missing.')
class-attribute
instance-attribute
¶
infer_edge_except = PydanticField(default_factory=list, description='Optional deny-list for inferred edges. Applies only to inferred (greedy) edges, not explicit edge actors.')
class-attribute
instance-attribute
¶
infer_edge_only = PydanticField(default_factory=list, description='Optional allow-list for inferred edges. Applies only to inferred (greedy) edges, not explicit edge actors.')
class-attribute
instance-attribute
¶
infer_edges = PydanticField(default=True, description='If True, infer edges from current vertex population. If False, emit only edges explicitly declared as edge actors in the pipeline.')
class-attribute
instance-attribute
¶
merge_collections = PydanticField(default_factory=list, description='Not implemented: nothing reads it, so a non-empty value is refused. Documents of one vertex fuse by identity without it.')
class-attribute
instance-attribute
¶
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
name = PydanticField(..., description='Name of the resource (e.g. table or file identifier).')
class-attribute
instance-attribute
¶
pipeline = PydanticField(..., description='Pipeline of actor steps to apply in sequence (vertex, edge, transform, descend). Each step is a dict, e.g. {"vertex": "user"} or {"edge": {"from": "a", "to": "b"}}.', validation_alias=AliasChoices('pipeline', 'apply'))
class-attribute
instance-attribute
¶
sync = PydanticField(default=None, description="Record sync ownership: the vertex type and the edges this resource's records replace when re-ingested in sync mode.")
class-attribute
instance-attribute
¶
tolerate_transform_errors = PydanticField(default=True, description='If True, a failing transform step sets its declared output fields to None, records the error, and continues the pipeline.')
class-attribute
instance-attribute
¶
types = PydanticField(default_factory=dict, description='Field name to Python type expression for casting (e.g. {"amount": "float"}).')
class-attribute
instance-attribute
¶
Methods:¶
canonical_field_payload(field_name)
¶
Canonical rendering of field_name, when it differs from its dump.
Consulted by content hashing and by the manifest differ. pipeline
is stored as authored dicts, and a step has several equivalent
spellings; this renders each step in one spelling (see
:func:~graflo.architecture.contract.ingestion.steps.parse.canonical_actor_step).
None means the field's ordinary dump is already canonical.
Source code in graflo/architecture/contract/ingestion/resource.py
collect_vertex_names()
¶
Vertex types referenced by this resource (pipeline and related config).
Source code in graflo/architecture/contract/ingestion/resource.py
pipeline_actor_count()
¶
Count actors in the pipeline without binding schema context.
Source code in graflo/architecture/contract/ingestion/resource.py
ResourceExtraWeightEntry
¶
Bases: ConfigBaseModel
Schema edge plus optional vertex-derived weight rules for DB enrichment.
Source code in graflo/architecture/contract/ingestion/resource.py
Functions:¶
collect_vertex_names_from_pipeline(steps)
¶
Collect vertex names referenced by pipeline steps (including nested descend).
Source code in graflo/architecture/contract/ingestion/resource.py
find_vertex_producing_levels(steps, vertex, *, known_vertices=None)
¶
Index paths of every pipeline level with a step producing vertex.
A path indexes one level's steps per element, descending through descend
steps: [] is the root level, [2] the level inside the root's third
step, [2, 0] one further down. Paths are returned outermost-first.
This is how a level-targeted op finds where to act. The level matters
because an actor reads its transform buffer at its own LocationIndex
with no ancestor fallback, so a derivation appended at the root is invisible
to a vertex produced under a descend.
Two tiers. Levels with an explicit producer — a vertex step, a
router whose table names the class, or one whose vertex_types lists
it — decide when any exist. Only when none does, and known_vertices
declares the class, every level holding an unbounded vertex_router
counts: the router routes the raw discriminator value as the class name,
which is the whole mechanism of a router without a type_map. An
explicit table outranks pass-through so that adding one dynamic router
elsewhere never turns a resolved level ambiguous.
Source code in graflo/architecture/contract/ingestion/resource.py
is_pass_through_router(step)
¶
Whether step is a vertex_router routing an unmapped value as itself.
Source code in graflo/architecture/contract/ingestion/resource.py
is_unbounded_router(step)
¶
Whether step is a vertex_router that can produce any declared class.
It passes unmapped values through and has no vertex_types.
Source code in graflo/architecture/contract/ingestion/resource.py
level_rewrites(level)
¶
Fields the transforms of one pipeline level may write; None if one does not say.
Every transform of a level runs before the level's routers, whatever its place in the list, so all of them count.
Source code in graflo/architecture/contract/ingestion/resource.py
pipeline_find_selectors(pipeline, *, known_vertices=None)
¶
The secondary identity each class is found by, over every level of pipeline.
Raises:
| Type | Description |
|---|---|
ValueError
|
A class gets two different selectors, or is produced both
by a |
Source code in graflo/architecture/contract/ingestion/resource.py
pipeline_has_pass_through_router(steps)
¶
Whether any level of steps holds a router routing unmapped values as-is.
pipeline_has_unbounded_router(steps)
¶
Whether any level of steps holds a router that can produce any class.
An unbounded router routes an unmapped discriminator value as the class
name, so a pipeline holding one can produce any class the schema declares
— not only the names its steps state. Anything scoping a schema to a
resource by the names its pipeline mentions must widen to every class when
this is true, or the router silently drops each record whose class it did
not name. A closed or bounded router's classes are its
:func:router_reach, which the pipeline names.
Source code in graflo/architecture/contract/ingestion/resource.py
resolve_pipeline_level(steps, path)
¶
Return the live step list path addresses inside steps.
Mutating the returned list mutates steps. Getting that guarantee requires
rewriting each walked descend step into its normalized form and storing
it back: the shorthand spellings ({descend: {apply: [...]}}, a bare
{key, apply}) keep their sub-steps under a different key, so returning
whatever normalize_actor_step built would hand back a list nothing
holds — and an append into it would vanish without a word. Steps off the
path, and the root level itself, are left exactly as authored.
Raises when the path does not resolve. Every index on the way must address
a descend step; those are the only steps that own a nested level.
Source code in graflo/architecture/contract/ingestion/resource.py
role_reach(pipeline)
¶
What each accumulator role in pipeline can hold, at any level.
A vertex step with a role holds its class; a router's role (its
role, else its type_field) holds its :func:router_reach, None
when that is any class. Several producers of one role add up.
Source code in graflo/architecture/contract/ingestion/resource.py
route_discriminator(step, raw, declared)
¶
The class a vertex_router sends a record with discriminator raw to.
The runtime's rule: a closed router (type_map_only) skips a value its
table lacks; type_map translates, and an unmapped value stands for the
class of that name; a class declared lacks, or vertex_types
excludes, is skipped. None for a skipped record.
Source code in graflo/architecture/contract/ingestion/resource.py
routed_row_condition(pipeline, declared)
¶
The rows pipeline produces anything from, as routed values per field.
When every top-level step is a transform, a vertex_router, or an
edge between router roles, a row produces something only if a router
routes its type_field value. The result maps each such field to the
values routed (routers on one field add up); a row counts when any field
holds one of its values. A field no value routes on is left out, so {}
means no row produces anything.
None when a row may produce something without a router: another kind
of top-level step, an edge end that is not a router role, or a transform
of the level that may write a router's type_field.
Source code in graflo/architecture/contract/ingestion/resource.py
router_accepted_values(step, declared)
¶
Every discriminator value a vertex_router sends to some class.
An unmapped value routes as the class of that name, so the values that
can route are the type_map keys and the declared class names; each
is kept when :func:route_discriminator routes it.
Source code in graflo/architecture/contract/ingestion/resource.py
router_keeps_subset(pipeline)
¶
Whether a top-level router of pipeline is closed or bounded by vertex_types.
Source code in graflo/architecture/contract/ingestion/resource.py
router_reach(step, *, known_vertices=None)
¶
The classes a vertex_router step can produce; None for any class.
A closed router (type_map_only) reaches the classes its table names.
An open one also routes an unmapped value as the class of that name, so it
reaches every class known_vertices declares -- or, without them, any
class. vertex_types bounds either: an open router with it reaches
exactly the listed classes, known or not.
Source code in graflo/architecture/contract/ingestion/resource.py
step_finds(step, vertex, *, known_vertices=None)
¶
The secondary identity step finds vertex by; None when it does not.
A vertex step names it in find; a vertex_router in its per-class
find map, for a class the router can reach (its :func:router_reach
over known_vertices, as in :func:step_produces_vertices).
Source code in graflo/architecture/contract/ingestion/resource.py
step_looks_up(step, vertex)
¶
Whether step only looks vertex up -- matches it, never writes it.
A vertex step says so with lookup_only: true; a vertex_router
with lookup_only: true (every class it routes to) or a list naming
vertex.
Source code in graflo/architecture/contract/ingestion/resource.py
step_produces_vertices(step, *, known_vertices=None)
¶
Vertex names a single (non-recursive) actor step produces.
Production, not reference: an edge step names endpoints it looks up, so
it is not counted. A vertex_router produces its :func:router_reach.
For an unbounded router without known_vertices that is unknown, and the
answer is its explicit targets -- the classes its type_map selects.
A vertex_from_map key is not one: it projects a class the router
reaches, and naming it does not make the router produce it.
Source code in graflo/architecture/contract/ingestion/resource.py
transform_writes(step)
¶
Fields a normalized transform step may write; None when it does not say.