From 35f885a052f5b3287acf8ee732cd3d71630721c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Wed, 14 Jun 2023 13:02:41 -0700 Subject: [PATCH] Add ruff (#243) --- .github/workflows/check.yml | 6 +- .github/workflows/release.yml | 2 +- .pre-commit-config.yaml | 50 ++---- .prettierrc.toml | 2 - README.md | 2 - docs/twine-pdt.png | Bin 97568 -> 0 bytes docs/v2beta-opts.org | 43 ----- pyproject.toml | 41 +++-- src/pipdeptree/__init__.py | 250 ++++++++++++++++-------------- src/pipdeptree/__main__.py | 2 + tests/guess_version_setuptools.py | 4 +- tests/test_pipdeptree.py | 97 ++++++------ tox.ini | 2 +- whitelist.txt | 36 ----- 14 files changed, 230 insertions(+), 307 deletions(-) delete mode 100644 .prettierrc.toml delete mode 100644 docs/twine-pdt.png delete mode 100644 docs/v2beta-opts.org delete mode 100644 whitelist.txt diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index dd1da3b..3f08c67 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -13,12 +13,12 @@ concurrency: jobs: test: name: test ${{ matrix.py }} - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: py: - - "3.12.0-beta.1" + - "3.12.0-beta.2" - "3.11" - "3.10" - "3.9" @@ -83,7 +83,7 @@ jobs: publish: if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') needs: [check, test] - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - name: setup python to build package uses: actions/setup-python@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a2458d2..4023d59 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,7 +5,7 @@ on: jobs: release: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest environment: name: release url: https://pypi.org/p/pipdeptree diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3a065dd..763b550 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,59 +2,33 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: - - id: check-ast - - id: check-builtin-literals - - id: check-docstring-first - - id: check-merge-conflict - - id: check-yaml - - id: check-toml - - id: debug-statements - id: end-of-file-fixer - id: trailing-whitespace - - repo: https://github.com/asottile/pyupgrade - rev: v3.3.1 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: "v0.0.272" hooks: - - id: pyupgrade - args: ["--py37-plus"] - - repo: https://github.com/PyCQA/isort - rev: 5.12.0 - hooks: - - id: isort + - id: ruff + args: [--fix, --exit-non-zero-on-fix] - repo: https://github.com/psf/black rev: 23.3.0 hooks: - id: black - args: [--safe] - - repo: https://github.com/asottile/blacken-docs - rev: 1.13.0 - hooks: - - id: blacken-docs - additional_dependencies: [black==23.3] - repo: https://github.com/tox-dev/tox-ini-fmt rev: "1.3.0" hooks: - id: tox-ini-fmt args: ["-p", "fix"] - repo: https://github.com/tox-dev/pyproject-fmt - rev: "0.9.2" + rev: "0.11.2" hooks: - id: pyproject-fmt - - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 - hooks: - - id: flake8 - additional_dependencies: - - flake8-bugbear==23.3.23 - - flake8-comprehensions==3.12 - - flake8-pytest-style==1.7.2 - - flake8-spellcheck==0.28 - - flake8-unused-arguments==0.0.13 - - flake8-noqa==1.3.1 - - pep8-naming==0.13.3 + additional_dependencies: ["tox>=4.6"] - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v2.7.1" + rev: "v3.0.0-alpha.9-for-vscode" hooks: - id: prettier - additional_dependencies: - - "prettier@2.7.1" - - "@prettier/plugin-xml@2.2" + args: ["--print-width=120", "--prose-wrap=always"] + - repo: meta + hooks: + - id: check-hooks-apply + - id: check-useless-excludes diff --git a/.prettierrc.toml b/.prettierrc.toml deleted file mode 100644 index ba170fe..0000000 --- a/.prettierrc.toml +++ /dev/null @@ -1,2 +0,0 @@ -printWidth = 120 -proseWrap = "always" diff --git a/README.md b/README.md index 9d1b3a5..cf21bac 100644 --- a/README.md +++ b/README.md @@ -199,8 +199,6 @@ $ pipdeptree --json-tree ## Visualizing the dependency graph -![image](https://raw.githubusercontent.com/tox-dev/pipdeptree/main/docs/twine-pdt.png) - The dependency graph can also be visualized using [GraphViz](http://www.graphviz.org/): ```bash diff --git a/docs/twine-pdt.png b/docs/twine-pdt.png deleted file mode 100644 index bea0494a54986cec5e58169c43f885be4ce38910..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97568 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Ð(FJ7evYF<5V7oP|6~2$ra&?-`$j&rhyF0L;8U;k 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

Uqox1LGf|QO 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 | | | | | | | | | | -| all | | | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| local-only | | | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| user-only | | | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| freeze | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ | | | | -| warn | ✓ | ✓ | ✓ | | | | | ✗ | ✗ | | -| reverse | ✓ | ✓ | ✓ | ✓ | | | ✓ | | ✗ | ✗ | -| packages | ✓ | ✓ | ✓ | ✓ | | ✓ | | ✗ | ✗ | ✗ | -| json | ✓ | ✓ | ✓ | | ✗ | | ✗ | | | | -| json-tree | ✓ | ✓ | ✓ | | ✗ | ✗ | ✗ | | | | -| graph-output | ✓ | ✓ | ✓ | | | ✗ | ✗ | | | | - - -** Plan for version 2.0.0 (work in progress) - -| *Features* | all | local-only | user-only | freeze | warn | reverse | packages | json | json-tree | graph-output | | -|--------------+-----+------------+-----------+--------+----------+----------+----------+----------+-----------+--------------+---| -| | | | | | | | | | | | | -| all | | | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | -| local-only | | | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | -| user-only | | | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | -| freeze | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ | | | | | -| warn | ✓ | ✓ | ✓ | | | | | ✓ (todo) | ✓ (todo) | | | -| reverse | ✓ | ✓ | ✓ | ✓ | | | ✓ | | ✓ (done) | ✓ (done) | | -| packages | ✓ | ✓ | ✓ | ✓ | | ✓ | | ✓ (done) | ✓ (done) | ✓ (done) | | -| json | ✓ | ✓ | ✓ | | ✓ (todo) | | ✓ (done) | | | | | -| json-tree | ✓ | ✓ | ✓ | | ✓ (todo) | ✓ (done) | ✓ (done) | | | | | -| graph-output | ✓ | ✓ | ✓ | | | ✓ (done) | ✓ (done) | | | | | diff --git a/pyproject.toml b/pyproject.toml index eb1f414..d31ee71 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ build-backend = "hatchling.build" requires = [ "hatch-vcs>=0.3", - "hatchling>=1.14", + "hatchling>=1.17.1", ] [project] @@ -29,8 +29,13 @@ classifiers = [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", - "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ] dynamic = [ "version", @@ -41,11 +46,11 @@ optional-dependencies.graphviz = [ optional-dependencies.test = [ "covdefaults>=2.3", "diff-cover>=7.5", - "pip>=23.1", + "pip>=23.1.2", "pytest>=7.3.1", - "pytest-cov>=4", + "pytest-cov>=4.1", "pytest-mock>=3.10", - "virtualenv<21,>=20.21", + "virtualenv<21,>=20.23", ] urls.Changelog = "https://github.com/tox-dev/pipdeptree/blob/main/CHANGES.md" urls.Documentation = "https://github.com/tox-dev/pipdeptree/blob/main/README.md#pipdeptree" @@ -61,13 +66,31 @@ version.source = "vcs" [tool.black] line-length = 120 -[tool.isort] -profile = "black" -known_first_party = ["pipdeptree"] - [tool.coverage] html.show_contexts = true html.skip_covered = false paths.source = ["src", ".tox/*/lib/python*/site-packages", "*/src"] run.parallel = true run.plugins = ["covdefaults"] + +[tool.ruff] +select = ["ALL"] +line-length = 120 +target-version = "py37" +isort = {known-first-party = ["pipdeptree"], required-imports = ["from __future__ import annotations"]} +ignore = [ + "INP001", # no implicit namespace + "D", # ignore documentation for now + "ANN", # No type annotations for now + "D203", # `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible + "D212", # `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible + "S104", # Possible binding to all interface +] +[tool.ruff.per-file-ignores] +"tests/**/*.py" = [ + "S101", # asserts allowed in tests... + "FBT", # don"t care about booleans as positional arguments in tests + "D", # don"t care about documentation in tests + "S603", # `subprocess` call: check for execution of untrusted input + "PLR2004", # Magic value used in comparison, consider replacing with a constant variable +] diff --git a/src/pipdeptree/__init__.py b/src/pipdeptree/__init__.py index 0e85016..d66207a 100644 --- a/src/pipdeptree/__init__.py +++ b/src/pipdeptree/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import argparse import fnmatch import inspect @@ -11,6 +13,7 @@ from collections import defaultdict, deque from collections.abc import Mapping from importlib import import_module from itertools import chain +from pathlib import Path from textwrap import dedent from pip._vendor import pkg_resources @@ -36,7 +39,8 @@ def sorted_tree(tree): def guess_version(pkg_key, default="?"): - """Guess the version of a pkg when pip doesn't provide it + """ + Guess the version of a pkg when pip doesn't provide it. :param str pkg_key: key of the package :param str default: default version to return if unable to find @@ -62,8 +66,7 @@ def guess_version(pkg_key, default="?"): v = getattr(m, "__version__", default) if inspect.ismodule(v): return getattr(v, "__version__", default) - else: - return v + return v def frozen_req_from_dist(dist): @@ -96,22 +99,21 @@ class Package: for `render_as_root` and `render_as_branch` methods. """ - def __init__(self, obj): + def __init__(self, obj) -> None: self._obj = obj self.project_name = obj.project_name self.key = obj.key - def render_as_root(self, frozen): # noqa: U100 + def render_as_root(self, frozen): # noqa: ARG002 return NotImplementedError - def render_as_branch(self, frozen): # noqa: U100 + def render_as_branch(self, frozen): # noqa: ARG002 return NotImplementedError - def render(self, parent=None, frozen=False): + def render(self, parent=None, frozen=False): # noqa: FBT002 if not parent: return self.render_as_root(frozen) - else: - return self.render_as_branch(frozen) + return self.render_as_branch(frozen) @staticmethod def frozen_repr(obj): @@ -121,7 +123,7 @@ class Package: def __getattr__(self, key): return getattr(self._obj, key) - def __repr__(self): + def __repr__(self) -> str: return f'<{self.__class__.__name__}("{self.key}")>' def __lt__(self, rhs): @@ -130,14 +132,14 @@ class Package: class DistPackage(Package): """ - Wrapper class for pkg_resources.Distribution instances + Wrapper class for pkg_resources.Distribution instances. :param obj: pkg_resources.Distribution to wrap over :param req: optional ReqPackage object to associate this DistPackage with. This is useful for displaying the tree in reverse """ - def __init__(self, obj, req=None): + def __init__(self, obj, req=None) -> None: super().__init__(obj) self.version_spec = None self.req = req @@ -145,22 +147,20 @@ class DistPackage(Package): def render_as_root(self, frozen): if not frozen: return f"{self.project_name}=={self.version}" - else: - return self.__class__.frozen_repr(self._obj) + return self.__class__.frozen_repr(self._obj) def render_as_branch(self, frozen): - assert self.req is not None + assert self.req is not None # noqa: S101 if not frozen: parent_ver_spec = self.req.version_spec parent_str = self.req.project_name if parent_ver_spec: parent_str += parent_ver_spec return f"{self.project_name}=={self.version} [requires: {parent_str}]" - else: - return self.render_as_root(frozen) + return self.render_as_root(frozen) def as_requirement(self): - """Return a ReqPackage representation of this DistPackage""" + """Return a ReqPackage representation of this DistPackage.""" return ReqPackage(self._obj.as_requirement(), dist=self) def as_parent_of(self, req): @@ -184,7 +184,7 @@ class DistPackage(Package): class ReqPackage(Package): """ - Wrapper class for Requirements instance + Wrapper class for Requirements instance. :param obj: The `Requirements` instance to wrap over :param dist: optional `pkg_resources.Distribution` instance for this requirement @@ -192,7 +192,7 @@ class ReqPackage(Package): UNKNOWN_VERSION = "?" - def __init__(self, obj, dist=None): + def __init__(self, obj, dist=None) -> None: super().__init__(obj) self.dist = dist @@ -212,7 +212,7 @@ class ReqPackage(Package): return self.installed_version == self.UNKNOWN_VERSION def is_conflicting(self): - """If installed version conflicts with required version""" + """If installed version conflicts with required version.""" # unknown installed version is also considered conflicting if self.installed_version == self.UNKNOWN_VERSION: return True @@ -224,17 +224,15 @@ class ReqPackage(Package): def render_as_root(self, frozen): if not frozen: return f"{self.project_name}=={self.installed_version}" - elif self.dist: - return self.__class__.frozen_repr(self.dist._obj) - else: - return self.project_name + if self.dist: + return self.__class__.frozen_repr(self.dist._obj) # noqa: SLF001 + return self.project_name def render_as_branch(self, frozen): if not frozen: req_ver = self.version_spec if self.version_spec else "Any" return f"{self.project_name} [required: {req_ver}, installed: {self.installed_version}]" - else: - return self.render_as_root(frozen) + return self.render_as_root(frozen) def as_dict(self): return { @@ -275,8 +273,9 @@ class PackageDAG(Mapping): m = {p: [ReqPackage(r, idx.get(r.key)) for r in p.requires()] for p in pkgs} return cls(m) - def __init__(self, m): - """Initialize the PackageDAG object + def __init__(self, m) -> None: + """ + Initialize the PackageDAG object. :param dict m: dict of node objects (refer class docstring) :returns: None @@ -304,7 +303,7 @@ class PackageDAG(Mapping): def get_children(self, node_key): """ - Get child nodes for a node by its key + Get child nodes for a node by its key. :param str node_key: key of the node to get children of :returns: list of child nodes @@ -313,9 +312,9 @@ class PackageDAG(Mapping): node = self.get_node_as_parent(node_key) return self._obj[node] if node else [] - def filter(self, include, exclude): + def filter_nodes(self, include, exclude): # noqa: C901, PLR0912 """ - Filters nodes in a graph by given parameters + Filters nodes in a graph by given parameters. If a node is included, then all it's children are also included. @@ -335,22 +334,19 @@ class PackageDAG(Mapping): # https://setuptools.readthedocs.io/en/latest/pkg_resources.html#distribution-objects if include: include = {s.lower() for s in include} - if exclude: - exclude = {s.lower() for s in exclude} - else: - exclude = set() + exclude = {s.lower() for s in exclude} if exclude else set() # Check for mutual exclusion of show_only and exclude sets # after normalizing the values to lowercase if include and exclude: - assert not (include & exclude) + assert not (include & exclude) # noqa: S101 # Traverse the graph in a depth first manner and filter the # nodes according to `show_only` and `exclude` sets stack = deque() m = {} seen = set() - for node in self._obj.keys(): + for node in self._obj: if any(fnmatch.fnmatch(node.key, e) for e in exclude): continue if include is None or any(fnmatch.fnmatch(node.key, i) for i in include): @@ -398,7 +394,7 @@ class PackageDAG(Mapping): # we are using the same object. This check is required # as we're using array mutation try: - node = [p for p in m.keys() if p.key == v.key][0] + node = [p for p in m if p.key == v.key][0] except IndexError: node = v m[node].append(k.as_parent_of(v)) @@ -421,12 +417,13 @@ class PackageDAG(Mapping): def __iter__(self): return self._obj.__iter__() - def __len__(self): + def __len__(self) -> int: return len(self._obj) class ReversedPackageDAG(PackageDAG): - """Representation of Package dependencies in the reverse order. + """ + Representation of Package dependencies in the reverse order. Similar to it's super class `PackageDAG`, the underlying datastructure is a dict, but here the keys are expected to be of type `ReqPackage` and each item in the values of type `DistPackage`. @@ -436,7 +433,7 @@ class ReversedPackageDAG(PackageDAG): def reverse(self): """ - Reverse the already reversed DAG to get the PackageDAG again + Reverse the already reversed DAG to get the PackageDAG again. :returns: reverse of the reversed DAG :rtype: PackageDAG @@ -446,7 +443,7 @@ class ReversedPackageDAG(PackageDAG): for k, vs in self._obj.items(): for v in vs: try: - node = [p for p in m.keys() if p.key == v.key][0] + node = [p for p in m if p.key == v.key][0] except IndexError: node = v.as_parent_of(None) m[node].append(k) @@ -455,8 +452,9 @@ class ReversedPackageDAG(PackageDAG): return PackageDAG(dict(m)) -def render_text(tree, max_depth, list_all=True, frozen=False): - """Print tree as text on console +def render_text(tree, max_depth, list_all=True, frozen=False): # noqa: FBT002 + """ + Print tree as text on console. :param dict tree: the package tree :param bool list_all: whether to list all the pgks at the root level or only those that are the sub-dependencies @@ -479,16 +477,16 @@ def render_text(tree, max_depth, list_all=True, frozen=False): def _render_text_with_unicode(tree, nodes, max_depth, frozen): use_bullets = not frozen - def aux( + def aux( # noqa: PLR0913 node, parent=None, indent=0, cur_chain=None, prefix="", depth=0, - has_grand_parent=False, - is_last_child=False, - parent_is_last_child=False, + has_grand_parent=False, # noqa: FBT002 + is_last_child=False, # noqa: FBT002 + parent_is_last_child=False, # noqa: FBT002 ): cur_chain = cur_chain or [] node_str = node.render(parent, frozen) @@ -525,7 +523,7 @@ def _render_text_with_unicode(tree, nodes, max_depth, frozen): c, node, indent=next_indent, - cur_chain=cur_chain + [c.project_name], + cur_chain=[*cur_chain, c.project_name], prefix=next_prefix, depth=depth + 1, has_grand_parent=parent is not None, @@ -540,7 +538,7 @@ def _render_text_with_unicode(tree, nodes, max_depth, frozen): return result lines = chain.from_iterable([aux(p) for p in nodes]) - print("\n".join(lines)) + print("\n".join(lines)) # noqa: T201 def _render_text_without_unicode(tree, nodes, max_depth, frozen): @@ -554,7 +552,7 @@ def _render_text_without_unicode(tree, nodes, max_depth, frozen): node_str = prefix + node_str result = [node_str] children = [ - aux(c, node, indent=indent + 2, cur_chain=cur_chain + [c.project_name], depth=depth + 1) + aux(c, node, indent=indent + 2, cur_chain=[*cur_chain, c.project_name], depth=depth + 1) for c in tree.get_children(node.key) if c.project_name not in cur_chain and depth + 1 <= max_depth ] @@ -562,7 +560,7 @@ def _render_text_without_unicode(tree, nodes, max_depth, frozen): return result lines = chain.from_iterable([aux(p) for p in nodes]) - print("\n".join(lines)) + print("\n".join(lines)) # noqa: T201 def render_json(tree, indent): @@ -580,7 +578,8 @@ def render_json(tree, indent): """ tree = tree.sort() return json.dumps( - [{"package": k.as_dict(), "dependencies": [v.as_dict() for v in vs]} for k, vs in tree.items()], indent=indent + [{"package": k.as_dict(), "dependencies": [v.as_dict() for v in vs]} for k, vs in tree.items()], + indent=indent, ) @@ -603,7 +602,7 @@ def render_json_tree(tree, indent): """ tree = tree.sort() branch_keys = {r.key for r in chain.from_iterable(tree.values())} - nodes = [p for p in tree.keys() if p.key not in branch_keys] + nodes = [p for p in tree if p.key not in branch_keys] def aux(node, parent=None, cur_chain=None): if cur_chain is None: @@ -616,7 +615,7 @@ def render_json_tree(tree, indent): d["required_version"] = d["installed_version"] d["dependencies"] = [ - aux(c, parent=node, cur_chain=cur_chain + [c.project_name]) + aux(c, parent=node, cur_chain=[*cur_chain, c.project_name]) for c in tree.get_children(node.key) if c.project_name not in cur_chain ] @@ -626,8 +625,9 @@ def render_json_tree(tree, indent): return json.dumps([aux(p) for p in nodes], indent=indent) -def render_mermaid(tree) -> str: - """Produce a Mermaid flowchart from the dependency graph. +def render_mermaid(tree) -> str: # noqa: C901 + """ + Produce a Mermaid flowchart from the dependency graph. :param dict tree: dependency graph """ @@ -683,7 +683,7 @@ def render_mermaid(tree) -> str: if isinstance(tree, ReversedPackageDAG): for package, reverse_dependencies in tree.items(): package_label = "\\n".join( - (package.project_name, "(missing)" if package.is_missing else package.installed_version) + (package.project_name, "(missing)" if package.is_missing else package.installed_version), ) package_key = mermaid_id(package.key) nodes.add(f'{package_key}["{package_label}"]') @@ -693,7 +693,7 @@ def render_mermaid(tree) -> str: edges.add(f'{package_key} -- "{edge_label}" --> {reverse_dependency_key}') else: for package, dependencies in tree.items(): - package_label = "\\n".join((package.project_name, package.version)) + package_label = f"{package.project_name}\\n{package.version}" package_key = mermaid_id(package.key) nodes.add(f'{package_key}["{package_label}"]') for dependency in dependencies: @@ -712,7 +712,7 @@ def render_mermaid(tree) -> str: f"""\ flowchart TD {indent}classDef missing stroke-dasharray: 5 - """ + """, ) # Sort the nodes and edges to make the output deterministic. output += indent @@ -723,8 +723,9 @@ def render_mermaid(tree) -> str: return output -def dump_graphviz(tree, output_format="dot", is_reverse=False): - """Output dependency graph as one of the supported GraphViz output formats. +def dump_graphviz(tree, output_format="dot", is_reverse=False): # noqa: C901, FBT002, PLR0912 + """ + Output dependency graph as one of the supported GraphViz output formats. :param dict tree: dependency graph :param string output_format: output format @@ -735,9 +736,12 @@ def dump_graphviz(tree, output_format="dot", is_reverse=False): """ try: from graphviz import Digraph - except ImportError: - print("graphviz is not available, but necessary for the output " "option. Please install it.", file=sys.stderr) - sys.exit(1) + except ImportError as exc: + print( # noqa: T201 + "graphviz is not available, but necessary for the output option. Please install it.", + file=sys.stderr, + ) + raise SystemExit(1) from exc try: from graphviz import parameters @@ -745,7 +749,7 @@ def dump_graphviz(tree, output_format="dot", is_reverse=False): from graphviz import backend valid_formats = backend.FORMATS - print( + print( # noqa: T201 "Deprecation warning! Please upgrade graphviz to version >=0.18.0 " "Support for older versions will be removed in upcoming release", file=sys.stderr, @@ -754,9 +758,9 @@ def dump_graphviz(tree, output_format="dot", is_reverse=False): valid_formats = parameters.FORMATS if output_format not in valid_formats: - print(f"{output_format} is not a supported output format.", file=sys.stderr) - print(f"Supported formats are: {', '.join(sorted(valid_formats))}", file=sys.stderr) - sys.exit(1) + print(f"{output_format} is not a supported output format.", file=sys.stderr) # noqa: T201 + print(f"Supported formats are: {', '.join(sorted(valid_formats))}", file=sys.stderr) # noqa: T201 + raise SystemExit(1) graph = Digraph(format=output_format) @@ -789,7 +793,7 @@ def dump_graphviz(tree, output_format="dot", is_reverse=False): # Fixes https://github.com/tox-dev/pipdeptree/issues/188 # That way we can guarantee the output of the dot format is deterministic # and stable. - return "".join([tuple(graph)[0]] + sorted(graph.body) + [graph._tail]) + return "".join([tuple(graph)[0], *sorted(graph.body), graph._tail]) # noqa: SLF001 # As it's unknown if the selected output format is binary or not, try to # decode it as UTF8 and only print it out in binary if that's not possible. @@ -806,7 +810,7 @@ def print_graphviz(dump_output): :param dump_output: The output from dump_graphviz """ if hasattr(dump_output, "encode"): - print(dump_output) + print(dump_output) # noqa: T201 else: with os.fdopen(sys.stdout.fileno(), "wb") as bytestream: bytestream.write(dump_output) @@ -832,20 +836,20 @@ def conflicting_deps(tree): def render_conflicts_text(conflicts): if conflicts: - print("Warning!!! Possibly conflicting dependencies found:", file=sys.stderr) + print("Warning!!! Possibly conflicting dependencies found:", file=sys.stderr) # noqa: T201 # Enforce alphabetical order when listing conflicts pkgs = sorted(conflicts.keys()) for p in pkgs: - pkg = p.render_as_root(False) - print(f"* {pkg}", file=sys.stderr) + pkg = p.render_as_root(False) # noqa: FBT003 + print(f"* {pkg}", file=sys.stderr) # noqa: T201 for req in conflicts[p]: - req_str = req.render_as_branch(False) - print(f" - {req_str}", file=sys.stderr) + req_str = req.render_as_branch(False) # noqa: FBT003 + print(f" - {req_str}", file=sys.stderr) # noqa: T201 def cyclic_deps(tree): """ - Return cyclic dependencies as list of tuples + Return cyclic dependencies as list of tuples. :param PackageDAG tree: package tree/dag :returns: list of tuples representing cyclic dependencies @@ -863,12 +867,12 @@ def cyclic_deps(tree): def render_cycles_text(cycles): if cycles: - print("Warning!! Cyclic dependencies found:", file=sys.stderr) + print("Warning!! Cyclic dependencies found:", file=sys.stderr) # noqa: T201 # List in alphabetical order of the dependency that's cycling # (2nd item in the tuple) cycles = sorted(cycles, key=lambda xs: xs[1].key) for a, b, c in cycles: - print(f"* {a.project_name} => {b.project_name} => {c.project_name}", file=sys.stderr) + print(f"* {a.project_name} => {b.project_name} => {c.project_name}", file=sys.stderr) # noqa: T201 def get_parser(): @@ -878,14 +882,14 @@ def get_parser(): parser.add_argument( "--python", default=sys.executable, - help="Python to use to look for packages in it (default: where" " installed)", + help="Python to use to look for packages in it (default: where installed)", ) parser.add_argument("-a", "--all", action="store_true", help="list all deps at top level") parser.add_argument( "-l", "--local-only", action="store_true", - help="If in a virtualenv that has global access " "do not show globally installed packages", + help="If in a virtualenv that has global access do not show globally installed packages", ) parser.add_argument("-u", "--user-only", action="store_true", help="Only show installations in the user site dir") parser.add_argument( @@ -960,7 +964,7 @@ def get_parser(): "--mermaid", action="store_true", default=False, - help=("Display dependency tree as a Mermaid graph. " "This option overrides all other options."), + help="Display dependency tree as a Mermaid graph. This option overrides all other options.", ) parser.add_argument( "--graph-output", @@ -990,12 +994,14 @@ def _get_args(): def handle_non_host_target(args): - of_python = os.path.abspath(args.python) # if target is not current python re-invoke it under the actual host - if of_python != os.path.abspath(sys.executable): + if Path(args.python).absolute() != Path(sys.executable).absolute(): # there's no way to guarantee that graphviz is available, so refuse if args.output_format: - print("graphviz functionality is not supported when querying" " non-host python", file=sys.stderr) + print( # noqa: T201 + "graphviz functionality is not supported when querying non-host python", + file=sys.stderr, + ) raise SystemExit(1) argv = sys.argv[1:] # remove current python executable for py_at, value in enumerate(argv): @@ -1007,18 +1013,17 @@ def handle_non_host_target(args): main_file = inspect.getsourcefile(sys.modules[__name__]) with tempfile.TemporaryDirectory() as project: - dest = os.path.join(project, "pipdeptree") - shutil.copytree(os.path.dirname(main_file), dest) + shutil.copytree(Path(main_file).parent, Path(project) / "pipdeptree") # invoke from an empty folder to avoid cwd altering sys.path env = os.environ.copy() env["PYTHONPATH"] = project - cmd = [of_python, "-m", "pipdeptree"] + cmd = [args.python, "-m", "pipdeptree"] cmd.extend(argv) - return subprocess.call(cmd, cwd=project, env=env) + return subprocess.call(cmd, cwd=project, env=env) # noqa: S603 return None -def get_installed_distributions(local_only=False, user_only=False): +def get_installed_distributions(local_only=False, user_only=False): # noqa: FBT002 try: from pip._internal.metadata import pkg_resources except ImportError: @@ -1030,9 +1035,11 @@ def get_installed_distributions(local_only=False, user_only=False): return misc.get_installed_distributions(local_only=local_only, user_only=user_only) else: dists = pkg_resources.Environment.from_paths(None).iter_installed_distributions( - local_only=local_only, skip=(), user_only=user_only + local_only=local_only, + skip=(), + user_only=user_only, ) - return [d._dist for d in dists] + return [d._dist for d in dists] # noqa: SLF001 def main(): @@ -1042,29 +1049,10 @@ def main(): return result pkgs = get_installed_distributions(local_only=args.local_only, user_only=args.user_only) - tree = PackageDAG.from_pkgs(pkgs) - is_text_output = not any([args.json, args.json_tree, args.output_format]) - return_code = 0 - - # Before any reversing or filtering, show warnings to console - # about possibly conflicting or cyclic deps if found and warnings - # are enabled (i.e. only if output is to be printed to console) - if is_text_output and args.warn != "silence": - conflicts = conflicting_deps(tree) - if conflicts: - render_conflicts_text(conflicts) - print("-" * 72, file=sys.stderr) - - cycles = cyclic_deps(tree) - if cycles: - render_cycles_text(cycles) - print("-" * 72, file=sys.stderr) - - if args.warn == "fail" and (conflicts or cycles): - return_code = 1 + return_code = _check_cycle_conflict(args, is_text_output, tree) # Reverse the tree (if applicable) before filtering, thus ensuring # that the filter will be applied on ReverseTree @@ -1075,18 +1063,42 @@ def main(): exclude = set(args.exclude.split(",")) if args.exclude else None if show_only is not None or exclude is not None: - tree = tree.filter(show_only, exclude) + tree = tree.filter_nodes(show_only, exclude) + _render(args, tree) + + return return_code + + +def _check_cycle_conflict(args, is_text_output, tree): + # Before any reversing or filtering, show warnings to console + # about possibly conflicting or cyclic deps if found and warnings + # are enabled (i.e. only if output is to be printed to console) + if is_text_output and args.warn != "silence": + conflicts = conflicting_deps(tree) + if conflicts: + render_conflicts_text(conflicts) + print("-" * 72, file=sys.stderr) # noqa: T201 + + cycles = cyclic_deps(tree) + if cycles: + render_cycles_text(cycles) + print("-" * 72, file=sys.stderr) # noqa: T201 + + if args.warn == "fail" and (conflicts or cycles): + return 1 + return 0 + + +def _render(args, tree): if args.json: - print(render_json(tree, indent=4)) + print(render_json(tree, indent=4)) # noqa: T201 elif args.json_tree: - print(render_json_tree(tree, indent=4)) + print(render_json_tree(tree, indent=4)) # noqa: T201 elif args.mermaid: - print(render_mermaid(tree)) + print(render_mermaid(tree)) # noqa: T201 elif args.output_format: output = dump_graphviz(tree, output_format=args.output_format, is_reverse=args.reverse) print_graphviz(output) else: render_text(tree, args.depth, args.all, args.freeze) - - return return_code diff --git a/src/pipdeptree/__main__.py b/src/pipdeptree/__main__.py index 85cca3c..35ce609 100644 --- a/src/pipdeptree/__main__.py +++ b/src/pipdeptree/__main__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import sys from pipdeptree import main diff --git a/tests/guess_version_setuptools.py b/tests/guess_version_setuptools.py index f9426f7..fcf7068 100644 --- a/tests/guess_version_setuptools.py +++ b/tests/guess_version_setuptools.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import sys import pipdeptree @@ -13,4 +15,4 @@ def raise_import_error(name): importlib_metadata.version = raise_import_error -print(pipdeptree.guess_version("setuptools"), end="") +print(pipdeptree.guess_version("setuptools"), end="") # noqa: T201 diff --git a/tests/test_pipdeptree.py b/tests/test_pipdeptree.py index f50094d..8b63dc4 100644 --- a/tests/test_pipdeptree.py +++ b/tests/test_pipdeptree.py @@ -1,13 +1,13 @@ +from __future__ import annotations + import platform import random import subprocess import sys -from contextlib import contextmanager from itertools import chain from pathlib import Path -from tempfile import NamedTemporaryFile from textwrap import dedent, indent -from typing import Any +from typing import TYPE_CHECKING, Any try: from unittest import mock @@ -19,6 +19,9 @@ import virtualenv import pipdeptree as p +if TYPE_CHECKING: + from pytest_mock import MockerFixture + # Tests for DAG classes @@ -44,7 +47,7 @@ def mock_package_dag(simple_graph): # util for comparing tree contents with a simple graph def dag_to_dict(g): - return {k.key: [v.key for v in vs] for k, vs in g._obj.items()} + return {k.key: [v.key for v in vs] for k, vs in g._obj.items()} # noqa: SLF001 def sort_map_values(m): @@ -60,39 +63,38 @@ t = mock_package_dag( ("e", "0.12.1"): [], ("f", "3.1"): [("b", [(">=", "2.1.0")])], ("g", "6.8.3rc1"): [("e", [(">=", "0.9.0")]), ("f", [(">=", "3.0.0")])], - } + }, ) def test_package_dag_get_node_as_parent(): - assert "b" == t.get_node_as_parent("b").key - assert "c" == t.get_node_as_parent("c").key + assert t.get_node_as_parent("b").key == "b" + assert t.get_node_as_parent("c").key == "c" def test_package_dag_filter(): # When both show_only and exclude are not specified, same tree - # object is returned - assert t.filter(None, None) is t + assert t.filter_nodes(None, None) is t # when show_only is specified - g1 = dag_to_dict(t.filter({"a", "d"}, None)) + g1 = dag_to_dict(t.filter_nodes({"a", "d"}, None)) expected = {"a": ["b", "c"], "b": ["d"], "c": ["d", "e"], "d": ["e"], "e": []} assert expected == g1 # when exclude is specified - g2 = dag_to_dict(t.filter(None, ["d"])) + g2 = dag_to_dict(t.filter_nodes(None, ["d"])) expected = {"a": ["b", "c"], "b": [], "c": ["e"], "e": [], "f": ["b"], "g": ["e", "f"]} assert expected == g2 # when both show_only and exclude are specified - g3 = dag_to_dict(t.filter({"a", "g"}, {"d", "e"})) + g3 = dag_to_dict(t.filter_nodes({"a", "g"}, {"d", "e"})) expected = {"a": ["b", "c"], "b": [], "c": [], "f": ["b"], "g": ["f"]} assert expected == g3 # when conflicting values in show_only and exclude, AssertionError # is raised with pytest.raises(AssertionError): - dag_to_dict(t.filter({"d"}, {"D", "e"})) + dag_to_dict(t.filter_nodes({"d"}, {"D", "e"})) @pytest.fixture(scope="session") @@ -103,32 +105,32 @@ def t_fnmatch() -> Any: ("a.b", "1"): [("a.c", [])], ("b.a", "1"): [("b.b", [])], ("b.b", "1"): [("a.b", [])], - } + }, ) def test_package_dag_filter_fnmatch_include_a(t_fnmatch: Any) -> None: # test include for a.*in the result we got only a.* nodes - graph = dag_to_dict(t_fnmatch.filter({"a.*"}, None)) + graph = dag_to_dict(t_fnmatch.filter_nodes({"a.*"}, None)) assert graph == {"a.a": ["a.b", "a.c"], "a.b": ["a.c"]} def test_package_dag_filter_fnmatch_include_b(t_fnmatch: Any) -> None: # test include for b.*, which has a.b and a.c in tree, but not a.a # in the result we got the b.* nodes plus the a.b node as child in the tree - graph = dag_to_dict(t_fnmatch.filter({"b.*"}, None)) + graph = dag_to_dict(t_fnmatch.filter_nodes({"b.*"}, None)) assert graph == {"b.a": ["b.b"], "b.b": ["a.b"], "a.b": ["a.c"]} def test_package_dag_filter_fnmatch_exclude_c(t_fnmatch: Any) -> None: # test exclude for b.* in the result we got only a.* nodes - graph = dag_to_dict(t_fnmatch.filter(None, {"b.*"})) + graph = dag_to_dict(t_fnmatch.filter_nodes(None, {"b.*"})) assert graph == {"a.a": ["a.b", "a.c"], "a.b": ["a.c"]} def test_package_dag_filter_fnmatch_exclude_a(t_fnmatch: Any) -> None: # test exclude for a.* in the result we got only b.* nodes - graph = dag_to_dict(t_fnmatch.filter(None, {"a.*"})) + graph = dag_to_dict(t_fnmatch.filter_nodes(None, {"a.*"})) assert graph == {"b.a": ["b.b"], "b.b": []} @@ -137,7 +139,7 @@ def test_package_dag_reverse(): expected = {"a": [], "b": ["a", "f"], "c": ["a"], "d": ["b", "c"], "e": ["c", "d", "g"], "f": ["g"], "g": []} assert isinstance(t1, p.ReversedPackageDAG) assert sort_map_values(expected) == sort_map_values(dag_to_dict(t1)) - assert all(isinstance(k, p.ReqPackage) for k in t1.keys()) + assert all(isinstance(k, p.ReqPackage) for k in t1) assert all(isinstance(v, p.DistPackage) for v in chain.from_iterable(t1.values())) # testing reversal of ReversedPackageDAG instance @@ -145,7 +147,7 @@ def test_package_dag_reverse(): t2 = t1.reverse() assert isinstance(t2, p.PackageDAG) assert sort_map_values(expected) == sort_map_values(dag_to_dict(t2)) - assert all(isinstance(k, p.DistPackage) for k in t2.keys()) + assert all(isinstance(k, p.DistPackage) for k in t2) assert all(isinstance(v, p.ReqPackage) for v in chain.from_iterable(t2.values())) @@ -159,7 +161,7 @@ def test_dist_package_render_as_root(): foo = mock.Mock(key="foo", project_name="foo", version="20.4.1") dp = p.DistPackage(foo) is_frozen = False - assert "foo==20.4.1" == dp.render_as_root(is_frozen) + assert dp.render_as_root(is_frozen) == "foo==20.4.1" def test_dist_package_render_as_branch(): @@ -169,7 +171,7 @@ def test_dist_package_render_as_branch(): rp = p.ReqPackage(bar_req, dist=bar) dp = p.DistPackage(foo).as_parent_of(rp) is_frozen = False - assert "foo==20.4.1 [requires: bar>=4.0]" == dp.render_as_branch(is_frozen) + assert dp.render_as_branch(is_frozen) == "foo==20.4.1 [requires: bar>=4.0]" def test_dist_package_as_parent_of(): @@ -181,7 +183,7 @@ def test_dist_package_as_parent_of(): bar_req = mock.Mock(key="bar", project_name="bar", version="4.1.0", specs=[(">=", "4.0")]) rp = p.ReqPackage(bar_req, dist=bar) dp1 = dp.as_parent_of(rp) - assert dp1._obj == dp._obj + assert dp1._obj == dp._obj # noqa: SLF001 assert dp1.req is rp dp2 = dp.as_parent_of(None) @@ -201,7 +203,7 @@ def test_req_package_render_as_root(): bar_req = mock.Mock(key="bar", project_name="bar", version="4.1.0", specs=[(">=", "4.0")]) rp = p.ReqPackage(bar_req, dist=bar) is_frozen = False - assert "bar==4.1.0" == rp.render_as_root(is_frozen) + assert rp.render_as_root(is_frozen) == "bar==4.1.0" def test_req_package_render_as_branch(): @@ -209,7 +211,7 @@ def test_req_package_render_as_branch(): bar_req = mock.Mock(key="bar", project_name="bar", version="4.1.0", specs=[(">=", "4.0")]) rp = p.ReqPackage(bar_req, dist=bar) is_frozen = False - assert "bar [required: >=4.0, installed: 4.1.0]" == rp.render_as_branch(is_frozen) + assert rp.render_as_branch(is_frozen) == "bar [required: >=4.0, installed: 4.1.0]" def test_req_package_as_dict(): @@ -230,7 +232,7 @@ class MockStdout: and `write()` (so that `print()` calls can write to stdout). """ - def __init__(self, encoding): + def __init__(self, encoding) -> None: self.stdout = sys.stdout self.encoding = encoding @@ -577,13 +579,13 @@ def randomized_dag_copy(t): """Returns a copy of the package tree fixture with dependencies in randomized order.""" # Extract the dependency graph from the package tree and randomize it. randomized_graph = {} - randomized_nodes = list(t._obj.keys()) + randomized_nodes = list(t._obj.keys()) # noqa: SLF001 random.shuffle(randomized_nodes) for node in randomized_nodes: - edges = t._obj[node] + edges = t._obj[node] # noqa: SLF001 random.shuffle(edges) randomized_graph[node] = edges - assert set(randomized_graph) == set(t._obj) + assert set(randomized_graph) == set(t._obj) # noqa: SLF001 # Create a randomized package tree. randomized_dag = p.PackageDAG(randomized_graph) @@ -612,7 +614,7 @@ def test_render_mermaid(): e["e\\n0.12.1"] f["f\\n3.1"] g["g\\n6.8.3rc1"] - """ + """, ) dependency_edges = indent( dedent( @@ -626,7 +628,7 @@ def test_render_mermaid(): f -- ">=2.1.0" --> b g -- ">=0.9.0" --> e g -- ">=3.0.0" --> f - """ + """, ), " " * 4, ).rstrip() @@ -642,7 +644,7 @@ def test_render_mermaid(): e -- ">=0.9.0" --> d e -- ">=0.9.0" --> g f -- ">=3.0.0" --> g - """ + """, ), " " * 4, ).rstrip() @@ -658,7 +660,7 @@ def test_mermaid_reserved_ids(): package_tree = mock_package_dag( { ("click", "3.4.0"): [("click-extra", [(">=", "2.0.0")])], - } + }, ) output = p.render_mermaid(package_tree) assert output == dedent( @@ -668,7 +670,7 @@ def test_mermaid_reserved_ids(): click-extra["click-extra\\n(missing)"]:::missing click_0["click\\n3.4.0"] click_0 -.-> click-extra - """ + """, ) @@ -700,27 +702,18 @@ def test_render_dot(capsys): \tg [label="g\\n6.8.3rc1"] } - """ + """, ) -def test_render_pdf(): +def test_render_pdf(tmp_path: Path, mocker: MockerFixture) -> None: output = p.dump_graphviz(t, output_format="pdf") - - @contextmanager - def redirect_stdout(new_target): - old_target, sys.stdout = sys.stdout, new_target - try: - yield new_target - finally: - sys.stdout = old_target - - with NamedTemporaryFile(delete=True) as f: - with redirect_stdout(f): + res = tmp_path / "file" + with pytest.raises(OSError, match="Bad file descriptor"): # noqa: PT012, SIM117 # because we reopen the file + with res.open("wb") as buf: + mocker.patch.object(sys, "stdout", buf) p.print_graphviz(output) - rf = open(f.name, "rb") - assert b"%PDF" == rf.read()[:4] - # @NOTE: rf is not closed to avoid "bad filedescriptor" error + assert res.read_bytes()[:4] == b"%PDF" def test_render_svg(capsys): @@ -914,13 +907,13 @@ def test_custom_interpreter(tmp_path, monkeypatch, capfd, args_joined): expected -= {"setuptools", "wheel"} assert found == expected, out - monkeypatch.setattr(sys, "argv", cmd + ["--graph-output", "something"]) + monkeypatch.setattr(sys, "argv", [*cmd, "--graph-output", "something"]) with pytest.raises(SystemExit) as context: p.main() out, err = capfd.readouterr() assert context.value.code == 1 assert not out - assert err == "graphviz functionality is not supported when querying" " non-host python\n" + assert err == "graphviz functionality is not supported when querying non-host python\n" def test_guess_version_setuptools(): diff --git a/tox.ini b/tox.ini index 5b23320..804b7b0 100644 --- a/tox.ini +++ b/tox.ini @@ -36,7 +36,7 @@ commands = description = format the code base to adhere to our styles, and complain about what we cannot do automatically skip_install = true deps = - pre-commit>=3.2.2 + pre-commit>=3.3.2 commands = pre-commit run --all-files --show-diff-on-failure diff --git a/whitelist.txt b/whitelist.txt deleted file mode 100644 index 2c3764f..0000000 --- a/whitelist.txt +++ /dev/null @@ -1,36 +0,0 @@ -2nd -basedistribution -bytestream -capfd -capsys -cld -cldn -copytree -deque -distinfodistribution -dists -dp1 -dp2 -exe -filedescriptor -fileno -frozenrequirement -g1 -g2 -g3 -getitem -getsourcefile -graphviz -hacky -ismodule -mpkgs -nk -pipdeptree -pkgs -readouterr -reqs -rhs -svg -t1 -t2 -virtualenv