cottax.core.driven.nodes module

What attaching a driver makes: a conditional node with the algorithm answering it, and the places its roles sit at. Nothing here knows what runs it: realisation/ sits above this and wraps a driven node like any other.

check_pairing(driven: Driven)[source]

Check that a driver can be paired with the ConditionalNode.

Return type:

Iterator[Violation]

check_slots(driven: Driven)[source]

One slot per role the driver declares, and each slot as many places as its role takes on this node.

Return type:

Iterator[Violation]

class DrivenNode[V: Place][source]

Bases: ConditionalNode[V], Generic[V]

A conditional node with a driver answering it. Abstract like FunctionalNode & ConditionalNode; so an implementation or no implementation is possible.

condition: AbstractVar[ConditionalNode[V]]

The node answered, without the driver.

contract: AbstractVar[DriverContract[V]]

abstract to ABC until a subclass binds the name, and absent on a class that declares it as a field.

Type:

What the level binds in place of the annotation

data: AbstractVar[tuple[tuple[V, ...], ...]]

One slot per role in driver.takes, each as many places as its role’s arity.

reports: AbstractVar[tuple[tuple[V, ...], ...]]

One slot per role in driver.reports, the same way.

abstractmethod undriven()[source]

The condition node with the driver taken off: what Undrive edits. A final that cannot have it taken off refuses here.

Return type:

ConditionalNode[V]

data_of(role: type)[source]

The places its driver takes role at, the slot read off the node: one per unknown for a per-unknown role, one for a per-problem one; None where the driver takes no such role.

Return type:

tuple[V, ...] | None

places_of(role: type)[source]

The places its driver takes or reports role at, laid out as data_of; None where it has no such role.

Return type:

tuple[V, ...] | None

class Driven[V: Place](condition: ConditionalNode[V], contract: DriverContract[V], data: tuple[tuple[V, ...], ...], reports: tuple[tuple[V, ...], ...])[source]

Bases: DrivenNode[V], Generic[V]

Final of DrivenNode that has no implementation.

condition: ConditionalNode[V]

The node answered, without the driver.

contract: DriverContract[V]
data: tuple[tuple[V, ...], ...]

One slot per role in driver.takes, each as many places as its role’s arity.

reports: tuple[tuple[V, ...], ...]

One slot per role in driver.reports, the same way.

checks: PerLevel[tuple[Callable[[Any], object], ...]] = (<function check_pairing>, <function check_slots>)

Callable [self] -> iterable of violations, which are raised at construction unless skipped (see unchecked).

property unknowns: tuple[V, ...]

abstract to ABC until a subclass binds the name, and absent on a class that declares it as a field.

Type:

What the level binds in place of the annotation

property conditions: tuple[V, ...]

abstract to ABC until a subclass binds the name, and absent on a class that declares it as a field.

Type:

What the level binds in place of the annotation

property reads: tuple[V, ...]

abstract to ABC until a subclass binds the name, and absent on a class that declares it as a field.

Type:

What the level binds in place of the annotation

property owns: tuple[V, ...]

abstract to ABC until a subclass binds the name, and absent on a class that declares it as a field.

Type:

What the level binds in place of the annotation

determined(unknowns: tuple[V, ...])[source]

Refused: an algorithm was chosen for the node as it stands, and its per-unknown slots are laid out against the unknowns it had.

Return type:

Driven[V]

undriven()[source]

The condition node with the driver taken off: what Undrive edits. A final that cannot have it taken off refuses here.

Return type:

ConditionalNode[V]

relabel(renaming: Renaming[V])[source]

The same definition with its places renamed.

Return type:

Driven[V]

is_driven(d: object)[source]

A node carrying a driver, bare or under what runs it.

Return type:

bool

condition_of(node: Any)[source]

A driven node’s condition, else the node itself.

Return type:

Any

role_slots[N: Label, V: Place](graph: NestingGraph[N, V], role: type[Role])[source]

Each place a driven problem takes or reports role at, in binding order: the place, its problem, and for a per-unknown role the unknown it pairs with (None for a per-problem one). A place two problems take is there twice.

Return type:

tuple[tuple[V, N, Optional[V]], ...]

class DeterminedWhileDriven(driver: str, unknowns: tuple, asked: tuple)[source]

Bases: Violation

driver: str
unknowns: tuple
asked: tuple
template: AbstractClassVar[str] = 'a {driver} answers this problem over {unknowns!r}, so it cannot be made to determine {asked!r} -- the algorithm was chosen for the problem as it stands; `Undrive` it first'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class DrivenTwice(problem: object, driver: str)[source]

Bases: Violation

problem: object
driver: str
template: AbstractClassVar[str] = '{problem!r} already carries an algorithm, so a {driver} cannot answer it too -- `Undrive` it first'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class NotAccepted(driver: str, problem: object, predicate: str)[source]

Bases: Violation

driver: str
problem: object
predicate: str
template: AbstractClassVar[str] = '{driver} does not answer {problem!r}: its `accepts` is `{predicate}` -- what makes an answer right is not negotiable, and what a driver takes is what that predicate says'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class SlotsMiscounted(driver: str, side: str, roles: tuple, slots: int)[source]

Bases: Violation

driver: str
side: str
roles: tuple
slots: int
template: AbstractClassVar[str] = '{driver} {side} {roles!r}, one slot each, and is handed {slots} slots'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class RoleTwice(driver: str, side: str, roles: tuple)[source]

Bases: Violation

driver: str
side: str
roles: tuple
template: AbstractClassVar[str] = '{driver} {side} {roles!r} more than once: a role is one slot, since a run hands its data over by role'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class RoleUnsized(role: str)[source]

Bases: Violation

role: str
template: AbstractClassVar[str] = '{role} leaves `arity` abstract, so nothing says how many places it takes: a role is per unknown, per problem, or binds its own'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class RoleMisplaced(role: str, wanted: object, places: tuple)[source]

Bases: Violation

role: str
wanted: object
places: tuple
template: AbstractClassVar[str] = '{role} sits at {places!r}, but takes {wanted} on this node'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class DriversDiffer(driver: object, other: object)[source]

Bases: Violation

driver: object
other: object
template: AbstractClassVar[str] = '{driver!r} and {other!r} answer the two: which algorithm answers their join is not read off the two -- drive them alike, or `Undrive` and join the conditions'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class RoleAtTwoPlaces(role: str, places: tuple, other: tuple)[source]

Bases: Violation

role: str
places: tuple
other: tuple
template: AbstractClassVar[str] = '{role} sits at {places!r} and at {other!r}: one problem takes it once -- name one place for both before joining them'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording