diff --git a/src/pipdeptree/_models.py b/src/pipdeptree/_models.py index 359a982e..3e747cef 100644 --- a/src/pipdeptree/_models.py +++ b/src/pipdeptree/_models.py @@ -256,7 +256,7 @@ def get_children(self, node_key: str) -> list[ReqPackage]: node = self.get_node_as_parent(node_key) return self._obj[node] if node else [] - def filter_nodes(self, include: set[str] | None, exclude: set[str] | None) -> PackageDAG: # noqa: C901, PLR0912 + def filter_nodes(self, include: set[str] | None, exclude: set[str] | None) -> PackageDAG: # noqa: C901 """ Filters nodes in a graph by given parameters. @@ -294,23 +294,20 @@ def filter_nodes(self, include: set[str] | None, exclude: set[str] | None) -> Pa continue if include is None or any(fnmatch(node.key, i) for i in include): stack.append(node) - while True: - if len(stack) > 0: - n = stack.pop() - cldn = [c for c in self._obj[n] if not any(fnmatch(c.key, e) for e in exclude)] - m[n] = cldn - seen.add(n.key) - for c in cldn: - if c.key not in seen: - cld_node = self.get_node_as_parent(c.key) - if cld_node: - stack.append(cld_node) - else: - # It means there's no root node corresponding to the child node i.e. - # a dependency is missing - continue - else: - break + while stack: + n = stack.pop() + cldn = [c for c in self._obj[n] if not any(fnmatch(c.key, e) for e in exclude)] + m[n] = cldn + seen.add(n.key) + for c in cldn: + if c.key not in seen: + cld_node = self.get_node_as_parent(c.key) + if cld_node: + stack.append(cld_node) + else: + # It means there's no root node corresponding to the child node i.e. + # a dependency is missing + continue return self.__class__(m) @@ -335,10 +332,7 @@ def reverse(self) -> ReversedPackageDAG: # if v is already added to the dict, then ensure that # we are using the same object. This check is required # as we're using array mutation - try: - node: ReqPackage = [p for p in m if p.key == v.key][0] - except IndexError: # noqa: PERF203 - node = v + node: ReqPackage = next((p for p in m if p.key == v.key), v) m[node].append(k.as_parent_of(v)) if k.key not in child_keys: m[k.as_requirement()] = [] @@ -383,10 +377,7 @@ def reverse(self) -> PackageDAG: # type: ignore[override] child_keys = {r.key for r in chain.from_iterable(self._obj.values())} for k, vs in self._obj.items(): for v in vs: - try: - node = [p for p in m if p.key == v.key][0] - except IndexError: # noqa: PERF203 - node = v.as_parent_of(None) + node = next((p for p in m if p.key == v.key), v.as_parent_of(None)) m[node].append(k) # type: ignore[arg-type] if k.key not in child_keys: m[k.dist] = [] diff --git a/src/pipdeptree/_render/mermaid.py b/src/pipdeptree/_render/mermaid.py index f5b52c78..00ec6e33 100644 --- a/src/pipdeptree/_render/mermaid.py +++ b/src/pipdeptree/_render/mermaid.py @@ -1,6 +1,6 @@ from __future__ import annotations -from textwrap import dedent +import itertools as it from typing import TYPE_CHECKING, Final from pipdeptree._models import ReversedPackageDAG @@ -56,13 +56,12 @@ def mermaid_id(key: str) -> str: node_ids_map[key] = key return key # If the key is a reserved keyword, append a number to it. - number = 0 - while True: + for number in it.count(): new_id = f"{key}_{number}" if new_id not in node_ids_map: node_ids_map[key] = new_id return new_id - number += 1 + raise NotImplementedError # Use a sets to avoid duplicate entries. nodes: set[str] = set() @@ -95,20 +94,13 @@ def mermaid_id(key: str) -> str: edges.add(f'{package_key} -- "{edge_label}" --> {dependency_key}') # Produce the Mermaid Markdown. - indent = " " * 4 - output = dedent( - f"""\ - flowchart TD - {indent}classDef missing stroke-dasharray: 5 - """, - ) - # Sort the nodes and edges to make the output deterministic. - output += indent - output += f"\n{indent}".join(node for node in sorted(nodes)) - output += "\n" + indent - output += f"\n{indent}".join(edge for edge in sorted(edges)) - output += "\n" - return output + lines = [ + "flowchart TD", + "classDef missing stroke-dasharray: 5", + *sorted(nodes), + *sorted(edges), + ] + return "".join(f"{' ' if i else ''}{line}\n" for i, line in enumerate(lines)) __all__ = [ diff --git a/src/pipdeptree/_validate.py b/src/pipdeptree/_validate.py index c1bf4bb4..f1e93551 100644 --- a/src/pipdeptree/_validate.py +++ b/src/pipdeptree/_validate.py @@ -76,7 +76,7 @@ def cyclic_deps(tree: PackageDAG) -> list[tuple[DistPackage, ReqPackage, ReqPack if val is not None: entry = tree.get(val) if entry is not None: - p_as_dep_of_r = [x for x in entry if x.key == p.key][0] + p_as_dep_of_r = next(x for x in entry if x.key == p.key) cyclic.append((p, r, p_as_dep_of_r)) return cyclic diff --git a/tests/conftest.py b/tests/conftest.py index b38d4276..b47c9d2d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -21,8 +21,7 @@ def func(simple_graph: MockGraph) -> Iterator[Mock]: as_req = Mock(key=nk, project_name=nk, specs=[("==", nv)]) m.as_requirement = Mock(return_value=as_req) reqs = [] - for child in children: - ck, cv = child + for ck, cv in children: r = Mock(key=ck, project_name=ck, specs=cv) reqs.append(r) m.requires = Mock(return_value=reqs)