Skip to content

Commit 22c5a00

Browse files
authored
[art:build-info] Add python requires as recipe dependencies in create command (#253)
* add python requires * fix * complete test * fix requestedBy * revert requestedBy fix and simplify test * fix test
1 parent 38f6293 commit 22c5a00

3 files changed

Lines changed: 78 additions & 8 deletions

File tree

extensions/commands/art/cmd_build_info.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,17 @@ def get_artifacts_folder(self, node, artifact_type):
173173
reference = RecipeReference.loads(node.get("ref"))
174174
return self._conan_api.cache.export_path(reference)
175175

176-
def get_artifacts(self, node, artifact_type, is_dependency=False):
176+
177+
def get_artifacts(self, node, artifact_type, is_dependency=False, requested_by=None):
177178
"""
178179
Function to get artifact information, those artifacts can be added as artifacts of a
179180
module or as artifacts from dependencies and depending on that the format is
180181
different. For artifacts of modules they have the keys 'name' and 'path'. If they come
181182
from a dependency they have an 'id' instead of 'name' and they don't have 'path'.
183+
184+
When is_dependency is True, requested_by may be set to a BuildInfo-style list of lists
185+
of recipe refs (e.g. for python_requires, which are not graph nodes). Otherwise it is
186+
computed from the dependency graph.
182187
"""
183188

184189
origin_repo = self._get_origin_repo(node)
@@ -304,9 +309,9 @@ def _get_remote_artifacts(artifact):
304309
# complete the information for the artifacts:
305310

306311
if is_dependency:
307-
requested_by = _get_requested_by(self._graph["graph"]["nodes"], node.get("id"), artifact_type)
312+
req_by = requested_by or _get_requested_by(self._graph["graph"]["nodes"], node.get("id"), artifact_type)
308313
for artifact in artifacts:
309-
artifact.update({"requestedBy": requested_by})
314+
artifact.update({"requestedBy": req_by})
310315

311316
return artifacts
312317

@@ -320,7 +325,8 @@ def get_modules(self):
320325
for node in nodes.values():
321326
ref = node.get("ref")
322327
if ref:
323-
transitive_dependencies = node.get("dependencies").keys() if node.get("dependencies").keys() else []
328+
transitive_dependencies = node.get("dependencies").keys() if node.get("dependencies") else []
329+
python_requires = node.get("python_requires").keys() if node.get("python_requires") else []
324330
binary = node.get("binary")
325331

326332
if ref and ((binary == "Build") or (binary in ["Cache", "Download", "Update"] and self._add_cached_deps)):
@@ -338,9 +344,13 @@ def get_modules(self):
338344
deps_artifacts = self.get_artifacts(nodes.get(require_id), "recipe",
339345
is_dependency=True)
340346
all_dependencies.extend(deps_artifacts)
341-
347+
for pr_ref in python_requires:
348+
owner_recipe_ref = str(node["ref"])
349+
pr_node = {"ref": pr_ref}
350+
pr_artifacts = self.get_artifacts(pr_node, "recipe", is_dependency=True,
351+
requested_by=[[owner_recipe_ref]])
352+
all_dependencies.extend(pr_artifacts)
342353
module.update({"dependencies": all_dependencies})
343-
344354
ret.append(module)
345355

346356
# package module

tests/test_build_info.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ def _fake_conan_sources(graph):
3838
if recipe_folder:
3939
fake_sources_tgz_path = os.path.join(os.path.dirname(node.get("recipe_folder")), "d", "conan_sources.tgz")
4040
save(fake_sources_tgz_path, "")
41+
if node.get("python_requires"):
42+
for _, pyreq_info in node.get("python_requires").items():
43+
fake_pyreq_tgz_path = os.path.join(os.path.dirname(pyreq_info.get("path")), "d", "conan_sources.tgz")
44+
save(fake_pyreq_tgz_path, "")
4145

4246

4347
def test_static_library_skip_binaries():
@@ -161,6 +165,62 @@ def package_info(self):
161165
assert len(build_info["modules"][3]["dependencies"]) == 2
162166

163167

168+
def test_python_requires_in_build_info_dependencies():
169+
pyreq_cf = textwrap.dedent("""
170+
from conan import ConanFile
171+
172+
class PyreqConan(ConanFile):
173+
name = "pyreq"
174+
version = "1.0"
175+
package_type = "python-require"
176+
""")
177+
save("conanfile.py", pyreq_cf)
178+
run("conan create .")
179+
180+
app_cf = textwrap.dedent("""
181+
from conan import ConanFile
182+
183+
class AppConan(ConanFile):
184+
name = "app"
185+
version = "1.0"
186+
package_type = "application"
187+
python_requires = "pyreq/1.0"
188+
""")
189+
save("conanfile.py", app_cf)
190+
run("conan create . -f json > create.json")
191+
192+
graph = json.loads(load("create.json"))["graph"]
193+
_fake_conan_sources(graph)
194+
195+
run("conan art:build-info create create.json build_name 1 repo --with-dependencies > bi.json")
196+
build_info = json.loads(load("bi.json"))
197+
198+
modules = build_info["modules"]
199+
app_recipe_module = [m for m in modules if m["id"] == "app/1.0#697c25af89f95d7c16b88d97972fb7ad"][0]
200+
app_pkg_module = [m for m in modules if
201+
"app/1.0#697c25af89f95d7c16b88d97972fb7ad:19f85b5f0cf7b39158b8bce1a58bcb78449fee9d" in m["id"]][0]
202+
203+
app_recipe_module_deps = [d["id"] for d in app_recipe_module.get("dependencies")]
204+
assert "pyreq/1.0#7ff25468818796e3c188019d6db1ff93 :: conan_sources.tgz" in app_recipe_module_deps
205+
assert "pyreq/1.0#7ff25468818796e3c188019d6db1ff93 :: conanfile.py" in app_recipe_module_deps
206+
assert "pyreq/1.0#7ff25468818796e3c188019d6db1ff93 :: conanmanifest.txt" in app_recipe_module_deps
207+
# assert python require is not a dependency of the package
208+
assert len(app_pkg_module.get("dependencies")) == 0
209+
210+
# Test no python_requires found if --with-dependencies is not used
211+
run("conan art:build-info create create.json build_name 1 repo > bi_nodeps.json")
212+
build_info = json.loads(load("bi_nodeps.json"))
213+
214+
modules = build_info["modules"]
215+
app_recipe_module = [m for m in modules if m["id"] == "app/1.0#697c25af89f95d7c16b88d97972fb7ad"][0]
216+
app_pkg_module = [m for m in modules if
217+
"app/1.0#697c25af89f95d7c16b88d97972fb7ad:19f85b5f0cf7b39158b8bce1a58bcb78449fee9d" in m["id"]][0]
218+
219+
assert "dependencies" not in app_recipe_module
220+
assert "dependencies" not in app_pkg_module
221+
222+
223+
164224
def test_formatted_time():
165225
"""Compare local timestamp hours from build-info JSON with current timestamp in UTC"""
166226
run("conan new cmake_lib -d name=lib1 -d version=1.0")

tests/tools.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ def run(cmd, error=False, *, stdout=subprocess.PIPE, stderr=subprocess.PIPE):
2424

2525

2626
def save(f, content):
27-
with open(f, "w") as f:
27+
with open(f, "w", encoding="utf-8", newline="\n") as f:
2828
f.write(content)
2929

3030

3131
def load(f):
32-
with open(f, "r") as f:
32+
with open(f, "r", encoding="utf-8") as f:
3333
return f.read()

0 commit comments

Comments
 (0)