Skip to content

Commit 883552d

Browse files
authored
fix: handle absolute package xml path in ros backend (#451)
1 parent dabf360 commit 883552d

File tree

4 files changed

+136
-4
lines changed

4 files changed

+136
-4
lines changed

backends/pixi-build-ros/src/pixi_build_ros/ros_generator.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,17 @@ def generate_recipe(
4545
channels: list[str] | None = None,
4646
) -> GeneratedRecipe:
4747
"""Generate a recipe for a Python package."""
48-
manifest_root = Path(manifest_path)
48+
manifest_path_obj = Path(manifest_path)
49+
# nichmor: I'm confused here what we should expect
50+
# an absolute path to package.xml or a directory containing it
51+
# so I'm handling both cases
52+
if manifest_path_obj.is_file():
53+
if manifest_path_obj.name != "package.xml":
54+
raise ValueError("Manifest filename must be package.xml for ROS packages.")
55+
manifest_root = manifest_path_obj.parent
56+
else:
57+
manifest_root = manifest_path_obj
58+
4959
backend_config: ROSBackendConfig = ROSBackendConfig.model_validate(
5060
config,
5161
context={
@@ -75,7 +85,7 @@ def generate_recipe(
7585
generated_recipe = GeneratedRecipe.from_model(model, metadata_provider)
7686

7787
# Read package.xml for dependency extraction
78-
package_xml_str = get_package_xml_content(manifest_root)
88+
package_xml_str = get_package_xml_content(package_xml_path)
7989
ros_env_defaults = {
8090
"ROS_DISTRO": backend_config.distro.name,
8191
"ROS_VERSION": "1" if backend_config.distro.check_ros1() else "2",

backends/pixi-build-ros/src/pixi_build_ros/utils.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,8 @@ def get_build_input_globs(config: dict[str, Any], editable: bool) -> list[str]:
5555
return all_globs
5656

5757

58-
def get_package_xml_content(manifest_root: Path) -> str:
58+
def get_package_xml_content(package_xml_path: Path) -> str:
5959
"""Read package.xml file from the manifest root."""
60-
package_xml_path = manifest_root / "package.xml"
6160
if not package_xml_path.exists():
6261
raise FileNotFoundError(f"package.xml not found at {package_xml_path}")
6362

backends/pixi-build-ros/tests/__snapshots__/test_version_constraints.ambr

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,81 @@
11
# serializer version: 1
2+
# name: test_generate_recipe_with_explicit_package_xml_path
3+
'''
4+
context: {}
5+
package:
6+
name: ros-noetic-custom-ros
7+
version: 0.0.1
8+
source: []
9+
build:
10+
number: null
11+
script:
12+
content: ''
13+
env: {}
14+
secrets: []
15+
requirements:
16+
build:
17+
- ros-noetic-catkin
18+
- libgl-devel
19+
- libopengl-devel
20+
- xorg-libx11
21+
- xorg-libxext
22+
- ros-noetic-ros-package <=2.0.0
23+
- ros-noetic-ros-package-msgs <=2.0.0
24+
- ros-noetic-ros-package2 <2.0.0a0
25+
- qt-main >=5.15.0,<5.16.0
26+
- tinyxml2 ==10.0.0
27+
- asio <10.0.0
28+
- ninja
29+
- python
30+
- setuptools
31+
- git
32+
- git-lfs
33+
- cmake
34+
- cpython
35+
- patch
36+
- make
37+
- coreutils
38+
- ${{ compiler('c') }}
39+
- ${{ compiler('cxx') }}
40+
host:
41+
- ros-noetic-catkin
42+
- libgl-devel
43+
- libopengl-devel
44+
- xorg-libx11
45+
- xorg-libxext
46+
- ros-noetic-ros-package <=2.0.0
47+
- ros-noetic-ros-package-msgs <=2.0.0
48+
- ros-noetic-ros-package2 <2.0.0a0
49+
- qt-main >=5.15.0,<5.16.0
50+
- tinyxml2 ==10.0.0
51+
- asio <10.0.0
52+
- python
53+
- numpy
54+
- pip
55+
- pkg-config
56+
- ros-distro-mutex
57+
run:
58+
- ros-noetic-ros-package <=2.0.0
59+
- ros-noetic-ros-package-msgs <=2.0.0
60+
- ros-noetic-ros-package2 <2.0.0a0
61+
- qt-main >=5.15.0,<5.16.0
62+
- tinyxml2 ==10.0.0
63+
- asio <10.0.0
64+
- ros-distro-mutex
65+
run_constraints: []
66+
tests: []
67+
about:
68+
homepage: null
69+
license: LicenseRef-Apache License 2.0
70+
license_file: null
71+
summary: Demo
72+
description: Demo
73+
documentation: null
74+
repository: null
75+
extra: null
76+
77+
'''
78+
# ---
279
# name: test_generate_recipe_with_mutex_version
380
'''
481
context: {}

backends/pixi-build-ros/tests/test_version_constraints.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,49 @@ def test_generate_recipe_with_versions_in_model_and_package(
158158
# remove the build script as it container a tmp variable
159159
generated_recipe.recipe.build.script = Script("")
160160
assert generated_recipe.recipe.to_yaml() == snapshot
161+
162+
163+
def test_generate_recipe_with_explicit_package_xml_path(
164+
package_xmls: Path, test_data_dir: Path, distro_noetic: Distro, snapshot
165+
):
166+
"""Test the generate_recipe function of ROSGenerator with versions."""
167+
# Create a temporary directory to simulate the package directory
168+
with tempfile.TemporaryDirectory() as temp_dir:
169+
temp_path = Path(temp_dir)
170+
171+
# Copy the test package.xml to the temp directory
172+
package_xml_source = package_xmls / "version_constraints.xml"
173+
package_xml_dest = temp_path / "package.xml"
174+
package_xml_dest.write_text(package_xml_source.read_text(encoding="utf-8"))
175+
176+
# Create a minimal ProjectModelV1 instance
177+
model = ProjectModelV1()
178+
179+
# Create config for ROS backend
180+
config = {
181+
"distro": distro_noetic,
182+
"noarch": False,
183+
"extra-package-mappings": [str(test_data_dir / "other_package_map.yaml")],
184+
}
185+
186+
# Create host platform
187+
host_platform = Platform("linux-64")
188+
189+
# Create ROSGenerator instance
190+
generator = ROSGenerator()
191+
192+
# Generate the recipe
193+
generated_recipe = generator.generate_recipe(
194+
model=model,
195+
config=config,
196+
# in other tests we always pass a directory,
197+
# here we pass the explicit package.xml path
198+
# to handle the situation that we do not multiply package.xml filename
199+
manifest_path=str(package_xml_dest),
200+
host_platform=host_platform,
201+
)
202+
203+
# Verify the generated recipe has the expected requirements
204+
# remove the build script as it container a tmp variable
205+
generated_recipe.recipe.build.script = Script("")
206+
assert generated_recipe.recipe.to_yaml() == snapshot

0 commit comments

Comments
 (0)