stratified_packager.toolbelt.relations

Plugin-agnostic QgsRelation graph and pathfinding utilities.

Builds an undirected multigraph over a project’s relation manager — nodes are layer ids, edges are (non-polymorphic) relations with their ordered field pairs — and answers the questions a partitioning engine asks of it: all shortest relation paths between two layers (more than one ⇒ ambiguity the caller must surface) and validation of a user-pinned relation chain.

Field pairs are read through referencingFields() / referencedFields(), which preserve composite-key pair order (fieldPairs() does not — it is an unordered map).

Error messages raised here are plain (untranslated) strings; callers presenting them to users are expected to wrap them into their own translated messages.

Module Attributes

RelationPath

An ordered chain of hops; empty when source and target are the same layer.

Functions

all_shortest_paths(graph, start, end, *[, ...])

Enumerate every shortest relation path from start to end.

build_relation_graph(manager)

Build the relation graph from a project's relation manager.

validate_pinned_path(graph, start, end, ...)

Validate a user-pinned relation chain from start to end.

Classes

RelationEdge(relation_id, name, ...)

One usable relation, reduced to plain data.

RelationGraph(edges)

Undirected multigraph of layers (nodes) and relations (edges).

RelationHop(edge, from_layer_id, to_layer_id)

One traversal step over an edge, in a concrete direction.

class stratified_packager.toolbelt.relations.RelationEdge(relation_id, name, referencing_layer_id, referenced_layer_id, referencing_fields, referenced_fields)[source]

One usable relation, reduced to plain data.

Parameters:
__init__(relation_id, name, referencing_layer_id, referenced_layer_id, referencing_fields, referenced_fields)
Parameters:
name: str

The relation’s display name.

referenced_fields: tuple[str, ...]

Ordered key field names on the referenced side, pairwise with the referencing ones.

referenced_layer_id: str

Layer id of the referenced (parent) side.

referencing_fields: tuple[str, ...]

Ordered key field names on the referencing side.

referencing_layer_id: str

Layer id of the referencing (child) side.

relation_id: str

The relation’s id in the relation manager.

class stratified_packager.toolbelt.relations.RelationGraph(edges)[source]

Undirected multigraph of layers (nodes) and relations (edges).

Parameters:

edges (Iterable[RelationEdge])

__init__(edges)[source]

Initialize the graph from plain edges.

Parameters:

edges (Iterable[RelationEdge]) – The usable relation edges.

edges_of(layer_id)[source]

Edges incident to layer_id.

Parameters:

layer_id (str) – The layer node.

Return type:

tuple[RelationEdge, ...]

Returns:

The incident edges (empty for unknown layers).

hops_from(layer_id)[source]

Directed hops leaving layer_id (one per incident edge, both edge directions).

A self-referencing relation (same layer on both sides) yields a single hop.

Parameters:

layer_id (str) – The layer node.

Return type:

tuple[RelationHop, ...]

Returns:

The outgoing hops.

_adjacency: defaultdict[str, list[RelationEdge]]
_edges_by_id: dict[str, RelationEdge]
property edges_by_id: Mapping[str, RelationEdge]

All edges keyed by relation id.

Returns:

A read-only view of the edge mapping.

class stratified_packager.toolbelt.relations.RelationHop(edge, from_layer_id, to_layer_id)[source]

One traversal step over an edge, in a concrete direction.

Parameters:
__init__(edge, from_layer_id, to_layer_id)
Parameters:
reversed()[source]

Return the same edge traversed in the opposite direction.

Return type:

RelationHop

Returns:

The reversed hop.

edge: RelationEdge

The relation being traversed.

property from_fields: tuple[str, ...]

Key field names on the hop’s start side.

Returns:

The ordered key fields of the from layer.

from_layer_id: str

Layer id the hop starts from.

property to_fields: tuple[str, ...]

Key field names on the hop’s arrival side.

Returns:

The ordered key fields of the to layer.

to_layer_id: str

Layer id the hop arrives at.

stratified_packager.toolbelt.relations.all_shortest_paths(graph, start, end, *, max_paths=16)[source]

Enumerate every shortest relation path from start to end.

Cycles cannot extend a shortest path, so traversal terminates on any graph. More than one result means the choice is ambiguous and the caller must require a pin.

Parameters:
  • graph (RelationGraph) – The relation graph.

  • start (str) – Source layer id.

  • end (str) – Target layer id.

  • max_paths (int) – Enumeration cap (ambiguity reporting needs only a few examples).

Return type:

list[tuple[RelationHop, ...]]

Returns:

All shortest paths (capped), shortest first by construction; empty when no path exists; [()] when start equals end.

stratified_packager.toolbelt.relations.build_relation_graph(manager)[source]

Build the relation graph from a project’s relation manager.

Invalid relations are skipped. Generated relations (the children of polymorphic relations) are skipped as well — polymorphic relations are not traversable as plain key chains.

Parameters:

manager (QgsRelationManager) – The project’s relation manager.

Return type:

RelationGraph

Returns:

The graph over all usable relations.

stratified_packager.toolbelt.relations.validate_pinned_path(graph, start, end, relation_ids)[source]

Validate a user-pinned relation chain from start to end.

Parameters:
  • graph (RelationGraph) – The relation graph.

  • start (str) – Source layer id (the packaged layer).

  • end (str) – Target layer id (the stratification layer).

  • relation_ids (Sequence[str]) – Ordered relation ids, from start towards end.

Return type:

tuple[RelationHop, ...]

Returns:

The validated hops.

Raises:

ValueError – If the pin is empty while the endpoints differ, names an unknown relation id, does not form a connected chain from start, or ends elsewhere than end.

type stratified_packager.toolbelt.relations.RelationPath = tuple[RelationHop, ...]

An ordered chain of hops; empty when source and target are the same layer.