pyecsca.ec.context module

Provides classes for tracing the execution of operations.

The operations include key generation, scalar multiplication, formula execution and individual operation evaluation. These operations are traced in Context classes using Actions. Different contexts trace actions differently.

A DefaultContext traces actions into a tree as they are executed (a scalar multiplication actions has as its children an ordered list of the individual formula executions it has done).

A PathContext works like a DefaultContext that only traces an action on a particular path in the tree.

class Action[source]

Bases: object

An Action.

Can be entered:

>>> with Action() as action:
...     print(action.inside)
True
inside: bool[source]
class ResultAction[source]

Bases: Action

An action that has a result.

>>> with ResultAction() as action:
...     r = action.exit("result")
>>> action.result == r
True
property result: Any[source]

The result of the action.

exit(result)[source]
inside: bool[source]
class Node(action, parent=None, children=None)[source]

Bases: NodeMixin

A node in an execution tree.

action: Action[source]

The action of the node.

property parent[source]

Parent Node.

On set, the node is detached from any previous parent node and attached to the new node.

>>> from anytree import Node, RenderTree
>>> udo = Node("Udo")
>>> marc = Node("Marc")
>>> lian = Node("Lian", parent=marc)
>>> print(RenderTree(udo))
Node('/Udo')
>>> print(RenderTree(marc))
Node('/Marc')
└── Node('/Marc/Lian')

Attach

>>> marc.parent = udo
>>> print(RenderTree(udo))
Node('/Udo')
└── Node('/Udo/Marc')
    └── Node('/Udo/Marc/Lian')

Detach

To make a node to a root node, just set this attribute to None.

>>> marc.is_root
False
>>> marc.parent = None
>>> marc.is_root
True
property children[source]

All child nodes.

>>> from anytree import Node
>>> n = Node("n")
>>> a = Node("a", parent=n)
>>> b = Node("b", parent=n)
>>> c = Node("c", parent=n)
>>> n.children
(Node('/n/a'), Node('/n/b'), Node('/n/c'))

Modifying the children attribute modifies the tree.

Detach

The children attribute can be updated by setting to an iterable.

>>> n.children = [a, b]
>>> n.children
(Node('/n/a'), Node('/n/b'))

Node c is removed from the tree. In case of an existing reference, the node c does not vanish and is the root of its own tree.

>>> c
Node('/c')

Attach

>>> d = Node("d")
>>> d
Node('/d')
>>> n.children = [a, b, d]
>>> n.children
(Node('/n/a'), Node('/n/b'), Node('/n/d'))
>>> d
Node('/n/d')

Duplicate

A node can just be the children once. Duplicates cause a TreeError:

>>> n.children = [a, b, d, a]
Traceback (most recent call last):
    ...
anytree.node.exceptions.TreeError: Cannot add node Node('/n/a') multiple times as child.
get_by_key(path)[source]

Get a Node from the tree by a path of Action s.

>>> tree = Node(Action())
>>> a_a = Action()
>>> a = Node(a_a, parent=tree)
>>> one_a = Action()
>>> one = Node(one_a, parent=a)
>>> other_a = Action()
>>> other = Node(other_a, parent=a)
>>> tree.get_by_key([]) == tree
True
>>> tree.get_by_key([a_a]) == a
True
>>> tree.get_by_key(([a_a, one_a])) == one
True
Parameters:

path (List[Action]) – The path of actions to walk.

Return type:

Node

Returns:

The node.

get_by_index(path)[source]

Get a Node from the tree by a path of indices.

>>> tree = Node(Action())
>>> a_a = Action()
>>> a = Node(a_a, parent=tree)
>>> one_a = Action()
>>> one = Node(one_a, parent=a)
>>> other_a = Action()
>>> other = Node(other_a, parent=a)
>>> tree.get_by_index([]) == tree
True
>>> tree.get_by_index([0]) == a
True
>>> tree.get_by_index(([0, 0])) == one
True
Parameters:

path (List[int]) – The path of indices.

Return type:

Node

Returns:

The node.

walk(callback)[source]

Walk the tree in post-order (as it was executed) and apply callback.

Parameters:

callback (Callable[[Action], None]) – The callback to apply to the actions in the nodes.

render()[source]

Render the tree.

Return type:

str

property ancestors[source]

All parent nodes and their parent nodes.

>>> from anytree import Node
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.ancestors
()
>>> marc.ancestors
(Node('/Udo'),)
>>> lian.ancestors
(Node('/Udo'), Node('/Udo/Marc'))
property anchestors[source]

All parent nodes and their parent nodes - see ancestors.

The attribute anchestors is just a typo of ancestors. Please use ancestors. This attribute will be removed in the 3.0.0 release.

property depth[source]

Number of edges to the root Node.

>>> from anytree import Node
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.depth
0
>>> marc.depth
1
>>> lian.depth
2
property descendants[source]

All child nodes and all their child nodes.

>>> from anytree import Node
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> loui = Node("Loui", parent=marc)
>>> soe = Node("Soe", parent=lian)
>>> udo.descendants
(Node('/Udo/Marc'), Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Lian/Soe'), Node('/Udo/Marc/Loui'))
>>> marc.descendants
(Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Lian/Soe'), Node('/Udo/Marc/Loui'))
>>> lian.descendants
(Node('/Udo/Marc/Lian/Soe'),)
property height[source]

Number of edges on the longest path to a leaf Node.

>>> from anytree import Node
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.height
2
>>> marc.height
1
>>> lian.height
0
property is_leaf[source]

Node has no children (External Node).

>>> from anytree import Node
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.is_leaf
False
>>> marc.is_leaf
False
>>> lian.is_leaf
True
property is_root[source]

Node is tree root.

>>> from anytree import Node
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.is_root
True
>>> marc.is_root
False
>>> lian.is_root
False
iter_path_reverse()[source]

Iterate up the tree from the current node to the root node.

>>> from anytree import Node
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> for node in udo.iter_path_reverse():
...     print(node)
Node('/Udo')
>>> for node in marc.iter_path_reverse():
...     print(node)
Node('/Udo/Marc')
Node('/Udo')
>>> for node in lian.iter_path_reverse():
...     print(node)
Node('/Udo/Marc/Lian')
Node('/Udo/Marc')
Node('/Udo')
property leaves[source]

Tuple of all leaf nodes.

>>> from anytree import Node
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> loui = Node("Loui", parent=marc)
>>> lazy = Node("Lazy", parent=marc)
>>> udo.leaves
(Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Loui'), Node('/Udo/Marc/Lazy'))
>>> marc.leaves
(Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Loui'), Node('/Udo/Marc/Lazy'))
property path[source]

Path from root node down to this Node.

>>> from anytree import Node
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.path
(Node('/Udo'),)
>>> marc.path
(Node('/Udo'), Node('/Udo/Marc'))
>>> lian.path
(Node('/Udo'), Node('/Udo/Marc'), Node('/Udo/Marc/Lian'))
property root[source]

Tree Root Node.

>>> from anytree import Node
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.root
Node('/Udo')
>>> marc.root
Node('/Udo')
>>> lian.root
Node('/Udo')
separator = '/'[source]
property siblings[source]

Tuple of nodes with the same parent.

>>> from anytree import Node
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> loui = Node("Loui", parent=marc)
>>> lazy = Node("Lazy", parent=marc)
>>> udo.siblings
()
>>> marc.siblings
()
>>> lian.siblings
(Node('/Udo/Marc/Loui'), Node('/Udo/Marc/Lazy'))
>>> loui.siblings
(Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Lazy'))
property size[source]

Tree size — the number of nodes in tree starting at this node.

>>> from anytree import Node
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> loui = Node("Loui", parent=marc)
>>> soe = Node("Soe", parent=lian)
>>> udo.size
5
>>> marc.size
4
>>> lian.size
2
>>> loui.size
1
class Context[source]

Bases: ABC

Context is an object that traces actions which happen.

There is always one context active, see functions getcontext(), setcontext() and resetcontext(). Also, the local() contextmanager.

abstract enter_action(action)[source]

Enter into an action (i.e. start executing it).

Parameters:

action (Action) – The action.

Return type:

None

abstract exit_action(action)[source]

Exit from an action (i.e. stop executing it).

Parameters:

action (Action) – The action.

Return type:

None

class DefaultContext[source]

Bases: Context

Context that traces executions of actions in a forest.

>>> with local(DefaultContext()) as ctx:
...     with Action() as one_action:
...         with ResultAction() as other_action:
...             r = other_action.exit("some result")
...         with Action() as yet_another:
...             pass
>>> print(ctx.actions[0]) 
Action()
├──ResultAction(result='some result')
└──Action()
>>> for other in ctx.actions[0].children: 
...     print(other.action)
ResultAction(result='some result')
Action()
actions: List[Node][source]

A forest of trees.

current: List[Action][source]

The path to the current action.

enter_action(action)[source]

Enter into an action (i.e. start executing it).

Parameters:

action (Action) – The action.

Return type:

None

exit_action(action)[source]

Exit from an action (i.e. stop executing it).

Parameters:

action (Action) – The action.

Return type:

None

class PathContext(path)[source]

Bases: Context

Context that traces targeted actions.

Create a PathContext.

Parameters:

path (Sequence[int]) – The path of an action in the execution tree that will be captured.

path: List[int][source]
current: List[int][source]
current_depth: int[source]
value: Optional[Action][source]
enter_action(action)[source]

Enter into an action (i.e. start executing it).

Parameters:

action (Action) – The action.

Return type:

None

exit_action(action)[source]

Exit from an action (i.e. stop executing it).

Parameters:

action (Action) – The action.

Return type:

None

local(ctx=None)[source]

Use a local context.

Use it like a contextmanager, the context is active during its execution.

>>> with local(DefaultContext()) as ctx:
...     with Action() as action:
...         pass
>>> ctx.actions[0].action == action
True
Parameters:

ctx (Optional[Context]) – If none, current context is copied.

Return type:

ContextManager

Returns:

A context manager.