Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pipdeptree for 
openSUSE:Factory checked in at 2026-03-17 19:04:31
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pipdeptree (Old)
 and      /work/SRC/openSUSE:Factory/.python-pipdeptree.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pipdeptree"

Tue Mar 17 19:04:31 2026 rev:12 rq:1339441 version:2.31.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pipdeptree/python-pipdeptree.changes      
2026-01-27 16:17:37.671278275 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-pipdeptree.new.8177/python-pipdeptree.changes
    2026-03-17 19:06:08.352753713 +0100
@@ -1,0 +2,7 @@
+Mon Mar 16 21:32:26 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 2.31.0:
+  * Bump packaging to 26
+  * Support --depth for graphviz output format
+
+-------------------------------------------------------------------

Old:
----
  pipdeptree-2.30.0.tar.gz

New:
----
  pipdeptree-2.31.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pipdeptree.spec ++++++
--- /var/tmp/diff_new_pack.KRCYj2/_old  2026-03-17 19:06:08.936777916 +0100
+++ /var/tmp/diff_new_pack.KRCYj2/_new  2026-03-17 19:06:08.940778082 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           python-pipdeptree
-Version:        2.30.0
+Version:        2.31.0
 Release:        0
 Summary:        Command line utility to show dependency tree of packages
 License:        MIT
@@ -28,13 +28,13 @@
 BuildRequires:  %{python_module hatchling}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
-Requires:       python-packaging >= 25
+Requires:       python-packaging >= 26
 Requires:       python-pip >= 25.2
 Suggests:       python-graphviz >= 0.21
 BuildArch:      noarch
 # SECTION test requirements
 BuildRequires:  %{python_module graphviz >= 0.21}
-BuildRequires:  %{python_module packaging >= 25}
+BuildRequires:  %{python_module packaging >= 26}
 BuildRequires:  %{python_module pip >= 25.2}
 BuildRequires:  %{python_module pytest-mock}
 BuildRequires:  %{python_module pytest}

++++++ pipdeptree-2.30.0.tar.gz -> pipdeptree-2.31.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pipdeptree-2.30.0/.github/workflows/check.yaml 
new/pipdeptree-2.31.0/.github/workflows/check.yaml
--- old/pipdeptree-2.30.0/.github/workflows/check.yaml  2025-11-12 
05:11:56.000000000 +0100
+++ new/pipdeptree-2.31.0/.github/workflows/check.yaml  2026-02-19 
06:25:53.000000000 +0100
@@ -31,7 +31,7 @@
     steps:
       - name: Install OS dependencies
         run: sudo apt-get install graphviz -y
-      - uses: actions/checkout@v5
+      - uses: actions/checkout@v6
         with:
           fetch-depth: 0
       - name: Install the latest version of uv
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pipdeptree-2.30.0/.github/workflows/release.yaml 
new/pipdeptree-2.31.0/.github/workflows/release.yaml
--- old/pipdeptree-2.30.0/.github/workflows/release.yaml        2025-11-12 
05:11:56.000000000 +0100
+++ new/pipdeptree-2.31.0/.github/workflows/release.yaml        2026-02-19 
06:25:53.000000000 +0100
@@ -10,7 +10,7 @@
   build:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v5
+      - uses: actions/checkout@v6
         with:
           fetch-depth: 0
       - name: Install the latest version of uv
@@ -22,7 +22,7 @@
       - name: Build package
         run: uv build --python 3.14 --python-preference only-managed --sdist 
--wheel . --out-dir dist
       - name: Store the distribution packages
-        uses: actions/upload-artifact@v5
+        uses: actions/upload-artifact@v6
         with:
           name: ${{ env.dists-artifact-name }}
           path: dist/*
@@ -38,7 +38,7 @@
       id-token: write
     steps:
       - name: Download all the dists
-        uses: actions/download-artifact@v6
+        uses: actions/download-artifact@v7
         with:
           name: ${{ env.dists-artifact-name }}
           path: dist/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pipdeptree-2.30.0/.pre-commit-config.yaml 
new/pipdeptree-2.31.0/.pre-commit-config.yaml
--- old/pipdeptree-2.30.0/.pre-commit-config.yaml       2025-11-12 
05:11:56.000000000 +0100
+++ new/pipdeptree-2.31.0/.pre-commit-config.yaml       2026-02-19 
06:25:53.000000000 +0100
@@ -5,7 +5,7 @@
       - id: end-of-file-fixer
       - id: trailing-whitespace
   - repo: https://github.com/python-jsonschema/check-jsonschema
-    rev: 0.34.1
+    rev: 0.36.2
     hooks:
       - id: check-github-workflows
         args: ["--verbose"]
@@ -15,21 +15,21 @@
       - id: codespell
         additional_dependencies: ["tomli>=2.3"]
   - repo: https://github.com/tox-dev/tox-toml-fmt
-    rev: "v1.2.0"
+    rev: "v1.6.0"
     hooks:
       - id: tox-toml-fmt
   - repo: https://github.com/tox-dev/pyproject-fmt
-    rev: "v2.11.1"
+    rev: "v2.16.0"
     hooks:
       - id: pyproject-fmt
   - repo: https://github.com/astral-sh/ruff-pre-commit
-    rev: "v0.14.4"
+    rev: "v0.15.1"
     hooks:
       - id: ruff-format
       - id: ruff-check
         args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"]
   - repo: https://github.com/rbubley/mirrors-prettier
-    rev: "v3.6.2"
+    rev: "v3.8.1"
     hooks:
       - id: prettier
         additional_dependencies:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pipdeptree-2.30.0/pyproject.toml 
new/pipdeptree-2.31.0/pyproject.toml
--- old/pipdeptree-2.30.0/pyproject.toml        2025-11-12 05:11:56.000000000 
+0100
+++ new/pipdeptree-2.31.0/pyproject.toml        2026-02-19 06:25:53.000000000 
+0100
@@ -22,6 +22,7 @@
 ]
 maintainers = [
   { name = "Bernát Gábor", email = "[email protected]" },
+  { name = "Kemal Zebari", email = "[email protected]" },
   { name = "Vineet Naik", email = "[email protected]" },
 ]
 requires-python = ">=3.10"
@@ -42,7 +43,7 @@
   "version",
 ]
 dependencies = [
-  "packaging>=25",
+  "packaging>=26",
   "pip>=25.2",
 ]
 optional-dependencies.graphviz = [
@@ -88,6 +89,7 @@
   "DOC501", # TODO: Remove this once ruff supports Sphinx-style doc-strings; 
see https://github.com/astral-sh/ruff/issues/12434
   "INP001", # no implicit namespace
   "ISC001", # Conflict with formatter
+  "RUF067", # `__init__` module should only contain docstrings and re-exports
   "S101",   # asserts allowed
   "S104",   # Possible binding to all interface
 ]
@@ -117,18 +119,18 @@
 max_supported_python = "3.14"
 
 [tool.coverage]
-html.show_contexts = true
-html.skip_covered = false
+run.parallel = true
+run.plugins = [
+  "covdefaults",
+]
 paths.source = [
   "src",
   ".tox/*/lib/python*/site-packages",
   "*/src",
 ]
-run.parallel = true
-run.plugins = [
-  "covdefaults",
-]
 report.fail_under = 88
+html.show_contexts = true
+html.skip_covered = false
 subtract_omit = "*/__main__.py"
 
 [tool.mypy]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pipdeptree-2.30.0/src/pipdeptree/_cli.py 
new/pipdeptree-2.31.0/src/pipdeptree/_cli.py
--- old/pipdeptree-2.30.0/src/pipdeptree/_cli.py        2025-11-12 
05:11:56.000000000 +0100
+++ new/pipdeptree-2.31.0/src/pipdeptree/_cli.py        2026-02-19 
06:25:53.000000000 +0100
@@ -121,7 +121,7 @@
         "--depth",
         type=lambda x: int(x) if x.isdigit() and (int(x) >= 0) else 
parser.error("Depth must be a number that is >= 0"),
         default=float("inf"),
-        help="limit the depth of the tree (text and freeze render only)",
+        help="limit the depth of the tree (text, freeze, and graphviz render 
only)",
         metavar="D",
     )
     render.add_argument(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pipdeptree-2.30.0/src/pipdeptree/_freeze.py 
new/pipdeptree-2.31.0/src/pipdeptree/_freeze.py
--- old/pipdeptree-2.30.0/src/pipdeptree/_freeze.py     2025-11-12 
05:11:56.000000000 +0100
+++ new/pipdeptree-2.31.0/src/pipdeptree/_freeze.py     2026-02-19 
06:25:53.000000000 +0100
@@ -5,9 +5,9 @@
 from pathlib import Path
 from typing import TYPE_CHECKING, Any
 
-from pip._internal.models.direct_url import (
-    DirectUrl,  # noqa: PLC2701
-    DirectUrlValidationError,  # noqa: PLC2701
+from pip._internal.models.direct_url import (  # noqa: PLC2701
+    DirectUrl,
+    DirectUrlValidationError,
 )
 from pip._internal.utils.egg_link import egg_link_path_from_sys_path  # noqa: 
PLC2701
 from pip._vendor.packaging.version import Version  # noqa: PLC2701
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pipdeptree-2.30.0/src/pipdeptree/_render/__init__.py 
new/pipdeptree-2.31.0/src/pipdeptree/_render/__init__.py
--- old/pipdeptree-2.30.0/src/pipdeptree/_render/__init__.py    2025-11-12 
05:11:56.000000000 +0100
+++ new/pipdeptree-2.31.0/src/pipdeptree/_render/__init__.py    2026-02-19 
06:25:53.000000000 +0100
@@ -25,7 +25,9 @@
     elif output_format == "freeze":
         render_freeze(tree, max_depth=options.depth, list_all=options.all)
     elif output_format.startswith("graphviz-"):
-        render_graphviz(tree, output_format=output_format[len("graphviz-") :], 
reverse=options.reverse)
+        render_graphviz(
+            tree, output_format=output_format[len("graphviz-") :], 
reverse=options.reverse, max_depth=options.depth
+        )
     else:
         render_text(
             tree,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pipdeptree-2.30.0/src/pipdeptree/_render/graphviz.py 
new/pipdeptree-2.31.0/src/pipdeptree/_render/graphviz.py
--- old/pipdeptree-2.30.0/src/pipdeptree/_render/graphviz.py    2025-11-12 
05:11:56.000000000 +0100
+++ new/pipdeptree-2.31.0/src/pipdeptree/_render/graphviz.py    2026-02-19 
06:25:53.000000000 +0100
@@ -1,19 +1,117 @@
 from __future__ import annotations
 
+import math
 import os
 import sys
+from collections import deque
 from typing import TYPE_CHECKING
 
 from pipdeptree._models import DistPackage, ReqPackage
 
 if TYPE_CHECKING:
+    from graphviz import Digraph
+
     from pipdeptree._models import PackageDAG
 
 
-def dump_graphviz(  # noqa: C901
+def _get_all_dep_keys(tree: PackageDAG) -> set[str]:
+    """Return the set of keys that appear as dependencies of some package."""
+    dep_keys: set[str] = set()
+    for deps in tree.values():
+        dep_keys.update(dep.key for dep in deps)
+    return dep_keys
+
+
+def _build_reverse_graph(tree: PackageDAG, graph: Digraph, max_depth: float) 
-> None:  # noqa: C901, PLR0912
+    """Build graphviz nodes and edges for a reversed dependency tree."""
+    if max_depth < math.inf:
+        parent_keys = _get_all_dep_keys(tree)
+        root_keys = {dep_rev.key for dep_rev in tree if dep_rev.key not in 
parent_keys}
+        visited: dict[str, int] = {}
+        queue: deque[tuple[str, int]] = deque((k, 0) for k in root_keys)
+        while queue:
+            key, depth = queue.popleft()
+            if key in visited:
+                continue
+            visited[key] = depth
+            if depth < max_depth:
+                for parent in tree.get_children(key):
+                    if parent.key not in visited:
+                        queue.append((parent.key, depth + 1))
+        for dep_rev, parents in tree.items():
+            if dep_rev.key not in visited:
+                continue
+            assert isinstance(dep_rev, ReqPackage)
+            dep_label = f"{dep_rev.project_name}\\n{dep_rev.installed_version}"
+            graph.node(dep_rev.key, label=dep_label)
+            if visited[dep_rev.key] < max_depth:
+                for parent in parents:
+                    assert isinstance(parent, DistPackage)
+                    if parent.key in visited:
+                        edge_label = (parent.req.version_spec if parent.req is 
not None else None) or "any"
+                        graph.edge(dep_rev.key, parent.key, label=edge_label)
+    else:
+        for dep_rev, parents in tree.items():
+            assert isinstance(dep_rev, ReqPackage)
+            dep_label = f"{dep_rev.project_name}\\n{dep_rev.installed_version}"
+            graph.node(dep_rev.key, label=dep_label)
+            for parent in parents:
+                assert isinstance(parent, DistPackage)
+                edge_label = (parent.req.version_spec if parent.req is not 
None else None) or "any"
+                graph.edge(dep_rev.key, parent.key, label=edge_label)
+
+
+def _build_forward_graph(tree: PackageDAG, graph: Digraph, max_depth: float) 
-> None:  # noqa: C901, PLR0912
+    """Build graphviz nodes and edges for a forward dependency tree."""
+    if max_depth < math.inf:  # noqa: PLR1702
+        dep_keys = _get_all_dep_keys(tree)
+        root_keys = {pkg.key for pkg in tree if pkg.key not in dep_keys}
+        visited: dict[str, int] = {}
+        queue: deque[tuple[str, int]] = deque((k, 0) for k in root_keys)
+        while queue:
+            key, depth = queue.popleft()
+            if key in visited:
+                continue
+            visited[key] = depth
+            if depth < max_depth:
+                children = tree.get_children(key)
+                for dep in children:
+                    if dep.key not in visited:
+                        queue.append((dep.key, depth + 1))
+        for pkg, deps in tree.items():
+            if pkg.key not in visited:
+                continue
+            pkg_label = f"{pkg.project_name}\\n{pkg.version}"
+            graph.node(pkg.key, label=pkg_label)
+            if visited[pkg.key] < max_depth:
+                for dep in deps:
+                    if dep.key in visited:
+                        edge_label = dep.version_spec or "any"
+                        if dep.is_missing:
+                            dep_label = f"{dep.project_name}\\n(missing)"
+                            graph.node(dep.key, label=dep_label, 
style="dashed")
+                            graph.edge(pkg.key, dep.key, style="dashed")
+                        else:
+                            graph.edge(pkg.key, dep.key, label=edge_label)
+    else:
+        for pkg, deps in tree.items():
+            pkg_label = f"{pkg.project_name}\\n{pkg.version}"
+            graph.node(pkg.key, label=pkg_label)
+            for dep in deps:
+                edge_label = dep.version_spec or "any"
+                if dep.is_missing:
+                    dep_label = f"{dep.project_name}\\n(missing)"
+                    graph.node(dep.key, label=dep_label, style="dashed")
+                    graph.edge(pkg.key, dep.key, style="dashed")
+                else:
+                    graph.edge(pkg.key, dep.key, label=edge_label)
+
+
+def dump_graphviz(
     tree: PackageDAG,
     output_format: str = "dot",
     is_reverse: bool = False,  # noqa: FBT001, FBT002
+    max_depth: float = math.inf,
 ) -> str | bytes:
     """
     Output dependency graph as one of the supported GraphViz output formats.
@@ -21,6 +119,7 @@
     :param dict tree: dependency graph
     :param string output_format: output format
     :param bool is_reverse: reverse or not
+    :param float max_depth: maximum depth of the dependency tree to include
     :returns: representation of tree in the specified output format
     :rtype: str or binary representation depending on the output format
     """
@@ -45,27 +144,9 @@
     graph = Digraph(format=output_format)
 
     if is_reverse:
-        for dep_rev, parents in tree.items():
-            assert isinstance(dep_rev, ReqPackage)
-            dep_label = f"{dep_rev.project_name}\\n{dep_rev.installed_version}"
-            graph.node(dep_rev.key, label=dep_label)
-            for parent in parents:
-                # req reference of the dep associated with this particular 
parent package
-                assert isinstance(parent, DistPackage)
-                edge_label = (parent.req.version_spec if parent.req is not 
None else None) or "any"
-                graph.edge(dep_rev.key, parent.key, label=edge_label)
+        _build_reverse_graph(tree, graph, max_depth)
     else:
-        for pkg, deps in tree.items():
-            pkg_label = f"{pkg.project_name}\\n{pkg.version}"
-            graph.node(pkg.key, label=pkg_label)
-            for dep in deps:
-                edge_label = dep.version_spec or "any"
-                if dep.is_missing:
-                    dep_label = f"{dep.project_name}\\n(missing)"
-                    graph.node(dep.key, label=dep_label, style="dashed")
-                    graph.edge(pkg.key, dep.key, style="dashed")
-                else:
-                    graph.edge(pkg.key, dep.key, label=edge_label)
+        _build_forward_graph(tree, graph, max_depth)
 
     # Allow output of dot format, even if GraphViz isn't installed.
     if output_format == "dot":
@@ -97,8 +178,8 @@
             bytestream.write(dump_output)
 
 
-def render_graphviz(tree: PackageDAG, *, output_format: str, reverse: bool) -> 
None:
-    output = dump_graphviz(tree, output_format=output_format, 
is_reverse=reverse)
+def render_graphviz(tree: PackageDAG, *, output_format: str, reverse: bool, 
max_depth: float = math.inf) -> None:
+    output = dump_graphviz(tree, output_format=output_format, 
is_reverse=reverse, max_depth=max_depth)
     print_graphviz(output)
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pipdeptree-2.30.0/tests/render/test_graphviz.py 
new/pipdeptree-2.31.0/tests/render/test_graphviz.py
--- old/pipdeptree-2.30.0/tests/render/test_graphviz.py 2025-11-12 
05:11:56.000000000 +0100
+++ new/pipdeptree-2.31.0/tests/render/test_graphviz.py 2026-02-19 
06:25:53.000000000 +0100
@@ -68,3 +68,61 @@
     assert out.startswith("<?xml")
     assert "<svg" in out
     assert out.strip().endswith("</svg>")
+
+
+def test_render_dot_with_depth(example_dag: PackageDAG) -> None:
+    output = dump_graphviz(example_dag, output_format="dot", max_depth=1)
+    assert isinstance(output, str)
+    # Roots are a and g (depth 0), their direct deps are at depth 1
+    # Deeper deps (d) should not appear
+    assert "a ->" in output
+    assert "g ->" in output
+    assert 'd [label="d' not in output  # d is only reachable at depth 2+
+    # Direct deps of roots should appear
+    assert 'b [label="b' in output
+    assert 'c [label="c' in output
+    assert 'e [label="e' in output
+    assert 'f [label="f' in output
+
+
+def test_render_dot_reverse_with_depth(example_dag: PackageDAG) -> None:
+    reversed_dag = example_dag.reverse()
+    output = dump_graphviz(reversed_dag, output_format="dot", is_reverse=True, 
max_depth=1)
+    assert isinstance(output, str)
+    # In reverse, root is e (only leaf in forward tree that's not a parent in 
reverse)
+    # At depth 0: e, at depth 1: c, d, g (e's parents)
+    assert 'e [label="e' in output
+    assert 'c [label="c' in output
+    assert 'd [label="d' in output
+    assert 'g [label="g' in output
+    # Deeper nodes should not appear
+    assert 'a [label="a' not in output
+    assert 'b [label="b' not in output
+    assert 'f [label="f' not in output
+    # Edges from e to its parents should exist
+    assert "e -> c" in output
+    assert "e -> d" in output
+    assert "e -> g" in output
+
+
+def test_render_dot_reverse_infinite_depth(example_dag: PackageDAG) -> None:
+    reversed_dag = example_dag.reverse()
+    output = dump_graphviz(reversed_dag, output_format="dot", is_reverse=True)
+    assert isinstance(output, str)
+    # All nodes should appear with no depth limit
+    for node in ("a", "b", "c", "d", "e", "f", "g"):
+        assert f'{node} [label="' in output
+    # Edges should include reverse relationships
+    assert "e -> c" in output
+    assert "e -> d" in output
+    assert "b -> a" in output
+    assert "f -> g" in output
+
+
+def test_render_dot_with_depth_zero(example_dag: PackageDAG) -> None:
+    output = dump_graphviz(example_dag, output_format="dot", max_depth=0)
+    assert isinstance(output, str)
+    # Depth 0 means only root nodes, no edges
+    assert "a [label=" in output
+    assert "g [label=" in output
+    assert "->" not in output
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pipdeptree-2.30.0/tests/render/test_render.py 
new/pipdeptree-2.31.0/tests/render/test_render.py
--- old/pipdeptree-2.30.0/tests/render/test_render.py   2025-11-12 
05:11:56.000000000 +0100
+++ new/pipdeptree-2.31.0/tests/render/test_render.py   2026-02-19 
06:25:53.000000000 +0100
@@ -37,7 +37,7 @@
 def test_grahpviz_routing(option: list[str], mocker: MockerFixture) -> None:
     render = mocker.patch("pipdeptree._render.render_graphviz")
     main(option)
-    render.assert_called_once_with(ANY, output_format="dot", reverse=False)
+    render.assert_called_once_with(ANY, output_format="dot", reverse=False, 
max_depth=inf)
 
 
 @pytest.mark.parametrize("option", [[], ["--output", "text"]])

Reply via email to