Repository: conan-io/conan
Pull request #17957 (2025-03-13 10:36:05)

add warning-risk for deprecated packages
Changelog: Fix: Add warning for ``deprecated`` attribute in recipes
Docs: TODO

Close https://github.com/conan-io/conan/issues/17952



Patch:
diff --git a/conan/cli/printers/graph.py b/conan/cli/printers/graph.py
index 2c4f3493c..e0bd79e16 100644
--- a/conan/cli/printers/graph.py
+++ b/conan/cli/printers/graph.py
@@ -18,7 +18,7 @@ def print_graph_basic(graph):
     deprecated = {}
     for node in graph.nodes:
         if hasattr(node.conanfile, "python_requires"):
-            for r in node.conanfile.python_requires._pyrequires.values():  # TODO: improve interface
+            for _, r in node.conanfile.python_requires.items():
                 python_requires[r.ref] = r.recipe, r.remote
         if node.recipe in (RECIPE_CONSUMER, RECIPE_VIRTUAL):
             continue
@@ -40,10 +40,10 @@ def print_graph_basic(graph):
         if not reqs_to_print:
             return
         output.info(title, Color.BRIGHT_YELLOW)
-        for ref, (recipe, remote) in sorted(reqs_to_print.items()):
+        for ref_, (recipe, remote) in sorted(reqs_to_print.items()):
             if remote is not None:
                 recipe = "{} ({})".format(recipe, remote.name)
-            output.info("    {} - {}".format(ref.repr_notime(), recipe), Color.BRIGHT_CYAN)
+            output.info("    {} - {}".format(ref_.repr_notime(), recipe), Color.BRIGHT_CYAN)
 
     _format_requires("Requirements", requires)
     _format_requires("Test requirements", test_requires)
@@ -54,8 +54,8 @@ def print_graph_basic(graph):
         if not reqs_to_print:
             return
         output.info(title, Color.BRIGHT_YELLOW)
-        for k, v in sorted(reqs_to_print.items()):
-            output.info("    {}: {}".format(k, v), Color.BRIGHT_CYAN)
+        for k_, v_ in sorted(reqs_to_print.items()):
+            output.info("    {}: {}".format(k_, v_), Color.BRIGHT_CYAN)
 
     if graph.replaced_requires:
         output.info("Replaced requires", Color.BRIGHT_YELLOW)
@@ -70,7 +70,8 @@ def print_graph_basic(graph):
     _format_resolved("Resolved version ranges", graph.resolved_ranges)
     for req in graph.resolved_ranges:
         if str(req.version) == "[]":
-            output.warning("Empty version range usage is discouraged. Use [*] instead", warn_tag="deprecated")
+            output.warning("Empty version range usage is discouraged. Use [*] instead",
+                           warn_tag="deprecated")
             break
 
     overrides = graph.overrides()
@@ -97,6 +98,9 @@ def print_graph_basic(graph):
                     Color.BRIGHT_CYAN)
         output.warning("There are options conflicts in the dependency graph", warn_tag="risk")
 
+    if deprecated:
+        output.warning("There are deprecated packages in the graph", warn_tag="risk")
+
 
 def print_graph_packages(graph):
     # I am excluding the "download"-"cache" or remote information, that is not
diff --git a/conans/client/graph/python_requires.py b/conans/client/graph/python_requires.py
index a2c1b9506..275ac8451 100644
--- a/conans/client/graph/python_requires.py
+++ b/conans/client/graph/python_requires.py
@@ -20,7 +20,7 @@ class PyRequire(object):
                 "path": self.path}
 
 
-class PyRequires(object):
+class PyRequires:
     """ this is the object that replaces the declared conanfile.py_requires"""
     def __init__(self):
         self._pyrequires = {}  # {pkg-name: PythonRequire}


Test patch:
diff --git a/test/integration/conanfile/test_deprecated.py b/test/integration/conanfile/test_deprecated.py
index fb42e7907..128cc5362 100644
--- a/test/integration/conanfile/test_deprecated.py
+++ b/test/integration/conanfile/test_deprecated.py
@@ -17,6 +17,7 @@ class TestDeprecated:
         t.run("create taskflow.py")
 
         assert "Deprecated\n    cpp-taskflow/1.0" in t.out
+        assert "WARN: risk: There are deprecated packages in the graph" in t.out
 
         t.run("create taskflow.py --user=conan --channel=stable")
         assert "Deprecated\n    cpp-taskflow/1.0" in t.out