├── .gitignore ├── Jenkinsfile ├── README.md ├── catkin_virtualenv ├── CHANGELOG.rst ├── CMakeLists.txt ├── cmake │ ├── catkin_generate_virtualenv.cmake │ ├── catkin_install_python.cmake │ ├── catkin_virtualenv-extras.cmake.em │ └── templates │ │ ├── program.devel.in │ │ └── program.install.in ├── package.xml ├── requirements.in ├── requirements.txt ├── scripts │ ├── collect_requirements │ ├── venv_check │ ├── venv_init │ ├── venv_install │ ├── venv_lock │ └── venv_relocate ├── setup.py └── src │ └── catkin_virtualenv │ ├── __init__.py │ ├── collect_requirements.py │ ├── relocate.py │ └── venv.py ├── pyproject.toml ├── setup.cfg ├── test_catkin_virtualenv ├── CHANGELOG.rst ├── CMakeLists.txt ├── package.xml ├── requirements.in ├── requirements.txt └── test │ ├── test_virtualenv_library.py │ ├── test_virtualenv_script │ └── virtualenv_script.test └── test_catkin_virtualenv_inherited ├── CHANGELOG.rst ├── CMakeLists.txt ├── package.xml ├── requirements.in ├── requirements.txt └── test ├── test_virtualenv_script └── virtualenv_script.test /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | @Library('tailor-meta@0.1.27')_ 3 | tailorTestPipeline( 4 | // Name of job that generated this test definition. 5 | rosdistro_job: '/ci/rosdistro/master', 6 | // Distribution name 7 | rosdistro_name: 'ros1', 8 | // Release track to test branch against. 9 | release_track: 'hotdog', 10 | // Release label to pull test images from. 11 | release_label: 'hotdog', 12 | // OS distributions to test. 13 | distributions: ['jammy'], 14 | // Version of tailor_meta to build against 15 | tailor_meta: '0.1.27', 16 | // Master or release branch associated with this track 17 | source_branch: 'master', 18 | // Docker registry where test image is stored 19 | docker_registry: 'https://084758475884.dkr.ecr.us-east-1.amazonaws.com/locus-tailor' 20 | ) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # catkin_virtualenv 2 | 3 | [![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) 4 | 5 | This package provides a mechanism to: 6 | 7 | - export python `pip` requirements via `package.xml`. 8 | - bundle a virtualenv within a catkin package, inheriting requirements from any dependencies. 9 | - wrap python scripts and tests in a catkin package with a virtualenv loader. 10 | - change which interpreter is used for executing scripts and tests (i.e. python2, python3, pypy, etc.) 11 | 12 | At build time, CMake macros provided by this package will create a virtualenv inside the devel space, and create 13 | wrapper scripts for any Python scripts in the package. Both will be included in any associated bloom artifacts. 14 | 15 | This library is GPL licensed due to the inclusion of dh_virtualenv. 16 | 17 | Compatibility: 18 | - Python 3.7+ 19 | - Ubuntu 20.04+, maybe others 20 | - ROS Noetic, maybe others 21 | - `catkin-tools`, `colcon`, `catkin_make_isolated` (i.e. ros_buildfarm), but not `catkin_make` 22 | 23 | For general help, please check the [FAQ](http://answers.ros.org/questions/tags:catkin_virtualenv). Report bugs on the [issue tracker](https://github.com/locusrobotics/catkin_virtualenv/issues). 24 | 25 | ## Exporting python requirements 26 | 27 | A package containing python modules with external `pip` dependencies should define a `requirements.txt`: 28 | 29 | ```python 30 | GitPython==2.1 31 | psutil==5.2.2 32 | ``` 33 | 34 | Add an export to `package.xml`: 35 | 36 | ```xml 37 | 38 | requirements.txt 39 | 40 | ``` 41 | 42 | Make sure to install the requirements file in `CMakeLists.txt`: 43 | 44 | ```cmake 45 | install(FILES requirements.txt 46 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) 47 | ``` 48 | 49 | If a catkin package exports dependencies in a `requirements.txt` file, any dependent catkin package that bundles a virtualenv (see below) will inherit those dependencies. 50 | 51 | 52 | 53 | ## Bundling virtualenv 54 | 55 | It's possible to bundle all of a catkin package's python requirements, as well as those of its catkin dependencies, 56 | into a virtualenv. This process will also override the standard `catkin_install_python` macro to wrap a virtualenv 57 | loader around the specified python scripts. 58 | 59 | Add an build dependency on catkin_virtualenv to `package.xml`, as well as on any library packages you may want. Traditionally 60 | 61 | ```xml 62 | catkin_virtualenv 63 | 64 | 66 | some_python_library 67 | ``` 68 | 69 | In CMakeLists.txt: 70 | 71 | ```cmake 72 | # Make sure to find-package `catkin_virtualenv` 73 | find_package(catkin REQUIRED ... catkin_virtualenv ...) 74 | 75 | # Generate the virtualenv 76 | catkin_generate_virtualenv() 77 | 78 | # Make sure your python executables are installed using `catkin_install_python`: 79 | catkin_install_python( 80 | PROGRAMS 81 | scripts/do_python_things 82 | DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) 83 | ``` 84 | 85 | Departing from convention, `scripts/do_python_things` should not be executable, and `catkin build` will warn to that effect. 86 | This package works by hijacking `catkin_install_python` to generate new wrapper scripts into the devel and install space, 87 | which bootstrap the `virtualenv`. In addition, `rosrun` gets confused if there's two executable files with the same name. 88 | 89 | Unit and integration tests will automatically pick up the `virtualenv` as well. The only change is to add a dependency 90 | from the test target to the virtualenv target: 91 | 92 | ```cmake 93 | if(CATKIN_ENABLE_TESTING) 94 | 95 | # nosetests 96 | catkin_add_nosetests(test 97 | DEPENDENCIES ${PROJECT_NAME}_generate_virtualenv 98 | ) 99 | 100 | # rostests 101 | catkin_install_python( 102 | PROGRAMS 103 | test/test_script 104 | DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) 105 | 106 | add_rostest(test/run_test_script.test 107 | DEPENDENCIES ${PROJECT_NAME}_generate_virtualenv 108 | ) 109 | ) 110 | ``` 111 | 112 | ### Additional CMake Options 113 | 114 | The following options are supported by `catkin_generate_virtualenv()`: 115 | 116 | ```cmake 117 | catkin_generate_virtualenv( 118 | # Specify the input requirements for this package that catkin_virtualenv will automatically lock. 119 | INPUT_REQUIREMENTS requirements.in 120 | 121 | # Select an alternative python interpreter - it must be installed on the system. 122 | PYTHON_INTERPRETER python3.7 # Default python3 123 | 124 | # Choose not to use underlying system packages. This excludes any python packages installed by apt or system-pip from the environment. 125 | USE_SYSTEM_PACKAGES FALSE # Default TRUE 126 | 127 | # Disable including pip requirements from catkin dependencies of this package. 128 | ISOLATE_REQUIREMENTS TRUE # Default FALSE 129 | # Note: due to https://github.com/nose-devs/nose/issues/1099 and nose being unmaintained, using this option will prevent catkin_add_nosetests from working. 130 | # Hence CATKIN_IGNORE in the test_catkin_virtualenv_isolated package. `nose-py3` seems to be a decent stopgap if used to replace `nose` in `catkin_virtualenv/requirements.txt` 131 | # but https://github.com/atsb/nose-py3/issues/9 is currently a show-stopper. 132 | 133 | # Disable creating a unit test to verify that package requirements are locked. 134 | CHECK_VENV FALSE # Default TRUE 135 | 136 | # Disable renaming the process names to hide the interpreter name, this has can create issues when executing the process as root. 137 | RENAME_PROCESS FALSE # Default TRUE 138 | 139 | # Provide extra arguments to the underlying pip invocation 140 | EXTRA_PIP_ARGS 141 | --no-binary=:all: 142 | -vvv 143 | ) 144 | ``` 145 | 146 | ### Locking dependencies 147 | 148 | This project allows you to lock dependencies by leveraging `pip-compile`. This is optional, but will prevent your 149 | python projects from spontaneously combusting in the future! 150 | 151 | Instead of managing a `requirements.txt` file, you will manage a `requirements.in` file, and catkin_virtualenv will generate the `requirements.txt` file for you upon build. 152 | 153 | Create a `requirements.in` file and populate it manually with your package's requirements. For example: 154 | 155 | ```python 156 | GitPython>=2 157 | psutil 158 | ``` 159 | 160 | The file specified in CMake options as `INPUT_REQUIREMENTS` will be used to generate a locked `requirements.txt` 161 | at build time. You should check both `requirements.in` and `requirements.txt` in with your sources! 162 | 163 | To regenerate the `requirements.txt` file, either delete it and rebuild the project, or run this command from your project directory: 164 | 165 | `catkin build --this --no-deps --catkin-make-args _venv_lock` where `` is the name for the project as specified in the package's CMakeLists.txt. 166 | 167 | Alternatively, you can specify the package name `catkin build --no-deps --catkin-make-args _venv_lock` 168 | 169 | To migrate a package from catkin_virtualenv <=0.5 to use lock files: 170 | 171 | - Rename `requirements.txt` to `requirements.in` 172 | - Relax the version requirements in `requirements.in` as much as sensibly possible. eg. requests>=2 vs. requests=2.23.0 173 | - Add `INPUT_REQUIREMENTS requirements.in` to catkin_generate_virtualenv() in CMakeLists.txt 174 | - Build and test that the package given the installed dependency versions might have changed slightly 175 | - Commit the new `requirements.in`, your updated `CMakeLists.txt` and the new version of `requirements.txt` and push changes 176 | 177 | See example: https://github.com/locusrobotics/aiorospy/pull/30/commits/839b17adbe0c672f5e0d9cca702d12e16b117bca 178 | -------------------------------------------------------------------------------- /catkin_virtualenv/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package catkin_virtualenv 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | 0.8.0 (2022-02-23) 6 | ------------------ 7 | * Switch default interpreter to python3 (#77) 8 | * Switch default interpreter to python3 9 | * Remove python2 10 | * Add back vitualenv, needed for python2 11 | * Tailor: Updating Jenkinsfile 12 | Co-authored-by: Gary Servin 13 | Co-authored-by: locus-services <33065330+locus-services@users.noreply.github.com> 14 | * Bump dependencies (#76) 15 | * Bump dependencies 16 | * Drop kinetic 17 | * Contributors: Paul Bovbel 18 | 19 | 0.9.0 (2023-02-22) 20 | ------------------ 21 | * 0.8.0 22 | * Update changelogs 23 | * Use upstream to configure logging (#94) 24 | * Allow disabling process rename when it creates issues (#93) 25 | * Check ensurepip to install pip via get-pip.py (#90) 26 | * Check ensurepip to install pip via get-pip.py 27 | * Add ImportError to pass lint 28 | * Fix catkin_virtualenv for python2 (#92) 29 | * Add python2 test package 30 | * Fix dependencies for python2 31 | * Skip python2 for noetic upstream 32 | * Rename process to program name (#50) 33 | * Rename process to node name 34 | * Rethink approach 35 | * Mirror how native processes are named 36 | * Bump dependencies 37 | * Try heredoc bash to python interp 38 | * Run catkin_run_tests_target only when CATKIN_ENABLE_TESTING is enabled (#89) 39 | * use PROJECT_SOURCE_DIR for requirements in venv_lock (#88) 40 | * Make CMake work in non-isolated builds. (#87) 41 | * Make CMake work in non-isolated builds. 42 | Specifically when `catkin_virtualenv` was used in multiple packages. 43 | * Updated docs. 44 | Removed split between isolated and non-isolated `venv_lock` targets. 45 | * fix rospkg to 1.3.0 (#85) 46 | * Improved _venv_bin to find binaries in local (#81) 47 | Co-authored-by: Jorge López Fueyo 48 | * Switch default interpreter to python3 (#77) 49 | * Switch default interpreter to python3 50 | * Remove python2 51 | * Add back vitualenv, needed for python2 52 | * Tailor: Updating Jenkinsfile 53 | Co-authored-by: Gary Servin 54 | Co-authored-by: locus-services <33065330+locus-services@users.noreply.github.com> 55 | * Bump dependencies (#76) 56 | * Bump dependencies 57 | * Drop kinetic 58 | * Contributors: Alec Tiefenthal, Gary Servin, Iori Yanokura, Jorge López Fueyo, Paul Bovbel, Shingo Kitagawa, Yuki Furuta 59 | 60 | 0.10.0 (2023-09-25) 61 | ------------------- 62 | * Fixing formatting with black 63 | * Add --no-cache-dir 64 | * Moving option 65 | * Testing with no-cache-dir during install 66 | * Updating pip version to 22.2.2 as a potential fix for https://github.com/pypa/pip/issues/11340 67 | * formatting with black 68 | * typos 69 | * Fixing typo 70 | * Adding verbose logging to attempt to catch pypi issue 71 | * Testing with pip cache purge prior to install pip packages 72 | * ignore order in requirements consistency check (#102) 73 | * Drop python2 and add Jammy support (#101) 74 | * Updating pip and pip-tools 75 | * Trying older version of pip and pip-tools 76 | * Using slightly newer version of pip and piptools 77 | * Ensuring we are using python3 78 | * fix typo 79 | * Updating catkin-pkg for Jammy support 80 | * Remove test_virtualenv_python2 81 | * Update requirements to fix build error 82 | * Remove python3 direct reference from venv 83 | * Update pip and pip-tools for 3.7+ compatibility 84 | * Don't enumerate python versions 85 | * Add compatibility notes 86 | * Remove melodic test and python2 references 87 | * Fix build error more 88 | * Get rid of requests as a package for testing 89 | * get_pip isn't versioned 3.6 onwards 90 | * Fixup double pip-tools 91 | * Revert "Get rid of requests as a package for testing" 92 | This reverts commit 55e5b5889d1080303c52fb4e6671d5061498ac57. 93 | * Try fix action 94 | * Disable isolated tests 95 | * Revert changes to match the dependencies 96 | --------- 97 | Co-authored-by: Kalpesh Lad 98 | Co-authored-by: Gary Servin 99 | * Import setup from setuptools instead of distutils.core (#100) 100 | * updated package.xml to format version 3 101 | * change to setuptools in accordance with migration guide 102 | * 0.9.0 103 | * Update changelogs 104 | * Add rosgraph dependency (#98) 105 | * 0.8.0 106 | * Update changelogs 107 | * Revert "Update changelogs" 108 | This reverts commit 33618e7dec29a058931e5e7190456b4418140c78. 109 | * Update changelogs 110 | * Use upstream to configure logging (#94) 111 | * Allow disabling process rename when it creates issues (#93) 112 | * Check ensurepip to install pip via get-pip.py (#90) 113 | * Check ensurepip to install pip via get-pip.py 114 | * Add ImportError to pass lint 115 | * Fix catkin_virtualenv for python2 (#92) 116 | * Add python2 test package 117 | * Fix dependencies for python2 118 | * Skip python2 for noetic upstream 119 | * Rename process to program name (#50) 120 | * Rename process to node name 121 | * Rethink approach 122 | * Mirror how native processes are named 123 | * Bump dependencies 124 | * Try heredoc bash to python interp 125 | * Run catkin_run_tests_target only when CATKIN_ENABLE_TESTING is enabled (#89) 126 | * use PROJECT_SOURCE_DIR for requirements in venv_lock (#88) 127 | * Make CMake work in non-isolated builds. (#87) 128 | * Make CMake work in non-isolated builds. 129 | Specifically when `catkin_virtualenv` was used in multiple packages. 130 | * Updated docs. 131 | Removed split between isolated and non-isolated `venv_lock` targets. 132 | * fix rospkg to 1.3.0 (#85) 133 | * Improved _venv_bin to find binaries in local (#81) 134 | Co-authored-by: Jorge López Fueyo 135 | * Switch default interpreter to python3 (#77) 136 | * Switch default interpreter to python3 137 | * Remove python2 138 | * Add back vitualenv, needed for python2 139 | * Tailor: Updating Jenkinsfile 140 | Co-authored-by: Gary Servin 141 | Co-authored-by: locus-services <33065330+locus-services@users.noreply.github.com> 142 | * Bump dependencies (#76) 143 | * Bump dependencies 144 | * Drop kinetic 145 | * Contributors: Alec Tiefenthal, Arne Hitzmann, Gary Servin, Iori Yanokura, Jorge López Fueyo, Kalpesh Lad, Paul Bovbel, Shingo Kitagawa, Yuki Furuta 146 | 147 | 0.15.1 (2025-05-29) 148 | ------------------- 149 | 150 | 0.15.0 (2025-05-29) 151 | ------------------- 152 | * Find pip-compile in global path if it does not exist in venv (`#114 `_) 153 | * Use program basename instead of full path (`#117 `_) 154 | * [ROS-O] Update dependencies version to support testing on Ubuntu noble / ROS-O (`#115 `_) 155 | * Contributors: Paul Bovbel, Yuki Furuta 156 | 157 | 0.14.0 (2025-02-04) 158 | ------------------- 159 | 160 | 0.13.0 (2024-09-16) 161 | ------------------- 162 | 163 | 0.12.0 (2024-06-17) 164 | ------------------- 165 | 166 | 0.11.0 (2024-02-02) 167 | ------------------- 168 | * 0.10.0 169 | * Update changelogs 170 | * Testing with pip cache purge prior to install pip packages (#103) 171 | * Testing with pip cache purge prior to install pip packages 172 | * Tailor: Updating Jenkinsfile 173 | * Adding verbose logging to attempt to catch pypi issue 174 | * Fixing typo 175 | * typos 176 | * formatting with black 177 | * Updating pip version to 22.2.2 as a potential fix for https://github.com/pypa/pip/issues/11340 178 | * Testing with no-cache-dir during install 179 | * Moving option 180 | * Add --no-cache-dir 181 | * Fixing formatting with black 182 | * Tailor: Updating Jenkinsfile 183 | * Tailor: Updating Jenkinsfile 184 | * Tailor: Updating Jenkinsfile 185 | --------- 186 | Co-authored-by: locus-services <33065330+locus-services@users.noreply.github.com> 187 | Co-authored-by: Gary Servin 188 | * ignore order in requirements consistency check (#102) 189 | * Drop python2 and add Jammy support (#101) 190 | * Updating pip and pip-tools 191 | * Trying older version of pip and pip-tools 192 | * Using slightly newer version of pip and piptools 193 | * Ensuring we are using python3 194 | * fix typo 195 | * Updating catkin-pkg for Jammy support 196 | * Remove test_virtualenv_python2 197 | * Update requirements to fix build error 198 | * Remove python3 direct reference from venv 199 | * Update pip and pip-tools for 3.7+ compatibility 200 | * Don't enumerate python versions 201 | * Add compatibility notes 202 | * Remove melodic test and python2 references 203 | * Fix build error more 204 | * Get rid of requests as a package for testing 205 | * get_pip isn't versioned 3.6 onwards 206 | * Fixup double pip-tools 207 | * Revert "Get rid of requests as a package for testing" 208 | This reverts commit 55e5b5889d1080303c52fb4e6671d5061498ac57. 209 | * Try fix action 210 | * Disable isolated tests 211 | * Revert changes to match the dependencies 212 | --------- 213 | Co-authored-by: Kalpesh Lad 214 | Co-authored-by: Gary Servin 215 | * Import setup from setuptools instead of distutils.core (#100) 216 | * updated package.xml to format version 3 217 | * change to setuptools in accordance with migration guide 218 | * 0.9.0 219 | * Update changelogs 220 | * Add rosgraph dependency (#98) 221 | * 0.8.0 222 | * Update changelogs 223 | * Revert "Update changelogs" 224 | This reverts commit 33618e7dec29a058931e5e7190456b4418140c78. 225 | * Update changelogs 226 | * Use upstream to configure logging (#94) 227 | * Allow disabling process rename when it creates issues (#93) 228 | * Check ensurepip to install pip via get-pip.py (#90) 229 | * Check ensurepip to install pip via get-pip.py 230 | * Add ImportError to pass lint 231 | * Fix catkin_virtualenv for python2 (#92) 232 | * Add python2 test package 233 | * Fix dependencies for python2 234 | * Skip python2 for noetic upstream 235 | * Rename process to program name (#50) 236 | * Rename process to node name 237 | * Rethink approach 238 | * Mirror how native processes are named 239 | * Bump dependencies 240 | * Try heredoc bash to python interp 241 | * Run catkin_run_tests_target only when CATKIN_ENABLE_TESTING is enabled (#89) 242 | * use PROJECT_SOURCE_DIR for requirements in venv_lock (#88) 243 | * Make CMake work in non-isolated builds. (#87) 244 | * Make CMake work in non-isolated builds. 245 | Specifically when `catkin_virtualenv` was used in multiple packages. 246 | * Updated docs. 247 | Removed split between isolated and non-isolated `venv_lock` targets. 248 | * fix rospkg to 1.3.0 (#85) 249 | * Improved _venv_bin to find binaries in local (#81) 250 | Co-authored-by: Jorge López Fueyo 251 | * Switch default interpreter to python3 (#77) 252 | * Switch default interpreter to python3 253 | * Remove python2 254 | * Add back vitualenv, needed for python2 255 | * Tailor: Updating Jenkinsfile 256 | Co-authored-by: Gary Servin 257 | Co-authored-by: locus-services <33065330+locus-services@users.noreply.github.com> 258 | * Bump dependencies (#76) 259 | * Bump dependencies 260 | * Drop kinetic 261 | * Contributors: Alec Tiefenthal, Arne Hitzmann, Gary Servin, Iori Yanokura, Jorge López Fueyo, Kalpesh Lad, Paul Bovbel, Shingo Kitagawa, Yuki Furuta 262 | 263 | 0.7.0 (2020-10-02) 264 | ------------------ 265 | 266 | 0.6.1 (2020-08-24) 267 | ------------------ 268 | * Correct dependencies and autoformat (`#72 `_) 269 | * Remove python-virtualenv dep 270 | * Add python2-dev 271 | * Lint 272 | * We're ok with any 44.x version of setuptools (`#71 `_) 273 | But not anything newer. 274 | Older versions don't appear to work reliably with `pip==20.1`. 275 | This helps when running a build of a package depending on catkin_virtualenv on OS which ship with an old version of setuptools (such as Ubuntu Xenial) when `USE_SYSTEM_PACKAGES` is not set to `FALSE`. In that situation, only specifying 'setuptools<45` will be true, as setuptools is installed (in the systems site packages), so pip will not upgrade it. Specifying a minimum version like this will force pip to always install an up-to-date version. 276 | * Contributors: G.A. vd. Hoorn, Paul Bovbel 277 | 278 | 0.6.0 (2020-07-14) 279 | ------------------ 280 | * Don't require catkin_package to be called before catkin_generate_virtualenv (`#67 `_) 281 | * Revert "Downgrade docutils so that boto works (`#66 `_)" 282 | This reverts commit 998cd6add2e43e12036d0db15a7c4d58fe3411cf. 283 | * Downgrade docutils so that boto works (`#66 `_) 284 | See https://github.com/boto/botocore/issues/1942 and related threads. 285 | * Make regex for Python bytecode more selective (`#65 `_) 286 | Fix regex to match only files ending in ".py[co]" and not files ending 287 | in "py[co]". 288 | * Remove user specific paths (`#63 `_) 289 | * Remove user specific paths 290 | * Change working directory of venv_lock command 291 | * Lock catkin_virtualenv base requirements 292 | Co-authored-by: Paul Bovbel 293 | * RST-3172 Check that requirements file is locked (`#62 `_) 294 | * Two helpful hints (`#61 `_) 295 | * Fix input requirements warning (`#58 `_) 296 | * Only warn about INPUT_REQUIREMENTS if a package exports requirements to begin with 297 | * Update catkin_virtualenv/cmake/catkin_generate_virtualenv.cmake 298 | Co-authored-by: Andrew Blakey 299 | Co-authored-by: Andrew Blakey 300 | * Preserve symlinks during copy (`#57 `_) 301 | * Don't ignore unknown args 302 | * RST-3172 Refactor catkin_virtualenv to allow locking dependencies (`#55 `_) 303 | * Remove unused options 304 | * Fix regex for comments 305 | * Migrate scripts 306 | * Remove old code 307 | * Move common requirements to an export file 308 | * Minor cleanup 309 | * Remove requirement-parsing unit tests 310 | * Fix logging config 311 | * Fix test builds 312 | * Generate lock files 313 | * Fix tests 314 | * Move dh-virtualenv functions into separate file 315 | * Fix roslint 316 | * Update docs 317 | * Update requirements 318 | * CMake comments 319 | * Fix pip-args 320 | * README fixup 321 | * Correct ARG_LOCK_FILE handling 322 | * Remove headers 323 | * Use set comprehension 324 | * Add migration doc 325 | * Respin 326 | * Use exec to dive into python (`#51 `_) 327 | * First python2 issue of 2020 (`#49 `_) 328 | * Clean up options, virtualenv installs setuptools by default 329 | * Make sure we install a compatible setuptools version for py2 venv 330 | * catkin-pkg-modules has disappeared off pypi (`#46 `_) 331 | * catkin-pkg-modules has disappeared off pypi, but catkin-pkg is still there 332 | * Version all requirements 333 | * Contributors: David V. Lu!!, Michael Johnson, Paul Bovbel, abencz 334 | 335 | 0.5.0 (2019-06-21) 336 | ------------------ 337 | * Don't inherit requirements from exec_depends (`#45 `_) 338 | * Contributors: Paul Bovbel 339 | 340 | 0.4.1 (2019-06-11) 341 | ------------------ 342 | * VCS support (`#40 `_) 343 | * Contributors: Paul Bovbel 344 | 345 | 0.4.0 (2019-03-18) 346 | ------------------ 347 | * Pin pip to known-working version (`#38 `_) 348 | * Fix python3 isolated builds (`#37 `_) 349 | - Pull in an upstream fix to deal with new shebang styles 350 | - add a new test for isolated py3 virtualenvs 351 | - switch to using an internal pip module 352 | * venv module doesn't support no-site-packages arg 353 | * Pass arguments to internal venv module if specified (`#36 `_) 354 | * Add missing dependency 355 | * Contributors: Paul Bovbel 356 | 357 | 0.3.0 (2019-01-16) 358 | ------------------ 359 | * Add retry to virtualenv creation (`#34 `_) 360 | * Echo check_call to stderr 361 | * Fixup bug from `#33 `_ 362 | * Add retry to virtualenv generation 363 | * Add debug line for virtualenv 364 | * Don't error on cleanup 365 | * Fixup debug line 366 | * Remove debug lines 367 | * Python3 re-enable, add PYTHON_VERSION support (`#33 `_) 368 | * replace PYTHON_VERSION_MAJOR with PYTHON_VERSION 369 | * Simplify nose usage for python3 370 | * Check for venv module directly rather than munging major version 371 | * Remove trailing whitespace 372 | * Add missing dependencies 373 | * Contributors: Paul Bovbel 374 | 375 | 0.2.2 (2018-12-04) 376 | ------------------ 377 | * Merge repeated requirements (`#32 `_) 378 | * Enable extra_pip_args `#31 `_ from locusrobotics/add-extra-pip-args 379 | * Contributors: Brian Barnes, Paul Bovbel, Shingo Kitagawa 380 | 381 | 0.2.1 (2018-06-04) 382 | ------------------ 383 | * Fix case and '.' handling 384 | * Bump pip to 10.0.1 385 | * Contributors: Paul Bovbel 386 | 387 | 0.2.0 (2018-05-03) 388 | ------------------ 389 | * Fixup python 3 dependencies 390 | * Merge pull request `#16 `_ from locusrobotics/system-site-packages 391 | Provide more CMake flags to customize behaviour 392 | * Make sure we find python exectuable 393 | * Implement ISOLATE_REQUIREMENTS and add docs 394 | * Make flags more flexible to support disabling system site packages 395 | * Merge pull request `#14 `_ from locusrobotics/fix-pip 396 | Fix issues due to pip 10 release 397 | * Review comments 398 | * Lock down pip version 399 | * Make logging optional 400 | * Contributors: Paul Bovbel 401 | 402 | 0.1.6 (2018-01-10) 403 | ------------------ 404 | * Re-enable pip upgrade 405 | * Contributors: Paul Bovbel 406 | 407 | 0.1.5 (2018-01-10) 408 | ------------------ 409 | * Disable pip upgrade 410 | * Drop strict requirements 411 | * Update package.xml 412 | * Contributors: Paul Bovbel 413 | 414 | 0.1.4 (2017-12-03) 415 | ------------------ 416 | * Fixup CMake and local directory cleanup 417 | * Merge pull request `#9 `_ from locusrobotics/python3-compat 418 | Python 3 compatiblity tweaks 419 | * Add base requirements file for python3 catkin; include extra data about requirement merge failure 420 | * Fix cmake lint errors 421 | * Add XML schema, README badges, fix travis config for debian jessie, and remove legacy scripts 422 | * Contributors: Paul Bovbel 423 | 424 | 0.1.3 (2017-11-27) 425 | ------------------ 426 | * Simplify install path 427 | * Clean up vars 428 | * Instantiate both a devel- and install-space venv 429 | * Contributors: Paul Bovbel 430 | 431 | 0.1.2 (2017-11-23) 432 | ------------------ 433 | * Drop rosbash dependency and move python scripts into cmake directory 434 | * More tweaks to get nosetests working in python3 435 | * Contributors: Paul Bovbel 436 | 437 | 0.1.1 (2017-11-22) 438 | ------------------ 439 | * Fixup module path 440 | * Contributors: Paul Bovbel 441 | 442 | 0.1.0 (2017-11-22) 443 | ------------------ 444 | * Fix trusty support 445 | * Contributors: Paul Bovbel 446 | 447 | 0.0.1 (2017-11-22) 448 | ------------------ 449 | * Add license 450 | * Overhaul virtualenv generation and add Python 3 support (`#1 `_) 451 | * Rewrite build_venv in python 452 | * Use dh_virtualenv to do the heavy lifting; embed new version of dh_virtualenv internally 453 | * Update CMake to generate virtualenv appropriately for install and devel space 454 | * Initial implementation 455 | * Contributors: Paul Bovbel 456 | -------------------------------------------------------------------------------- /catkin_virtualenv/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5.1) 2 | project(catkin_virtualenv) 3 | 4 | find_package(catkin REQUIRED) 5 | 6 | catkin_package(CFG_EXTRAS ${PROJECT_NAME}-extras.cmake) 7 | 8 | catkin_python_setup() 9 | 10 | install(DIRECTORY cmake 11 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} 12 | PATTERN ${PROJECT_NAME}-extras.cmake* EXCLUDE 13 | ) 14 | 15 | set(python_scripts 16 | scripts/collect_requirements 17 | scripts/venv_init 18 | scripts/venv_check 19 | scripts/venv_lock 20 | scripts/venv_install 21 | scripts/venv_relocate 22 | ) 23 | 24 | catkin_install_python(PROGRAMS ${python_scripts} 25 | DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) 26 | 27 | install(FILES requirements.txt 28 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) 29 | 30 | if(CATKIN_ENABLE_TESTING) 31 | find_package(roslint REQUIRED) 32 | roslint_python() 33 | roslint_python(${python_scripts}) 34 | roslint_add_test() 35 | endif() 36 | -------------------------------------------------------------------------------- /catkin_virtualenv/cmake/catkin_generate_virtualenv.cmake: -------------------------------------------------------------------------------- 1 | # Software License Agreement (GPL) 2 | # 3 | # \file catkin_generate_virtualenv.cmake 4 | # \authors Paul Bovbel 5 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 6 | # 7 | # This program is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License as 9 | # published by the Free Software Foundation, either version 2 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, but 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | function(catkin_generate_virtualenv) 20 | set(oneValueArgs PYTHON_VERSION PYTHON_INTERPRETER USE_SYSTEM_PACKAGES ISOLATE_REQUIREMENTS INPUT_REQUIREMENTS CHECK_VENV) 21 | set(multiValueArgs EXTRA_PIP_ARGS) 22 | cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) 23 | 24 | ### Handle argument defaults and deprecations 25 | 26 | if(DEFINED ARG_PYTHON_VERSION) 27 | message(WARNING "PYTHON_VERSION has been deprecated, set 'PYTHON_INTERPRETER python${ARG_PYTHON_VERSION}' instead") 28 | set(ARG_PYTHON_INTERPRETER "python${ARG_PYTHON_VERSION}") 29 | endif() 30 | 31 | if(NOT DEFINED ARG_PYTHON_INTERPRETER) 32 | set(ARG_PYTHON_INTERPRETER "python3") 33 | endif() 34 | 35 | if(NOT DEFINED ARG_USE_SYSTEM_PACKAGES OR ARG_USE_SYSTEM_PACKAGES) 36 | message(STATUS "Using system site packages") 37 | set(venv_args "--use-system-packages") 38 | endif() 39 | 40 | if(ARG_ISOLATE_REQUIREMENTS) 41 | message(STATUS "Only using requirements from this catkin package") 42 | set(lock_args "${lock_args} --no-deps") 43 | endif() 44 | 45 | if (NOT DEFINED ARG_EXTRA_PIP_ARGS) 46 | set(ARG_EXTRA_PIP_ARGS "-qq" "--retries 10" "--timeout 30") 47 | endif() 48 | 49 | # Convert CMake list to ' '-separated list 50 | string(REPLACE ";" "\ " processed_pip_args "${ARG_EXTRA_PIP_ARGS}") 51 | # Double-escape needed to get quote down through cmake->make->shell layering 52 | set(processed_pip_args \\\"${processed_pip_args}\\\") 53 | 54 | # Check if this package already has a virtualenv target before creating one 55 | if(TARGET ${PROJECT_NAME}_generate_virtualenv) 56 | message(WARNING "catkin_generate_virtualenv was called twice") 57 | return() 58 | endif() 59 | 60 | # Make sure CATKIN_* paths are initialized 61 | catkin_destinations() # oh the places we'll go 62 | 63 | ### Start building virtualenv 64 | set(venv_dir venv) 65 | 66 | set(venv_devel_dir ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_SHARE_DESTINATION}/${venv_dir}) 67 | set(venv_install_dir ${CMAKE_INSTALL_PREFIX}/${CATKIN_PACKAGE_SHARE_DESTINATION}/${venv_dir}) 68 | 69 | set(${PROJECT_NAME}_VENV_DEVEL_DIR ${venv_devel_dir} PARENT_SCOPE) 70 | set(${PROJECT_NAME}_VENV_INSTALL_DIR ${venv_install_dir} PARENT_SCOPE) 71 | 72 | # Store just _this_ project's requirements file in ${package_requirements} 73 | execute_process( 74 | COMMAND ${CATKIN_ENV} rosrun catkin_virtualenv collect_requirements --no-deps 75 | --package-name ${PROJECT_NAME} ${lock_args} 76 | OUTPUT_VARIABLE package_requirements 77 | OUTPUT_STRIP_TRAILING_WHITESPACE 78 | ) 79 | 80 | # Collect all of this project's inherited requirements into ${requirements_list} 81 | execute_process( 82 | COMMAND ${CATKIN_ENV} rosrun catkin_virtualenv collect_requirements 83 | --package-name ${PROJECT_NAME} ${lock_args} 84 | OUTPUT_VARIABLE requirements_list 85 | OUTPUT_STRIP_TRAILING_WHITESPACE 86 | ) 87 | 88 | # Trigger rebuild if any of the requirements files change 89 | foreach(requirements_file ${requirements_list}) 90 | if(EXISTS ${requirements_file}) 91 | stamp(${requirements_file}) 92 | endif() 93 | endforeach() 94 | 95 | add_custom_command(COMMENT "Generate virtualenv in ${CMAKE_BINARY_DIR}/${venv_dir}" 96 | OUTPUT ${CMAKE_BINARY_DIR}/${venv_dir}/bin/python 97 | COMMAND ${CATKIN_ENV} rosrun catkin_virtualenv venv_init ${venv_dir} 98 | --python ${ARG_PYTHON_INTERPRETER} ${venv_args} --extra-pip-args ${processed_pip_args} 99 | ) 100 | 101 | if(DEFINED ARG_INPUT_REQUIREMENTS AND NOT package_requirements STREQUAL "") 102 | add_custom_command(COMMENT "Lock input requirements if they don't exist" 103 | OUTPUT ${package_requirements} 104 | COMMAND ${CATKIN_ENV} rosrun catkin_virtualenv venv_lock ${CMAKE_BINARY_DIR}/${venv_dir} 105 | --package-name ${PROJECT_NAME} --input-requirements ${ARG_INPUT_REQUIREMENTS} 106 | --no-overwrite --extra-pip-args ${processed_pip_args} 107 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 108 | DEPENDS 109 | ${CMAKE_BINARY_DIR}/${venv_dir}/bin/python 110 | ${PROJECT_SOURCE_DIR}/${ARG_INPUT_REQUIREMENTS} 111 | ) 112 | endif() 113 | 114 | add_custom_command(COMMENT "Install requirements to ${CMAKE_BINARY_DIR}/${venv_dir}" 115 | OUTPUT ${CMAKE_BINARY_DIR}/${venv_dir}/bin/activate 116 | COMMAND ${CATKIN_ENV} rosrun catkin_virtualenv venv_install ${venv_dir} 117 | --requirements ${requirements_list} --extra-pip-args ${processed_pip_args} 118 | DEPENDS 119 | ${CMAKE_BINARY_DIR}/${venv_dir}/bin/python 120 | ${package_requirements} 121 | ${requirements_list} 122 | ) 123 | 124 | add_custom_command(COMMENT "Prepare relocated virtualenvs for develspace and installspace" 125 | OUTPUT ${venv_devel_dir} install/${venv_dir} 126 | # CMake copy_directory doesn't preserve symlinks https://gitlab.kitware.com/cmake/cmake/issues/14609 127 | # COMMAND ${CMAKE_COMMAND} -E copy_directory ${venv_dir} ${venv_devel_dir} 128 | # COMMAND ${CMAKE_COMMAND} -E copy_directory ${venv_dir} install/${venv_dir} 129 | COMMAND mkdir -p ${venv_devel_dir} && cp -r ${venv_dir}/* ${venv_devel_dir} 130 | COMMAND mkdir -p install/${venv_dir} && cp -r ${venv_dir}/* install/${venv_dir} 131 | 132 | COMMAND ${CATKIN_ENV} rosrun catkin_virtualenv venv_relocate ${venv_devel_dir} --target-dir ${venv_devel_dir} 133 | COMMAND ${CATKIN_ENV} rosrun catkin_virtualenv venv_relocate install/${venv_dir} --target-dir ${venv_install_dir} 134 | DEPENDS ${CMAKE_BINARY_DIR}/${venv_dir}/bin/activate 135 | ) 136 | 137 | add_custom_target(${PROJECT_NAME}_generate_virtualenv ALL 138 | COMMENT "Per-package virtualenv target" 139 | DEPENDS 140 | ${venv_devel_dir} 141 | install/${venv_dir} 142 | ) 143 | 144 | add_custom_target(${PROJECT_NAME}_venv_lock 145 | COMMENT "Manually invoked target to generate the lock file on demand" 146 | COMMAND ${CATKIN_ENV} rosrun catkin_virtualenv venv_lock ${CMAKE_BINARY_DIR}/${venv_dir} 147 | --package-name ${PROJECT_NAME} --input-requirements ${ARG_INPUT_REQUIREMENTS} 148 | --extra-pip-args ${processed_pip_args} 149 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 150 | DEPENDS 151 | ${venv_devel_dir} 152 | ${PROJECT_SOURCE_DIR}/${ARG_INPUT_REQUIREMENTS} 153 | ) 154 | 155 | if(CATKIN_ENABLE_TESTING AND NOT package_requirements STREQUAL "" AND (NOT DEFINED ARG_CHECK_VENV OR ARG_CHECK_VENV)) 156 | file(MAKE_DIRECTORY ${CATKIN_TEST_RESULTS_DIR}/${PROJECT_NAME}) 157 | catkin_run_tests_target("venv_check" "${PROJECT_NAME}-requirements" "venv_check-${PROJECT_NAME}-requirements.xml" 158 | COMMAND "${CATKIN_ENV} rosrun catkin_virtualenv venv_check ${venv_dir} --requirements ${package_requirements} \ 159 | --extra-pip-args \"${processed_pip_args}\" \ 160 | --xunit-output ${CATKIN_TEST_RESULTS_DIR}/${PROJECT_NAME}/venv_check-${PROJECT_NAME}-requirements.xml" 161 | DEPENDENCIES ${PROJECT_NAME}_generate_virtualenv 162 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 163 | ) 164 | endif() 165 | 166 | install(DIRECTORY ${CMAKE_BINARY_DIR}/install/${venv_dir} 167 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} 168 | USE_SOURCE_PERMISSIONS) 169 | 170 | # (pbovbel): NOSETESTS originally set by catkin here: 171 | # 172 | message(STATUS "Using virtualenv to run Python nosetests: ${nosetests}") 173 | set(NOSETESTS "${venv_devel_dir}/bin/python -m nose" PARENT_SCOPE) 174 | 175 | endfunction() 176 | -------------------------------------------------------------------------------- /catkin_virtualenv/cmake/catkin_install_python.cmake: -------------------------------------------------------------------------------- 1 | # Software License Agreement (GPL) 2 | # 3 | # \file catkin_install_python.cmake 4 | # \authors Paul Bovbel 5 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 6 | # 7 | # This program is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License as 9 | # published by the Free Software Foundation, either version 2 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, but 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | function(catkin_install_python) 20 | # See https://github.com/ros/catkin/blob/kinetic-devel/cmake/catkin_install_python.cmake for overriden function 21 | set(options OPTIONAL) 22 | set(oneValueArgs DESTINATION RENAME_PROCESS) 23 | set(multiValueArgs PROGRAMS) 24 | cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) 25 | 26 | if(NOT ARG_PROGRAMS) 27 | message(FATAL_ERROR "catkin_install_python() called without required PROGRAMS argument.") 28 | endif() 29 | if(NOT ARG_DESTINATION) 30 | message(FATAL_ERROR "catkin_install_python() called without required DESTINATION argument.") 31 | endif() 32 | 33 | if(NOT TARGET ${PROJECT_NAME}_generate_virtualenv) 34 | message(FATAL_ERROR "${PROJECT_NAME} loaded catkin_virtualenv, but never invoked 'catkin_generate_virtualenv'") 35 | return() 36 | endif() 37 | 38 | if (NOT DEFINED ARG_RENAME_PROCESS) 39 | set(ARG_RENAME_PROCESS TRUE) 40 | endif() 41 | 42 | # Use CMake templating to create virtualenv loaders for all specified python scripts 43 | set(install_programs "") 44 | 45 | foreach(program_path ${ARG_PROGRAMS}) 46 | if(NOT IS_ABSOLUTE ${program_path}) 47 | set(program_path "${CMAKE_CURRENT_SOURCE_DIR}/${program_path}") 48 | endif() 49 | get_filename_component(program_basename ${program_path} NAME) 50 | 51 | if(EXISTS ${program_path}) 52 | stamp(${program_path}) # Reconfigure when the python script changes. This mirrors upstream behaviour. 53 | 54 | execute_process( 55 | COMMAND ${CATKIN_ENV} test -x ${program_path} 56 | RESULT_VARIABLE is_program_executable 57 | ) 58 | 59 | if(is_program_executable STREQUAL "0") 60 | message(WARNING "Making ${program_path} non-executable. Otherwise 'rosrun ${PROJECT_NAME} ${program_basename}' \ 61 | will not work as expected.") 62 | execute_process( 63 | COMMAND ${CATKIN_ENV} chmod -x ${program_path} # This is touching the source space 64 | ) 65 | endif() 66 | 67 | set(program_install_location ${CATKIN_PACKAGE_SHARE_DESTINATION}/catkin_virtualenv_scripts) 68 | 69 | # For devel-space support, we generate a bash script that invokes the source script via the virtualenv's 70 | # python interpreter. 71 | set(devel_program ${CATKIN_DEVEL_PREFIX}/${ARG_DESTINATION}/${program_basename}) 72 | configure_file(${catkin_virtualenv_CMAKE_DIR}/templates/program.devel.in ${devel_program}) 73 | execute_process( 74 | COMMAND ${CATKIN_ENV} chmod +x ${devel_program} 75 | ) 76 | 77 | # For install-space support, we install the source script, and then generate a bash script to invoke it using 78 | # the virtualenv's python interpreter. 79 | set(install_program ${CMAKE_BINARY_DIR}/${program_basename}) 80 | configure_file(${catkin_virtualenv_CMAKE_DIR}/templates/program.install.in ${install_program}) 81 | execute_process( 82 | COMMAND ${CATKIN_ENV} chmod +x ${install_program} 83 | ) 84 | 85 | install( 86 | FILES ${program_path} 87 | DESTINATION ${program_install_location} 88 | ) 89 | 90 | install( 91 | PROGRAMS ${install_program} 92 | DESTINATION ${ARG_DESTINATION} 93 | ) 94 | 95 | elseif(NOT ARG_OPTIONAL) 96 | message(FATAL_ERROR "catkin_install_python() called with non-existent file '${program_path}'.") 97 | endif() 98 | endforeach() 99 | 100 | endfunction() 101 | -------------------------------------------------------------------------------- /catkin_virtualenv/cmake/catkin_virtualenv-extras.cmake.em: -------------------------------------------------------------------------------- 1 | @[if DEVELSPACE]@ 2 | set(@(PROJECT_NAME)_CMAKE_DIR @(CMAKE_CURRENT_SOURCE_DIR)/cmake) 3 | @[else]@ 4 | set(catkin_virtualenv_CMAKE_DIR ${@(PROJECT_NAME)_DIR}) 5 | @[end if]@ 6 | 7 | # Include cmake modules from @(PROJECT_NAME) 8 | include(${@(PROJECT_NAME)_CMAKE_DIR}/catkin_generate_virtualenv.cmake) 9 | include(${@(PROJECT_NAME)_CMAKE_DIR}/catkin_install_python.cmake) 10 | -------------------------------------------------------------------------------- /catkin_virtualenv/cmake/templates/program.devel.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "${ARG_RENAME_PROCESS}" = "TRUE" ]; then 4 | exec ${${PROJECT_NAME}_VENV_DEVEL_DIR}/bin/python - "$@" <<- EOF 5 | import re 6 | import sys 7 | 8 | from setproctitle import setproctitle 9 | 10 | program_path = "${program_path}" 11 | setproctitle(' '.join(["${program_basename}"] + sys.argv[1:])) 12 | exec(open(program_path).read()) 13 | EOF 14 | else 15 | exec ${${PROJECT_NAME}_VENV_DEVEL_DIR}/bin/python ${program_path} "$@" 16 | fi 17 | -------------------------------------------------------------------------------- /catkin_virtualenv/cmake/templates/program.install.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "${ARG_RENAME_PROCESS}" = "TRUE" ]; then 4 | exec ${${PROJECT_NAME}_VENV_INSTALL_DIR}/bin/python - "$@" <<- EOF 5 | import re 6 | import sys 7 | 8 | from setproctitle import setproctitle 9 | 10 | program_path = "${CMAKE_INSTALL_PREFIX}/${program_install_location}/${program_basename}" 11 | setproctitle(' '.join(["${program_basename}"] + sys.argv[1:])) 12 | exec(open(program_path).read()) 13 | EOF 14 | else 15 | exec ${${PROJECT_NAME}_VENV_INSTALL_DIR}/bin/python ${CMAKE_INSTALL_PREFIX}/${program_install_location}/${program_basename} "$@" 16 | fi 17 | -------------------------------------------------------------------------------- /catkin_virtualenv/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | 24 | catkin_virtualenv 25 | 0.15.1 26 | Bundle python requirements in a catkin package via virtualenv. 27 | 28 | Paul Bovbel 29 | GPL 30 | Paul Bovbel 31 | 32 | catkin 33 | python3-setuptools 34 | 35 | python3-dev 36 | python3-nose 37 | python3-rospkg-modules 38 | python3-venv 39 | rosbash 40 | rosgraph 41 | virtualenv 42 | 43 | roslint 44 | 45 | 46 | requirements.txt 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /catkin_virtualenv/requirements.in: -------------------------------------------------------------------------------- 1 | catkin-pkg 2 | nose 3 | rospkg 4 | setproctitle 5 | -------------------------------------------------------------------------------- /catkin_virtualenv/requirements.txt: -------------------------------------------------------------------------------- 1 | catkin-pkg==1.0.0 # via -r requirements.in, rospkg 2 | distro==1.9.0 # via rospkg 3 | docutils==0.20.1 # via catkin-pkg 4 | nose==1.3.7 # via -r requirements.in 5 | pyparsing==3.1.1 # via catkin-pkg 6 | python-dateutil==2.8.2 # via catkin-pkg 7 | pyyaml==6.0.1 # via rospkg 8 | rospkg==1.5.1 # via -r requirements.in 9 | setproctitle==1.3.4 # via -r requirements.in 10 | six==1.16.0 # via python-dateutil 11 | 12 | # The following packages are considered to be unsafe in a requirements file: 13 | # setuptools 14 | -------------------------------------------------------------------------------- /catkin_virtualenv/scripts/collect_requirements: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Software License Agreement (GPL) 3 | # 4 | # \file collect_requirements 5 | # \authors Paul Bovbel 6 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 7 | # 8 | # This program is free software: you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License as 10 | # published by the Free Software Foundation, either version 2 of the 11 | # License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, but 14 | # WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | import argparse 22 | 23 | from catkin_virtualenv import configure_logging, collect_requirements 24 | 25 | 26 | if __name__ == '__main__': 27 | configure_logging() 28 | 29 | parser = argparse.ArgumentParser(description=collect_requirements.collect_requirements.__doc__) 30 | parser.add_argument( 31 | 'package_name', help="Package name that virtualenv belongs to.") 32 | parser.add_argument( 33 | '--no-deps', action="store_true", help="Only collect requirements for top-level package.") 34 | 35 | args, unknown = parser.parse_known_args() 36 | 37 | requirements = collect_requirements.collect_requirements( 38 | package_name=args.package_name, 39 | no_deps=args.no_deps, 40 | ) 41 | 42 | print(';'.join(requirements)) 43 | -------------------------------------------------------------------------------- /catkin_virtualenv/scripts/venv_check: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Software License Agreement (GPL) 3 | # 4 | # \file venv_install 5 | # \authors Paul Bovbel 6 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 7 | # 8 | # This program is free software: you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License as 10 | # published by the Free Software Foundation, either version 2 of the 11 | # License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, but 14 | # WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | import argparse 22 | import inspect 23 | import sys 24 | 25 | import xml.etree.ElementTree as ET 26 | 27 | from catkin_virtualenv import configure_logging 28 | from catkin_virtualenv.venv import Virtualenv 29 | 30 | 31 | if __name__ == '__main__': 32 | logger = configure_logging() 33 | 34 | parser = argparse.ArgumentParser(description=Virtualenv.install.__doc__) 35 | parser.add_argument( 36 | 'venv', help="Path of virtualenv to manage.") 37 | parser.add_argument( 38 | '--requirements', required=True, help="Requirements to check.") 39 | parser.add_argument( 40 | '--extra-pip-args', default='""', type=str, help="Extra pip args for install.") 41 | parser.add_argument( 42 | '--xunit-output', help="Destination where to write xunit output.") 43 | 44 | args = parser.parse_args() 45 | 46 | extra_pip_args = args.extra_pip_args[1:-1] 47 | 48 | venv = Virtualenv(args.venv) 49 | diff = venv.check( 50 | requirements=args.requirements, 51 | extra_pip_args=[arg for arg in extra_pip_args.split(" ") if arg != ""], 52 | ) 53 | 54 | if args.xunit_output: 55 | testsuite = ET.Element('testsuite', name="venv_check", tests="1", failures="1" if diff else "0", errors="0") 56 | testcase = ET.SubElement(testsuite, 'testcase', name="check_locked", classname="catkin_virtualenv.Venv") 57 | if diff: 58 | failure = ET.SubElement(testcase, 'failure', message="{} is not fully locked".format(args.requirements)) 59 | message = inspect.cleandoc(""" 60 | Consider defining INPUT_REQUIREMENTS to have catkin_virtualenv generate a lock file for this package. 61 | See https://github.com/locusrobotics/catkin_virtualenv/blob/master/README.md#locking-dependencies. 62 | The following changes would fully lock {requirements}: 63 | """.format(requirements=args.requirements)) 64 | message += '\n' + '\n'.join(diff) 65 | failure.text = message 66 | 67 | else: 68 | success = ET.SubElement(testcase, 'success', message="{} is fully locked".format(args.requirements)) 69 | 70 | tree = ET.ElementTree(testsuite) 71 | tree.write(args.xunit_output, encoding='utf-8', xml_declaration=True) 72 | 73 | else: 74 | if diff: 75 | logger.error("{} is not fully locked, see diff:\n{}".format(args.requirements, '\n'.join(diff))) 76 | sys.exit(1) 77 | -------------------------------------------------------------------------------- /catkin_virtualenv/scripts/venv_init: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Software License Agreement (GPL) 3 | # 4 | # \file venv_init 5 | # \authors Paul Bovbel 6 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 7 | # 8 | # This program is free software: you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License as 10 | # published by the Free Software Foundation, either version 2 of the 11 | # License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, but 14 | # WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | import argparse 22 | 23 | from catkin_virtualenv import configure_logging 24 | from catkin_virtualenv.venv import Virtualenv 25 | 26 | 27 | if __name__ == '__main__': 28 | configure_logging() 29 | 30 | parser = argparse.ArgumentParser(description=Virtualenv.initialize.__doc__) 31 | parser.add_argument( 32 | 'venv', help="Path where to initialize the virtualenv") 33 | parser.add_argument( 34 | '--python', default="python3", help="Build the virtualenv with which python version.") 35 | parser.add_argument( 36 | '--use-system-packages', action="store_true", help="Use system site packages.") 37 | parser.add_argument( 38 | '--extra-pip-args', default='""', type=str, help="Extra pip args for install.") 39 | 40 | args = parser.parse_args() 41 | 42 | extra_pip_args = args.extra_pip_args[1:-1] 43 | 44 | print(args.use_system_packages) 45 | venv = Virtualenv(args.venv) 46 | venv.initialize( 47 | python=args.python, 48 | use_system_packages=args.use_system_packages, 49 | extra_pip_args=[arg for arg in extra_pip_args.split(" ") if arg != ""], 50 | ) 51 | -------------------------------------------------------------------------------- /catkin_virtualenv/scripts/venv_install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Software License Agreement (GPL) 3 | # 4 | # \file venv_install 5 | # \authors Paul Bovbel 6 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 7 | # 8 | # This program is free software: you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License as 10 | # published by the Free Software Foundation, either version 2 of the 11 | # License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, but 14 | # WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | import argparse 22 | 23 | from catkin_virtualenv import configure_logging 24 | from catkin_virtualenv.venv import Virtualenv 25 | 26 | 27 | if __name__ == '__main__': 28 | configure_logging() 29 | 30 | parser = argparse.ArgumentParser(description=Virtualenv.install.__doc__) 31 | parser.add_argument( 32 | 'venv', help="Path of virtualenv to manage.") 33 | parser.add_argument( 34 | '--requirements', required=True, nargs='+', help="Requirements to sync to virtualenv.") 35 | parser.add_argument( 36 | '--extra-pip-args', default='""', type=str, help="Extra pip args for install.") 37 | 38 | args = parser.parse_args() 39 | 40 | extra_pip_args = args.extra_pip_args[1:-1] 41 | 42 | venv = Virtualenv(args.venv) 43 | venv.install( 44 | requirements=args.requirements, 45 | extra_pip_args=[arg for arg in extra_pip_args.split(" ") if arg != ""], 46 | ) 47 | -------------------------------------------------------------------------------- /catkin_virtualenv/scripts/venv_lock: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Software License Agreement (GPL) 3 | # 4 | # \file venv_init 5 | # \authors Paul Bovbel 6 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 7 | # 8 | # This program is free software: you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License as 10 | # published by the Free Software Foundation, either version 2 of the 11 | # License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, but 14 | # WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | import argparse 22 | 23 | from catkin_virtualenv import configure_logging 24 | from catkin_virtualenv.venv import Virtualenv 25 | 26 | 27 | if __name__ == '__main__': 28 | configure_logging() 29 | 30 | parser = argparse.ArgumentParser(description=Virtualenv.lock.__doc__) 31 | parser.add_argument( 32 | 'venv', help="Path of virtualenv to manage.") 33 | parser.add_argument( 34 | '--package-name', required=True, help="Package name that virtualenv belongs to.") 35 | parser.add_argument( 36 | '--input-requirements', required=True, help="Where to write read requirement specs.") 37 | parser.add_argument( 38 | '--no-overwrite', action="store_true", help="Don't overwrite lock file if it exists.") 39 | parser.add_argument( 40 | '--extra-pip-args', default='""', type=str, help="Extra pip args for install.") 41 | 42 | args = parser.parse_args() 43 | 44 | extra_pip_args = args.extra_pip_args[1:-1] 45 | 46 | venv = Virtualenv(args.venv) 47 | venv.lock( 48 | package_name=args.package_name, 49 | input_requirements=args.input_requirements, 50 | no_overwrite=args.no_overwrite, 51 | extra_pip_args=[arg for arg in extra_pip_args.split(" ") if arg != ""], 52 | ) 53 | -------------------------------------------------------------------------------- /catkin_virtualenv/scripts/venv_relocate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Software License Agreement (GPL) 3 | # 4 | # \file venv_relocate 5 | # \authors Paul Bovbel 6 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 7 | # 8 | # This program is free software: you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License as 10 | # published by the Free Software Foundation, either version 2 of the 11 | # License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, but 14 | # WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | import argparse 22 | 23 | from catkin_virtualenv import configure_logging 24 | from catkin_virtualenv.venv import Virtualenv 25 | 26 | 27 | if __name__ == '__main__': 28 | configure_logging() 29 | 30 | parser = argparse.ArgumentParser(description=Virtualenv.relocate.__doc__) 31 | parser.add_argument( 32 | 'venv', help="Path where virtualenv currently is") 33 | parser.add_argument( 34 | '--target-dir', required=True, help="Path where virtualenv will live.") 35 | 36 | args = parser.parse_args() 37 | 38 | venv = Virtualenv(args.venv) 39 | venv.relocate( 40 | target_dir=args.target_dir, 41 | ) 42 | -------------------------------------------------------------------------------- /catkin_virtualenv/setup.py: -------------------------------------------------------------------------------- 1 | # Software License Agreement (GPL) 2 | # 3 | # \file setup.py 4 | # \authors Paul Bovbel 5 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 6 | # 7 | # This program is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License as 9 | # published by the Free Software Foundation, either version 2 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, but 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | from setuptools import setup 20 | from catkin_pkg.python_setup import generate_distutils_setup 21 | 22 | d = generate_distutils_setup(packages=["catkin_virtualenv"], package_dir={"": "src"}) 23 | 24 | setup(**d) 25 | -------------------------------------------------------------------------------- /catkin_virtualenv/src/catkin_virtualenv/__init__.py: -------------------------------------------------------------------------------- 1 | # Software License Agreement (GPL) 2 | # 3 | # \file __init__.py 4 | # \authors Paul Bovbel 5 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 6 | # 7 | # This program is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License as 9 | # published by the Free Software Foundation, either version 2 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, but 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | 20 | import logging 21 | import subprocess 22 | import rosgraph.roslogging 23 | 24 | logger = logging.getLogger(__name__) 25 | 26 | 27 | def configure_logging(): 28 | rosgraph.roslogging.configure_logging('catkin_virtualenv') 29 | return logging.getLogger() 30 | 31 | 32 | def run_command(cmd, *args, **kwargs): 33 | logger.info(" ".join(cmd)) 34 | if kwargs.pop("capture_output", False): 35 | kwargs["stdout"] = subprocess.PIPE 36 | kwargs["stderr"] = subprocess.PIPE 37 | return subprocess.run(cmd, *args, **kwargs) 38 | -------------------------------------------------------------------------------- /catkin_virtualenv/src/catkin_virtualenv/collect_requirements.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Software License Agreement (GPL) 3 | # 4 | # \file collect_requirements.py 5 | # \authors Paul Bovbel 6 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 7 | # 8 | # This program is free software: you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License as 10 | # published by the Free Software Foundation, either version 2 of the 11 | # License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, but 14 | # WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | from __future__ import print_function 21 | 22 | import os 23 | 24 | from queue import Queue 25 | from catkin.find_in_workspaces import find_in_workspaces 26 | from catkin_pkg.package import parse_package 27 | 28 | 29 | CATKIN_VIRTUALENV_TAGNAME = "pip_requirements" 30 | 31 | 32 | def parse_exported_requirements(package, package_dir): 33 | # type: (catkin_pkg.package.Package) -> List[str] 34 | requirements_list = [] 35 | for export in package.exports: 36 | if export.tagname == CATKIN_VIRTUALENV_TAGNAME: 37 | requirements_list.append(os.path.join(package_dir, export.content)) 38 | return requirements_list 39 | 40 | 41 | def process_package(package_name, soft_fail=True): 42 | # type: (str) -> List[str], List[str] 43 | try: 44 | package_path = find_in_workspaces(project=package_name, path="package.xml", first_match_only=True,)[0] 45 | except IndexError: 46 | if not soft_fail: 47 | raise RuntimeError("Unable to process package {}".format(package_name)) 48 | else: 49 | # This is not a catkin dependency 50 | return [], [] 51 | else: 52 | package = parse_package(package_path) 53 | dependencies = package.build_depends + package.test_depends 54 | return parse_exported_requirements(package, os.path.dirname(package_path)), dependencies 55 | 56 | 57 | def collect_requirements(package_name, no_deps=False): 58 | # type: (str, bool) -> List[str] 59 | """ Collect requirements inherited by a package. """ 60 | package_queue = Queue() 61 | package_queue.put(package_name) 62 | processed_packages = set() 63 | requirements_list = [] 64 | 65 | while not package_queue.empty(): 66 | queued_package = package_queue.get() 67 | 68 | if queued_package not in processed_packages: 69 | processed_packages.add(queued_package) 70 | requirements, dependencies = process_package( 71 | package_name=queued_package, soft_fail=(queued_package != package_name) 72 | ) 73 | requirements_list = requirements + requirements_list 74 | 75 | if not no_deps: 76 | for dependency in dependencies: 77 | package_queue.put(dependency.name) 78 | 79 | return requirements_list 80 | -------------------------------------------------------------------------------- /catkin_virtualenv/src/catkin_virtualenv/relocate.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright (c) 2013 - 2014 Spotify AB 3 | # Copyright (c) 2020 Locus Robotics 4 | 5 | # This file is part of dh-virtualenv. 6 | 7 | # dh-virtualenv is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License as 9 | # published by the Free Software Foundation, either version 2 of the 10 | # License, or (at your option) any later version. 11 | 12 | # dh-virtualenv is distributed in the hope that it will be useful, but 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # General Public License for more details. 16 | 17 | # You should have received a copy of the GNU General Public License 18 | # along with dh-virtualenv. If not, see 19 | # . 20 | 21 | import os 22 | import re 23 | import subprocess 24 | 25 | from . import run_command 26 | 27 | PYTHON_INTERPRETERS = ["python", "pypy", "ipy", "jython"] 28 | _PYTHON_INTERPRETERS_REGEX = r"\(" + r"\|".join(PYTHON_INTERPRETERS) + r"\)" 29 | 30 | 31 | def find_script_files(venv_dir): 32 | """Find list of files containing python shebangs in the bin directory. """ 33 | command = [ 34 | "grep", 35 | "-l", 36 | "-r", 37 | "-e", 38 | r"^#!.*bin/\(env \)\?{0}".format(_PYTHON_INTERPRETERS_REGEX), 39 | "-e", 40 | r"^'''exec.*bin/{0}".format(_PYTHON_INTERPRETERS_REGEX), 41 | os.path.join(venv_dir, "bin"), 42 | ] 43 | files = run_command(command, check=True, capture_output=True).stdout 44 | return {f for f in files.decode("utf-8").strip().split("\n") if f} 45 | 46 | 47 | def fix_shebangs(venv_dir, target_dir): 48 | """Translate /usr/bin/python and /usr/bin/env python shebang 49 | lines to point to our virtualenv python. 50 | """ 51 | pythonpath = os.path.join(target_dir, "bin/python") 52 | for f in find_script_files(venv_dir): 53 | regex = ( 54 | r"s-^#!.*bin/\(env \)\?{names}\"\?-#!{pythonpath}-;" r"s-^'''exec'.*bin/{names}-'''exec' {pythonpath}-" 55 | ).format(names=_PYTHON_INTERPRETERS_REGEX, pythonpath=re.escape(pythonpath)) 56 | run_command(["sed", "-i", regex, f], check=True) 57 | 58 | 59 | def fix_activate_path(venv_dir, target_dir): 60 | """Replace the `VIRTUAL_ENV` path in bin/activate to reflect the 61 | post-install path of the virtualenv. 62 | """ 63 | activate_settings = [ 64 | ['VIRTUAL_ENV="{0}"'.format(target_dir), r"^VIRTUAL_ENV=.*$", "activate"], 65 | ['setenv VIRTUAL_ENV "{0}"'.format(target_dir), r"^setenv VIRTUAL_ENV.*$", "activate.csh"], 66 | ['set -gx VIRTUAL_ENV "{0}"'.format(target_dir), r"^set -gx VIRTUAL_ENV.*$", "activate.fish"], 67 | ] 68 | 69 | for activate_args in activate_settings: 70 | virtualenv_path = activate_args[0] 71 | pattern = re.compile(activate_args[1], flags=re.M) 72 | activate_file = activate_args[2] 73 | 74 | with open(os.path.join(venv_dir, "bin", activate_file), "r+") as fh: 75 | content = pattern.sub(virtualenv_path, fh.read()) 76 | fh.seek(0) 77 | fh.truncate() 78 | fh.write(content) 79 | 80 | 81 | def fix_local_symlinks(venv_dir): 82 | # The virtualenv might end up with a local folder that points outside the package 83 | # Specifically it might point at the build environment that created it! 84 | # Make those links relative 85 | # See https://github.com/pypa/virtualenv/commit/5cb7cd652953441a6696c15bdac3c4f9746dfaa1 86 | local_dir = os.path.join(venv_dir, "local") 87 | if not os.path.isdir(local_dir): 88 | return 89 | elif os.path.samefile(venv_dir, local_dir): 90 | # "local" points directly to its containing directory 91 | os.unlink(local_dir) 92 | os.symlink(".", local_dir) 93 | return 94 | 95 | for d in os.listdir(local_dir): 96 | path = os.path.join(local_dir, d) 97 | if not os.path.islink(path): 98 | continue 99 | 100 | existing_target = os.readlink(path) 101 | if not os.path.isabs(existing_target): 102 | # If the symlink is already relative, we don't 103 | # want to touch it. 104 | continue 105 | 106 | new_target = os.path.relpath(existing_target, local_dir) 107 | os.unlink(path) 108 | os.symlink(new_target, path) 109 | -------------------------------------------------------------------------------- /catkin_virtualenv/src/catkin_virtualenv/venv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Software License Agreement (GPL) 3 | # 4 | # \file venv.py 5 | # \authors Paul Bovbel 6 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 7 | # 8 | # This program is free software: you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License as 10 | # published by the Free Software Foundation, either version 2 of the 11 | # License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, but 14 | # WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | from __future__ import print_function 21 | 22 | import difflib 23 | import logging 24 | import os 25 | import re 26 | import shutil 27 | import subprocess 28 | import tempfile 29 | 30 | try: 31 | from urllib.request import urlretrieve 32 | except ImportError: 33 | # for python2 34 | from urllib import urlretrieve 35 | 36 | from distutils.spawn import find_executable 37 | 38 | from . import run_command, relocate 39 | from .collect_requirements import collect_requirements 40 | 41 | _BYTECODE_REGEX = re.compile(r".*\.py[co]") 42 | _COMMENT_REGEX = re.compile(r"(^|\s+)#.*$", flags=re.MULTILINE) 43 | 44 | logger = logging.getLogger(__name__) 45 | 46 | 47 | class Virtualenv: 48 | def __init__(self, path): 49 | """Manage a virtualenv at the specified path.""" 50 | self.path = path 51 | 52 | def initialize(self, python, use_system_packages, extra_pip_args, clean=True): 53 | """Initialize a new virtualenv using the specified python version and extra arguments.""" 54 | if clean: 55 | try: 56 | shutil.rmtree(self.path) 57 | except Exception: 58 | pass 59 | 60 | system_python = find_executable(python) 61 | 62 | if not system_python: 63 | error_msg = "Unable to find a system-installed {}.".format(python) 64 | if python and python[0].isdigit(): 65 | error_msg += " Perhaps you meant python{}".format(python) 66 | raise RuntimeError(error_msg) 67 | 68 | preinstall = [ 69 | "pip==24.0", 70 | "pip-tools==7.4.1", 71 | ] 72 | 73 | builtin_venv = self._check_module(system_python, "venv") 74 | if builtin_venv: 75 | virtualenv = [system_python, "-m", "venv"] 76 | else: 77 | virtualenv = ["virtualenv", "--no-setuptools", "--verbose", "--python", python] 78 | # py2's virtualenv command will try install latest setuptools. setuptools>=45 not compatible with py2, 79 | # but we do require a reasonably up-to-date version (because of pip==20.1), so v44 at least. 80 | preinstall += ["setuptools>=44,<45"] 81 | 82 | if use_system_packages: 83 | virtualenv.append("--system-site-packages") 84 | 85 | without_pip = self._check_module(system_python, "ensurepip") is False 86 | if without_pip: 87 | virtualenv.append("--without-pip") 88 | 89 | virtualenv.append(self.path) 90 | run_command(virtualenv, check=True) 91 | 92 | if without_pip: 93 | # install pip via get-pip.py 94 | version_proc = run_command( 95 | ["python", "-cimport sys; print('{}.{}'.format(*sys.version_info))"], capture_output=True 96 | ) 97 | version = version_proc.stdout 98 | if isinstance(version, bytes): 99 | version = version.decode("utf-8") 100 | version = version.strip() 101 | # download pip from https://bootstrap.pypa.io/pip/ 102 | get_pip_path, _ = urlretrieve("https://bootstrap.pypa.io/pip/get-pip.py") 103 | run_command([self._venv_bin("python"), get_pip_path], check=True) 104 | 105 | # (gservin): test --no-cache-dir 106 | run_command( 107 | [self._venv_bin("python"), "-m", "pip", "install", "--no-cache-dir", "-vvv"] + extra_pip_args + preinstall, 108 | check=True, 109 | ) 110 | 111 | def install(self, requirements, extra_pip_args): 112 | """Purge the cache first before installing.""" # (KLAD) testing to debug an issue on build farm 113 | command = [self._venv_bin("python"), "-m", "pip", "cache", "purge"] 114 | """ Sync a virtualenv with the specified requirements.""" # (KLAD) testing no-cache-dir 115 | command = [self._venv_bin("python"), "-m", "pip", "install", "-vvv", "--no-cache-dir"] + extra_pip_args 116 | for req in requirements: 117 | run_command(command + ["-r", req], check=True) 118 | 119 | def check(self, requirements, extra_pip_args): 120 | """Check if a set of requirements is completely locked.""" 121 | with open(requirements, "r") as f: 122 | existing_requirements = f.read() 123 | 124 | # Re-lock the requirements 125 | command = [self._find_pip_compile(), "--no-header", "--annotation-style", "line", requirements, "-o", "-"] 126 | if extra_pip_args: 127 | command += ["--pip-args", " ".join(extra_pip_args)] 128 | 129 | generated_requirements = run_command(command, check=True, capture_output=True).stdout.decode() 130 | 131 | def _format(content): 132 | # Remove comments 133 | content = _COMMENT_REGEX.sub("", content) 134 | # Remove case sensitivity 135 | content = content.lower() 136 | # Split into lines for diff 137 | content = content.splitlines() 138 | # ignore order 139 | content.sort() 140 | return content 141 | 142 | # Compare against existing requirements 143 | diff = list(difflib.unified_diff(_format(existing_requirements), _format(generated_requirements))) 144 | 145 | return diff 146 | 147 | def lock(self, package_name, input_requirements, no_overwrite, extra_pip_args): 148 | """Create a frozen requirement set from a set of input specifications.""" 149 | try: 150 | output_requirements = collect_requirements(package_name, no_deps=True)[0] 151 | except IndexError: 152 | logger.info("Package doesn't export any requirements, step can be skipped") 153 | return 154 | 155 | if no_overwrite and os.path.exists(output_requirements): 156 | logger.info("Lock file already exists, not overwriting") 157 | return 158 | 159 | pip_compile = self._find_pip_compile() 160 | command = [pip_compile, "--no-header", "--annotation-style", "line", input_requirements] 161 | 162 | if os.path.normpath(input_requirements) == os.path.normpath(output_requirements): 163 | raise RuntimeError( 164 | "Trying to write locked requirements {} into a path specified as input: {}".format( 165 | output_requirements, input_requirements 166 | ) 167 | ) 168 | 169 | if extra_pip_args: 170 | command += ["--pip-args", " ".join(extra_pip_args)] 171 | 172 | command += ["-o", output_requirements] 173 | 174 | run_command(command, check=True) 175 | 176 | logger.info("Wrote new lock file to {}".format(output_requirements)) 177 | 178 | def relocate(self, target_dir): 179 | """Relocate a virtualenv to another directory.""" 180 | self._delete_bytecode() 181 | relocate.fix_shebangs(self.path, target_dir) 182 | relocate.fix_activate_path(self.path, target_dir) 183 | 184 | # This workaround has been flaky - let's just delete the 'local' folder entirely 185 | # relocate.fix_local_symlinks(self.path) 186 | local_dir = os.path.join(self.path, "local") 187 | if os.path.exists(local_dir): 188 | shutil.rmtree(local_dir) 189 | 190 | def _venv_bin(self, binary_name): 191 | if os.path.exists(os.path.join(self.path, "bin", binary_name)): 192 | return os.path.abspath(os.path.join(self.path, "bin", binary_name)) 193 | elif os.path.exists(os.path.join(self.path, "local", "bin", binary_name)): 194 | return os.path.abspath(os.path.join(self.path, "local", "bin", binary_name)) 195 | raise RuntimeError("Binary {} not found in venv".format(binary_name)) 196 | 197 | def _find_pip_compile(self): 198 | try: 199 | return self._venv_bin("pip-compile") 200 | except RuntimeError as exc: 201 | global_pip_compile = shutil.which("pip-compile") 202 | if global_pip_compile is None: 203 | raise RuntimeError("pip-compile not found found in Venv or global PATH") from exc 204 | return global_pip_compile 205 | 206 | def _check_module(self, python_executable, module): 207 | try: 208 | with open(os.devnull, "w") as devnull: 209 | # "-c 'import venv'" does not work with the subprocess module, but '-cimport venv' does 210 | run_command([python_executable, "-cimport {}".format(module)], stderr=devnull, check=True) 211 | return True 212 | except subprocess.CalledProcessError: 213 | return False 214 | 215 | def _delete_bytecode(self): 216 | """Remove all .py[co] files since they embed absolute paths.""" 217 | for root, _, files in os.walk(self.path): 218 | for f in files: 219 | if _BYTECODE_REGEX.match(f): 220 | os.remove(os.path.join(root, f)) 221 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 120 3 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [pep8] 2 | max-line-length = 120 3 | 4 | [flake8] 5 | max-line-length = 120 6 | -------------------------------------------------------------------------------- /test_catkin_virtualenv/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package test_catkin_virtualenv 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | 0.8.0 (2022-02-23) 6 | ------------------ 7 | 8 | 0.9.0 (2023-02-22) 9 | ------------------ 10 | * 0.8.0 11 | * Update changelogs 12 | * Contributors: Gary Servin 13 | 14 | 0.10.0 (2023-09-25) 15 | ------------------- 16 | * Drop python2 and add Jammy support (#101) 17 | * Updating pip and pip-tools 18 | * Trying older version of pip and pip-tools 19 | * Using slightly newer version of pip and piptools 20 | * Ensuring we are using python3 21 | * fix typo 22 | * Updating catkin-pkg for Jammy support 23 | * Remove test_virtualenv_python2 24 | * Update requirements to fix build error 25 | * Remove python3 direct reference from venv 26 | * Update pip and pip-tools for 3.7+ compatibility 27 | * Don't enumerate python versions 28 | * Add compatibility notes 29 | * Remove melodic test and python2 references 30 | * Fix build error more 31 | * Get rid of requests as a package for testing 32 | * get_pip isn't versioned 3.6 onwards 33 | * Fixup double pip-tools 34 | * Revert "Get rid of requests as a package for testing" 35 | This reverts commit 55e5b5889d1080303c52fb4e6671d5061498ac57. 36 | * Try fix action 37 | * Disable isolated tests 38 | * Revert changes to match the dependencies 39 | --------- 40 | Co-authored-by: Kalpesh Lad 41 | Co-authored-by: Gary Servin 42 | * 0.9.0 43 | * Update changelogs 44 | * 0.8.0 45 | * Update changelogs 46 | * Revert "Update changelogs" 47 | This reverts commit 33618e7dec29a058931e5e7190456b4418140c78. 48 | * Update changelogs 49 | * Contributors: Gary Servin, Paul Bovbel 50 | 51 | 0.15.1 (2025-05-29) 52 | ------------------- 53 | 54 | 0.15.0 (2025-05-29) 55 | ------------------- 56 | * [ROS-O] Update dependencies version to support testing on Ubuntu noble / ROS-O (`#115 `_) 57 | * Contributors: Yuki Furuta 58 | 59 | 0.14.0 (2025-02-04) 60 | ------------------- 61 | 62 | 0.13.0 (2024-09-16) 63 | ------------------- 64 | 65 | 0.12.0 (2024-06-17) 66 | ------------------- 67 | 68 | 0.11.0 (2024-02-02) 69 | ------------------- 70 | * 0.10.0 71 | * Update changelogs 72 | * Drop python2 and add Jammy support (#101) 73 | * Updating pip and pip-tools 74 | * Trying older version of pip and pip-tools 75 | * Using slightly newer version of pip and piptools 76 | * Ensuring we are using python3 77 | * fix typo 78 | * Updating catkin-pkg for Jammy support 79 | * Remove test_virtualenv_python2 80 | * Update requirements to fix build error 81 | * Remove python3 direct reference from venv 82 | * Update pip and pip-tools for 3.7+ compatibility 83 | * Don't enumerate python versions 84 | * Add compatibility notes 85 | * Remove melodic test and python2 references 86 | * Fix build error more 87 | * Get rid of requests as a package for testing 88 | * get_pip isn't versioned 3.6 onwards 89 | * Fixup double pip-tools 90 | * Revert "Get rid of requests as a package for testing" 91 | This reverts commit 55e5b5889d1080303c52fb4e6671d5061498ac57. 92 | * Try fix action 93 | * Disable isolated tests 94 | * Revert changes to match the dependencies 95 | --------- 96 | Co-authored-by: Kalpesh Lad 97 | Co-authored-by: Gary Servin 98 | * 0.9.0 99 | * Update changelogs 100 | * 0.8.0 101 | * Update changelogs 102 | * Revert "Update changelogs" 103 | This reverts commit 33618e7dec29a058931e5e7190456b4418140c78. 104 | * Update changelogs 105 | * Contributors: Gary Servin, Paul Bovbel 106 | 107 | 0.7.0 (2020-10-02) 108 | ------------------ 109 | 110 | 0.6.1 (2020-08-24) 111 | ------------------ 112 | * Correct dependencies and autoformat (`#72 `_) 113 | * Remove python-virtualenv dep 114 | * Add python2-dev 115 | * Lint 116 | * Contributors: Paul Bovbel 117 | 118 | 0.6.0 (2020-07-14) 119 | ------------------ 120 | * Don't require catkin_package to be called before catkin_generate_virtualenv (`#67 `_) 121 | * Remove user specific paths (`#63 `_) 122 | * Remove user specific paths 123 | * Change working directory of venv_lock command 124 | * Lock catkin_virtualenv base requirements 125 | Co-authored-by: Paul Bovbel 126 | * RST-3172 Refactor catkin_virtualenv to allow locking dependencies (`#55 `_) 127 | * Remove unused options 128 | * Fix regex for comments 129 | * Migrate scripts 130 | * Remove old code 131 | * Move common requirements to an export file 132 | * Minor cleanup 133 | * Remove requirement-parsing unit tests 134 | * Fix logging config 135 | * Fix test builds 136 | * Generate lock files 137 | * Fix tests 138 | * Move dh-virtualenv functions into separate file 139 | * Fix roslint 140 | * Update docs 141 | * Update requirements 142 | * CMake comments 143 | * Fix pip-args 144 | * README fixup 145 | * Correct ARG_LOCK_FILE handling 146 | * Remove headers 147 | * Use set comprehension 148 | * Add migration doc 149 | * Respin 150 | * Contributors: David V. Lu!!, Paul Bovbel 151 | 152 | 0.5.0 (2019-06-21) 153 | ------------------ 154 | 155 | 0.4.1 (2019-06-11) 156 | ------------------ 157 | 158 | 0.4.0 (2019-03-18) 159 | ------------------ 160 | 161 | 0.3.0 (2019-01-16) 162 | ------------------ 163 | * Python3 re-enable, add PYTHON_VERSION support (`#33 `_) 164 | * replace PYTHON_VERSION_MAJOR with PYTHON_VERSION 165 | * Simplify nose usage for python3 166 | * Check for venv module directly rather than munging major version 167 | * Contributors: Paul Bovbel 168 | 169 | 0.2.2 (2018-12-04) 170 | ------------------ 171 | * Merge repeated requirements (`#32 `_) 172 | * Contributors: Paul Bovbel 173 | 174 | 0.2.1 (2018-06-04) 175 | ------------------ 176 | 177 | 0.2.0 (2018-05-03) 178 | ------------------ 179 | 180 | 0.1.6 (2018-01-10) 181 | ------------------ 182 | 183 | 0.1.5 (2018-01-10) 184 | ------------------ 185 | * Drop strict requirements 186 | * Contributors: Paul Bovbel 187 | 188 | 0.1.4 (2017-12-03) 189 | ------------------ 190 | * Fix cmake lint errors 191 | * Add XML schema, README badges, fix travis config for debian jessie, and remove legacy scripts 192 | * Merge pull request `#5 `_ from gavanderhoorn/manifest_fix 193 | Remove stray 's' from test package manifests. 194 | * Remove stray 's' from test package manifests. 195 | * Contributors: Paul Bovbel, gavanderhoorn 196 | 197 | 0.1.3 (2017-11-27) 198 | ------------------ 199 | 200 | 0.1.2 (2017-11-23) 201 | ------------------ 202 | * Drop rosbash dependency and move python scripts into cmake directory 203 | * More tweaks to get nosetests working in python3 204 | * Contributors: Paul Bovbel 205 | 206 | 0.1.1 (2017-11-22) 207 | ------------------ 208 | 209 | 0.1.0 (2017-11-22) 210 | ------------------ 211 | * Fix trusty support 212 | * Contributors: Paul Bovbel 213 | 214 | 0.0.1 (2017-11-22) 215 | ------------------ 216 | * Add license 217 | * Overhaul virtualenv generation and add Python 3 support (`#1 `_) 218 | * Rewrite build_venv in python 219 | * Use dh_virtualenv to do the heavy lifting; embed new version of dh_virtualenv internally 220 | * Update CMake to generate virtualenv appropriately for install and devel space 221 | * Initial implementation 222 | * Contributors: Paul Bovbel 223 | -------------------------------------------------------------------------------- /test_catkin_virtualenv/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5.1) 2 | project(test_catkin_virtualenv) 3 | 4 | find_package(catkin REQUIRED COMPONENTS catkin_virtualenv) 5 | 6 | catkin_generate_virtualenv( 7 | INPUT_REQUIREMENTS requirements.in 8 | ) 9 | 10 | # Order with catkin_generate_virtualenv shouldn't matter 11 | catkin_package() 12 | 13 | install(FILES requirements.txt 14 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) 15 | 16 | if(CATKIN_ENABLE_TESTING) 17 | find_package(rostest REQUIRED) 18 | 19 | catkin_install_python( 20 | PROGRAMS 21 | test/test_virtualenv_script 22 | DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) 23 | 24 | catkin_add_nosetests(test 25 | DEPENDENCIES ${PROJECT_NAME}_generate_virtualenv 26 | ) 27 | 28 | add_rostest(test/virtualenv_script.test 29 | DEPENDENCIES ${PROJECT_NAME}_generate_virtualenv 30 | ) 31 | 32 | endif() 33 | -------------------------------------------------------------------------------- /test_catkin_virtualenv/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | 24 | test_catkin_virtualenv 25 | 0.15.1 26 | Basic catkin_virtualenv test. 27 | 28 | Paul Bovbel 29 | GPL 30 | Paul Bovbel 31 | 32 | catkin 33 | 34 | catkin_virtualenv 35 | 36 | rostest 37 | 38 | 39 | requirements.txt 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /test_catkin_virtualenv/requirements.in: -------------------------------------------------------------------------------- 1 | requests>=2 2 | packaging 3 | urllib3>=2 4 | -------------------------------------------------------------------------------- /test_catkin_virtualenv/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2025.1.31 # via requests 2 | charset-normalizer==3.4.1 # via requests 3 | idna==3.10 # via requests 4 | packaging==24.2 # via -r requirements.in 5 | requests==2.32.3 # via -r requirements.in 6 | urllib3==2.2.3 # via -r requirements.in, requests 7 | -------------------------------------------------------------------------------- /test_catkin_virtualenv/test/test_virtualenv_library.py: -------------------------------------------------------------------------------- 1 | # Software License Agreement (GPL) 2 | # 3 | # \file test_virtualenv_library.py 4 | # \authors Paul Bovbel 5 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 6 | # 7 | # This program is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License as 9 | # published by the Free Software Foundation, either version 2 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, but 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | import importlib 20 | import unittest 21 | 22 | from packaging import version 23 | 24 | 25 | class TestVirtualenv(unittest.TestCase): 26 | def test_import(self): 27 | requests = importlib.import_module("requests") 28 | self.assertGreaterEqual(version.parse(requests.__version__), version.parse("2")) 29 | -------------------------------------------------------------------------------- /test_catkin_virtualenv/test/test_virtualenv_script: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Software License Agreement (GPL) 3 | # 4 | # \file test_virtualenv_script 5 | # \authors Paul Bovbel 6 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 7 | # 8 | # This program is free software: you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License as 10 | # published by the Free Software Foundation, either version 2 of the 11 | # License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, but 14 | # WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | import importlib 21 | import rostest 22 | import sys 23 | import unittest 24 | 25 | from packaging import version 26 | 27 | 28 | class TestVirtualenv(unittest.TestCase): 29 | 30 | def test_import(self): 31 | requests = importlib.import_module("requests") 32 | self.assertGreaterEqual(version.parse(requests.__version__), version.parse("2")) 33 | 34 | 35 | if __name__ == '__main__': 36 | rostest.rosrun('test_catkin_virtualenv', 'test_virtualenv_script', TestVirtualenv, sys.argv) 37 | -------------------------------------------------------------------------------- /test_catkin_virtualenv/test/virtualenv_script.test: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /test_catkin_virtualenv_inherited/CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package test_catkin_virtualenv_inherited 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | 0.8.0 (2022-02-23) 6 | ------------------ 7 | 8 | 0.9.0 (2023-02-22) 9 | ------------------ 10 | * 0.8.0 11 | * Update changelogs 12 | * Contributors: Gary Servin 13 | 14 | 0.10.0 (2023-09-25) 15 | ------------------- 16 | * Drop python2 and add Jammy support (#101) 17 | * Updating pip and pip-tools 18 | * Trying older version of pip and pip-tools 19 | * Using slightly newer version of pip and piptools 20 | * Ensuring we are using python3 21 | * fix typo 22 | * Updating catkin-pkg for Jammy support 23 | * Remove test_virtualenv_python2 24 | * Update requirements to fix build error 25 | * Remove python3 direct reference from venv 26 | * Update pip and pip-tools for 3.7+ compatibility 27 | * Don't enumerate python versions 28 | * Add compatibility notes 29 | * Remove melodic test and python2 references 30 | * Fix build error more 31 | * Get rid of requests as a package for testing 32 | * get_pip isn't versioned 3.6 onwards 33 | * Fixup double pip-tools 34 | * Revert "Get rid of requests as a package for testing" 35 | This reverts commit 55e5b5889d1080303c52fb4e6671d5061498ac57. 36 | * Try fix action 37 | * Disable isolated tests 38 | * Revert changes to match the dependencies 39 | --------- 40 | Co-authored-by: Kalpesh Lad 41 | Co-authored-by: Gary Servin 42 | * 0.9.0 43 | * Update changelogs 44 | * 0.8.0 45 | * Update changelogs 46 | * Revert "Update changelogs" 47 | This reverts commit 33618e7dec29a058931e5e7190456b4418140c78. 48 | * Update changelogs 49 | * Contributors: Gary Servin, Paul Bovbel 50 | 51 | 0.15.1 (2025-05-29) 52 | ------------------- 53 | 54 | 0.15.0 (2025-05-29) 55 | ------------------- 56 | * [ROS-O] Update dependencies version to support testing on Ubuntu noble / ROS-O (`#115 `_) 57 | * Contributors: Yuki Furuta 58 | 59 | 0.14.0 (2025-02-04) 60 | ------------------- 61 | 62 | 0.13.0 (2024-09-16) 63 | ------------------- 64 | 65 | 0.12.0 (2024-06-17) 66 | ------------------- 67 | 68 | 0.11.0 (2024-02-02) 69 | ------------------- 70 | * 0.10.0 71 | * Update changelogs 72 | * Drop python2 and add Jammy support (#101) 73 | * Updating pip and pip-tools 74 | * Trying older version of pip and pip-tools 75 | * Using slightly newer version of pip and piptools 76 | * Ensuring we are using python3 77 | * fix typo 78 | * Updating catkin-pkg for Jammy support 79 | * Remove test_virtualenv_python2 80 | * Update requirements to fix build error 81 | * Remove python3 direct reference from venv 82 | * Update pip and pip-tools for 3.7+ compatibility 83 | * Don't enumerate python versions 84 | * Add compatibility notes 85 | * Remove melodic test and python2 references 86 | * Fix build error more 87 | * Get rid of requests as a package for testing 88 | * get_pip isn't versioned 3.6 onwards 89 | * Fixup double pip-tools 90 | * Revert "Get rid of requests as a package for testing" 91 | This reverts commit 55e5b5889d1080303c52fb4e6671d5061498ac57. 92 | * Try fix action 93 | * Disable isolated tests 94 | * Revert changes to match the dependencies 95 | --------- 96 | Co-authored-by: Kalpesh Lad 97 | Co-authored-by: Gary Servin 98 | * 0.9.0 99 | * Update changelogs 100 | * 0.8.0 101 | * Update changelogs 102 | * Revert "Update changelogs" 103 | This reverts commit 33618e7dec29a058931e5e7190456b4418140c78. 104 | * Update changelogs 105 | * Contributors: Gary Servin, Paul Bovbel 106 | 107 | 0.7.0 (2020-10-02) 108 | ------------------ 109 | 110 | 0.6.1 (2020-08-24) 111 | ------------------ 112 | * Correct dependencies and autoformat (`#72 `_) 113 | * Remove python-virtualenv dep 114 | * Add python2-dev 115 | * Lint 116 | * Contributors: Paul Bovbel 117 | 118 | 0.6.0 (2020-07-14) 119 | ------------------ 120 | * Remove user specific paths (`#63 `_) 121 | * Remove user specific paths 122 | * Change working directory of venv_lock command 123 | * Lock catkin_virtualenv base requirements 124 | Co-authored-by: Paul Bovbel 125 | * RST-3172 Refactor catkin_virtualenv to allow locking dependencies (`#55 `_) 126 | * Remove unused options 127 | * Fix regex for comments 128 | * Migrate scripts 129 | * Remove old code 130 | * Move common requirements to an export file 131 | * Minor cleanup 132 | * Remove requirement-parsing unit tests 133 | * Fix logging config 134 | * Fix test builds 135 | * Generate lock files 136 | * Fix tests 137 | * Move dh-virtualenv functions into separate file 138 | * Fix roslint 139 | * Update docs 140 | * Update requirements 141 | * CMake comments 142 | * Fix pip-args 143 | * README fixup 144 | * Correct ARG_LOCK_FILE handling 145 | * Remove headers 146 | * Use set comprehension 147 | * Add migration doc 148 | * Respin 149 | * Contributors: David V. Lu!!, Paul Bovbel 150 | 151 | 0.5.0 (2019-06-21) 152 | ------------------ 153 | 154 | 0.4.1 (2019-06-11) 155 | ------------------ 156 | 157 | 0.4.0 (2019-03-18) 158 | ------------------ 159 | 160 | 0.3.0 (2019-01-16) 161 | ------------------ 162 | * Python3 re-enable, add PYTHON_VERSION support (`#33 `_) 163 | * replace PYTHON_VERSION_MAJOR with PYTHON_VERSION 164 | * Simplify nose usage for python3 165 | * Check for venv module directly rather than munging major version 166 | * Contributors: Paul Bovbel 167 | 168 | 0.2.2 (2018-12-04) 169 | ------------------ 170 | * Merge repeated requirements (`#32 `_) 171 | * Contributors: Paul Bovbel 172 | 173 | 0.2.1 (2018-06-04) 174 | ------------------ 175 | 176 | 0.2.0 (2018-05-03) 177 | ------------------ 178 | 179 | 0.1.6 (2018-01-10 12:05) 180 | ------------------------ 181 | 182 | 0.1.5 (2018-01-10 11:15) 183 | ------------------------ 184 | 185 | 0.1.4 (2017-12-03) 186 | ------------------ 187 | 188 | 0.1.3 (2017-11-27) 189 | ------------------ 190 | 191 | 0.1.2 (2017-11-23) 192 | ------------------ 193 | 194 | 0.1.1 (2017-11-22 17:42) 195 | ------------------------ 196 | 197 | 0.1.0 (2017-11-22 17:30) 198 | ------------------------ 199 | 200 | 0.0.1 (2017-11-22 14:14) 201 | ------------------------ 202 | -------------------------------------------------------------------------------- /test_catkin_virtualenv_inherited/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5.1) 2 | project(test_catkin_virtualenv_inherited) 3 | 4 | find_package(catkin REQUIRED COMPONENTS catkin_virtualenv) 5 | 6 | catkin_package() 7 | 8 | catkin_generate_virtualenv( 9 | INPUT_REQUIREMENTS requirements.in 10 | ) 11 | 12 | install(FILES requirements.txt 13 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) 14 | 15 | if(CATKIN_ENABLE_TESTING) 16 | find_package(rostest REQUIRED) 17 | 18 | catkin_install_python( 19 | PROGRAMS 20 | test/test_virtualenv_script 21 | DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) 22 | 23 | catkin_add_nosetests(test 24 | DEPENDENCIES ${PROJECT_NAME}_generate_virtualenv 25 | ) 26 | 27 | add_rostest(test/virtualenv_script.test 28 | DEPENDENCIES ${PROJECT_NAME}_generate_virtualenv 29 | ) 30 | 31 | endif() 32 | -------------------------------------------------------------------------------- /test_catkin_virtualenv_inherited/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | 24 | test_catkin_virtualenv_inherited 25 | 0.15.1 26 | Test to make sure a package inherits it's dependency's dependencies, but is able to override the version. 27 | 28 | Paul Bovbel 29 | GPL 30 | Paul Bovbel 31 | 32 | catkin 33 | 34 | catkin_virtualenv 35 | 36 | test_catkin_virtualenv 37 | 38 | rostest 39 | 40 | 41 | requirements.txt 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /test_catkin_virtualenv_inherited/requirements.in: -------------------------------------------------------------------------------- 1 | requests>2.30,<=2.32 2 | urllib3>=2 3 | -------------------------------------------------------------------------------- /test_catkin_virtualenv_inherited/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2022.12.7 # via requests 2 | charset-normalizer==3.4.1 # via requests 3 | idna==2.8 # via requests 4 | requests==2.31.0 # via -r requirements.in 5 | urllib3==2.2.3 # via -r requirements.in, requests 6 | -------------------------------------------------------------------------------- /test_catkin_virtualenv_inherited/test/test_virtualenv_script: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Software License Agreement (GPL) 3 | # 4 | # \file test_virtualenv_script 5 | # \authors Paul Bovbel 6 | # \copyright Copyright (c) (2017,), Locus Robotics, All rights reserved. 7 | # 8 | # This program is free software: you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License as 10 | # published by the Free Software Foundation, either version 2 of the 11 | # License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, but 14 | # WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | import importlib 21 | import rostest 22 | import sys 23 | import unittest 24 | 25 | from packaging import version 26 | 27 | 28 | class TestVirtualenv(unittest.TestCase): 29 | 30 | def test_import(self): 31 | requests = importlib.import_module("requests") 32 | self.assertLessEqual(version.parse(requests.__version__), version.parse("2.32")) 33 | self.assertGreater(version.parse(requests.__version__), version.parse("2.30")) 34 | 35 | _ = importlib.import_module("packaging") 36 | 37 | 38 | if __name__ == '__main__': 39 | rostest.rosrun('test_catkin_virtualenv_inherited', 'test_virtualenv_script', TestVirtualenv, sys.argv) 40 | -------------------------------------------------------------------------------- /test_catkin_virtualenv_inherited/test/virtualenv_script.test: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 25 | --------------------------------------------------------------------------------