graphtage.builder

A module intended to simplify building Graphtage IR trees from other tree-like data structures.

builder classes

BasicBuilder

class graphtage.builder.BasicBuilder(options: BuildOptions | None = None)

Bases: Builder

A builder for basic Python types

BUILDERS: Dict[Type[Any], Callable[[Builder, Any, List[TreeNode]], TreeNode]] = {<class 'int'>: <function BasicBuilder.build_int>, <class 'bytes'>: <function BasicBuilder.build_str>, <class 'str'>: <function BasicBuilder.build_str>, <class 'NoneType'>: <function BasicBuilder.build_none>, <class 'float'>: <function BasicBuilder.build_float>, <class 'bool'>: <function BasicBuilder.build_bool>, <class 'tuple'>: <function BasicBuilder.build_list>, <class 'list'>: <function BasicBuilder.build_list>, <class 'frozenset'>: <function BasicBuilder.build_set>, <class 'set'>: <function BasicBuilder.build_set>, <class 'dict'>: <function BasicBuilder.build_dict>}
EXPANDERS: Dict[Type[Any], Callable[[Builder, Any], Iterable[Any] | None]] = {<class 'frozenset'>: <function BasicBuilder.expand_list>, <class 'set'>: <function BasicBuilder.expand_list>, <class 'tuple'>: <function BasicBuilder.expand_list>, <class 'list'>: <function BasicBuilder.expand_list>, <class 'dict'>: <function BasicBuilder.expand_dict>}
__init__(options: BuildOptions | None = None)
classmethod _resolve(obj_type: Type[Any], choices: Dict[Type[Any], T]) T | None

Resolves the most specialized expander or builder for obj_type

build(node: Any, children: List[TreeNode]) TreeNode
build_bool(obj: bool, _) BoolNode
build_dict(_, children: List[TreeNode])
build_float(obj: float, _) FloatNode
build_int(obj: int, _) IntegerNode
build_list(obj, children: List[TreeNode]) ListNode
build_none(obj, _) NullNode
build_set(obj, children: List[TreeNode]) MultiSetNode
build_str(obj: str, _) StringNode
build_tree(root_obj) TreeNode
static builder(node_type: Type[T])
default_builder(node: Any, children: List[TreeNode]) TreeNode
default_expander(node: Any) Iterable[Any]
expand(node: Any) Iterable[Any]
expand_dict(obj: dict)
expand_list(obj: list)
static expander(node_type: Type[T])
classmethod resolve_builder(obj_type: Type[Any]) Callable[[Any, List[TreeNode]], TreeNode] | None

Resolves the most specialized builder for obj_type

classmethod resolve_expander(obj_type: Type[Any]) Callable[[Any], Iterable[Any] | None] | None

Resolves the most specialized expander for obj_type

Builder

class graphtage.builder.Builder(options: BuildOptions | None = None)

Bases: ABC

BUILDERS: Dict[Type[Any], Callable[[Builder, Any, List[TreeNode]], TreeNode]]
EXPANDERS: Dict[Type[Any], Callable[[Builder, Any], Iterable[Any] | None]]
__init__(options: BuildOptions | None = None)
classmethod _resolve(obj_type: Type[Any], choices: Dict[Type[Any], T]) T | None

Resolves the most specialized expander or builder for obj_type

build(node: Any, children: List[TreeNode]) TreeNode
build_tree(root_obj) TreeNode
static builder(node_type: Type[T])
default_builder(node: Any, children: List[TreeNode]) TreeNode
default_expander(node: Any) Iterable[Any]
expand(node: Any) Iterable[Any]
static expander(node_type: Type[T])
classmethod resolve_builder(obj_type: Type[Any]) Callable[[Any, List[TreeNode]], TreeNode] | None

Resolves the most specialized builder for obj_type

classmethod resolve_expander(obj_type: Type[Any]) Callable[[Any], Iterable[Any] | None] | None

Resolves the most specialized expander for obj_type

CyclicReference

class graphtage.builder.CyclicReference(obj)

Bases: LeafNode

__init__(obj)

Creates a node with the given object.

Parameters:

obj – The underlying Python object wrapped by the node.

add_edit_modifier(modifier: Callable[[TreeNode, TreeNode], Edit | None])
calculate_total_size() int

By default, leaf nodes’ sizes are equal to the length of their wrapped object’s string representation.

This is equivalent to:

return len(str(self.object))

However, subclasses may override this function to return whatever size is required.

Returns:

The length of the string representation of self.object.

Return type:

int

children() Collection[TreeNode]

Leaf nodes have no children, so this always returns an empty tuple.

Returns:

An empty tuple.

Return type:

tuple

copy() T

Creates a deep copy of this node

copy_from(children: Iterable[TreeNode]) C

Constructs a new instance of this tree node from a list of its children

dfs() Iterator[TreeNode]

Performs a depth-first traversal over all of this node’s descendants.

self is always included and yielded first.

This implementation is equivalent to:

stack = [self]
while stack:
    node = stack.pop()
    yield node
    stack.extend(reversed(node.children()))
diff(node: TreeNode) EditedTreeNode | T

Performs a diff against the provided node.

Parameters:

node – The node against which to perform the diff.

Returns:

An edited version of this node with all edits being completed.

Return type:

Union[EditedTreeNode, T]

editable_dict() Dict[str, Any]

Copies self.__dict__, calling TreeNode.editable_dict() on any TreeNode objects therein.

This is equivalent to:

ret = dict(self.__dict__)
if not self.is_leaf:
    for key, value in ret.items():
        if isinstance(value, TreeNode):
            ret[key] = value.make_edited()
return ret

This is used by TreeNode.make_edited().

property edited: bool

Returns whether this node has been edited.

The default implementation returns False, whereas EditedTreeNode.edited() returns True.

edits(node: TreeNode) Edit

Calculates the best edit to transform this node into the provided node.

Parameters:

node – The node to which to transform.

Returns:

The best possible edit.

Return type:

Edit

get_all_edit_contexts(node: TreeNode) Iterator[Tuple[Tuple[TreeNode, ...], Edit]]

Returns an iterator over all edit contexts that will transform this node into the provided node.

Parameters:

node – The node to which to transform this one.

Returns:

An iterator over pairs of paths from node to the edited node, as well as its edit. Note that this iterator will automatically explode any CompoundEdit in the sequence.

Return type:

Iterator[Tuple[Tuple[“TreeNode”, …], Edit]

get_all_edits(node: TreeNode) Iterator[Edit]

Returns an iterator over all edits that will transform this node into the provided node.

Parameters:

node – The node to which to transform this one.

Returns:

An iterator over edits. Note that this iterator will automatically explode any CompoundEdit in the sequence.

Return type:

Iterator[Edit]

property is_leaf: bool

Returns whether this node is a leaf.

This implementation is equivalent to:

return len(self.children()) == 0
make_edited() EditedTreeNode | T

Returns a new, copied instance of this node that is also an instance of EditedTreeNode.

This is equivalent to:

return self.__class__.edited_type()(self)
Returns:

A copied version of this node that is also an instance of EditedTreeNode and thereby mutable.

Return type:

Union[EditedTreeNode, T]

property parent: TreeNode | None

The parent node of this node, or None if it has no parent.

The setter for this property should only be called by the parent node setting itself as the parent of its child.

ContainerNode subclasses automatically set this property for all of their children. However, if you define a subclass of TreeNode does not extend off of ContainerNode and for which len(self.children()) > 0, then each child’s parent must be set.

print(printer: Printer)

Prints this leaf node.

By default, leaf nodes print the repr() of their wrapped object:

printer.write(repr(self.object))
Parameters:

printer – The printer to which to write this node.

print_parent_context(printer: Printer, for_child: TreeNode)

Prints the context for the given child node.

For example, if this node represents a list and the child is the element at index 3, then “[3]” might be printed.

The child is expected to be one of this node’s children, but this is not validated.

The default implementation prints nothing.

to_obj()

Returns the object wrapped by this node.

This is equivalent to:

return self.object
property total_size: int

The size of this node.

This is an arbitrary, immutable value that is used to calculate the bounded costs of edits on this node.

The first time this property is called, its value will be set and memoized by calling TreeNode.calculate_total_size().

Returns:

An arbitrary integer representing the size of this node.

Return type:

int