Skip to content

Marq/fix/python install paths - #393

Open
MarqRazz wants to merge 5 commits into
PickNikRobotics:mainfrom
MarqRazz:marq/fix/python-install-paths
Open

MarqRazz wants to merge 5 commits into
PickNikRobotics:mainfrom
MarqRazz:marq/fix/python-install-paths

Conversation

@MarqRazz

@MarqRazz MarqRazz commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Generate Python parameter modules from setuptools' build_py/develop commands instead of inferring paths from sys.argv. Alternative to #348 but also vibe coded.

setup(..., cmdclass=parameter_cmdclass('my_parameters', 'my_package/parameters.yaml'))
  • Regular builds generate into the build tree, so the module installs with the package wherever it goes (merge-install, overlays, custom --install-base) and the user's __init__.py is kept.
  • --symlink-install and editable pip install -e generate into the source package, which is the copy Python imports there.
  • Supports several modules via modules=[...]; generate_parameter_module() is unchanged.

Tested on Lyrical across regular, symlink, merge, overlay, and --install-base builds plus pip install -e. The example now has a non-empty __init__.py, so the --symlink-install break in #348 shows up as a test failure. Windows and the buildfarm are untested.

Fixes #192, #255, #257. The README documents a test conftest.py workaround for #233.

@MarqRazz MarqRazz mentioned this pull request Oct 7, 2026

@christophfroehlich christophfroehlich left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't care how the fix looks like as long as it works ;)

It seems that this one has problems on distros older than lyrical. Is there a reason for that, can we fix it? I applied the same strategy we have in ros-controls to make the rolling version usable on all active distros.. and only want to drop that if really necessary

you guys have a suggestion how we could test all the possible colcon settings for the install paths with github actions? tokens welcome!

Without this, pytest walks generate_parameter_module_example/ as a
package on pytest<8 and reinserts the source root ahead of the
installed copy on sys.path, shadowing the generated module.
@MarqRazz

MarqRazz commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

The older-distro failures weren't in parameter_cmdclass; the generated module builds and installs correctly on Humble, Jazzy and Kilted. With no testpaths set, pytest < 8 also collects generate_parameter_module_example/ as a package, which puts the source tree back ahead of the installed copy on sys.path, so the tests imported the source package without the generated module. Scoping collection to test/ fixes it on all distros. Humble's setuptools (59.6) has no PEP 660 editable support, so that one test is skipped there. Verified locally in the Humble/Jazzy/Kilted/Lyrical docker images; Windows is untested.

@christophfroehlich christophfroehlich left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI seems to be happy, how can we test the build options from this repo?
At least "no option" (normal workflows) and the "buildfarm settings" are tested (pre-release job)

@christophfroehlich christophfroehlich added the check-prerelease Runs the pre-release workflow without downstream dependencies label Oct 9, 2026
Covers humble/rolling, regular and symlink-install builds, to catch
pytest-collection and setuptools-editable regressions like bd3ebf1.
@MarqRazz

MarqRazz commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

Added a small Python Install Paths workflow for this. It builds and tests only generate_parameter_library_py and example_python (sparse checkout, --packages-up-to), so each job finishes in about a minute and only runs when those paths change. The matrix is Humble × Rolling (oldest and newest setuptools/pip/pytest, which is what actually varies across distros), crossed with a regular build and --symlink-install, the two code paths the helper has. --merge-install, --install-base and overlays only change where setuptools copies the build output, which the helper no longer computes, so they aren't in the matrix. When Humble goes EOL the matrix becomes [jazzy, rolling].

@christophfroehlich christophfroehlich left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it desired behavior or just not possible otherwise as that the generated python module is generated in the source folder with --symlink-install?
I see that it isn't symlinked into the install folder actually, which is wrong?

@MarqRazz

MarqRazz commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor Author

It's not avoidable for setup.py packages. With --symlink-install, colcon doesn't install a Python package's files at all; it puts the source package on PYTHONPATH (via a symlink in build/). Python only looks for submodules in that one directory, so the generated module has to go there. pip install -e works the same way.

C++ is different because ament_cmake installs each file, so it can symlink the generated header from the build dir. Python packages built with ament_cmake get the same behavior through the existing CMake generate_parameter_module() (see example_cmake_python).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

check-prerelease Runs the pre-release workflow without downstream dependencies

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error when building with different package structure

2 participants