Utilities

delb.utils.compare_trees(lhr: delb.typing.XMLNodeType, rhr: delb.typing.XMLNodeType) TreesComparisonResult[source]

Compares two node trees for equality. Upon the first detection of a difference of nodes that are located at the same position within the compared (sub-)trees a mismatch is reported.

Parameters:
  • lhr – The node that is considered as root of the left hand operand.

  • rhr – The node that is considered as root of the right hand operand.

Returns:

An object that contains information about the first or no difference.

While node types that can’t have descendants are comparable with a comparison expression, the delb.nodes.TagNode type deliberately doesn’t implement the == operator, because it isn’t clear whether a comparison should also consider the node’s descendants as this function does.

class delb.utils.TreesComparisonResult(difference_kind: TreeDifferenceKind, lhn: XMLNodeType | None, rhn: XMLNodeType | None)[source]

Instances of this class describe one or no difference between two trees. Casting an instance to bool will yield True when it describes no difference, thus the compared trees were equal. Casted to strings they’re intended to support debugging.

delb.utils.first(iterable: Iterable) Any | None[source]

Returns the first item of the given iterable or None if it’s empty. Note that the first item is consumed when the iterable is an iterator.

delb.utils.get_traverser(*, from_left=True, depth_first=True, from_top=True)[source]

Returns a function that can be used to traverse a (sub)tree with the given node as root.

Parameters:
  • from_left – The traverser yields sibling nodes from left to right if True, or starting from the right if False.

  • depth_first – The child nodes resp. the parent node are yielded before the siblings of a node by a traverser if True. Siblings are favored if False.

  • from_top – The traverser starts yielding nodes with the lowest depth if True. When False, again, the opposite is in effect.

While traversing the given root node is yielded at some point if it also passes the filters. The globally set default filters are not considered by the traverser routines.

The returned functions have this signature:

def traverser(root: XMLNodeType, *filters: Filter) -> Iterator[XMLNodeType]:
    ...
delb.utils.last(iterable: Iterable) Any | None[source]

Returns the last item of the given iterable or None if it’s empty. Note that the whole iterator is consumed when such is given.

delb.tag(local_name: str)[source]
delb.tag(local_name: str, attributes: Mapping[AttributeAccessor, str])
delb.tag(local_name: str, child: NodeSource)
delb.tag(local_name: str, children: Sequence[NodeSource])
delb.tag(local_name: str, attributes: Mapping[AttributeAccessor, str], child: NodeSource)
delb.tag(local_name: str, attributes: Mapping[AttributeAccessor, str], children: Sequence[NodeSource])

This function can be used for in-place creation (or call it templating if you want to) of delb.nodes.TagNode instances as:

  • node argument to methods that add nodes to a tree

  • items in the children argument of delb.nodes.TagNode

The first argument to the function is always the local name of the tag node. Optionally, the second argument can be a mapping that specifies attributes for that node. The optional last argument is either a single object that will be appended as child node or a sequence of such, these objects can be node instances of any type, strings (for derived delb.nodes.TextNode instances) or other definitions from this function (for derived delb.nodes.TagNode instances).

The actual nodes that are constructed always inherit the namespace of the context node they are created in. That also applies to attribute names that are given as single string.

>>> root = TagNode('root', children=[
...     tag("head", {"lvl": "1"}, "Hello!"),
...     tag("items", (
...         tag("item1"),
...         tag("item2"),
...         )
...     )
... ])
>>> str(root)
'<root><head lvl="1">Hello!</head><items><item1/><item2/></items></root>'
>>> root.append_children(tag("addendum"))
(<TagNode("{}addendum", {}, /*/*[3]) [0x...]>,)
>>> str(root)[-26:]
'</items><addendum/></root>'