Repository: conan-io/conan

Issue:
[bug] python_require test_package failure
### Describe the bug

The documented solution to test python_requires doesn't seem to work anymore. I could have sworn I tried this a long time ago, but I can't find an earlier version of Conan that's working either.


### How to reproduce it

Create the files as described under "Testing python-requires":
[https://docs.conan.io/2/reference/extensions/python_requires.html](url)

conanfile.py
```
from conan import ConanFile

def mynumber():
    return 42

class PyReq(ConanFile):
    name = "pyreq"
    version = "1.0"
    package_type = "python-require"
```

test_package/conanfile.py
```
from conan import ConanFile

class Tool(ConanFile):

    # Literal "tested_reference_str", Conan will dynamically replace it
    python_requires = "tested_reference_str"

    def test(self):
        pyreq = self.python_requires["pyreq"].module
        mynumber = pyreq.mynumber()
        self.output.info("{}!!!".format(mynumber))
```

```
% conan create .          

======== Exporting recipe to the cache ========
pyreq/1.0: Exporting package recipe: /Users/gmeeker/pyreq/conanfile.py
pyreq/1.0: Copied 1 '.py' file: conanfile.py
pyreq/1.0: Exported to cache folder: /Users/gmeeker/.conan2/p/pyreq97d601f99a9e5/e
pyreq/1.0: Exported: pyreq/1.0#9e00258c26ecf124355588c57a5aaa4a (2025-05-02 19:59:26 UTC)

======== Input profiles ========
Profile host:
[settings]
arch=armv8
build_type=Release
compiler=apple-clang
compiler.cppstd=17
compiler.libcxx=libc++
compiler.version=15
os=Macos
os.version=11.0

Profile build:
[settings]
arch=armv8
build_type=Release
compiler=apple-clang
compiler.cppstd=17
compiler.libcxx=libc++
compiler.version=15
os=Macos
os.version=11.0


======== Computing dependency graph ========
WARN: deprecated: test_package/conanfile.py should declare 'python_requires = "tested_reference_str"'

======== Launching test_package ========

======== Computing dependency graph ========
Graph root
    pyreq/1.0 (test package): /Users/gmeeker/pyreq/test_package/conanfile.py
Build requirements
    cmake/3.31.6#ed0e6c1d49bd564ce6fed1a19653b86d - Cache
Python requires
    pyreq/1.0#9e00258c26ecf124355588c57a5aaa4a - Cache
Resolved version ranges
    cmake/[>=3 <4]: cmake/3.31.6

======== Computing necessary packages ========
ERROR: Traceback (most recent call last):
  File "/Users/gmeeker/pyreq/venv/lib/python3.13/site-packages/conan/cli/cli.py", line 308, in main
    cli.run(args)
    ~~~~~~~^^^^^^
  File "/Users/gmeeker/pyreq/venv/lib/python3.13/site-packages/conan/cli/cli.py", line 193, in run
    command.run(self._conan_api, args[0][1:])
    ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/gmeeker/pyreq/venv/lib/python3.13/site-packages/conan/cli/command.py", line 179, in run
    info = self._method(conan_api, parser, *args)
  File "/Users/gmeeker/pyreq/venv/lib/python3.13/site-packages/conan/cli/commands/create.py", line 123, in create
    run_test(conan_api, test_conanfile_path, ref, profile_host, profile_build, remotes, lockfile,
    ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
             update=None, build_modes=args.build, build_modes_test=args.build_test,
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
             tested_python_requires=tested_python_requires, tested_graph=deps_graph)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/gmeeker/pyreq/venv/lib/python3.13/site-packages/conan/cli/commands/test.py", line 75, in run_test
    conan_api.graph.analyze_binaries(deps_graph, build_modes, remotes=remotes, update=update,
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                     lockfile=lockfile, build_modes_test=build_modes_test,
                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                     tested_graph=tested_graph)
                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/gmeeker/pyreq/venv/lib/python3.13/site-packages/conan/api/subapi/graph.py", line 203, in analyze_binaries
    binaries_analyzer.evaluate_graph(graph, build_mode, lockfile, remotes, update,
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                     build_modes_test, tested_graph)
                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/gmeeker/pyreq/venv/lib/python3.13/site-packages/conans/client/graph/graph_binaries.py", line 420, in evaluate_graph
    mainprefs = [str(n.pref) for n in tested_graph.nodes
                     ^^^^^^
  File "/Users/gmeeker/pyreq/venv/lib/python3.13/site-packages/conans/client/graph/graph.py", line 231, in pref
    assert self.ref is not None and self.package_id is not None, "Node %s" % self.recipe
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: Node Cache

ERROR: Node Cache
```


Discussion:
Hi @gmeeker 

Thanks for your feedback.

I have just tested your above files, and it seems to be working fine.
What version of Conan are you running?

Maybe your installation of Conan has become corrupt, or something, it might be worth trying a fresh re-install to see if it is fixed.
2.16.1

It turns out the problem is caused by having using a profile with [tool_requires] as recommended here:
https://github.com/conan-io/conan-center-index/issues/26878

Here's a profile causing the issue:
```
[settings]
arch=armv8
build_type=Release
compiler=apple-clang
compiler.cppstd=gnu17
compiler.libcxx=libc++
compiler.version=17
os=Macos
[tool_requires]
!cmake/*: cmake/[>=3 <4]
```

I can workaround that now, and eventually the cmake 4 work be complete, but it still seems like a bug.
Thanks for the information.
That was the detail that I was missing, the profile ``tool-require``.
I have been managed to reproduce, and I am proposing a fix for it in https://github.com/conan-io/conan/pull/18226, for next Conan 2.17 release. In the meantime, you are right, the workaround is to avoid that tool-require.



Patch:
diff --git a/conan/api/subapi/graph.py b/conan/api/subapi/graph.py
index b5f7d4da66d..041b3a2c3df 100644
--- a/conan/api/subapi/graph.py
+++ b/conan/api/subapi/graph.py
@@ -2,7 +2,7 @@
 from conan.internal.conan_app import ConanApp, ConanBasicApp
 from conan.internal.model.recipe_ref import ref_matches
 from conan.internal.graph.graph import Node, RECIPE_CONSUMER, CONTEXT_HOST, RECIPE_VIRTUAL, \
-    CONTEXT_BUILD, BINARY_MISSING
+    CONTEXT_BUILD, BINARY_MISSING, DepsGraph
 from conan.internal.graph.graph_binaries import GraphBinariesAnalyzer
 from conan.internal.graph.graph_builder import DepsGraphBuilder
 from conan.internal.graph.install_graph import InstallGraph, ProfileArgs
@@ -129,6 +129,12 @@ def load_graph_requires(self, requires, tool_requires, profile_host, profile_bui
                                                       update=update,
                                                       python_requires=python_requires)
 
+        if not requires and not tool_requires and python_requires is not None:
+            # This only happens at `conan create` for python-requires, the graph is not needed
+            # in fact, it can cause errors, if tool-requires injected
+            dep_graph = DepsGraph()
+            dep_graph.add_node(root_node)
+            return dep_graph
         # check_updates = args.check_updates if "check_updates" in args else False
         deps_graph = self.load_graph(root_node, profile_host=profile_host,
                                      profile_build=profile_build,
diff --git a/conan/internal/loader.py b/conan/internal/loader.py
index 05351e4d9ca..2390ef8562d 100644
--- a/conan/internal/loader.py
+++ b/conan/internal/loader.py
@@ -12,6 +12,7 @@
 
 from pathlib import Path
 
+from conan.api.output import ConanOutput
 from conan.tools.cmake import cmake_layout
 from conan.tools.google import bazel_layout
 from conan.tools.microsoft import vs_layout
@@ -60,6 +61,9 @@ def load_basic_module(self, conanfile_path, graph_lock=None, display="", remotes
                 if getattr(conanfile, "python_requires", None) == "tested_reference_str":
                     conanfile.python_requires = tested_python_requires.repr_notime()
             elif tested_python_requires:
+                if getattr(conanfile, "python_requires", None) != "tested_reference_str":
+                    ConanOutput().warning("test_package/conanfile.py should declare 'python_requires"
+                                      " = \"tested_reference_str\"'", warn_tag="deprecated")
                 conanfile.python_requires = tested_python_requires
 
             if self._pyreq_loader:


Test patch:
diff --git a/conan/cli/commands/test.py b/conan/cli/commands/test.py
index 1e057a4a1b8..b030a8eb645 100644
--- a/conan/cli/commands/test.py
+++ b/conan/cli/commands/test.py
@@ -55,12 +55,6 @@ def run_test(conan_api, path, ref, profile_host, profile_build, remotes, lockfil
                                                          update=update,
                                                          lockfile=lockfile,
                                                          tested_python_requires=tested_python_requires)
-    if isinstance(tested_python_requires, str):  # create python-require
-        conanfile = root_node.conanfile
-        if not getattr(conanfile, "python_requires", None) == "tested_reference_str":
-            ConanOutput().warning("test_package/conanfile.py should declare 'python_requires"
-                                  " = \"tested_reference_str\"'", warn_tag="deprecated")
-
     out = ConanOutput()
     out.title("Launching test_package")
     deps_graph = conan_api.graph.load_graph(root_node, profile_host=profile_host,
diff --git a/test/integration/py_requires/python_requires_test.py b/test/integration/py_requires/python_requires_test.py
index 232f389fbb2..dbe85119f02 100644
--- a/test/integration/py_requires/python_requires_test.py
+++ b/test/integration/py_requires/python_requires_test.py
@@ -1077,6 +1077,8 @@ def test_test_package_python_requires(self):
         """
 
         c = TestClient(light=True)
+        c.save({"conanfile.py": GenConanfile("mytool", "0.1")})
+        c.run("create .")
         conanfile = textwrap.dedent("""
             from conan import ConanFile
             def mycommon():
@@ -1097,9 +1099,16 @@ def test(self):
         c.save({"conanfile.py": conanfile,
                 "test_package/conanfile.py": test})
         c.run("create .")
+        assert "WARN: deprecated: test_package/conanfile.py" not in c.out
         assert "common/0.1 (test package): 42!!!" in c.out
 
         c.run("test test_package common/0.1")
+        assert "WARN: deprecated: test_package/conanfile.py" not in c.out
+        assert "common/0.1 (test package): 42!!!" in c.out
+
+        # https://github.com/conan-io/conan/issues/18224
+        c.save({"myprofile": "[tool_requires]\nmytool/0.1"})
+        c.run("create . -pr=myprofile")
         assert "common/0.1 (test package): 42!!!" in c.out
 
     def test_test_package_python_requires_configs(self):