diff --git a/pyproject.toml b/pyproject.toml index bd9065d..6f1a2a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,63 +68,63 @@ select = [ "W", # pydocstyle "D", - # # pep8-naming - # "N", - # # flake8-2020 - # "YTT", - # # flake8-bugbear - # "B", - # # flake8-quotes - # "Q", - # # flake8-debugger - # "T10", - # # flake8-gettext - # "INT", - # # pylint - # "PL", - # # misc lints - # "PIE", - # # flake8-pyi + # pep8-naming + "N", + # flake8-2020 + "YTT", + # flake8-bugbear + "B", + # flake8-quotes + "Q", + # flake8-debugger + "T10", + # flake8-gettext + "INT", + # pylint + "PL", + # misc lints + "PIE", + # flake8-pyi # "PYI", - # # tidy imports - # "TID", - # # implicit string concatenation - # "ISC", - # # type-checking imports - # "TC", - # # comprehensions + # tidy imports + "TID", + # implicit string concatenation + "ISC", + # type-checking imports + "TC", + # comprehensions # "C", - # "C4", - # # pygrep-hooks - # "PGH", - # # Ruff-specific rules - # "RUF", - # # flake8-bandit: exec-builtin - # "S102", - # # numpy-legacy-random - # "NPY002", - # # Perflint + "C4", + # pygrep-hooks + "PGH", + # Ruff-specific rules + "RUF", + # flake8-bandit: exec-builtin + "S102", + # numpy-legacy-random + "NPY002", + # Perflint # "PERF", - # # flynt - # "FLY", - # # flake8-logging-format - # "G", - # # pyupgrade - # "UP", - # # annotation - # # "ANN" - # # bandit + # flynt + "FLY", + # flake8-logging-format + "G", + # pyupgrade + "UP", + # annotation + # "ANN" + # bandit # "S", - # # Argument - # # "ARG", - # # Pathlib + # Argument + # "ARG", + # Pathlib # "PTH", - # # Simplify - # # "SIM", - # # Return - # "RET", - # # Raise - # "RSE", + # Simplify + # "SIM", + # Return + "RET", + # Raise + "RSE", ] ignore = [ # too-many-arguments @@ -150,6 +150,8 @@ ignore = [ 'TC001', # Indent of doctest 'D412', + # unused loop + 'B007', ] [tool.ruff.lint.per-file-ignores] "tests/*" = [ @@ -164,6 +166,8 @@ ignore = [ "D103", # Unused variables "F841", + # complexity + 'PLR0915', ] [tool.ruff.lint.pydocstyle] @@ -195,7 +199,3 @@ exclude_lines = [ [tool.mypy] disable_error_code = "misc" ignore_missing_imports = true - -[[tool.mypy.overrides]] -module = "tests.*" -allow_untyped_defs = true diff --git a/src/anytree/__init__.py b/src/anytree/__init__.py index b990d47..f8c4ad1 100644 --- a/src/anytree/__init__.py +++ b/src/anytree/__init__.py @@ -27,10 +27,10 @@ "ContStyle", "CountError", "DoubleStyle", + "LevelGroupOrderIter", "LevelOrderGroupIter", "LevelOrderIter", "LightNodeMixin", - "LevelGroupOrderIter", "LoopError", "Node", "NodeMixin", diff --git a/src/anytree/config.py b/src/anytree/config.py index 55a163c..a0d7b2d 100644 --- a/src/anytree/config.py +++ b/src/anytree/config.py @@ -3,4 +3,4 @@ import os # Global Option which enables all internal assertions. -ASSERTIONS = bool(int(os.environ.get("ANYTREE_ASSERTIONS", 0))) +ASSERTIONS = bool(int(os.environ.get("ANYTREE_ASSERTIONS", "0"))) diff --git a/src/anytree/dotexport.py b/src/anytree/dotexport.py index ff1d5e6..4a52368 100644 --- a/src/anytree/dotexport.py +++ b/src/anytree/dotexport.py @@ -7,6 +7,8 @@ class RenderTreeGraph(DotExporter): def __init__(self, *args, **kwargs): """Legacy. Use :any:`anytree.exporter.DotExporter` instead.""" warnings.warn( - ("anytree.RenderTreeGraph has moved. Use anytree.exporter.DotExporter instead"), DeprecationWarning + ("anytree.RenderTreeGraph has moved. Use anytree.exporter.DotExporter instead"), + DeprecationWarning, + stacklevel=2, ) - super(RenderTreeGraph, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) diff --git a/src/anytree/exporter/__init__.py b/src/anytree/exporter/__init__.py index 6834006..8a58f35 100644 --- a/src/anytree/exporter/__init__.py +++ b/src/anytree/exporter/__init__.py @@ -1,7 +1,14 @@ """Exporter.""" -from .dictexporter import DictExporter # noqa -from .dotexporter import DotExporter # noqa -from .dotexporter import UniqueDotExporter # noqa -from .jsonexporter import JsonExporter # noqa -from .mermaidexporter import MermaidExporter # noqa +from .dictexporter import DictExporter +from .dotexporter import DotExporter, UniqueDotExporter +from .jsonexporter import JsonExporter +from .mermaidexporter import MermaidExporter + +__all__ = [ + "DictExporter", + "DotExporter", + "JsonExporter", + "MermaidExporter", + "UniqueDotExporter", +] diff --git a/src/anytree/exporter/dotexporter.py b/src/anytree/exporter/dotexporter.py index a22eb7a..7a13617 100644 --- a/src/anytree/exporter/dotexporter.py +++ b/src/anytree/exporter/dotexporter.py @@ -223,26 +223,23 @@ def _default_filter(node): def __iter(self, indent, nodenamefunc, nodeattrfunc, edgeattrfunc, edgetypefunc, filter_): yield f"{self.graph} {self.name} {{" - for option in self.__iter_options(indent): - yield option - for node in self.__iter_nodes(indent, nodenamefunc, nodeattrfunc, filter_): - yield node - for edge in self.__iter_edges(indent, nodenamefunc, edgeattrfunc, edgetypefunc, filter_): - yield edge + yield from self.__iter_options(indent) + yield from self.__iter_nodes(indent, nodenamefunc, nodeattrfunc, filter_) + yield from self.__iter_edges(indent, nodenamefunc, edgeattrfunc, edgetypefunc, filter_) yield "}" def __iter_options(self, indent): options = self.options if options: for option in options: - yield "%s%s" % (indent, option) + yield f"{indent}{option}" def __iter_nodes(self, indent, nodenamefunc, nodeattrfunc, filter_): for node in PreOrderIter(self.node, filter_=filter_, stop=self.stop, maxlevel=self.maxlevel): nodename = nodenamefunc(node) nodeattr = nodeattrfunc(node) - nodeattr = " [%s]" % nodeattr if nodeattr is not None else "" - yield '%s"%s"%s;' % (indent, DotExporter.esc(nodename), nodeattr) + nodeattr = f" [{nodeattr}]" if nodeattr is not None else "" + yield f'{indent}"{DotExporter.esc(nodename)}"{nodeattr};' def __iter_edges(self, indent, nodenamefunc, edgeattrfunc, edgetypefunc, filter_): maxlevel = self.maxlevel - 1 if self.maxlevel else None @@ -254,14 +251,8 @@ def __iter_edges(self, indent, nodenamefunc, edgeattrfunc, edgetypefunc, filter_ childname = nodenamefunc(child) edgeattr = edgeattrfunc(node, child) edgetype = edgetypefunc(node, child) - edgeattr = " [%s]" % edgeattr if edgeattr is not None else "" - yield '%s"%s" %s "%s"%s;' % ( - indent, - DotExporter.esc(nodename), - edgetype, - DotExporter.esc(childname), - edgeattr, - ) + edgeattr = f" [{edgeattr}]" if edgeattr is not None else "" + yield f'{indent}"{DotExporter.esc(nodename)}" {edgetype} "{DotExporter.esc(childname)}"{edgeattr};' def to_dotfile(self, filename): """ @@ -288,7 +279,7 @@ def to_dotfile(self, filename): """ with codecs.open(filename, "w", "utf-8") as file: for line in self: - file.write("%s\n" % line) + file.write(f"{line}\n") def to_picture(self, filename): """ @@ -302,7 +293,7 @@ def to_picture(self, filename): with NamedTemporaryFile("wb", delete=False) as dotfile: dotfilename = dotfile.name for line in self: - dotfile.write(("%s\n" % line).encode("utf-8")) + dotfile.write((f"{line}\n").encode()) dotfile.flush() cmd = ["dot", dotfilename, "-T", fileformat, "-o", filename] check_call(cmd) @@ -315,7 +306,7 @@ def to_picture(self, filename): @staticmethod def esc(value): """Escape Strings.""" - return _RE_ESC.sub(lambda m: r"\%s" % m.group(0), six.text_type(value)) + return _RE_ESC.sub(lambda m: rf"\{m.group(0)}", six.text_type(value)) class UniqueDotExporter(DotExporter): @@ -438,7 +429,7 @@ def __init__( stop=None, maxlevel=None, ): - super(UniqueDotExporter, self).__init__( + super().__init__( node, graph=graph, name=name, @@ -466,4 +457,4 @@ def _default_nodenamefunc(self, node): @staticmethod def _default_nodeattrfunc(node): - return 'label="%s"' % (node.name,) + return f'label="{node.name}"' diff --git a/src/anytree/exporter/mermaidexporter.py b/src/anytree/exporter/mermaidexporter.py index f413321..010849a 100644 --- a/src/anytree/exporter/mermaidexporter.py +++ b/src/anytree/exporter/mermaidexporter.py @@ -166,12 +166,12 @@ def _default_nodenamefunc(self, node): num = self.__node_ids[node_id] except KeyError: num = self.__node_ids[node_id] = next(self.__node_counter) - return "N%d" % (num,) + return f"N{num}" @staticmethod def _default_nodefunc(node): # pylint: disable=W0613 - return '["%s"]' % (MermaidExporter.esc(node.name),) + return f'["{MermaidExporter.esc(node.name)}"]' @staticmethod def _default_edgefunc(node, child): @@ -180,24 +180,20 @@ def _default_edgefunc(node, child): def __iter(self, indent, nodenamefunc, nodefunc, edgefunc, filter_, stop): yield f"{self.graph} {self.name}" - for option in self.__iter_options(indent): - yield option - for node in self.__iter_nodes(indent, nodenamefunc, nodefunc, filter_, stop): - yield node - for edge in self.__iter_edges(indent, nodenamefunc, edgefunc, filter_, stop): - yield edge + yield from self.__iter_options(indent) + yield from self.__iter_nodes(indent, nodenamefunc, nodefunc, filter_, stop) + yield from self.__iter_edges(indent, nodenamefunc, edgefunc, filter_, stop) def __iter_options(self, indent): options = self.options if options: for option in options: - yield "%s%s" % (indent, option) + yield f"{indent}{option}" def __iter_nodes(self, indent, nodenamefunc, nodefunc, filter_, stop): for node in PreOrderIter(self.node, filter_=filter_, stop=stop, maxlevel=self.maxlevel): nodename = nodenamefunc(node) - node = nodefunc(node) - yield "%s%s%s" % (indent, nodename, node) + yield f"{indent}{nodename}{nodefunc(node)}" def __iter_edges(self, indent, nodenamefunc, edgefunc, filter_, stop): maxlevel = self.maxlevel - 1 if self.maxlevel else None @@ -207,12 +203,7 @@ def __iter_edges(self, indent, nodenamefunc, edgefunc, filter_, stop): if filter_(child) and not stop(child): childname = nodenamefunc(child) edge = edgefunc(node, child) - yield "%s%s%s%s" % ( - indent, - nodename, - edge, - childname, - ) + yield f"{indent}{nodename}{edge}{childname}" def to_file(self, filename): """ @@ -235,10 +226,10 @@ def to_file(self, filename): with codecs.open(filename, "w", "utf-8") as file: file.write("```mermaid\n") for line in self: - file.write("%s\n" % line) + file.write(f"{line}\n") file.write("```") @staticmethod def esc(value): """Escape Strings.""" - return _RE_ESC.sub(lambda m: r"\%s" % m.group(0), six.text_type(value)) + return _RE_ESC.sub(lambda m: rf"\{m.group(0)}", six.text_type(value)) diff --git a/src/anytree/importer/__init__.py b/src/anytree/importer/__init__.py index 15a3f70..c42741f 100644 --- a/src/anytree/importer/__init__.py +++ b/src/anytree/importer/__init__.py @@ -1,4 +1,9 @@ """Importer.""" -from .dictimporter import DictImporter # noqa -from .jsonimporter import JsonImporter # noqa +from .dictimporter import DictImporter +from .jsonimporter import JsonImporter + +__all__ = [ + "DictImporter", + "JsonImporter", +] diff --git a/src/anytree/importer/dictimporter.py b/src/anytree/importer/dictimporter.py index 3c334c7..feb66ac 100644 --- a/src/anytree/importer/dictimporter.py +++ b/src/anytree/importer/dictimporter.py @@ -1,6 +1,5 @@ from anytree import AnyNode - -from ..config import ASSERTIONS +from anytree.config import ASSERTIONS class DictImporter: diff --git a/src/anytree/iterators/__init__.py b/src/anytree/iterators/__init__.py index a00f74f..4af768d 100644 --- a/src/anytree/iterators/__init__.py +++ b/src/anytree/iterators/__init__.py @@ -8,9 +8,18 @@ * :any:`ZigZagGroupIter`: iterate over tree using level-order strategy returning group for every level """ -from .abstractiter import AbstractIter # noqa -from .levelordergroupiter import LevelOrderGroupIter # noqa -from .levelorderiter import LevelOrderIter # noqa -from .postorderiter import PostOrderIter # noqa -from .preorderiter import PreOrderIter # noqa -from .zigzaggroupiter import ZigZagGroupIter # noqa +from .abstractiter import AbstractIter +from .levelordergroupiter import LevelOrderGroupIter +from .levelorderiter import LevelOrderIter +from .postorderiter import PostOrderIter +from .preorderiter import PreOrderIter +from .zigzaggroupiter import ZigZagGroupIter + +__all__ = [ + "AbstractIter", + "LevelOrderGroupIter", + "LevelOrderIter", + "PostOrderIter", + "PreOrderIter", + "ZigZagGroupIter", +] diff --git a/src/anytree/iterators/postorderiter.py b/src/anytree/iterators/postorderiter.py index c64da65..98f53ea 100644 --- a/src/anytree/iterators/postorderiter.py +++ b/src/anytree/iterators/postorderiter.py @@ -44,7 +44,6 @@ def __next(children, level, filter_, stop, maxlevel): if not AbstractIter._abort_at_level(level, maxlevel): for child in children: grandchildren = AbstractIter._get_children(child.children, stop) - for grandchild in PostOrderIter.__next(grandchildren, level + 1, filter_, stop, maxlevel): - yield grandchild + yield from PostOrderIter.__next(grandchildren, level + 1, filter_, stop, maxlevel) if filter_(child): yield child diff --git a/src/anytree/iterators/preorderiter.py b/src/anytree/iterators/preorderiter.py index 4af9e06..b07cf38 100644 --- a/src/anytree/iterators/preorderiter.py +++ b/src/anytree/iterators/preorderiter.py @@ -47,5 +47,4 @@ def _iter(children, filter_, stop, maxlevel): yield child_ if not AbstractIter._abort_at_level(2, maxlevel): descendantmaxlevel = maxlevel - 1 if maxlevel else None - for descendant_ in PreOrderIter._iter(child_.children, filter_, stop, descendantmaxlevel): - yield descendant_ + yield from PreOrderIter._iter(child_.children, filter_, stop, descendantmaxlevel) diff --git a/src/anytree/iterators/zigzaggroupiter.py b/src/anytree/iterators/zigzaggroupiter.py index 7a81d8c..0699422 100644 --- a/src/anytree/iterators/zigzaggroupiter.py +++ b/src/anytree/iterators/zigzaggroupiter.py @@ -1,4 +1,5 @@ -from ..config import ASSERTIONS +from anytree.config import ASSERTIONS + from .abstractiter import AbstractIter from .levelordergroupiter import LevelOrderGroupIter diff --git a/src/anytree/node/__init__.py b/src/anytree/node/__init__.py index 71221d7..3336d03 100644 --- a/src/anytree/node/__init__.py +++ b/src/anytree/node/__init__.py @@ -9,11 +9,21 @@ * :any:`LightNodeMixin`: A :any:`NodeMixin` using slots. """ -from .anynode import AnyNode # noqa -from .exceptions import LoopError # noqa -from .exceptions import TreeError # noqa -from .lightnodemixin import LightNodeMixin # noqa -from .node import Node # noqa -from .nodemixin import NodeMixin # noqa -from .symlinknode import SymlinkNode # noqa -from .symlinknodemixin import SymlinkNodeMixin # noqa +from .anynode import AnyNode +from .exceptions import LoopError, TreeError +from .lightnodemixin import LightNodeMixin +from .node import Node +from .nodemixin import NodeMixin +from .symlinknode import SymlinkNode +from .symlinknodemixin import SymlinkNodeMixin + +__all__ = [ + "AnyNode", + "LightNodeMixin", + "LoopError", + "Node", + "NodeMixin", + "SymlinkNode", + "SymlinkNodeMixin", + "TreeError", +] diff --git a/src/anytree/node/lightnodemixin.py b/src/anytree/node/lightnodemixin.py index 80bbb62..08d3447 100644 --- a/src/anytree/node/lightnodemixin.py +++ b/src/anytree/node/lightnodemixin.py @@ -1,6 +1,6 @@ +from anytree.config import ASSERTIONS from anytree.iterators import PreOrderIter -from ..config import ASSERTIONS from .exceptions import LoopError, TreeError @@ -233,7 +233,7 @@ def __check_children(children): if childid not in seen: seen.add(childid) else: - msg = "Cannot add node %r multiple times as child." % (child,) + msg = f"Cannot add node {child!r} multiple times as child." raise TreeError(msg) @children.setter # type: ignore[no-redef] @@ -343,7 +343,7 @@ def ancestors(self): (Node('/Udo'), Node('/Udo/Marc')) """ if self.parent is None: - return tuple() + return () return self.parent.path @property @@ -409,7 +409,7 @@ def siblings(self): """ parent = self.parent if parent is None: - return tuple() + return () return tuple(node for node in parent.children if node is not self) @property diff --git a/src/anytree/node/node.py b/src/anytree/node/node.py index 18be90c..05ae187 100644 --- a/src/anytree/node/node.py +++ b/src/anytree/node/node.py @@ -77,5 +77,5 @@ def __init__(self, name, parent=None, children=None, **kwargs): self.children = children def __repr__(self): - args = ["%r" % self.separator.join([""] + [str(node.name) for node in self.path])] + args = ["{!r}".format(self.separator.join([""] + [str(node.name) for node in self.path]))] return _repr(self, args=args, nameblacklist=["name"]) diff --git a/src/anytree/node/nodemixin.py b/src/anytree/node/nodemixin.py index cd3036e..542884a 100644 --- a/src/anytree/node/nodemixin.py +++ b/src/anytree/node/nodemixin.py @@ -1,8 +1,8 @@ import warnings +from anytree.config import ASSERTIONS from anytree.iterators import PreOrderIter -from ..config import ASSERTIONS from .exceptions import LoopError, TreeError from .lightnodemixin import LightNodeMixin @@ -120,7 +120,7 @@ def parent(self): @parent.setter def parent(self, value): if value is not None and not isinstance(value, (NodeMixin, LightNodeMixin)): - msg = "Parent node %r is not of type 'NodeMixin'." % (value,) + msg = f"Parent node {value!r} is not of type 'NodeMixin'." raise TreeError(msg) if hasattr(self, "_NodeMixin__parent"): parent = self.__parent @@ -228,13 +228,13 @@ def __check_children(children): seen = set() for child in children: if not isinstance(child, (NodeMixin, LightNodeMixin)): - msg = "Cannot add non-node object %r. It is not a subclass of 'NodeMixin'." % (child,) + msg = f"Cannot add non-node object {child!r}. It is not a subclass of 'NodeMixin'." raise TreeError(msg) childid = id(child) if childid not in seen: seen.add(childid) else: - msg = "Cannot add node %r multiple times as child." % (child,) + msg = f"Cannot add node {child!r} multiple times as child." raise TreeError(msg) @children.setter # type: ignore[no-redef] @@ -344,7 +344,7 @@ def ancestors(self): (Node('/Udo'), Node('/Udo/Marc')) """ if self.parent is None: - return tuple() + return () return self.parent.path @property @@ -355,7 +355,7 @@ def anchestors(self): The attribute `anchestors` is just a typo of `ancestors`. Please use `ancestors`. This attribute will be removed in the 3.0.0 release. """ - warnings.warn(".anchestors was a typo and will be removed in version 3.0.0", DeprecationWarning) + warnings.warn(".anchestors was a typo and will be removed in version 3.0.0", DeprecationWarning, stacklevel=2) return self.ancestors @property @@ -421,7 +421,7 @@ def siblings(self): """ parent = self.parent if parent is None: - return tuple() + return () return tuple(node for node in parent.children if node is not self) @property diff --git a/src/anytree/node/symlinknodemixin.py b/src/anytree/node/symlinknodemixin.py index 6335690..3500a59 100644 --- a/src/anytree/node/symlinknodemixin.py +++ b/src/anytree/node/symlinknodemixin.py @@ -46,13 +46,13 @@ class SymlinkNodeMixin(NodeMixin): def __getattr__(self, name): if name in ("_NodeMixin__parent", "_NodeMixin__children"): - return super(SymlinkNodeMixin, self).__getattr__(name) + return super().__getattr__(name) if name == "__setstate__": raise AttributeError(name) return getattr(self.target, name) def __setattr__(self, name, value): if name in ("_NodeMixin__parent", "_NodeMixin__children", "parent", "children", "target"): - super(SymlinkNodeMixin, self).__setattr__(name, value) + super().__setattr__(name, value) else: setattr(self.target, name, value) diff --git a/src/anytree/node/util.py b/src/anytree/node/util.py index 6fb71ec..860e27a 100644 --- a/src/anytree/node/util.py +++ b/src/anytree/node/util.py @@ -6,5 +6,5 @@ def _repr(node, args=None, nameblacklist=None): lambda item: not item[0].startswith("_") and item[0] not in nameblacklist, sorted(node.__dict__.items(), key=lambda item: item[0]), ): - args.append("%s=%r" % (key, value)) - return "%s(%s)" % (classname, ", ".join(args)) + args.append(f"{key}={value!r}") + return "{}({})".format(classname, ", ".join(args)) diff --git a/src/anytree/render.py b/src/anytree/render.py index 20c5217..25f97ba 100644 --- a/src/anytree/render.py +++ b/src/anytree/render.py @@ -31,15 +31,13 @@ class AbstractStyle: """ def __init__(self, vertical, cont, end): - super(AbstractStyle, self).__init__() + super().__init__() self.vertical = vertical self.cont = cont self.end = end if ASSERTIONS: # pragma: no branch - assert len(cont) == len(vertical) == len(end), "'%s', '%s' and '%s' need to have equal length" % ( - vertical, - cont, - end, + assert len(cont) == len(vertical) == len(end), ( + f"'{vertical}', '{cont}' and '{end}' need to have equal length" ) @property @@ -49,7 +47,7 @@ def empty(self): def __repr__(self): classname = self.__class__.__name__ - return "%s()" % classname + return f"{classname}()" class AsciiStyle(AbstractStyle): @@ -72,7 +70,7 @@ class AsciiStyle(AbstractStyle): """ def __init__(self): - super(AsciiStyle, self).__init__("| ", "|-- ", "+-- ") + super().__init__("| ", "|-- ", "+-- ") class ContStyle(AbstractStyle): @@ -95,7 +93,10 @@ class ContStyle(AbstractStyle): """ def __init__(self): - super(ContStyle, self).__init__("\u2502 ", "\u251c\u2500\u2500 ", "\u2514\u2500\u2500 ") + super().__init__("\u2502 ", "\u251c\u2500\u2500 ", "\u2514\u2500\u2500 ") + + +CONT_STYLE = ContStyle() class ContRoundStyle(AbstractStyle): @@ -118,7 +119,7 @@ class ContRoundStyle(AbstractStyle): """ def __init__(self): - super(ContRoundStyle, self).__init__("\u2502 ", "\u251c\u2500\u2500 ", "\u2570\u2500\u2500 ") + super().__init__("\u2502 ", "\u251c\u2500\u2500 ", "\u2570\u2500\u2500 ") class DoubleStyle(AbstractStyle): @@ -142,7 +143,7 @@ class DoubleStyle(AbstractStyle): """ def __init__(self): - super(DoubleStyle, self).__init__("\u2551 ", "\u2560\u2550\u2550 ", "\u255a\u2550\u2550 ") + super().__init__("\u2551 ", "\u2560\u2550\u2550 ", "\u255a\u2550\u2550 ") @six.python_2_unicode_compatible @@ -262,7 +263,7 @@ class RenderTree: └── Z """ - def __init__(self, node, style=ContStyle(), childiter=list, maxlevel=None): + def __init__(self, node, style=CONT_STYLE, childiter=list, maxlevel=None): if not isinstance(style, AbstractStyle): style = style() self.node = node @@ -271,7 +272,7 @@ def __init__(self, node, style=ContStyle(), childiter=list, maxlevel=None): self.maxlevel = maxlevel def __iter__(self): - return self.__next(self.node, tuple()) + return self.__next(self.node, ()) def __next(self, node, continues, level=0): yield RenderTree.__item(node, continues, self.style) @@ -281,8 +282,7 @@ def __next(self, node, continues, level=0): if children: children = self.childiter(children) for child, is_last in _is_last(children): - for grandchild in self.__next(child, continues + (not is_last,), level=level): - yield grandchild + yield from self.__next(child, (*continues, not is_last), level=level) @staticmethod def __item(node, continues, style): @@ -299,16 +299,16 @@ def __str__(self): def get(): for row in self: lines = repr(row.node).splitlines() or [""] - yield "%s%s" % (row.pre, lines[0]) + yield f"{row.pre}{lines[0]}" for line in lines[1:]: - yield "%s%s" % (row.fill, line) + yield f"{row.fill}{line}" return "\n".join(get()) def __repr__(self): classname = self.__class__.__name__ - args = [repr(self.node), "style=%s" % repr(self.style), "childiter=%s" % repr(self.childiter)] - return "%s(%s)" % (classname, ", ".join(args)) + args = [repr(self.node), f"style={self.style!r}", f"childiter={self.childiter!r}"] + return "{}({})".format(classname, ", ".join(args)) def by_attr(self, attrname="name"): """ @@ -355,9 +355,9 @@ def _format_row_any(row, attr): lines = attr or [""] else: lines = str(attr).splitlines() or [""] - yield "%s%s" % (row.pre, lines[0]) + yield f"{row.pre}{lines[0]}" for line in lines[1:]: - yield "%s%s" % (row.fill, line) + yield f"{row.fill}{line}" def _is_last(iterable): diff --git a/src/anytree/resolver.py b/src/anytree/resolver.py index f29a51c..31854c9 100644 --- a/src/anytree/resolver.py +++ b/src/anytree/resolver.py @@ -17,10 +17,10 @@ class Resolver: relax (bool): Do not raise an exception. """ - _match_cache = {} # type: ignore[var-annotated] + _match_cache = {} # type: ignore[var-annotated] # noqa: RUF012 def __init__(self, pathattr="name", ignorecase=False, relax=False): - super(Resolver, self).__init__() + super().__init__() self.pathattr = pathattr self.ignorecase = ignorecase self.relax = relax @@ -325,7 +325,7 @@ def __translate(pat): class ResolverError(RuntimeError): def __init__(self, node, child, msg): """Resolve Error at `node` handling `child`.""" - super(ResolverError, self).__init__(msg) + super().__init__(msg) self.node = node self.child = child @@ -333,16 +333,16 @@ def __init__(self, node, child, msg): class RootResolverError(ResolverError): def __init__(self, root): """Root Resolve Error, cannot go above root node.""" - msg = "Cannot go above root node %r" % (root,) - super(RootResolverError, self).__init__(root, None, msg) + msg = f"Cannot go above root node {root!r}" + super().__init__(root, None, msg) class ChildResolverError(ResolverError): def __init__(self, node, child, pathattr): """Child Resolve Error at `node` handling `child`.""" names = [repr(_getattr(c, pathattr)) for c in node.children] - msg = "%r has no child %s. Children are: %s." % (node, child, ", ".join(names)) - super(ChildResolverError, self).__init__(node, child, msg) + msg = "{!r} has no child {}. Children are: {}.".format(node, child, ", ".join(names)) + super().__init__(node, child, msg) def _getattr(node, name): diff --git a/src/anytree/search.py b/src/anytree/search.py index f6c7718..fcbe9c6 100644 --- a/src/anytree/search.py +++ b/src/anytree/search.py @@ -241,4 +241,4 @@ def __init__(self, msg, result): """Error raised on `mincount` or `maxcount` mismatch.""" if result: msg += " " + repr(result) - super(CountError, self).__init__(msg) + super().__init__(msg) diff --git a/src/anytree/walker.py b/src/anytree/walker.py index 7dde80f..cbc144a 100644 --- a/src/anytree/walker.py +++ b/src/anytree/walker.py @@ -66,7 +66,7 @@ def walk(start, end): startpath = start.path endpath = end.path if start.root is not end.root: - msg = "%r and %r are not part of the same tree." % (start, end) + msg = f"{start!r} and {end!r} are not part of the same tree." raise WalkError(msg) # common common = Walker.__calc_common(startpath, endpath) @@ -75,12 +75,12 @@ def walk(start, end): len_common = len(common) # upwards if start is common[-1]: - upwards = tuple() + upwards = () else: upwards = tuple(reversed(startpath[len_common:])) # down if end is common[-1]: - down = tuple() + down = () else: down = endpath[len_common:] return upwards, common[-1], down diff --git a/tests/helper.py b/tests/helper.py index 4d7a553..6994875 100644 --- a/tests/helper.py +++ b/tests/helper.py @@ -14,9 +14,9 @@ def assert_raises(exccls, msg): """Check exception of class `exccls` to be raised with message `msg`.""" try: yield - assert False, "%r not raised" % exccls + raise AssertionError(f"{exccls!r} not raised") except Exception as exc: - assert isinstance(exc, exccls), "%r is not a %r" % (exc, exccls) + assert isinstance(exc, exccls), f"{exc!r} is not a {exccls!r}" eq_(str(exc), msg) diff --git a/tests/test_dictexporter.py b/tests/test_dictexporter.py index 03ed634..13d03f3 100644 --- a/tests/test_dictexporter.py +++ b/tests/test_dictexporter.py @@ -103,7 +103,7 @@ def test_dict_exporter_mixin(): class MyClass(NodeMixin): def __init__(self, foo, parent=None): - super(MyClass, self).__init__() + super().__init__() self.foo = foo self.parent = parent diff --git a/tests/test_dotexport.py b/tests/test_dotexport.py index 4d37f97..4679209 100644 --- a/tests/test_dotexport.py +++ b/tests/test_dotexport.py @@ -36,10 +36,10 @@ def test_tree2(tmp_path): Node("sub1Ca", parent=s1c, edge=42) def nodenamefunc(node): - return "%s:%s" % (node.name, node.depth) + return f"{node.name}:{node.depth}" def edgeattrfunc(node, child): - return 'label="%s:%s"' % (node.name, child.name) + return f'label="{node.name}:{child.name}"' r = RenderTreeGraph( root, diff --git a/tests/test_dotexporter.py b/tests/test_dotexporter.py index 8baa542..8b633f4 100644 --- a/tests/test_dotexporter.py +++ b/tests/test_dotexporter.py @@ -29,13 +29,13 @@ def test_tree_custom(tmp_path, root): """Tree Custom.""" def nodenamefunc(node): - return "%s:%s" % (node.name, node.depth) + return f"{node.name}:{node.depth}" def edgeattrfunc(node, child): - return 'label="%s:%s"' % (node.name, child.name) + return f'label="{node.name}:{child.name}"' def nodefunc(node): - return '("%s")' % (node.name) + return f'("{node.name}")' def edgefunc(node, child): return f"--{child.edge}-->" diff --git a/tests/test_examples.py b/tests/test_examples.py index b457802..ae2cd67 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -17,7 +17,7 @@ def test_stackoverflow(): eq_(str(joe), "Node('/Udo/Dan/Joe')") eq_( - ["%s%s" % (pre, node.name) for pre, fill, node in RenderTree(udo)], + [f"{pre}{node.name}" for pre, fill, node in RenderTree(udo)], [ "Udo", "├── Marc", diff --git a/tests/test_lightnode.py b/tests/test_lightnode.py index 07e480c..e1aa008 100644 --- a/tests/test_lightnode.py +++ b/tests/test_lightnode.py @@ -14,7 +14,7 @@ def __init__(self, name, parent=None, children=None): def __repr__(self): path = self.separator.join([""] + [str(node.name) for node in self.path]) - return "%s(%r)" % (self.__class__.__name__, path) + return f"{self.__class__.__name__}({path!r})" def test_parent_child(): @@ -30,89 +30,89 @@ def test_parent_child(): s1ca = LightNode("sub1Ca", parent=s1c) assert root.parent is None - assert root.children == tuple([s0, s1]) + assert root.children == (s0, s1) assert s0.parent == root - assert s0.children == tuple([s0b, s0a]) + assert s0.children == (s0b, s0a) assert s0b.parent == s0 - assert s0b.children == tuple() + assert s0b.children == () assert s0a.parent == s0 - assert s0a.children == tuple() + assert s0a.children == () assert s1.parent == root - assert s1.children == tuple([s1a, s1b, s1c]) + assert s1.children == (s1a, s1b, s1c) assert s1a.parent == s1 - assert s1a.children == tuple() + assert s1a.children == () assert s1b.parent == s1 - assert s1b.children == tuple() + assert s1b.children == () assert s1c.parent == s1 - assert s1c.children == tuple([s1ca]) + assert s1c.children == (s1ca,) assert s1ca.parent == s1c - assert s1ca.children == tuple() + assert s1ca.children == () # change parent s1ca.parent = s0 assert root.parent is None - assert root.children == tuple([s0, s1]) + assert root.children == (s0, s1) assert s0.parent == root - assert s0.children == tuple([s0b, s0a, s1ca]) + assert s0.children == (s0b, s0a, s1ca) assert s0b.parent == s0 - assert s0b.children == tuple() + assert s0b.children == () assert s0a.parent == s0 - assert s0a.children == tuple() + assert s0a.children == () assert s1.parent == root - assert s1.children == tuple([s1a, s1b, s1c]) + assert s1.children == (s1a, s1b, s1c) assert s1a.parent == s1 - assert s1a.children == tuple() + assert s1a.children == () assert s1b.parent == s1 - assert s1b.children == tuple() + assert s1b.children == () assert s1c.parent == s1 - assert s1c.children == tuple() + assert s1c.children == () assert s1ca.parent == s0 - assert s1ca.children == tuple() + assert s1ca.children == () # break tree into two s1.parent = None assert root.parent is None - assert root.children == tuple([s0]) + assert root.children == (s0,) assert s0.parent == root - assert s0.children == tuple([s0b, s0a, s1ca]) + assert s0.children == (s0b, s0a, s1ca) assert s0b.parent == s0 - assert s0b.children == tuple() + assert s0b.children == () assert s0a.parent == s0 - assert s0a.children == tuple() + assert s0a.children == () assert s1.parent is None - assert s1.children == tuple([s1a, s1b, s1c]) + assert s1.children == (s1a, s1b, s1c) assert s1a.parent == s1 - assert s1a.children == tuple() + assert s1a.children == () assert s1b.parent == s1 - assert s1b.children == tuple() + assert s1b.children == () assert s1c.parent == s1 - assert s1c.children == tuple() + assert s1c.children == () assert s1ca.parent == s0 - assert s1ca.children == tuple() + assert s1ca.children == () # set to the same s1b.parent = s1 assert root.parent is None - assert root.children == tuple([s0]) + assert root.children == (s0,) assert s0.parent == root - assert s0.children == tuple([s0b, s0a, s1ca]) + assert s0.children == (s0b, s0a, s1ca) assert s0b.parent == s0 - assert s0b.children == tuple() + assert s0b.children == () assert s0a.parent == s0 - assert s0a.children == tuple() + assert s0a.children == () assert s1.parent is None - assert s1.children == tuple([s1a, s1b, s1c]) + assert s1.children == (s1a, s1b, s1c) assert s1a.parent == s1 - assert s1a.children == tuple() + assert s1a.children == () assert s1b.parent == s1 - assert s1b.children == tuple() + assert s1b.children == () assert s1c.parent == s1 - assert s1c.children == tuple() + assert s1c.children == () assert s1ca.parent == s0 - assert s1ca.children == tuple() + assert s1ca.children == () def test_detach_children(): @@ -207,7 +207,7 @@ def test_recursion_detection(): assert str(exc) == "Cannot set parent. LightNode('/root') cannot be parent of itself." assert root.parent is None else: - assert False + raise AssertionError assert root.parent is None try: @@ -216,7 +216,7 @@ def test_recursion_detection(): assert str(exc) == ("Cannot set parent. LightNode('/root') is parent of LightNode('/root/sub0/sub0A').") assert root.parent is None else: - assert False + raise AssertionError assert s0.parent is root try: @@ -225,7 +225,7 @@ def test_recursion_detection(): assert str(exc) == ("Cannot set parent. LightNode('/root/sub0') is parent of LightNode('/root/sub0/sub0A').") assert s0.parent is root else: - assert False + raise AssertionError def test_ancestors(): @@ -238,11 +238,11 @@ def test_ancestors(): s1c = LightNode("sub1C", parent=s1) s1ca = LightNode("sub1Ca", parent=s1c) - assert root.ancestors == tuple() - assert s0.ancestors == tuple([root]) - assert s0b.ancestors == tuple([root, s0]) - assert s0a.ancestors == tuple([root, s0]) - assert s1ca.ancestors == tuple([root, s1, s1c]) + assert root.ancestors == () + assert s0.ancestors == (root,) + assert s0b.ancestors == (root, s0) + assert s0a.ancestors == (root, s0) + assert s1ca.ancestors == (root, s1, s1c) def test_node_children_init(): @@ -261,10 +261,10 @@ def test_descendants(): s1c = LightNode("sub1C", parent=s1) s1ca = LightNode("sub1Ca", parent=s1c) - assert root.descendants == tuple([s0, s0b, s0a, s1, s1c, s1ca]) - assert s1.descendants == tuple([s1c, s1ca]) - assert s1c.descendants == tuple([s1ca]) - assert s1ca.descendants == tuple() + assert root.descendants == (s0, s0b, s0a, s1, s1c, s1ca) + assert s1.descendants == (s1c, s1ca) + assert s1c.descendants == (s1ca,) + assert s1ca.descendants == () def test_root(): @@ -296,13 +296,13 @@ def test_siblings(): s1c = LightNode("sub1C", parent=s1) s1ca = LightNode("sub1Ca", parent=s1c) - assert root.siblings == tuple() - assert s0.siblings == tuple([s1]) - assert s0b.siblings == tuple([s0a]) - assert s0a.siblings == tuple([s0b]) - assert s1.siblings == tuple([s0]) - assert s1c.siblings == tuple() - assert s1ca.siblings == tuple() + assert root.siblings == () + assert s0.siblings == (s1,) + assert s0b.siblings == (s0a,) + assert s0a.siblings == (s0b,) + assert s1.siblings == (s0,) + assert s1c.siblings == () + assert s1ca.siblings == () def test_is_leaf(): @@ -334,13 +334,13 @@ def test_leaves(): s1c = LightNode("sub1C", parent=s1) s1ca = LightNode("sub1Ca", parent=s1c) - assert root.leaves == tuple([s0b, s0a, s1ca]) - assert s0.leaves == tuple([s0b, s0a]) - assert s0b.leaves == tuple([s0b]) - assert s0a.leaves == tuple([s0a]) - assert s1.leaves == tuple([s1ca]) - assert s1c.leaves == tuple([s1ca]) - assert s1ca.leaves == tuple([s1ca]) + assert root.leaves == (s0b, s0a, s1ca) + assert s0.leaves == (s0b, s0a) + assert s0b.leaves == (s0b,) + assert s0a.leaves == (s0a,) + assert s1.leaves == (s1ca,) + assert s1c.leaves == (s1ca,) + assert s1ca.leaves == (s1ca,) def test_is_root(): @@ -461,22 +461,22 @@ def test_hookups(): class MyLightNode(LightNode): def _pre_attach(self, parent): assert str(self.parent) == "None" - assert self.children == tuple() + assert self.children == () assert str(self.path) == "(MyLightNode('/B'),)" def _post_attach(self, parent): assert str(self.parent) == "MyLightNode('/A')" - assert self.children == tuple() + assert self.children == () assert str(self.path) == "(MyLightNode('/A'), MyLightNode('/A/B'))" def _pre_detach(self, parent): assert str(self.parent) == "MyLightNode('/A')" - assert self.children == tuple() + assert self.children == () assert str(self.path) == "(MyLightNode('/A'), MyLightNode('/A/B'))" def _post_detach(self, parent): assert str(self.parent) == "None" - assert self.children == tuple() + assert self.children == () assert str(self.path) == "(MyLightNode('/B'),)" node_a = MyLightNode("A") diff --git a/tests/test_mermaidexporter.py b/tests/test_mermaidexporter.py index e4cabf1..80a02f2 100644 --- a/tests/test_mermaidexporter.py +++ b/tests/test_mermaidexporter.py @@ -29,7 +29,7 @@ def test_tree_custom(tmp_path, root): """Tree Custom.""" def nodefunc(node): - return '("%s")' % (node.name) + return f'("{node.name}")' def edgefunc(node, child): return f"--{child.edge}-->" diff --git a/tests/test_node.py b/tests/test_node.py index 44d0a4a..ffb61d9 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -22,89 +22,89 @@ def test_parent_child(): s1ca = Node("sub1Ca", parent=s1c) assert root.parent is None - assert root.children == tuple([s0, s1]) + assert root.children == (s0, s1) assert s0.parent == root - assert s0.children == tuple([s0b, s0a]) + assert s0.children == (s0b, s0a) assert s0b.parent == s0 - assert s0b.children == tuple() + assert s0b.children == () assert s0a.parent == s0 - assert s0a.children == tuple() + assert s0a.children == () assert s1.parent == root - assert s1.children == tuple([s1a, s1b, s1c]) + assert s1.children == (s1a, s1b, s1c) assert s1a.parent == s1 - assert s1a.children == tuple() + assert s1a.children == () assert s1b.parent == s1 - assert s1b.children == tuple() + assert s1b.children == () assert s1c.parent == s1 - assert s1c.children == tuple([s1ca]) + assert s1c.children == (s1ca,) assert s1ca.parent == s1c - assert s1ca.children == tuple() + assert s1ca.children == () # change parent s1ca.parent = s0 assert root.parent is None - assert root.children == tuple([s0, s1]) + assert root.children == (s0, s1) assert s0.parent == root - assert s0.children == tuple([s0b, s0a, s1ca]) + assert s0.children == (s0b, s0a, s1ca) assert s0b.parent == s0 - assert s0b.children == tuple() + assert s0b.children == () assert s0a.parent == s0 - assert s0a.children == tuple() + assert s0a.children == () assert s1.parent == root - assert s1.children == tuple([s1a, s1b, s1c]) + assert s1.children == (s1a, s1b, s1c) assert s1a.parent == s1 - assert s1a.children == tuple() + assert s1a.children == () assert s1b.parent == s1 - assert s1b.children == tuple() + assert s1b.children == () assert s1c.parent == s1 - assert s1c.children == tuple() + assert s1c.children == () assert s1ca.parent == s0 - assert s1ca.children == tuple() + assert s1ca.children == () # break tree into two s1.parent = None assert root.parent is None - assert root.children == tuple([s0]) + assert root.children == (s0,) assert s0.parent == root - assert s0.children == tuple([s0b, s0a, s1ca]) + assert s0.children == (s0b, s0a, s1ca) assert s0b.parent == s0 - assert s0b.children == tuple() + assert s0b.children == () assert s0a.parent == s0 - assert s0a.children == tuple() + assert s0a.children == () assert s1.parent is None - assert s1.children == tuple([s1a, s1b, s1c]) + assert s1.children == (s1a, s1b, s1c) assert s1a.parent == s1 - assert s1a.children == tuple() + assert s1a.children == () assert s1b.parent == s1 - assert s1b.children == tuple() + assert s1b.children == () assert s1c.parent == s1 - assert s1c.children == tuple() + assert s1c.children == () assert s1ca.parent == s0 - assert s1ca.children == tuple() + assert s1ca.children == () # set to the same s1b.parent = s1 assert root.parent is None - assert root.children == tuple([s0]) + assert root.children == (s0,) assert s0.parent == root - assert s0.children == tuple([s0b, s0a, s1ca]) + assert s0.children == (s0b, s0a, s1ca) assert s0b.parent == s0 - assert s0b.children == tuple() + assert s0b.children == () assert s0a.parent == s0 - assert s0a.children == tuple() + assert s0a.children == () assert s1.parent is None - assert s1.children == tuple([s1a, s1b, s1c]) + assert s1.children == (s1a, s1b, s1c) assert s1a.parent == s1 - assert s1a.children == tuple() + assert s1a.children == () assert s1b.parent == s1 - assert s1b.children == tuple() + assert s1b.children == () assert s1c.parent == s1 - assert s1c.children == tuple() + assert s1c.children == () assert s1ca.parent == s0 - assert s1ca.children == tuple() + assert s1ca.children == () def test_detach_children(): @@ -203,7 +203,7 @@ def test_recursion_detection(): assert str(exc) == "Cannot set parent. Node('/root') cannot be parent of itself." assert root.parent is None else: - assert False + raise AssertionError assert root.parent is None try: @@ -212,7 +212,7 @@ def test_recursion_detection(): assert str(exc) == ("Cannot set parent. Node('/root') is parent of Node('/root/sub0/sub0A').") assert root.parent is None else: - assert False + raise AssertionError assert s0.parent is root try: @@ -221,7 +221,7 @@ def test_recursion_detection(): assert str(exc) == ("Cannot set parent. Node('/root/sub0') is parent of Node('/root/sub0/sub0A').") assert s0.parent is root else: - assert False + raise AssertionError def test_repr(): @@ -245,13 +245,13 @@ def test_ancestors(): s1c = Node("sub1C", parent=s1) s1ca = Node("sub1Ca", parent=s1c) - assert root.ancestors == tuple() - assert s0.ancestors == tuple([root]) - assert s0b.ancestors == tuple([root, s0]) - assert s0a.ancestors == tuple([root, s0]) - assert s1ca.ancestors == tuple([root, s1, s1c]) + assert root.ancestors == () + assert s0.ancestors == (root,) + assert s0b.ancestors == (root, s0) + assert s0a.ancestors == (root, s0) + assert s1ca.ancestors == (root, s1, s1c) # deprecated typo - assert s1ca.ancestors == tuple([root, s1, s1c]) + assert s1ca.ancestors == (root, s1, s1c) def test_node_children_init(): @@ -276,10 +276,10 @@ def test_descendants(): s1c = Node("sub1C", parent=s1) s1ca = Node("sub1Ca", parent=s1c) - assert root.descendants == tuple([s0, s0b, s0a, s1, s1c, s1ca]) - assert s1.descendants == tuple([s1c, s1ca]) - assert s1c.descendants == tuple([s1ca]) - assert s1ca.descendants == tuple() + assert root.descendants == (s0, s0b, s0a, s1, s1c, s1ca) + assert s1.descendants == (s1c, s1ca) + assert s1c.descendants == (s1ca,) + assert s1ca.descendants == () def test_root(): @@ -311,13 +311,13 @@ def test_siblings(): s1c = Node("sub1C", parent=s1) s1ca = Node("sub1Ca", parent=s1c) - assert root.siblings == tuple() - assert s0.siblings == tuple([s1]) - assert s0b.siblings == tuple([s0a]) - assert s0a.siblings == tuple([s0b]) - assert s1.siblings == tuple([s0]) - assert s1c.siblings == tuple() - assert s1ca.siblings == tuple() + assert root.siblings == () + assert s0.siblings == (s1,) + assert s0b.siblings == (s0a,) + assert s0a.siblings == (s0b,) + assert s1.siblings == (s0,) + assert s1c.siblings == () + assert s1ca.siblings == () def test_is_leaf(): @@ -349,13 +349,13 @@ def test_leaves(): s1c = Node("sub1C", parent=s1) s1ca = Node("sub1Ca", parent=s1c) - assert root.leaves == tuple([s0b, s0a, s1ca]) - assert s0.leaves == tuple([s0b, s0a]) - assert s0b.leaves == tuple([s0b]) - assert s0a.leaves == tuple([s0a]) - assert s1.leaves == tuple([s1ca]) - assert s1c.leaves == tuple([s1ca]) - assert s1ca.leaves == tuple([s1ca]) + assert root.leaves == (s0b, s0a, s1ca) + assert s0.leaves == (s0b, s0a) + assert s0b.leaves == (s0b,) + assert s0a.leaves == (s0a,) + assert s1.leaves == (s1ca,) + assert s1c.leaves == (s1ca,) + assert s1ca.leaves == (s1ca,) def test_is_root(): @@ -482,7 +482,7 @@ def test_node_kwargs(): class MyNode(Node): def __init__(self, name, parent=None, **kwargs): - super(MyNode, self).__init__(name, parent, **kwargs) + super().__init__(name, parent, **kwargs) def _post_attach(self, parent): print(self.my_attribute) @@ -498,22 +498,22 @@ def test_hookups(): class MyNode(Node): def _pre_attach(self, parent): assert str(self.parent) == "None" - assert self.children == tuple() + assert self.children == () assert str(self.path) == "(MyNode('/B'),)" def _post_attach(self, parent): assert str(self.parent) == "MyNode('/A')" - assert self.children == tuple() + assert self.children == () assert str(self.path) == "(MyNode('/A'), MyNode('/A/B'))" def _pre_detach(self, parent): assert str(self.parent) == "MyNode('/A')" - assert self.children == tuple() + assert self.children == () assert str(self.path) == "(MyNode('/A'), MyNode('/A/B'))" def _post_detach(self, parent): assert str(self.parent) == "None" - assert self.children == tuple() + assert self.children == () assert str(self.path) == "(MyNode('/B'),)" node_a = MyNode("A") @@ -548,7 +548,7 @@ def test_eq_overwrite(): class EqOverwrittingNode(NodeMixin): def __init__(self, a, b, parent=None): - super(EqOverwrittingNode, self).__init__() + super().__init__() self.a = a self.b = b self.parent = parent diff --git a/tests/test_node_attach_detach.py b/tests/test_node_attach_detach.py index cd9fb4b..fd56a36 100644 --- a/tests/test_node_attach_detach.py +++ b/tests/test_node_attach_detach.py @@ -4,39 +4,39 @@ class TNode(Node): - TRACKING = [] + TRACKING = [] # noqa: RUF012 def _pre_detach(self, parent): """Method call before detaching from `parent`.""" - self.TRACKING.append("_pre_detach(%r, %r)" % (self.name, parent.name)) + self.TRACKING.append(f"_pre_detach({self.name!r}, {parent.name!r})") def _post_detach(self, parent): """Method call after detaching from `parent`.""" - self.TRACKING.append("_post_detach(%r, %r)" % (self.name, parent.name)) + self.TRACKING.append(f"_post_detach({self.name!r}, {parent.name!r})") def _pre_attach(self, parent): """Method call before attaching to `parent`.""" - self.TRACKING.append("_pre_attach(%r, %r)" % (self.name, parent.name)) + self.TRACKING.append(f"_pre_attach({self.name!r}, {parent.name!r})") def _post_attach(self, parent): """Method call after attaching to `parent`.""" - self.TRACKING.append("_post_attach(%r, %r)" % (self.name, parent.name)) + self.TRACKING.append(f"_post_attach({self.name!r}, {parent.name!r})") def _pre_detach_children(self, children): """Method call before detaching `children`.""" - self.TRACKING.append("_pre_detach_children(%r, %r)" % (self.name, tuple(child.name for child in children))) + self.TRACKING.append(f"_pre_detach_children({self.name!r}, {tuple(child.name for child in children)!r})") def _post_detach_children(self, children): """Method call after detaching `children`.""" - self.TRACKING.append("_post_detach_children(%r, %r)" % (self.name, tuple(child.name for child in children))) + self.TRACKING.append(f"_post_detach_children({self.name!r}, {tuple(child.name for child in children)!r})") def _pre_attach_children(self, children): """Method call before attaching `children`.""" - self.TRACKING.append("_pre_attach_children(%r, %r)" % (self.name, tuple(child.name for child in children))) + self.TRACKING.append(f"_pre_attach_children({self.name!r}, {tuple(child.name for child in children)!r})") def _post_attach_children(self, children): """Method call after attaching `children`.""" - self.TRACKING.append("_post_attach_children(%r, %r)" % (self.name, tuple(child.name for child in children))) + self.TRACKING.append(f"_post_attach_children({self.name!r}, {tuple(child.name for child in children)!r})") def test_parent_child(): diff --git a/tests/test_node_integrity.py b/tests/test_node_integrity.py index 51293d1..8c80be2 100644 --- a/tests/test_node_integrity.py +++ b/tests/test_node_integrity.py @@ -34,23 +34,23 @@ def _pre_detach(self, parent): def check(): eq_(root.parent, None) - eq_(root.children, tuple([s0, s1])) + eq_(root.children, (s0, s1)) eq_(s0.parent, root) - eq_(s0.children, tuple([s0b, s0a])) + eq_(s0.children, (s0b, s0a)) eq_(s0b.parent, s0) - eq_(s0b.children, tuple()) + eq_(s0b.children, ()) eq_(s0a.parent, s0) - eq_(s0a.children, tuple()) + eq_(s0a.children, ()) eq_(s1.parent, root) - eq_(s1.children, tuple([s1a, s1b, s1c])) + eq_(s1.children, (s1a, s1b, s1c)) eq_(s1a.parent, s1) - eq_(s1a.children, tuple()) + eq_(s1a.children, ()) eq_(s1b.parent, s1) - eq_(s1b.children, tuple()) + eq_(s1b.children, ()) eq_(s1c.parent, s1) - eq_(s1c.children, tuple([s1ca])) + eq_(s1c.children, (s1ca,)) eq_(s1ca.parent, s1c) - eq_(s1ca.children, tuple()) + eq_(s1ca.children, ()) check() with assert_raises(ReadonlyError, ""): diff --git a/tests/test_node_symlink.py b/tests/test_node_symlink.py index 44071a6..a4a1c44 100644 --- a/tests/test_node_symlink.py +++ b/tests/test_node_symlink.py @@ -17,26 +17,26 @@ def test_symlink(): l0 = Node("l0", parent=ln) eq_(root.parent, None) - eq_(root.children, tuple([s0, s1, ln])) + eq_(root.children, (s0, s1, ln)) eq_(s0.parent, root) - eq_(s0.children, tuple([s0b, s0a])) + eq_(s0.children, (s0b, s0a)) eq_(s0b.parent, s0) - eq_(s0b.children, tuple()) + eq_(s0b.children, ()) eq_(s0a.parent, s0) - eq_(s0a.children, tuple()) + eq_(s0a.children, ()) eq_(s1.parent, root) - eq_(s1.children, tuple([s1a, s1b, s1c])) + eq_(s1.children, (s1a, s1b, s1c)) eq_(s1.foo, 4) eq_(s1a.parent, s1) - eq_(s1a.children, tuple()) + eq_(s1a.children, ()) eq_(s1b.parent, s1) - eq_(s1b.children, tuple()) + eq_(s1b.children, ()) eq_(s1c.parent, s1) - eq_(s1c.children, tuple([s1ca])) + eq_(s1c.children, (s1ca,)) eq_(s1ca.parent, s1c) - eq_(s1ca.children, tuple()) + eq_(s1ca.children, ()) eq_(ln.parent, root) - eq_(ln.children, tuple([l0])) + eq_(ln.children, (l0,)) eq_(ln.foo, 4) eq_(s1.blub, 17) diff --git a/tests/test_render.py b/tests/test_render.py index 3158f7c..9d1990a 100644 --- a/tests/test_render.py +++ b/tests/test_render.py @@ -55,9 +55,9 @@ def test_render(): def multi(root): for pre, fill, node in anytree.RenderTree(root): - yield "%s%s" % (pre, node.lines[0]), node + yield f"{pre}{node.lines[0]}", node for line in node.lines[1:]: - yield "%s%s" % (fill, line), node + yield f"{fill}{line}", node assert list(multi(root)) == [ ("c0fe", root), diff --git a/tests/test_special_methods_access.py b/tests/test_special_methods_access.py index 14a9285..631e1aa 100644 --- a/tests/test_special_methods_access.py +++ b/tests/test_special_methods_access.py @@ -192,11 +192,10 @@ class MyNode(NodeMixin): def __new__(cls, *args, **kwargs): for attr in SPECIAL_METHODS: setattr(cls, attr, functools.partial(prevent_access, attr)) - instance = super(NodeMixin, cls).__new__(cls) - return instance + return super(NodeMixin, cls).__new__(cls) def __init__(self, name, parent=None, children=None): - super(MyNode, self).__init__() + super().__init__() self.name = name self.parent = parent if children: @@ -207,7 +206,7 @@ class TestConsistency(unittest.TestCase): """Control the access to special methods.""" def setUp(self): - super(TestConsistency, self).setUp() + super().setUp() self.root1 = MyNode("root1") self.child1 = MyNode("child1", parent=self.root1) self.child2a = MyNode("child2a", parent=self.child1) @@ -313,7 +312,7 @@ class MyMapping(NodeMixin, Mapping): """ def __init__(self, name, parent=None, children=None): - super(MyMapping, self).__init__() + super().__init__() self.name = name self.parent = parent if children: @@ -323,8 +322,7 @@ def __iter__(self): """Iterate over all children recursively.""" for child in self.children: yield child - for item in child: - yield item + yield from child def __len__(self): """Total number of children.""" @@ -339,7 +337,7 @@ def __getitem__(self, name): class TestMyMapping(unittest.TestCase): def setUp(self): - super(TestMyMapping, self).setUp() + super().setUp() self.root1 = MyMapping("root1") self.child1 = MyMapping("child1", parent=self.root1) self.child2a = MyMapping("child2a", parent=self.child1) diff --git a/tests/test_uniquedotexporter.py b/tests/test_uniquedotexporter.py index 89128f1..ff6090c 100644 --- a/tests/test_uniquedotexporter.py +++ b/tests/test_uniquedotexporter.py @@ -29,13 +29,13 @@ def test_tree_custom(tmp_path, root): """Tree Custom.""" def nodenamefunc(node): - return "%s:%s" % (node.name, node.depth) + return f"{node.name}:{node.depth}" def edgeattrfunc(node, child): - return 'label="%s:%s"' % (node.name, child.name) + return f'label="{node.name}:{child.name}"' def nodefunc(node): - return '("%s")' % (node.name) + return f'("{node.name}")' def edgefunc(node, child): return f"--{child.edge}-->"