diff -Nru ros-rosdep-0.11.8/CHANGELOG.rst ros-rosdep-0.12.2/CHANGELOG.rst --- ros-rosdep-0.11.8/CHANGELOG.rst 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/CHANGELOG.rst 2018-03-21 23:40:00.000000000 +0000 @@ -1,3 +1,38 @@ +0.12.2 (2018-03-21) +------------------- +- Fix bug introduced in https://github.com/ros-infrastructure/rosdep/pull/521, reported in https://github.com/ros-infrastructure/rosdep/issues/589 + - https://github.com/ros-infrastructure/rosdep/pull/585 + +0.12.1 (2018-02-08) +------------------- +- Revert "Use ROS_ETC_DIR environment variable" to fix regression introduced in 0.12.0 + - https://github.com/ros-infrastructure/rosdep/pull/584 + +0.12.0 (2018-02-07) +------------------- +- Support for wildcard OS versions as specified in the updated REP 111 + - https://github.com/ros-infrastructure/rosdep/pull/573 +- Add conflict with Debian package python-rosdep2 + - https://github.com/ros-infrastructure/rosdep/pull/579 +- Remove redundant dependency checks + - https://github.com/ros-infrastructure/rosdep/pull/556 +- Update the FreeBSD installer + - https://github.com/ros-infrastructure/rosdep/pull/574 +- Fix detection of installed rpms and warn if slow method is being used + - https://github.com/ros-infrastructure/rosdep/pull/568 +- Support for installing virtual packages (Debian) + - https://github.com/ros-infrastructure/rosdep/pull/521 +- Remove non-interactive mode in slackware + - https://github.com/ros-infrastructure/rosdep/pull/553 +- Use ROS_ETC_DIR environment variable + - https://github.com/ros-infrastructure/rosdep/pull/551 +- Add __repr__ for SourceInstall + - https://github.com/ros-infrastructure/rosdep/pull/543 +- Keep dependencies order + - https://github.com/ros-infrastructure/rosdep/pull/545 +- Fix db command on OS X + - https://github.com/ros-infrastructure/rosdep/pull/541 + 0.11.8 (2017-08-03) ------------------- - Fix handling of metapackages diff -Nru ros-rosdep-0.11.8/debian/changelog ros-rosdep-0.12.2/debian/changelog --- ros-rosdep-0.11.8/debian/changelog 2017-08-12 14:48:07.000000000 +0000 +++ ros-rosdep-0.12.2/debian/changelog 2018-03-31 21:09:38.000000000 +0000 @@ -1,3 +1,21 @@ +ros-rosdep (0.12.2-2) unstable; urgency=medium + + * Add missing build dependency + + -- Jochen Sprickerhof Sat, 31 Mar 2018 23:09:38 +0200 + +ros-rosdep (0.12.2-1) unstable; urgency=medium + + * Update Vcs URLs to salsa.d.o + * Add R³ + * http -> https + * New upstream version 0.12.2 + * Update copyright + * Update policy and debhelper versions + * Rebase patch + + -- Jochen Sprickerhof Sat, 31 Mar 2018 21:19:58 +0200 + ros-rosdep (0.11.8-1) unstable; urgency=medium * New upstream version 0.11.8 diff -Nru ros-rosdep-0.11.8/debian/compat ros-rosdep-0.12.2/debian/compat --- ros-rosdep-0.11.8/debian/compat 2017-08-02 14:29:27.000000000 +0000 +++ ros-rosdep-0.12.2/debian/compat 2018-03-31 19:18:26.000000000 +0000 @@ -1 +1 @@ -10 +11 diff -Nru ros-rosdep-0.11.8/debian/control ros-rosdep-0.12.2/debian/control --- ros-rosdep-0.11.8/debian/control 2017-08-12 13:07:16.000000000 +0000 +++ ros-rosdep-0.12.2/debian/control 2018-03-31 21:06:59.000000000 +0000 @@ -3,13 +3,14 @@ Priority: optional Maintainer: Debian Science Maintainers Uploaders: Leopold Palomo-Avellaneda , Jochen Sprickerhof -Build-Depends: debhelper (>= 10), dh-python, python-all, python-setuptools, python3-all, python3-setuptools, python-nose, python3-nose, python-rospkg, python-mock, python-yaml, python-catkin-pkg, python-rosdistro, python-dev, python3-rospkg, python3-mock, python3-yaml, python3-catkin-pkg, python3-rosdistro -Standards-Version: 4.0.0 -Homepage: http://wiki.ros.org/rosdep +Build-Depends: debhelper (>= 11), dh-python, python-all, python-setuptools, python3-all, python3-setuptools, python-nose, python3-nose, python-rospkg, python-mock, python-yaml, python-catkin-pkg, python-rosdistro, python-dev, python3-rospkg, python3-mock, python3-yaml, python3-catkin-pkg, python3-rosdistro, python-flake8, python3-flake8 +Standards-Version: 4.1.3 +Rules-Requires-Root: no +Homepage: https://wiki.ros.org/rosdep X-Python-Version: >= 2.6 X-Python3-Version: >= 3.2 -Vcs-Git: https://anonscm.debian.org/cgit/debian-science/packages/ros/ros-rosdep.git -Vcs-Browser: https://anonscm.debian.org/cgit/debian-science/packages/ros/ros-rosdep.git +Vcs-Git: https://salsa.debian.org/science-team/ros-rosdep.git +Vcs-Browser: https://salsa.debian.org/science-team/ros-rosdep Testsuite: autopkgtest-pkg-python Package: python-rosdep2 diff -Nru ros-rosdep-0.11.8/debian/copyright ros-rosdep-0.12.2/debian/copyright --- ros-rosdep-0.11.8/debian/copyright 2017-08-02 14:29:27.000000000 +0000 +++ ros-rosdep-0.12.2/debian/copyright 2018-03-31 19:18:26.000000000 +0000 @@ -1,11 +1,11 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: rosdep Upstream-Contact: Tully Foote , Ken Conley -Source: http://ros.org/wiki/rosdep +Source: https://github.com/ros-infrastructure/rosdep Files: * Copyright: 2009-2013, Willow Garage, Inc. - 2013, Open Source Robotics Foundation, Inc + 2013-2018, Open Source Robotics Foundation, Inc License: BSD-3-clause Files: src/rosdep2/platforms/gem.py diff -Nru ros-rosdep-0.11.8/debian/patches/0001-Disable-some-tests-due-to-missing-network-connection.patch ros-rosdep-0.12.2/debian/patches/0001-Disable-some-tests-due-to-missing-network-connection.patch --- ros-rosdep-0.11.8/debian/patches/0001-Disable-some-tests-due-to-missing-network-connection.patch 2017-08-02 14:29:27.000000000 +0000 +++ ros-rosdep-0.12.2/debian/patches/0001-Disable-some-tests-due-to-missing-network-connection.patch 2018-03-31 19:18:44.000000000 +0000 @@ -10,7 +10,7 @@ 4 files changed, 13 insertions(+) diff --git a/test/test_rosdep_gbpdistro_support.py b/test/test_rosdep_gbpdistro_support.py -index 824d6b9..9066f18 100644 +index 560bb7c..3918e4f 100644 --- a/test/test_rosdep_gbpdistro_support.py +++ b/test/test_rosdep_gbpdistro_support.py @@ -38,6 +38,7 @@ def get_test_dir(): @@ -20,7 +20,7 @@ + return # disabled because sbuild doesn't allow network connections from rosdep2.gbpdistro_support import FUERTE_GBPDISTRO_URL for url_name, url in [ - ('FUERTE_GBPDISTRO_URL', FUERTE_GBPDISTRO_URL)]: + ('FUERTE_GBPDISTRO_URL', FUERTE_GBPDISTRO_URL)]: @@ -50,6 +51,7 @@ def test_url_constants(): @@ -28,7 +28,7 @@ + return # disabled because sbuild doesn't allow network connections from rosdep2.rosdistrohelper import get_index from rosdep2.gbpdistro_support import get_gbprepo_as_rosdep_data - distro = list(get_index().distributions.keys())[0] + distro = sorted(get_index().distributions.keys())[0] @@ -66,6 +68,7 @@ def test_get_gbprepo_as_rosdep_data(): @@ -38,19 +38,19 @@ from rosdep2.gbpdistro_support import FUERTE_GBPDISTRO_URL from rosdep2.rep3 import REP3_TARGETS_URL diff --git a/test/test_rosdep_rep3.py b/test/test_rosdep_rep3.py -index a12a398..df5d2bb 100644 +index b6e5de8..2663bb4 100644 --- a/test/test_rosdep_rep3.py +++ b/test/test_rosdep_rep3.py -@@ -35,6 +35,7 @@ def get_test_dir(): - return os.path.abspath(os.path.join(os.path.dirname(__file__), 'sources.list.d')) +@@ -37,6 +37,7 @@ def get_test_dir(): + def test_url_constants(): + return # disabled because sbuild doesn't allow network connections from rosdep2.rep3 import REP3_TARGETS_URL for url_name, url in [('REP3_TARGETS_URL', REP3_TARGETS_URL), ]: -@@ -46,6 +47,7 @@ def test_url_constants(): - assert False, "URL [%s][%s] failed to download"%(url_name, url) +@@ -49,6 +50,7 @@ def test_url_constants(): + def test_download_targets_data(): + return # disabled because sbuild doesn't allow network connections @@ -58,29 +58,30 @@ from rosdep2 import DownloadFailure data = download_targets_data(REP3_TARGETS_URL) diff --git a/test/test_rosdep_source.py b/test/test_rosdep_source.py -index 24e63a2..db5cfa9 100644 +index 73fe5b9..72a9c19 100644 --- a/test/test_rosdep_source.py +++ b/test/test_rosdep_source.py -@@ -288,11 +288,13 @@ def test_download_rdmanifest(): +@@ -301,12 +301,14 @@ def test_download_rdmanifest(): + - def test_install_from_file(): + return # disabled because sbuild doesn't allow network connections from rosdep2.platforms.source import install_from_file f = os.path.join(get_test_dir(), 'noop-not-installed.rdmanifest') install_from_file(f) + def test_install_source(): + return # disabled because sbuild doesn't allow network connections from rosdep2.platforms.source import install_source, SourceInstall resolved = SourceInstall() resolved.tarball = 'https://github.com/ros-infrastructure/rosdep/raw/master/test/source/foo.tar.gz' diff --git a/test/test_rosdep_sources_list.py b/test/test_rosdep_sources_list.py -index 70da7ef..e614688 100644 +index 175d409..c53c516 100644 --- a/test/test_rosdep_sources_list.py +++ b/test/test_rosdep_sources_list.py -@@ -55,6 +55,7 @@ def test_parse_sources_data(): - parse_sources_data +@@ -54,6 +54,7 @@ def test_get_sources_cache_dir(): + def test_url_constants(): + return # disabled because sbuild doesn't allow network connections @@ -88,40 +89,40 @@ for url_name, url in [('DEFAULT_SOURCES_LIST_URL', DEFAULT_SOURCES_LIST_URL)]: try: @@ -65,6 +66,7 @@ def test_url_constants(): - assert False, "URL [%s][%s] failed to download"%(url_name, url) + def test_download_default_sources_list(): + return # disabled because sbuild doesn't allow network connections from rosdep2.sources_list import download_default_sources_list data = download_default_sources_list() - assert 'http' in data, data # sanity check, all sources files have urls -@@ -188,6 +190,7 @@ def test_write_cache_file(): - assert {'data': 1} == pickle.loads(f.read()) - + assert 'http' in data, data # sanity check, all sources files have urls +@@ -194,6 +196,7 @@ def test_write_cache_file(): + + def test_update_sources_list(): + return # disabled because sbuild doesn't allow network connections from rosdep2.sources_list import update_sources_list, InvalidData, compute_filename_hash, PICKLE_CACHE_EXT try: import cPickle as pickle -@@ -238,6 +241,7 @@ def test_update_sources_list(): - assert expected == index, "\n[%s]\nvs\n[%s]"%(expected, index) +@@ -246,6 +249,7 @@ def test_update_sources_list(): + def test_load_cached_sources_list(): + return # disabled because sbuild doesn't allow network connections from rosdep2.sources_list import load_cached_sources_list, update_sources_list tempdir = tempfile.mkdtemp() -@@ -287,6 +291,7 @@ def test_DataSourceMatcher(): - assert not matcher.matches(data_source) +@@ -297,6 +301,7 @@ def test_DataSourceMatcher(): + def test_download_rosdep_data(): + return # disabled because sbuild doesn't allow network connections from rosdep2.sources_list import download_rosdep_data from rosdep2 import DownloadFailure url = GITHUB_BASE_URL -@@ -397,6 +402,7 @@ def test_DataSourceMatcher_create_default(): - assert not matcher.matches(data_source) - +@@ -412,6 +417,7 @@ def test_DataSourceMatcher_create_default(): + + def test_SourcesListLoader_create_default(): + return # disabled because sbuild doesn't allow network connections from rosdep2.sources_list import update_sources_list, SourcesListLoader, DataSourceMatcher diff -Nru ros-rosdep-0.11.8/README.md ros-rosdep-0.12.2/README.md --- ros-rosdep-0.11.8/README.md 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/README.md 2018-03-21 23:40:00.000000000 +0000 @@ -1,5 +1,7 @@ rosdep ------ +[![Build status](https://travis-ci.org/ros-infrastructure/rosdep.svg?branch=master)](https://travis-ci.org/ros-infrastructure/rosdep) +[![codecov](https://codecov.io/gh/ros-infrastructure/rosdep/branch/master/graph/badge.svg)](https://codecov.io/gh/ros-infrastructure/rosdep) rosdep is a command-line tool for installing system dependencies. For *end-users*, rosdep helps you install system dependencies for software that you are building from source. For *developers*, rosdep simplifies the problem of installing system dependencies on different platforms. Instead of having to figure out which debian package on Ubuntu Oneiric contains Boost, you can just specify a dependency on 'boost'. diff -Nru ros-rosdep-0.11.8/scripts/rosdep-source ros-rosdep-0.12.2/scripts/rosdep-source --- ros-rosdep-0.11.8/scripts/rosdep-source 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/scripts/rosdep-source 2018-03-21 23:40:00.000000000 +0000 @@ -1,10 +1,10 @@ #!/usr/bin/env python # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -13,7 +13,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -40,13 +40,15 @@ from rosdep2.platforms import source NAME='rosdep-source' + + def install_main(): parser = OptionParser(usage="usage: %prog install ", prog=NAME) options, args = parser.parse_args() if len(args) != 2: parser.error("please specify one and only one rdmanifest url") if args[0] != 'install': - parser.error("currently only support the 'install' command") + parser.error("currently only support the 'install' command") rdmanifest_url= args[1] try: if os.path.isfile(rdmanifest_url): @@ -57,5 +59,6 @@ print("ERROR: installation failed:\n%s"%e, file=sys.stderr) sys.exit(1) + if __name__ == '__main__': install_main() diff -Nru ros-rosdep-0.11.8/setup.py ros-rosdep-0.12.2/setup.py --- ros-rosdep-0.11.8/setup.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/setup.py 2018-03-21 23:40:00.000000000 +0000 @@ -5,23 +5,23 @@ setup( name='rosdep', - version=__version__, + version=__version__, # noqa:F821 packages=['rosdep2', 'rosdep2.platforms'], package_dir={'': 'src'}, install_requires=['catkin_pkg', 'rospkg >= 1.0.37', 'rosdistro >= 0.4.0', 'PyYAML >= 3.1'], test_suite='nose.collector', test_requires=['mock', 'nose >= 1.0'], scripts=['scripts/rosdep', 'scripts/rosdep-source'], - author="Tully Foote, Ken Conley", - author_email="tfoote@osrfoundation.org", - url="http://wiki.ros.org/rosdep", - download_url="http://download.ros.org/downloads/rosdep/", + author='Tully Foote, Ken Conley', + author_email='tfoote@osrfoundation.org', + url='http://wiki.ros.org/rosdep', + download_url='http://download.ros.org/downloads/rosdep/', keywords=['ROS'], classifiers=[ - "Programming Language :: Python", - "License :: OSI Approved :: BSD License"], - description="rosdep package manager abstrction tool for ROS", - long_description="Command-line tool for installing system " - "dependencies on a variety of platforms.", - license="BSD" + 'Programming Language :: Python', + 'License :: OSI Approved :: BSD License'], + description='rosdep package manager abstraction tool for ROS', + long_description='Command-line tool for installing system ' + 'dependencies on a variety of platforms.', + license='BSD' ) diff -Nru ros-rosdep-0.11.8/src/rosdep2/catkin_packages.py ros-rosdep-0.12.2/src/rosdep2/catkin_packages.py --- ros-rosdep-0.11.8/src/rosdep2/catkin_packages.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/catkin_packages.py 2018-03-21 23:40:00.000000000 +0000 @@ -6,7 +6,7 @@ try: from catkin_pkg.packages import find_packages except ImportError: - print("catkin_pkg was not detected, please install it.", + print('catkin_pkg was not detected, please install it.', file=sys.stderr) sys.exit(1) @@ -28,20 +28,20 @@ path = os.path.abspath(path) if path in _catkin_packages_cache: if verbose: - print("found in cache.", file=sys.stderr) + print('found in cache.', file=sys.stderr) return _catkin_packages_cache[path] packages = find_packages(path) if type(packages) == dict and packages != {}: package_names = [package.name for package in packages.values()] if verbose: - print("found " + str(len(packages)) + " packages.") + print('found ' + str(len(packages)) + ' packages.') for package in package_names: - print(" {0}".format(package)) + print(' {0}'.format(package)) _catkin_packages_cache[path] = package_names return package_names else: if verbose: - print("failed to find packages.", file=sys.stderr) + print('failed to find packages.', file=sys.stderr) return [] diff -Nru ros-rosdep-0.11.8/src/rosdep2/catkin_support.py ros-rosdep-0.12.2/src/rosdep2/catkin_support.py --- ros-rosdep-0.11.8/src/rosdep2/catkin_support.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/catkin_support.py 2018-03-21 23:40:00.000000000 +0000 @@ -27,20 +27,23 @@ from .platforms.osx import BREW_INSTALLER from .platforms.pip import PIP_INSTALLER from .platforms.redhat import YUM_INSTALLER +from .platforms.freebsd import PKG_INSTALLER from .rep3 import download_targets_data from .rosdistrohelper import get_targets from .rospkg_loader import DEFAULT_VIEW_KEY from .sources_list import get_sources_list_dir, DataSourceMatcher, SourcesListLoader + class ValidationFailed(Exception): pass + def call(command, pipe=None): """ Copy of call() function from catkin-generate-debian to mimic output """ working_dir = '.' - #print('+ cd %s && ' % working_dir + ' '.join(command)) + # print('+ cd %s && ' % working_dir + ' '.join(command)) process = Popen(command, stdout=pipe, stderr=pipe, cwd=working_dir) output, unused_err = process.communicate() retcode = process.poll() @@ -49,6 +52,7 @@ if pipe: return output + def get_ubuntu_targets(rosdistro): """ Get a list of Ubuntu distro codenames for the specified ROS @@ -64,16 +68,18 @@ targets_data['electric'] = {'ubuntu': legacy_targets['electric']} return targets_data[rosdistro]['ubuntu'] + def get_installer(installer_name): """ Expected installers APT_INSTALLER, YUM_INSTALLER, ...""" installer_context = create_default_installer_context() return installer_context.get_installer(installer_name) + def resolve_for_os(rosdep_key, view, installer, os_name, os_version): """ Resolve rosdep key to dependencies. - + :param os_name: OS name, e.g. 'ubuntu' :raises: :exc:`rosdep2.ResolutionError` @@ -110,8 +116,8 @@ raise ValidationFailed("""rosdep database does not have any sources. Please make sure you have a valid configuration in: \t%s -"""%(sources_list_dir)) - +""" % (sources_list_dir)) + # for vestigial reasons, using the roskg loader, but we're only # actually using the backend db as resolution is not resource-name based lookup = RosdepLookup.create_from_rospkg(sources_loader=sources_loader) diff -Nru ros-rosdep-0.11.8/src/rosdep2/core.py ros-rosdep-0.12.2/src/rosdep2/core.py --- ros-rosdep-0.11.8/src/rosdep2/core.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/core.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,20 +31,23 @@ import sys import traceback + def rd_debug(s): - if "ROSDEP_DEBUG" in os.environ: + if 'ROSDEP_DEBUG' in os.environ: print(s) + def print_bold(msg): """ print message printed to screen with bold decoration for greater clarity :param msg: message to print, ``str`` """ if sys.platform in ['win32']: - print('%s'%msg) #windows console is terrifically boring + print('%s' % msg) # windows console is terrifically boring else: - print('\033[1m%s\033[0m'%msg) - + print('\033[1m%s\033[0m' % msg) + + class InvalidData(Exception): """ Data is not in valid rosdep format. @@ -54,9 +57,11 @@ super(InvalidData, self).__init__(message) self.origin = origin + class UnsupportedOs(Exception): pass - + + class RosdepInternalError(Exception): def __init__(self, e, message=None): @@ -69,33 +74,36 @@ def __str__(self): return self.message + class CachePermissionError(Exception): """Failure when writing the cache.""" pass - + + class DownloadFailure(Exception): """ Failure downloading sources list data for I/O or other format reasons. """ pass + class InstallFailed(Exception): def __init__(self, failure=None, failures=None): """ One of failure/failures must be set. - - :param failure: single (installer_key, message) tuple. + + :param failure: single (installer_key, message) tuple. :param failures: list of (installer_key, message) tuples """ if failures is not None: self.failures = failures elif not failure: - raise ValueError("failure is None") + raise ValueError('failure is None') else: self.failures = [failure] - + def __str__(self): - return '\n'.join(['%s: %s'%(key, message) for (key, message) in self.failures]) + return '\n'.join(['%s: %s' % (key, message) for (key, message) in self.failures]) diff -Nru ros-rosdep-0.11.8/src/rosdep2/dependency_graph.py ros-rosdep-0.12.2/src/rosdep2/dependency_graph.py --- ros-rosdep-0.11.8/src/rosdep2/dependency_graph.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/dependency_graph.py 2018-03-21 23:40:00.000000000 +0000 @@ -74,7 +74,7 @@ :raises: :exc:`AssertionError` if the rosdep_key is in the traveled keys, indicating a cycle has occurred. """ - assert rosdep_key not in traveled_keys, "A cycle in the dependency graph occurred with key `%s`." % rosdep_key + assert rosdep_key not in traveled_keys, 'A cycle in the dependency graph occurred with key `%s`.' % rosdep_key traveled_keys.append(rosdep_key) for dependency in self[rosdep_key]['dependencies']: self.detect_cycles(dependency, traveled_keys) @@ -92,7 +92,7 @@ for dependency in self[rosdep_key]['dependencies']: if dependency not in self: raise KeyError( - "Invalid Graph Structure: rosdep key `%s` does not exist in the dictionary of resolutions." + 'Invalid Graph Structure: rosdep key `%s` does not exist in the dictionary of resolutions.' % dependency) self[dependency]['is_root'] = False # Check each entry for cyclical dependencies diff -Nru ros-rosdep-0.11.8/src/rosdep2/gbpdistro_support.py ros-rosdep-0.12.2/src/rosdep2/gbpdistro_support.py --- ros-rosdep-0.11.8/src/rosdep2/gbpdistro_support.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/gbpdistro_support.py 2018-03-21 23:40:00.000000000 +0000 @@ -6,7 +6,7 @@ try: import urlparse except ImportError: - import urllib.parse as urlparse #py3k + import urllib.parse as urlparse # py3k import os from rospkg.os_detect import OS_DEBIAN @@ -14,7 +14,6 @@ from rospkg.os_detect import OS_OSX from rospkg.os_detect import OS_UBUNTU -create_default_installer_context = None from .core import InvalidData, DownloadFailure from .platforms.debian import APT_INSTALLER from .platforms.osx import BREW_INSTALLER @@ -25,17 +24,19 @@ import warnings -#py3k +create_default_installer_context = None + +# py3k try: unicode -except: +except NameError: basestring = unicode = str # location of an example gbpdistro file for reference and testing FUERTE_GBPDISTRO_URL = 'https://raw.github.com/ros/rosdistro/' \ - + 'master/releases/fuerte.yaml' + 'master/releases/fuerte.yaml' -#seconds to wait before aborting download of gbpdistro data +# seconds to wait before aborting download of gbpdistro data DOWNLOAD_TIMEOUT = 15.0 @@ -61,6 +62,7 @@ # For compatability url defaults to '' + def gbprepo_to_rosdep_data(gbpdistro_data, targets_data, url=''): """ DEPRECATED: the rosdistro file format has changed according to REP137 @@ -69,23 +71,23 @@ :raises: :exc:`InvalidData` """ - warnings.warn("deprecated: see REP137 and rosdistro", PreRep137Warning) + warnings.warn('deprecated: see REP137 and rosdistro', PreRep137Warning) # Error reporting for this isn't nearly as good as it could be # (e.g. doesn't separate gbpdistro vs. targets, nor provide # origin), but rushing this implementation a bit. try: if not type(targets_data) == dict: - raise InvalidData("targets data must be a dict") + raise InvalidData('targets data must be a dict') if not type(gbpdistro_data) == dict: - raise InvalidData("gbpdistro data must be a dictionary") + raise InvalidData('gbpdistro data must be a dictionary') if gbpdistro_data['type'] != 'gbp': raise InvalidData('gbpdistro must be of type "gbp"') # compute the default target data for the release_name release_name = gbpdistro_data['release-name'] - if not release_name in targets_data: - raise InvalidData("targets file does not contain information " - + "for release [%s]" % (release_name)) + if release_name not in targets_data: + raise InvalidData('targets file does not contain information ' + 'for release [%s]' % (release_name)) else: # take the first match target_data = targets_data[release_name] @@ -95,12 +97,12 @@ gbp_repos = gbpdistro_data['repositories'] # Ensure gbp_repos is a dict if type(gbp_repos) != dict: - raise InvalidData("invalid repo spec in gbpdistro data: " + str(gbp_repos) - + ". Invalid repositories entry, must be dict.") + raise InvalidData('invalid repo spec in gbpdistro data: ' + str(gbp_repos) + + '. Invalid repositories entry, must be dict.') for rosdep_key, repo in gbp_repos.items(): if type(repo) != dict: - raise InvalidData("invalid repo spec in gbpdistro data: " - + str(repo)) + raise InvalidData('invalid repo spec in gbpdistro data: ' + + str(repo)) for pkg in repo.get('packages', {rosdep_key: None}): rosdep_data[pkg] = {} @@ -125,7 +127,7 @@ for t in repo_targets: if not isinstance(t, basestring): - raise InvalidData("invalid target spec: %s" % (t)) + raise InvalidData('invalid target spec: %s' % (t)) # rosdep_data[pkg][OS_UBUNTU][t] = { rosdep_data[pkg][OS_UBUNTU][t] = { APT_INSTALLER: {'packages': [deb_package_name]} @@ -134,11 +136,12 @@ rosdep_data[pkg]['_is_ros'] = True return rosdep_data except KeyError as e: - raise InvalidData("Invalid GBP-distro/targets format: missing key: " - + str(e)) + raise InvalidData('Invalid GBP-distro/targets format: missing key: ' + + str(e)) # REP137 compliant + def get_gbprepo_as_rosdep_data(gbpdistro): """ :raises: :exc:`InvalidData` @@ -167,9 +170,9 @@ package_name = package_name.replace('_', '-') for os_name in distro_file.platforms: - if not os_name in rosdep_data[pkg]: + if os_name not in rosdep_data[pkg]: rosdep_data[pkg][os_name] = {} - if not os_name in default_installers: + if os_name not in default_installers: default_installers[os_name] = ctx.get_default_os_installer_key(os_name) for os_code_name in distro_file.platforms[os_name]: rosdep_data[pkg][os_name][os_code_name] = { @@ -207,5 +210,5 @@ targets_data, gbpdistro_url) except Exception as e: - raise DownloadFailure("Failed to download target platform data " - + "for gbpdistro:\n\t" + str(e)) + raise DownloadFailure('Failed to download target platform data ' + 'for gbpdistro:\n\t' + str(e)) diff -Nru ros-rosdep-0.11.8/src/rosdep2/__init__.py ros-rosdep-0.12.2/src/rosdep2/__init__.py --- ros-rosdep-0.11.8/src/rosdep2/__init__.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/__init__.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -38,20 +38,20 @@ import sys from .installers import InstallerContext, Installer, \ - PackageManagerInstaller + PackageManagerInstaller from .core import RosdepInternalError, InstallFailed, UnsupportedOs, \ - InvalidData, DownloadFailure + InvalidData, DownloadFailure from .model import RosdepDatabase, RosdepDatabaseEntry from .lookup import RosdepDefinition, RosdepView, RosdepLookup, \ - ResolutionError + ResolutionError from .loader import RosdepLoader # don't let import error take down code as when attempting to compute version number try: from .rospkg_loader import RosPkgLoader except ImportError: - print("Cannot import rospkg, rosdep will not function properly", - file=sys.stderr) + print('Cannot import rospkg, rosdep will not function properly', + file=sys.stderr) def create_default_installer_context(verbose=False): @@ -64,10 +64,11 @@ from .platforms import pip from .platforms import gem from .platforms import redhat + from .platforms import freebsd from .platforms import slackware from .platforms import source - platform_mods = [arch, cygwin, debian, gentoo, opensuse, osx, redhat, slackware] + platform_mods = [arch, cygwin, debian, gentoo, opensuse, osx, redhat, slackware, freebsd] installer_mods = [source, pip, gem] + platform_mods context = InstallerContext() @@ -76,31 +77,33 @@ # setup installers for m in installer_mods: if verbose: - print("registering installers for %s"%(m.__name__)) + print('registering installers for %s' % (m.__name__)) m.register_installers(context) # setup platforms for m in platform_mods: if verbose: - print("registering platforms for %s"%(m.__name__)) + print('registering platforms for %s' % (m.__name__)) m.register_platforms(context) return context -from . import gbpdistro_support + +from . import gbpdistro_support # noqa gbpdistro_support.create_default_installer_context = create_default_installer_context -#TODO: this was partially abstracted from main() for another library, +# TODO: this was partially abstracted from main() for another library, # but it turned out to be unnecessary. Not sure it's worth maintaining # separately, especially in the top-level module. + def get_default_installer(installer_context=None, verbose=False): """ Based on the active OS and installer context configuration, get the installer to use and the necessary configuration state (installer keys, OS name/version). - - :returns: installer, installer_keys, default_key, os_name, os_version. + + :returns: installer, installer_keys, default_key, os_name, os_version. """ if installer_context is None: installer_context = create_default_installer_context(verbose=verbose) @@ -114,12 +117,14 @@ installer = installer_context.get_installer(default_key) return installer, installer_keys, default_key, os_name, os_version -__all__ = ['InstallerContext', 'Installer', 'PackageManagerInstaller', - 'RosdepInternalError', 'InstallFailed', 'UnsupportedOs', 'InvalidData', - 'DownloadFailure', - 'RosdepDatabase', 'RosdepDatabaseEntry', - 'RosdepDefinition', 'RosdepView', 'RosdepLookup', 'ResolutionError', - 'RosdepLoader', 'RosPkgLoader', - 'get_default_installer', - 'create_default_installer_context', - ] + +__all__ = [ + 'InstallerContext', 'Installer', 'PackageManagerInstaller', + 'RosdepInternalError', 'InstallFailed', 'UnsupportedOs', 'InvalidData', + 'DownloadFailure', + 'RosdepDatabase', 'RosdepDatabaseEntry', + 'RosdepDefinition', 'RosdepView', 'RosdepLookup', 'ResolutionError', + 'RosdepLoader', 'RosPkgLoader', + 'get_default_installer', + 'create_default_installer_context', +] diff -Nru ros-rosdep-0.11.8/src/rosdep2/installers.py ros-rosdep-0.12.2/src/rosdep2/installers.py --- ros-rosdep-0.11.8/src/rosdep2/installers.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/installers.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -45,13 +45,15 @@ # though there are some touch points over how this interfaces with the # rospkg.os_detect library, i.e. how platforms can tweak these # detectors and how the higher-level APIs can override them. + + class InstallerContext(object): """ :class:`InstallerContext` manages the context of execution for rosdep as it relates to the installers, OS detectors, and other extensible APIs. """ - + def __init__(self, os_detect=None): """ :param os_detect: (optional) @@ -74,10 +76,10 @@ self.os_override = None self.verbose = False - + def set_verbose(self, verbose): self.verbose = verbose - + def set_os_override(self, os_name, os_version): """ Override the OS detector with *os_name* and *os_version*. See @@ -87,7 +89,7 @@ :param os_version: OS version value to use, ``str`` """ if self.verbose: - print("overriding OS to [%s:%s]"%(os_name, os_version)) + print('overriding OS to [%s:%s]' % (os_name, os_version)) self.os_override = os_name, os_version def get_os_version_type(self, os_name): @@ -95,9 +97,9 @@ def set_os_version_type(self, os_name, version_type): if not hasattr(version_type, '__call__'): - raise ValueError("version type should be a method") + raise ValueError('version type should be a method') self.os_version_type[os_name] = version_type - + def get_os_name_and_version(self): """ Get the OS name and version key to use for resolution and @@ -114,7 +116,7 @@ os_key = self.get_os_version_type(os_name) os_version = os_key(self.os_detect) return os_name, os_version - + def get_os_detect(self): """ :returns os_detect: :class:`OsDetect` instance used for @@ -140,11 +142,11 @@ del self.installers[installer_key] return if not isinstance(installer, Installer): - raise TypeError("installer must be a instance of Installer") + raise TypeError('installer must be a instance of Installer') if self.verbose: - print("registering installer [%s]"%(installer_key)) + print('registering installer [%s]' % (installer_key)) self.installers[installer_key] = installer - + def get_installer(self, installer_key): """ :returns: :class:`Installer` class associated with *installer_key*. @@ -164,13 +166,13 @@ :returns: list of OS keys that have registered with this context, ``[str]`` """ return self.os_installers.keys() - + def add_os_installer_key(self, os_key, installer_key): """ Register an installer for the specified OS. This will fail with a :exc:`KeyError` if no :class:`Installer` can be found with the associated *installer_key*. - + :param os_key: Key for OS :param installer_key: Key for installer to add to OS :raises: :exc:`KeyError`: if installer for *installer_key* @@ -179,7 +181,7 @@ # validate, will throw KeyError self.get_installer(installer_key) if self.verbose: - print("add installer [%s] to OS [%s]"%(installer_key, os_key)) + print('add installer [%s] to OS [%s]' % (installer_key, os_key)) if os_key in self.os_installers: self.os_installers[os_key].append(installer_key) else: @@ -190,7 +192,7 @@ Get list of installer keys registered for the specified OS. These keys can be resolved by calling :meth:`InstallerContext.get_installer`. - + :param os_key: Key for OS :raises: :exc:`KeyError`: if no information for OS *os_key* is registered. """ @@ -210,14 +212,14 @@ :raises: :exc:`KeyError`: if installer for *installer_key* is not set or if OS for *os_key* has no associated installers. """ - if not os_key in self.os_installers: - raise KeyError("unknown OS: %s"%(os_key)) + if os_key not in self.os_installers: + raise KeyError('unknown OS: %s' % (os_key)) if not hasattr(installer_key, '__call__'): - raise ValueError("version type should be a method") + raise ValueError('version type should be a method') if not installer_key(self.os_detect) in self.os_installers[os_key]: - raise KeyError("installer [%s] is not associated with OS [%s]. call add_os_installer_key() first"%(installer_key(self.os_detect), os_key)) + raise KeyError('installer [%s] is not associated with OS [%s]. call add_os_installer_key() first' % (installer_key(self.os_detect), os_key)) if self.verbose: - print("set default installer for OS [%s]"%(os_key,)) + print('set default installer for OS [%s]' % (os_key,)) self.default_os_installer[os_key] = installer_key def get_default_os_installer_key(self, os_key): @@ -229,18 +231,19 @@ :returns: :class:`Installer` :raises: :exc:`KeyError`: if no information for OS *os_key* is registered. """ - if not os_key in self.os_installers: - raise KeyError("unknown OS: %s"%(os_key)) + if os_key not in self.os_installers: + raise KeyError('unknown OS: %s' % (os_key)) try: installer_key = self.default_os_installer[os_key](self.os_detect) - if not installer_key in self.os_installers[os_key]: - raise KeyError("installer [%s] is not associated with OS [%s]. call add_os_installer_key() first"%(installer_key, os_key)) + if installer_key not in self.os_installers[os_key]: + raise KeyError('installer [%s] is not associated with OS [%s]. call add_os_installer_key() first' % (installer_key, os_key)) # validate, will throw KeyError self.get_installer(installer_key) return installer_key except KeyError: return None + class Installer(object): """ The :class:`Installer` API is designed around opaque *resolved* @@ -256,8 +259,8 @@ :returns: ``True`` if all of the *resolved* items are installed on the local system """ - raise NotImplementedError("is_installed", resolved_item) - + raise NotImplementedError('is_installed', resolved_item) + def get_install_command(self, resolved, interactive=True, reinstall=False, quiet=False): """ :param resolved: list of resolved installation items, ``[opaque]`` @@ -265,22 +268,22 @@ e.g. Pass through ``-y`` or equivalant to package manager. :param reinstall: If `True`, install everything even if already installed """ - raise NotImplementedError("get_package_install_command", resolved, interactive, reinstall, quiet) + raise NotImplementedError('get_package_install_command', resolved, interactive, reinstall, quiet) - def get_depends(self, rosdep_args): - """ + def get_depends(self, rosdep_args): + """ :returns: list of dependencies on other rosdep keys. Only necessary if the package manager doesn't handle dependencies. """ - return [] # Default return empty list + return [] # Default return empty list def resolve(self, rosdep_args_dict): """ :param rosdep_args_dict: argument dictionary to the rosdep rule for this package manager :returns: [resolutions]. resolved objects should be printable to a user, but are otherwise opaque. """ - raise NotImplementedError("Base class resolve", rosdep_args_dict) + raise NotImplementedError('Base class resolve', rosdep_args_dict) def unique(self, *resolved_rules): """ @@ -297,8 +300,9 @@ :param resolved_rules: resolved arguments. Resolved arguments must all be from this :class:`Installer` instance. """ - raise NotImplementedError("Base class unique", resolved_rules) - + raise NotImplementedError('Base class unique', resolved_rules) + + class PackageManagerInstaller(Installer): """ General form of a package manager :class:`Installer` @@ -308,7 +312,7 @@ - a detect function exists that can return a list of packages that are installed Also, if *supports_depends* is set to ``True``: - + - installer rosdep args spec can also include dependency specification with the key "depends" """ @@ -321,7 +325,7 @@ self.detect_fn = detect_fn self.supports_depends = supports_depends self.as_root = True - self.sudo_command = 'sudo -H' if os.geteuid() != 0 else "" + self.sudo_command = 'sudo -H' if os.geteuid() != 0 else '' def elevate_priv(self, cmd): """ @@ -338,15 +342,15 @@ """ packages = None if type(rosdep_args) == dict: - packages = rosdep_args.get("packages", []) - if type(packages) == type("string"): + packages = rosdep_args.get('packages', []) + if isinstance(packages, str): packages = packages.split() - elif type(rosdep_args) == type('str'): + elif isinstance(rosdep_args, str): packages = rosdep_args.split(' ') elif type(rosdep_args) == list: packages = rosdep_args else: - raise InvalidData("Invalid rosdep args: %s"%(rosdep_args)) + raise InvalidData('Invalid rosdep args: %s' % (rosdep_args)) return packages def unique(self, *resolved_rules): @@ -357,46 +361,47 @@ for resolved in resolved_rules: s.update(resolved) return sorted(list(s)) - + def get_packages_to_install(self, resolved, reinstall=False): - ''' + """ Return a list of packages (out of *resolved*) that still need to get installed. - ''' + """ if reinstall: return resolved if not resolved: return [] else: - return list(set(resolved) - set(self.detect_fn(resolved))) + detected = self.detect_fn(resolved) + return [x for x in resolved if x not in detected] def is_installed(self, resolved_item): - ''' + """ Check if a given package was installed. - ''' + """ return not self.get_packages_to_install([resolved_item]) def get_version_strings(self): - ''' + """ Return a list of version information strings. Where each string is of the form " ". For example, ["apt-get x.y.z"] or ["pip x.y.z", "setuptools x.y.z"]. - ''' + """ raise NotImplementedError('subclasses must implement get_version_strings method') def get_install_command(self, resolved, interactive=True, reinstall=False, quiet=False): raise NotImplementedError('subclasses must implement', resolved, interactive, reinstall, quiet) - def get_depends(self, rosdep_args): - """ + def get_depends(self, rosdep_args): + """ :returns: list of dependencies on other rosdep keys. Only necessary if the package manager doesn't handle dependencies. """ if self.supports_depends and type(rosdep_args) == dict: return rosdep_args.get('depends', []) - return [] # Default return empty list + return [] # Default return empty list def normalize_uninstalled_to_list(uninstalled): @@ -415,7 +420,7 @@ def __init__(self, installer_context, lookup): self.installer_context = installer_context self.lookup = lookup - + def get_uninstalled(self, resources, implicit=False, verbose=False): """ Get list of system dependencies that have not been installed @@ -431,39 +436,39 @@ Uninstalled is a dictionary with the installer_key as the key. :raises: :exc:`RosdepInternalError` """ - + installer_context = self.installer_context # resolutions have been unique()d if verbose: - print("resolving for resources [%s]"%(', '.join(resources))) + print('resolving for resources [%s]' % (', '.join(resources))) resolutions, errors = self.lookup.resolve_all(resources, installer_context, implicit=implicit) # for each installer, figure out what is left to install uninstalled = [] if resolutions == []: return uninstalled, errors - for installer_key, resolved in resolutions: #py3k + for installer_key, resolved in resolutions: # py3k if verbose: - print("resolution: %s [%s]" % (installer_key, ', '.join([str(r) for r in resolved]))) + print('resolution: %s [%s]' % (installer_key, ', '.join([str(r) for r in resolved]))) try: installer = installer_context.get_installer(installer_key) - except KeyError as e: # lookup has to be buggy to cause this + except KeyError as e: # lookup has to be buggy to cause this raise RosdepInternalError(e) try: packages_to_install = installer.get_packages_to_install(resolved) except Exception as e: rd_debug(traceback.format_exc()) - raise RosdepInternalError(e, message="Bad installer [%s]: %s"%(installer_key, e)) + raise RosdepInternalError(e, message='Bad installer [%s]: %s' % (installer_key, e)) # only create key if there is something to do if packages_to_install: uninstalled.append((installer_key, packages_to_install)) if verbose: - print("uninstalled: [%s]"%(', '.join([str(p) for p in packages_to_install]))) - + print('uninstalled: [%s]' % (', '.join([str(p) for p in packages_to_install]))) + return uninstalled, errors - + def install(self, uninstalled, interactive=True, simulate=False, continue_on_error=False, reinstall=False, verbose=False, quiet=False): """ @@ -489,7 +494,7 @@ and *continue_on_error* is ``False``. :raises: :exc:`KeyError` If *uninstalled* value has invalid installer keys - + Example:: uninstalled, errors = installer.get_uninstalled(packages) @@ -497,11 +502,11 @@ """ if verbose: print( - "install options: reinstall[%s] simulate[%s] interactive[%s]" % + 'install options: reinstall[%s] simulate[%s] interactive[%s]' % (reinstall, simulate, interactive) ) uninstalled_list = normalize_uninstalled_to_list(uninstalled) - print("install: uninstalled keys are %s" % ', '.join(uninstalled_list)) + print('install: uninstalled keys are %s' % ', '.join(uninstalled_list)) # Squash uninstalled again, in case some dependencies were already installed squashed_uninstalled = [] @@ -522,7 +527,7 @@ if not continue_on_error: raise else: - #accumulate errors + # accumulate errors failures.extend(e.failures) if failures: raise InstallFailed(failures=failures) @@ -533,7 +538,7 @@ Lower-level API for installing a rosdep dependency. The rosdep keys have already been resolved to *installer_key* and *resolved* via :exc:`RosdepLookup` or other means. - + :param installer_key: Key for installer to apply to *resolved*, ``str`` :param resolved: Opaque resolution list from :class:`RosdepLookup`. :param interactive: If ``True``, allow interactive prompts (default ``True``) @@ -542,7 +547,7 @@ already installed (default ``False``). :param verbose: If ``True``, print verbose output to screen (default ``False``) :param quiet: If ``True``, supress output except for errors (default ``False``) - + :raises: :exc:`InstallFailed` if any of *resolved* fail to install. """ installer_context = self.installer_context @@ -550,37 +555,56 @@ command = installer.get_install_command(resolved, interactive=interactive, reinstall=reinstall, quiet=quiet) if not command: if verbose: - print("#No packages to install") + print('#No packages to install') return if simulate: - print("#[%s] Installation commands:"%(installer_key)) + print('#[%s] Installation commands:' % (installer_key)) for sub_command in command: - print(' '+' '.join(sub_command)) + if isinstance(sub_command[0], list): + sub_cmd_len = len(sub_command) + for i, cmd in enumerate(sub_command): + print(" '%s' (alternative %d/%d)" % (' '.join(cmd), i + 1, sub_cmd_len)) + else: + print(' ' + ' '.join(sub_command)) # nothing left to do for simulation if simulate: return - + + def run_command(command, installer_key, failures, verbose): + # always echo commands to screen + print_bold('executing command [%s]' % ' '.join(command)) + result = subprocess.call(command) + if verbose: + print('command return code [%s]: %s' % (' '.join(command), result)) + if result != 0: + failures.append((installer_key, 'command [%s] failed' % (' '.join(command)))) + return result + # run each install command set and collect errors failures = [] for sub_command in command: - # always echo commands to screen - print_bold("executing command [%s]"%' '.join(sub_command)) - result = subprocess.call(sub_command) - if verbose: - print("command return code [%s]: %s"%(' '.join(sub_command), result)) + if isinstance(sub_command[0], list): # list of alternatives + alt_failures = [] + for alt_command in sub_command: + result = run_command(alt_command, installer_key, alt_failures, verbose) + if result == 0: # one successsfull command is sufficient + alt_failures = [] # clear failuers from other alternatives + break + failures.extend(alt_failures) + else: + result = run_command(sub_command, installer_key, failures, verbose) if result != 0: - failures.append((installer_key, 'command [%s] failed'%(' '.join(sub_command))) ) if not continue_on_error: raise InstallFailed(failures=failures) # test installation of each for r in resolved: if not installer.is_installed(r): - failures.append((installer_key, "Failed to detect successful installation of [%s]"%(r))) + failures.append((installer_key, 'Failed to detect successful installation of [%s]' % (r))) # finalize result if failures: raise InstallFailed(failures=failures) elif verbose: - print("#successfully installed") + print('#successfully installed') diff -Nru ros-rosdep-0.11.8/src/rosdep2/loader.py ros-rosdep-0.12.2/src/rosdep2/loader.py --- ros-rosdep-0.11.8/src/rosdep2/loader.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/loader.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -41,11 +41,12 @@ ROSDEP_YAML = 'rosdep.yaml' + class RosdepLoader: """ - Base API for loading rosdep information by package or stack name. + Base API for loading rosdep information by package or stack name. """ - + def load_rosdep_yaml(self, yaml_contents, origin): """ Utility routine for unmarshalling rosdep data encoded as YAML. @@ -56,7 +57,7 @@ try: return yaml.load(yaml_contents) except yaml.YAMLError as e: - raise InvalidData("Invalid YAML in [%s]: %s"%(origin, e), origin=origin) + raise InvalidData('Invalid YAML in [%s]: %s' % (origin, e), origin=origin) def load_view(self, view_name, rosdep_db, verbose=False): """ @@ -69,7 +70,7 @@ :raises: :exc:`InvalidData` :raises: :exc:`rospkg.ResourceNotFound` if view cannot be located """ - raise NotImplementedError(view_name, rosdep_db, verbose) #pychecker + raise NotImplementedError(view_name, rosdep_db, verbose) # pychecker def get_loadable_resources(self): raise NotImplementedError() @@ -81,8 +82,8 @@ """ :raises: :exc:`rospkg.ResourceNotFound` if *resource_name* cannot be found. """ - raise NotImplementedError(resource_name, implicit) #pychecker - + raise NotImplementedError(resource_name, implicit) # pychecker + def get_view_key(self, resource_name): """ Map *resource_name* to a view key. In rospkg, this maps a ROS @@ -92,4 +93,4 @@ :returns: Name of view that *resource_name* is in, ``None`` if no associated view. :raises: :exc:`rospkg.ResourceNotFound` if *resource_name* cannot be found. """ - raise NotImplementedError(resource_name) + raise NotImplementedError(resource_name) diff -Nru ros-rosdep-0.11.8/src/rosdep2/lookup.py ros-rosdep-0.12.2/src/rosdep2/lookup.py --- ros-rosdep-0.11.8/src/rosdep2/lookup.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/lookup.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -45,6 +45,7 @@ from . import catkin_packages + class RosdepDefinition(object): """ Single rosdep dependency definition. This data is stored as the @@ -53,8 +54,8 @@ See REP 111, 'Multiple Package Manager Support for Rosdep' for a discussion of this raw format. """ - - def __init__(self, rosdep_key, data, origin=""): + + def __init__(self, rosdep_key, data, origin=''): """ :param rosdep_key: key/name of rosdep dependency :param data: raw rosdep data for a single rosdep dependency, ``dict`` @@ -62,11 +63,11 @@ """ self.rosdep_key = rosdep_key if not isinstance(data, dict): - raise InvalidData("rosdep data for [%s] must be a dictionary" % (self.rosdep_key), origin=origin) + raise InvalidData('rosdep data for [%s] must be a dictionary' % (self.rosdep_key), origin=origin) self.data = data self.origin = origin - def reverse_merge(self, new_data, origin="", verbose=False): + def reverse_merge(self, new_data, origin='', verbose=False): """ Merge two definitions together, with existing rules taking precendence. Definitions are merged at the os_name level, meaning that if two rules @@ -78,10 +79,10 @@ for os_name, rules in new_data.items(): if os_name not in self.data: if verbose: - print("[%s] adding rules for os [%s] to [%s]"%(origin, os_name, self.rosdep_key), file=sys.stderr) + print('[%s] adding rules for os [%s] to [%s]' % (origin, os_name, self.rosdep_key), file=sys.stderr) self.data[os_name] = rules elif verbose: - print("[%s] ignoring [%s] for os [%s], already loaded"%(origin, self.rosdep_key, os_name), file=sys.stderr) + print('[%s] ignoring [%s] for os [%s], already loaded' % (origin, self.rosdep_key, os_name), file=sys.stderr) def get_rule_for_platform(self, os_name, os_version, installer_keys, default_installer_key): """ @@ -100,12 +101,12 @@ data = self.data if type(data) != dict: - raise InvalidData("rosdep value for [%s] must be a dictionary"%(self.rosdep_key), origin=self.origin) + raise InvalidData('rosdep value for [%s] must be a dictionary' % (self.rosdep_key), origin=self.origin) if os_name not in data: - raise ResolutionError(rosdep_key, data, os_name, os_version, "No definition of [%s] for OS [%s]"%(rosdep_key, os_name)) + raise ResolutionError(rosdep_key, data, os_name, os_version, 'No definition of [%s] for OS [%s]' % (rosdep_key, os_name)) data = data[os_name] return_key = default_installer_key - + # REP 111: rosdep first interprets the key as a # PACKAGE_MANAGER. If this test fails, it will be interpreted # as an OS_VERSION_CODENAME. @@ -126,24 +127,32 @@ # we've already checked for PACKAGE_MANAGER_KEY, so # version key must be present here for data to be valid # dictionary value. + # if the os_version is not defined and there is no wildcard + if os_version not in data and '*' not in data: + raise ResolutionError(rosdep_key, self.data, os_name, os_version, 'No definition of [%s] for OS version [%s]' % (rosdep_key, os_version)) + # if the os_version has the value None + if os_version in data and data[os_version] is None: + raise ResolutionError(rosdep_key, self.data, os_name, os_version, '[%s] defined as "not available" for OS version [%s]' % (rosdep_key, os_version)) + # if os version is not defined (and there is a wildcard) fallback to the wildcard if os_version not in data: - raise ResolutionError(rosdep_key, self.data, os_name, os_version, "No definition of [%s] for OS version [%s]"%(rosdep_key, os_version)) + os_version = '*' data = data[os_version] if type(data) == dict: for installer_key in installer_keys: if installer_key in data: data = data[installer_key] - return_key = installer_key + return_key = installer_key break if type(data) not in (dict, list, type('str')): - raise InvalidData("rosdep OS definition for [%s:%s] must be a dictionary, string, or list: %s"%(self.rosdep_key, os_name, data), origin=self.origin) + raise InvalidData('rosdep OS definition for [%s:%s] must be a dictionary, string, or list: %s' % (self.rosdep_key, os_name, data), origin=self.origin) return return_key, data def __str__(self): - return "%s:\n%s"%(self.origin, yaml.dump(self.data, default_flow_style=False)) - + return '%s:\n%s' % (self.origin, yaml.dump(self.data, default_flow_style=False)) + + class ResolutionError(Exception): def __init__(self, rosdep_key, rosdep_data, os_name, os_version, message): @@ -162,7 +171,8 @@ \trosdep key : %s \tOS name : %s \tOS version : %s -\tData: %s"""%(self.args[0], self.rosdep_key, self.os_name, self.os_version, pretty_data) +\tData: %s""" % (self.args[0], self.rosdep_key, self.os_name, self.os_version, pretty_data) + class RosdepView(object): """ @@ -171,14 +181,14 @@ view merges entries for a particular stack. This view can then be queries to lookup and resolve individual rosdep dependencies. """ - + def __init__(self, name): self.name = name - self.rosdep_defs = {} # {str: RosdepDefinition} + self.rosdep_defs = {} # {str: RosdepDefinition} def __str__(self): - return '\n'.join(["%s: %s"%val for val in self.rosdep_defs.items()]) - + return '\n'.join(['%s: %s' % val for val in self.rosdep_defs.items()]) + def lookup(self, rosdep_name): """ :returns: :class:`RosdepDefinition` @@ -191,7 +201,7 @@ :returns: list of rosdep names in this view """ return self.rosdep_defs.keys() - + def merge(self, update_entry, override=False, verbose=False): """ Merge rosdep database update into main database. Merge rules @@ -203,14 +213,14 @@ always use rules from update_entry """ if verbose: - print("view[%s]: merging from cache of [%s]"%(self.name, update_entry.origin)) + print('view[%s]: merging from cache of [%s]' % (self.name, update_entry.origin)) db = self.rosdep_defs for dep_name, dep_data in update_entry.rosdep_data.items(): # convert data into RosdepDefinition model update_definition = RosdepDefinition(dep_name, dep_data, update_entry.origin) # First rule wins or override, no rule-merging. - if override or not dep_name in db: + if override or dep_name not in db: db[dep_name] = update_definition elif dep_name in db: db[dep_name].reverse_merge(dep_data, update_entry.origin, verbose=verbose) @@ -227,7 +237,7 @@ # workspace, then skip it rather than resolve it if verbose: print("rosdep key '{0}'".format(rosdep_key) + - " is in the catkin workspace, skipping.", + ' is in the catkin workspace, skipping.', file=sys.stderr) del rosdep_keys[i] return rosdep_keys @@ -241,7 +251,7 @@ # If the key is in the list of keys to explicitly skip, skip it if verbose: print("rosdep key '{0}'".format(rosdep_key) + - " was listed in the skipped packages, skipping.", + ' was listed in the skipped packages, skipping.', file=sys.stderr) del rosdep_keys[i] return rosdep_keys @@ -256,7 +266,7 @@ on the filesystem will not be reflected if the rosdep information has already been loaded. """ - + def __init__(self, rosdep_db, loader): """ :param loader: Loader to use for loading rosdep data by stack @@ -265,10 +275,10 @@ """ self.rosdep_db = rosdep_db self.loader = loader - - self._view_cache = {} # {str: {RosdepView}} - self._resolve_cache = {} # {str : (os_name, os_version, installer_key, resolution, dependencies)} - + + self._view_cache = {} # {str: {RosdepView}} + self._resolve_cache = {} # {str : (os_name, os_version, installer_key, resolution, dependencies)} + # some APIs that deal with the entire environment save errors # in to self.errors instead of raising them in order to be # robust to single-stack faults. @@ -281,7 +291,7 @@ def get_loader(self): return self.loader - + def get_errors(self): """ Retrieve error state for API calls that do not directly report @@ -292,7 +302,7 @@ :returns: List of exceptions, ``[Exception]`` """ return self.errors[:] - + def get_rosdeps(self, resource_name, implicit=True): """ Get rosdeps that *resource_name* (e.g. package) requires. @@ -307,14 +317,14 @@ def get_resources_that_need(self, rosdep_name): """ :param rosdep_name: name of rosdep dependency - + :returns: list of package names that require rosdep, ``[str]`` """ return [k for k in self.loader.get_loadable_resources() if rosdep_name in self.get_rosdeps(k, implicit=False)] @staticmethod - def create_from_rospkg(rospack=None, rosstack=None, - sources_loader=None, + def create_from_rospkg(rospack=None, rosstack=None, + sources_loader=None, verbose=False): """ Create :class:`RosdepLookup` based on current ROS package @@ -342,7 +352,7 @@ # individual sources it can load from. SourcesListLoader # cannot do delayed evaluation of OS setting due to matcher. underlay_key = SourcesListLoader.ALL_VIEW_KEY - + # Create the rospkg loader on top of the underlay loader = RosPkgLoader(rospack=rospack, rosstack=rosstack, underlay_key=underlay_key) @@ -366,10 +376,10 @@ :param installer_context: :class:`InstallerContext` :param implicit: Install implicit (recursive) dependencies of resources. Default ``False``. - - :returns: (resolutions, errors), ``([(str, [str])], {str: ResolutionError})``. resolutions provides - an ordered list of resolution tuples. A resolution tuple's first element is the installer - key (e.g.: apt or homebrew) and the second element is a list of opaque resolution values for that + + :returns: (resolutions, errors), ``([(str, [str])], {str: ResolutionError})``. resolutions provides + an ordered list of resolution tuples. A resolution tuple's first element is the installer + key (e.g.: apt or homebrew) and the second element is a list of opaque resolution values for that installer. errors maps package names to an :exc:`ResolutionError` or :exc:`KeyError` exception. :raises: :exc:`RosdepInternalError` if unexpected error in constructing dependency graph @@ -382,13 +392,13 @@ try: rosdep_keys = self.get_rosdeps(resource_name, implicit=implicit) if self.verbose: - print("resolve_all: resource [%s] requires rosdep keys [%s]"%(resource_name, ', '.join(rosdep_keys)), file=sys.stderr) + print('resolve_all: resource [%s] requires rosdep keys [%s]' % (resource_name, ', '.join(rosdep_keys)), file=sys.stderr) rosdep_keys = prune_catkin_packages(rosdep_keys, self.verbose) rosdep_keys = prune_skipped_packages(rosdep_keys, self.skipped_keys, self.verbose) for rosdep_key in rosdep_keys: try: installer_key, resolution, dependencies = \ - self.resolve(rosdep_key, resource_name, installer_context) + self.resolve(rosdep_key, resource_name, installer_context) depend_graph[rosdep_key]['installer_key'] = installer_key depend_graph[rosdep_key]['install_keys'] = list(resolution) depend_graph[rosdep_key]['dependencies'] = list(dependencies) @@ -398,7 +408,7 @@ if depend_rosdep_key in depend_graph: continue installer_key, resolution, more_dependencies = \ - self.resolve(depend_rosdep_key, resource_name, installer_context) + self.resolve(depend_rosdep_key, resource_name, installer_context) dependencies.extend(more_dependencies) depend_graph[depend_rosdep_key]['installer_key'] = installer_key depend_graph[depend_rosdep_key]['install_keys'] = list(resolution) @@ -410,11 +420,11 @@ errors[resource_name] = e try: - # TODO: I really don't like AssertionErrors here; this should be modeled as 'CyclicGraphError' + # TODO: I really don't like AssertionErrors here; this should be modeled as 'CyclicGraphError' # or something more explicit. No need to continue if this API errors. resolutions_flat = depend_graph.get_ordered_dependency_list() except AssertionError as e: - raise InvalidData("cycle in dependency graph detected: %s"%(e)) + raise InvalidData('cycle in dependency graph detected: %s' % (e)) except KeyError as e: raise RosdepInternalError(e) @@ -444,13 +454,13 @@ view = self.get_rosdep_view_for_resource(resource_name) if view is None: - raise ResolutionError(rosdep_key, None, os_name, os_version, "[%s] does not have a rosdep view"%(resource_name)) + raise ResolutionError(rosdep_key, None, os_name, os_version, '[%s] does not have a rosdep view' % (resource_name)) try: - #print("KEYS", view.rosdep_defs.keys()) + # print("KEYS", view.rosdep_defs.keys()) definition = view.lookup(rosdep_key) except KeyError: rd_debug(view) - raise ResolutionError(rosdep_key, None, os_name, os_version, "Cannot locate rosdep definition for [%s]"%(rosdep_key)) + raise ResolutionError(rosdep_key, None, os_name, os_version, 'Cannot locate rosdep definition for [%s]' % (rosdep_key)) # check cache: the main motivation for the cache is that # source rosdeps are expensive to resolve @@ -459,9 +469,11 @@ cache_os_name = cache_value[0] cache_os_version = cache_value[1] cache_view_name = cache_value[2] - if cache_os_name == os_name and \ - cache_os_version == os_version and \ - cache_view_name == view.name: + if ( + cache_os_name == os_name and + cache_os_version == os_version and + cache_view_name == view.name + ): return cache_value[3:] # get the rosdep data for the platform @@ -469,14 +481,14 @@ installer_keys = installer_context.get_os_installer_keys(os_name) default_key = installer_context.get_default_os_installer_key(os_name) except KeyError: - raise ResolutionError(rosdep_key, definition.data, os_name, os_version, "Unsupported OS [%s]"%(os_name)) + raise ResolutionError(rosdep_key, definition.data, os_name, os_version, 'Unsupported OS [%s]' % (os_name)) installer_key, rosdep_args_dict = definition.get_rule_for_platform(os_name, os_version, installer_keys, default_key) # resolve the rosdep data for the platform try: installer = installer_context.get_installer(installer_key) except KeyError: - raise ResolutionError(rosdep_key, definition.data, os_name, os_version, "Unsupported installer [%s]"%(installer_key)) + raise ResolutionError(rosdep_key, definition.data, os_name, os_version, 'Unsupported installer [%s]' % (installer_key)) resolution = installer.resolve(rosdep_args_dict) dependencies = installer.get_depends(rosdep_args_dict) @@ -485,7 +497,7 @@ self._resolve_cache[rosdep_key] = os_name, os_version, view.name, installer_key, resolution, list(dependencies) return installer_key, resolution, dependencies - + def _load_all_views(self, loader): """ Load all available view keys. In general, this is equivalent @@ -494,7 +506,7 @@ they will be saved in the *errors* field. :param loader: override self.loader - :raises: :exc:`RosdepInternalError` + :raises: :exc:`RosdepInternalError` """ for resource_name in loader.get_loadable_views(): try: @@ -503,26 +515,26 @@ self.errors.append(e) except InvalidData as e: self.errors.append(e) - + def _load_view_dependencies(self, view_key, loader): """ Initialize internal :exc:`RosdepDatabase` on demand. Not thread-safe. :param view_key: name of view to load dependencies for. - + :raises: :exc:`rospkg.ResourceNotFound` If view cannot be located :raises: :exc:`InvalidData` if view's data is invaid :raises: :exc:`RosdepInternalError` """ - rd_debug("_load_view_dependencies[%s]"%(view_key)) + rd_debug('_load_view_dependencies[%s]' % (view_key)) db = self.rosdep_db if db.is_loaded(view_key): return try: loader.load_view(view_key, db, verbose=self.verbose) entry = db.get_view_data(view_key) - rd_debug("_load_view_dependencies[%s]: %s"%(view_key, entry.view_dependencies)) + rd_debug('_load_view_dependencies[%s]: %s' % (view_key, entry.view_dependencies)) for d in entry.view_dependencies: self._load_view_dependencies(d, loader) except InvalidData: @@ -534,7 +546,7 @@ raise except KeyError as e: raise RosdepInternalError(e) - + def create_rosdep_view(self, view_name, view_keys, verbose=False): """ :param view_name: name of view to create @@ -550,9 +562,9 @@ db_entry = db.get_view_data(view_key) view.merge(db_entry, verbose=verbose) if verbose: - print("View [%s], merged views:\n"%(view_name)+"\n".join([" * %s"%view_key for view_key in view_keys]), file=sys.stderr) + print('View [%s], merged views:\n' % (view_name) + '\n'.join([' * %s' % view_key for view_key in view_keys]), file=sys.stderr) return view - + def get_rosdep_view_for_resource(self, resource_name, verbose=False): """ Get a :class:`RosdepView` for a specific ROS resource *resource_name*. @@ -564,30 +576,30 @@ :returns: :class:`RosdepView` for specific ROS resource *resource_name*, or ``None`` if no view is associated with this resource. - + :raises: :exc:`RosdepConflict` if view cannot be created due to conflict rosdep definitions. :raises: :exc:`rospkg.ResourceNotFound` if *view_key* cannot be located - :raises: :exc:`RosdepInternalError` + :raises: :exc:`RosdepInternalError` """ view_key = self.loader.get_view_key(resource_name) if not view_key: - #NOTE: this may not be the right behavior and this happens - #for packages that are not in a stack. + # NOTE: this may not be the right behavior and this happens + # for packages that are not in a stack. return None return self.get_rosdep_view(view_key, verbose=verbose) - + def get_rosdep_view(self, view_key, verbose=False): """ Get a :class:`RosdepView` associated with *view_key*. Views can be queries to resolve rosdep keys to definitions. :param view_key: Name of rosdep view (e.g. ROS stack name), ``str`` - + :raises: :exc:`RosdepConflict` if view cannot be created due to conflict rosdep definitions. :raises: :exc:`rospkg.ResourceNotFound` if *view_key* cannot be located - :raises: :exc:`RosdepInternalError` + :raises: :exc:`RosdepInternalError` """ if view_key in self._view_cache: return self._view_cache[view_key] @@ -622,9 +634,9 @@ :param rosdep_name: name of rosdep to lookup :returns: list of (stack_name, origin) where rosdep is defined. - :raises: :exc:`RosdepInternalError` + :raises: :exc:`RosdepInternalError` """ - #TODOXXX: change this to return errors object so that caller cannot ignore + # TODOXXX: change this to return errors object so that caller cannot ignore self._load_all_views(self.loader) db = self.rosdep_db retval = [] @@ -633,5 +645,5 @@ # not much abstraction in the entry object if rosdep_name in entry.rosdep_data: retval.append((view_name, entry.origin)) - + return retval diff -Nru ros-rosdep-0.11.8/src/rosdep2/main.py ros-rosdep-0.12.2/src/rosdep2/main.py --- ros-rosdep-0.11.8/src/rosdep2/main.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/main.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,10 +1,10 @@ #!/usr/bin/env python # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -13,7 +13,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -65,9 +65,9 @@ from .lookup import RosdepLookup, ResolutionError from .rospkg_loader import DEFAULT_VIEW_KEY from .sources_list import update_sources_list, get_sources_cache_dir,\ - download_default_sources_list, SourcesListLoader,CACHE_INDEX,\ - get_sources_list_dir, get_default_sources_list_file,\ - DEFAULT_SOURCES_LIST_URL + download_default_sources_list, SourcesListLoader, CACHE_INDEX,\ + get_sources_list_dir, get_default_sources_list_file,\ + DEFAULT_SOURCES_LIST_URL from .rosdistrohelper import PreRep137Warning from .catkin_packages import find_catkin_packages_in @@ -78,6 +78,7 @@ class UsageError(Exception): pass + _usage = """usage: rosdep [options] Commands: @@ -93,16 +94,16 @@ rosdep init initialize rosdep sources in /etc/ros/rosdep. May require sudo. - + rosdep keys ... list the rosdep keys that the packages depend on. rosdep resolve resolve to system dependencies - + rosdep update update the local rosdep database based on the rosdep sources. - + rosdep what-needs ... print a list of packages that declare a rosdep on (at least one of) @@ -117,6 +118,7 @@ "rosdep update" with sudo accidentally. """ + def _get_default_RosdepLookup(options): """ Helper routine for converting command-line options into @@ -130,6 +132,7 @@ lookup.verbose = options.verbose return lookup + def rosdep_main(args=None): if args is None: args = sys.argv[1:] @@ -141,11 +144,11 @@ print(""" ERROR: Rosdep cannot find all required resources to answer your query %s -"""%(error_to_human_readable(e)), file=sys.stderr) +""" % (error_to_human_readable(e)), file=sys.stderr) sys.exit(1) except UsageError as e: print(_usage, file=sys.stderr) - print("ERROR: %s"%(str(e)), file=sys.stderr) + print('ERROR: %s' % (str(e)), file=sys.stderr) sys.exit(os.EX_USAGE) except RosdepInternalError as e: print(""" @@ -156,21 +159,21 @@ rosdep version: %s %s -"""%(__version__, e.message), file=sys.stderr) +""" % (__version__, e.message), file=sys.stderr) sys.exit(1) except ResolutionError as e: print(""" ERROR: %s %s -"""%(e.args[0], e), file=sys.stderr) +""" % (e.args[0], e), file=sys.stderr) sys.exit(1) except CachePermissionError as e: print(str(e)) print("Try running 'sudo rosdep fix-permissions'") sys.exit(1) except UnsupportedOs as e: - print("Unsupported OS: %s\nSupported OSes are [%s]"%(e.args[0], ', '.join(e.args[1])), file=sys.stderr) + print('Unsupported OS: %s\nSupported OSes are [%s]' % (e.args[0], ', '.join(e.args[1])), file=sys.stderr) sys.exit(1) except Exception as e: print(""" @@ -181,15 +184,16 @@ rosdep version: %s %s -"""%(e, __version__, traceback.format_exc()), file=sys.stderr) +""" % (e, __version__, traceback.format_exc()), file=sys.stderr) sys.exit(1) - + + def check_for_sources_list_init(sources_cache_dir): """ Check to see if sources list and cache are present. *sources_cache_dir* alone is enough to pass as the user has the option of passing in a cache dir. - + If check fails, tell user how to resolve and sys exit. """ commands = [] @@ -203,17 +207,17 @@ if not os.path.exists(sources_list_dir): commands.insert(0, 'sudo rosdep init') else: - filelist = [f for f in os.listdir(sources_list_dir) if f.endswith('.list')] + filelist = [f for f in os.listdir(sources_list_dir) if f.endswith('.list')] if not filelist: commands.insert(0, 'sudo rosdep init') if commands: - commands = '\n'.join([" %s"%c for c in commands]) + commands = '\n'.join([' %s' % c for c in commands]) print(""" ERROR: your rosdep installation has not been initialized yet. Please run: - + %s -"""%(commands), file=sys.stderr) +""" % (commands), file=sys.stderr) sys.exit(1) else: return True @@ -253,74 +257,75 @@ opener = build_opener(proxy, auth, HTTPHandler) install_opener(opener) + def _rosdep_main(args): - # sources cache dir is our local database. + # sources cache dir is our local database. default_sources_cache = get_sources_cache_dir() parser = OptionParser(usage=_usage, prog='rosdep') - parser.add_option("--os", dest="os_override", default=None, - metavar="OS_NAME:OS_VERSION", help="Override OS name and version (colon-separated), e.g. ubuntu:lucid") - parser.add_option("-c", "--sources-cache-dir", dest="sources_cache_dir", default=default_sources_cache, - metavar='SOURCES_CACHE_DIR', help="Override %s"%(default_sources_cache)) - parser.add_option("--verbose", "-v", dest="verbose", default=False, - action="store_true", help="verbose display") - parser.add_option("--version", dest="print_version", default=False, - action="store_true", help="print just the rosdep version, then exit") - parser.add_option("--all-versions", dest="print_all_versions", default=False, - action="store_true", help="print rosdep version and version of installers, then exit") - parser.add_option("--reinstall", dest="reinstall", default=False, - action="store_true", help="(re)install all dependencies, even if already installed") - parser.add_option("--default-yes", "-y", dest="default_yes", default=False, - action="store_true", help="Tell the package manager to default to y or fail when installing") - parser.add_option("--simulate", "-s", dest="simulate", default=False, - action="store_true", help="Simulate install") - parser.add_option("-r", dest="robust", default=False, - action="store_true", help="Continue installing despite errors.") - parser.add_option("-q", dest="quiet", default=False, - action="store_true", help="Quiet. Suppress output except for errors.") - parser.add_option("-a", "--all", dest="rosdep_all", default=False, - action="store_true", help="select all packages") - parser.add_option("-n", dest="recursive", default=True, - action="store_false", help="Do not consider implicit/recursive dependencies. Only valid with 'keys', 'check', and 'install' commands.") - parser.add_option("--ignore-packages-from-source", "--ignore-src", "-i", - dest='ignore_src', default=False, action="store_true", + parser.add_option('--os', dest='os_override', default=None, + metavar='OS_NAME:OS_VERSION', help='Override OS name and version (colon-separated), e.g. ubuntu:lucid') + parser.add_option('-c', '--sources-cache-dir', dest='sources_cache_dir', default=default_sources_cache, + metavar='SOURCES_CACHE_DIR', help='Override %s' % (default_sources_cache)) + parser.add_option('--verbose', '-v', dest='verbose', default=False, + action='store_true', help='verbose display') + parser.add_option('--version', dest='print_version', default=False, + action='store_true', help='print just the rosdep version, then exit') + parser.add_option('--all-versions', dest='print_all_versions', default=False, + action='store_true', help='print rosdep version and version of installers, then exit') + parser.add_option('--reinstall', dest='reinstall', default=False, + action='store_true', help='(re)install all dependencies, even if already installed') + parser.add_option('--default-yes', '-y', dest='default_yes', default=False, + action='store_true', help='Tell the package manager to default to y or fail when installing') + parser.add_option('--simulate', '-s', dest='simulate', default=False, + action='store_true', help='Simulate install') + parser.add_option('-r', dest='robust', default=False, + action='store_true', help='Continue installing despite errors.') + parser.add_option('-q', dest='quiet', default=False, + action='store_true', help='Quiet. Suppress output except for errors.') + parser.add_option('-a', '--all', dest='rosdep_all', default=False, + action='store_true', help='select all packages') + parser.add_option('-n', dest='recursive', default=True, + action='store_false', help="Do not consider implicit/recursive dependencies. Only valid with 'keys', 'check', and 'install' commands.") + parser.add_option('--ignore-packages-from-source', '--ignore-src', '-i', + dest='ignore_src', default=False, action='store_true', help="Affects the 'check' and 'install' verbs. If " - "specified then rosdep will not install keys " - "that are found to be catkin packages anywhere in " - "the ROS_PACKAGE_PATH or in any of the directories " - "given by the --from-paths option.") - parser.add_option("--skip-keys", - dest='skip_keys', action="append", default=[], + 'specified then rosdep will not install keys ' + 'that are found to be catkin packages anywhere in ' + 'the ROS_PACKAGE_PATH or in any of the directories ' + 'given by the --from-paths option.') + parser.add_option('--skip-keys', + dest='skip_keys', action='append', default=[], help="Affects the 'check' and 'install' verbs. The " - "specified rosdep keys will be ignored, i.e. not " - "resolved and not installed. The option can be supplied multiple " - "times. A space separated list of rosdep keys can also " - "be passed as a string. A more permanent solution to " - "locally ignore a rosdep key is creating a local rosdep rule " - "with an empty list of packages (include it in " - "/etc/ros/rosdep/sources.list.d/ before the defaults).") - parser.add_option("--filter-for-installers", - action="append", default=[], + 'specified rosdep keys will be ignored, i.e. not ' + 'resolved and not installed. The option can be supplied multiple ' + 'times. A space separated list of rosdep keys can also ' + 'be passed as a string. A more permanent solution to ' + 'locally ignore a rosdep key is creating a local rosdep rule ' + 'with an empty list of packages (include it in ' + '/etc/ros/rosdep/sources.list.d/ before the defaults).') + parser.add_option('--filter-for-installers', + action='append', default=[], help="Affects the 'db' verb. If supplied, the output of the 'db' " - "command is filtered to only list packages whose installer " - "is in the provided list. The option can be supplied " - "multiple times. A space separated list of installers can also " - "be passed as a string. Example: `--filter-for-installers \"apt pip\"`") - parser.add_option("--from-paths", dest='from_paths', - default=False, action="store_true", + 'command is filtered to only list packages whose installer ' + 'is in the provided list. The option can be supplied ' + 'multiple times. A space separated list of installers can also ' + 'be passed as a string. Example: `--filter-for-installers "apt pip"`') + parser.add_option('--from-paths', dest='from_paths', + default=False, action='store_true', help="Affects the 'check', 'keys', and 'install' verbs. " - "If specified the arguments to those verbs will be " - "considered paths to be searched, acting on all " - "catkin packages found there in.") - parser.add_option("--rosdistro", dest='ros_distro', default=None, - help="Explicitly sets the ROS distro to use, overriding " - "the normal method of detecting the ROS distro " - "using the ROS_DISTRO environment variable.") - parser.add_option("--as-root", default=[], action='append', - metavar="INSTALLER_KEY:", help="Override " - "whether sudo is used for a specific installer, " + 'If specified the arguments to those verbs will be ' + 'considered paths to be searched, acting on all ' + 'catkin packages found there in.') + parser.add_option('--rosdistro', dest='ros_distro', default=None, + help='Explicitly sets the ROS distro to use, overriding ' + 'the normal method of detecting the ROS distro ' + 'using the ROS_DISTRO environment variable.') + parser.add_option('--as-root', default=[], action='append', + metavar='INSTALLER_KEY:', help='Override ' + 'whether sudo is used for a specific installer, ' "e.g. '--as-root pip:false' or '--as-root \"pip:no homebrew:yes\"'. " - "Can be specified multiple times.") + 'Can be specified multiple times.') options, args = parser.parse_args(args) if options.print_version or options.print_all_versions: @@ -347,11 +352,11 @@ continue if version_strings: print() - print("Versions of installers:") + print('Versions of installers:') print('\n'.join([' ' + x for x in version_strings if x])) else: print() - print("No installers with versions available found.") + print('No installers with versions available found.') sys.exit(0) # flatten list of skipped keys and filter-for-installers @@ -359,10 +364,10 @@ options.filter_for_installers = [inst for s in options.filter_for_installers for inst in s.split(' ')] if len(args) == 0: - parser.error("Please enter a command") + parser.error('Please enter a command') command = args[0] - if not command in _commands: - parser.error("Unsupported command %s."%command) + if command not in _commands: + parser.error('Unsupported command %s.' % command) args = args[1:] if options.ros_distro: @@ -371,30 +376,32 @@ # Convert list of keys to dictionary options.as_root = dict((k, str_to_bool(v)) for k, v in key_list_to_dict(options.as_root).items()) - if not command in ['init', 'update', 'fix-permissions']: + if command not in ['init', 'update', 'fix-permissions']: check_for_sources_list_init(options.sources_cache_dir) - elif not command in ['fix-permissions']: + elif command not in ['fix-permissions']: setup_proxy_opener() if command in _command_rosdep_args: return _rosdep_args_handler(command, parser, options, args) elif command in _command_no_args: - return _no_args_handler(command, parser, options, args) + return _no_args_handler(command, parser, options, args) else: return _package_args_handler(command, parser, options, args) + def _no_args_handler(command, parser, options, args): if args: - parser.error("command [%s] takes no arguments"%(command)) + parser.error('command [%s] takes no arguments' % (command)) else: return command_handlers[command](options) - + + def _rosdep_args_handler(command, parser, options, args): # rosdep keys as args if options.rosdep_all: - parser.error("-a, --all is not a valid option for this command") + parser.error('-a, --all is not a valid option for this command') elif len(args) < 1: - parser.error("Please enter arguments for '%s'"%command) + parser.error("Please enter arguments for '%s'" % command) else: return command_handlers[command](args, options) @@ -402,7 +409,7 @@ def _package_args_handler(command, parser, options, args): if options.rosdep_all: if args: - parser.error("cannot specify additional arguments with -a") + parser.error('cannot specify additional arguments with -a') else: # let the loader filter the -a. This will take out some # packages that are catkinized (for now). @@ -411,7 +418,7 @@ args = loader.get_loadable_resources() not_found = [] elif not args: - parser.error("no packages or stacks specified") + parser.error('no packages or stacks specified') # package or stack names as args. have to convert stack names to packages. # - overrides to enable testing @@ -449,8 +456,8 @@ # Handle the --ignore-src option if command in ['install', 'check'] and options.ignore_src: if options.verbose: - print("Searching ROS_PACKAGE_PATH for " - "sources: " + str(os.environ['ROS_PACKAGE_PATH'].split(':'))) + print('Searching ROS_PACKAGE_PATH for ' + 'sources: ' + str(os.environ['ROS_PACKAGE_PATH'].split(':'))) ws_pkgs = get_workspace_packages() for path in os.environ['ROS_PACKAGE_PATH'].split(':'): path = os.path.abspath(path.strip()) @@ -458,7 +465,7 @@ pkgs = find_catkin_packages_in(path, options.verbose) ws_pkgs.extend(pkgs) elif options.verbose: - print("Skipping non-existent path " + path) + print('Skipping non-existent path ' + path) set_workspace_packages(ws_pkgs) lookup = _get_default_RosdepLookup(options) @@ -466,16 +473,17 @@ # Handle the --skip-keys option by pretending that they are packages in the catkin workspace if command in ['install', 'check'] and options.skip_keys: if options.verbose: - print("Skipping the specified rosdep keys:\n- " + '\n- '.join(options.skip_keys)) + print('Skipping the specified rosdep keys:\n- ' + '\n- '.join(options.skip_keys)) lookup.skipped_keys = options.skip_keys if 0 and not packages: # disable, let individual handlers specify behavior # possible with empty stacks - print("No packages in arguments, aborting") + print('No packages in arguments, aborting') return return command_handlers[command](lookup, packages, options) + def convert_os_override_option(options_os_override): """ Convert os_override option flag to ``(os_name, os_version)`` tuple, or @@ -487,12 +495,13 @@ if not options_os_override: return None val = options_os_override - if not ':' in val: - raise UsageError("OS override must be colon-separated OS_NAME:OS_VERSION, e.g. ubuntu:maverick") + if ':' not in val: + raise UsageError('OS override must be colon-separated OS_NAME:OS_VERSION, e.g. ubuntu:maverick') os_name = val[:val.find(':')] - os_version = val[val.find(':')+1:] + os_version = val[val.find(':') + 1:] return os_name, os_version - + + def configure_installer_context(installer_context, options): """ Configure the *installer_context* from *options*. @@ -505,23 +514,24 @@ os_override = convert_os_override_option(options.os_override) if os_override is not None: installer_context.set_os_override(*os_override) - for k,v in options.as_root.items(): + for k, v in options.as_root.items(): try: installer_context.get_installer(k).as_root = v except KeyError: raise UsageError("Installer '%s' not defined." % k) - + + def command_init(options): try: data = download_default_sources_list() except URLError as e: - print("ERROR: cannot download default sources list from:\n%s\nWebsite may be down."%(DEFAULT_SOURCES_LIST_URL)) + print('ERROR: cannot download default sources list from:\n%s\nWebsite may be down.' % (DEFAULT_SOURCES_LIST_URL)) return 4 except DownloadFailure as e: - print("ERROR: cannot download default sources list from:\n%s\nWebsite may be down."%(DEFAULT_SOURCES_LIST_URL)) + print('ERROR: cannot download default sources list from:\n%s\nWebsite may be down.' % (DEFAULT_SOURCES_LIST_URL)) print(e) return 4 - # reuse path variable for error message + # reuse path variable for error message path = get_sources_list_dir() old_umask = os.umask(0o022) try: @@ -529,44 +539,47 @@ os.makedirs(path) path = get_default_sources_list_file() if os.path.exists(path): - print("ERROR: default sources list file already exists:\n\t%s\nPlease delete if you wish to re-initialize"%(path)) + print('ERROR: default sources list file already exists:\n\t%s\nPlease delete if you wish to re-initialize' % (path)) return 1 with open(path, 'w') as f: f.write(data) - print("Wrote %s"%(path)) - print("Recommended: please run\n\n\trosdep update\n") + print('Wrote %s' % (path)) + print('Recommended: please run\n\n\trosdep update\n') except IOError as e: - print("ERROR: cannot create %s:\n\t%s"%(path, e), file=sys.stderr) + print('ERROR: cannot create %s:\n\t%s' % (path, e), file=sys.stderr) return 2 except OSError as e: - print("ERROR: cannot create %s:\n\t%s\nPerhaps you need to run 'sudo rosdep init' instead"%(path, e), file=sys.stderr) + print("ERROR: cannot create %s:\n\t%s\nPerhaps you need to run 'sudo rosdep init' instead" % (path, e), file=sys.stderr) return 3 finally: os.umask(old_umask) - + + def command_update(options): error_occured = [] + def update_success_handler(data_source): - print("Hit %s"%(data_source.url)) + print('Hit %s' % (data_source.url)) + def update_error_handler(data_source, exc): - error_string = "ERROR: unable to process source [%s]:\n\t%s"%(data_source.url, exc) + error_string = 'ERROR: unable to process source [%s]:\n\t%s' % (data_source.url, exc) print(error_string, file=sys.stderr) error_occured.append(error_string) sources_list_dir = get_sources_list_dir() # disable deprecation warnings when using the command-line tool - warnings.filterwarnings("ignore", category=PreRep137Warning) + warnings.filterwarnings('ignore', category=PreRep137Warning) if not os.path.exists(sources_list_dir): - print("ERROR: no sources directory exists on the system meaning rosdep has not yet been initialized.\n\nPlease initialize your rosdep with\n\n\tsudo rosdep init\n") + print('ERROR: no sources directory exists on the system meaning rosdep has not yet been initialized.\n\nPlease initialize your rosdep with\n\n\tsudo rosdep init\n') return 1 - filelist = [f for f in os.listdir(sources_list_dir) if f.endswith('.list')] + filelist = [f for f in os.listdir(sources_list_dir) if f.endswith('.list')] if not filelist: - print("ERROR: no data sources in %s\n\nPlease initialize your rosdep with\n\n\tsudo rosdep init\n"%sources_list_dir, file=sys.stderr) + print('ERROR: no data sources in %s\n\nPlease initialize your rosdep with\n\n\tsudo rosdep init\n' % sources_list_dir, file=sys.stderr) return 1 try: - print("reading in sources list data from %s"%(sources_list_dir)) + print('reading in sources list data from %s' % (sources_list_dir)) sources_cache_dir = get_sources_cache_dir() try: if os.geteuid() == 0: @@ -577,27 +590,28 @@ pass update_sources_list(success_handler=update_success_handler, error_handler=update_error_handler) - print("updated cache in %s"%(sources_cache_dir)) + print('updated cache in %s' % (sources_cache_dir)) except InvalidData as e: - print("ERROR: invalid sources list file:\n\t%s"%(e), file=sys.stderr) + print('ERROR: invalid sources list file:\n\t%s' % (e), file=sys.stderr) return 1 except IOError as e: - print("ERROR: error loading sources list:\n\t%s"%(e), file=sys.stderr) + print('ERROR: error loading sources list:\n\t%s' % (e), file=sys.stderr) return 1 if error_occured: - print ("ERROR: Not all sources were able to be updated.\n[[[") + print('ERROR: Not all sources were able to be updated.\n[[[') for e in error_occured: - print (e) - print("]]]") + print(e) + print(']]]') return 1 - + def command_keys(lookup, packages, options): lookup = _get_default_RosdepLookup(options) rosdep_keys = get_keys(lookup, packages, options.recursive) _print_lookup_errors(lookup) print('\n'.join(rosdep_keys)) + def get_keys(lookup, packages, recursive): rosdep_keys = [] for package_name in packages: @@ -605,9 +619,10 @@ rosdep_keys.extend(deps) return set(rosdep_keys) + def command_check(lookup, packages, options): verbose = options.verbose - + installer_context = create_default_installer_context(verbose=verbose) configure_installer_context(installer_context, options) installer = RosdepInstaller(installer_context, lookup) @@ -616,32 +631,34 @@ # pretty print the result if [v for k, v in uninstalled if v]: - print("System dependencies have not been satisified:") + print('System dependencies have not been satisified:') for installer_key, resolved in uninstalled: if resolved: for r in resolved: - print("%s\t%s"%(installer_key, r)) + print('%s\t%s' % (installer_key, r)) else: - print("All system dependencies have been satisified") + print('All system dependencies have been satisified') if errors: for package_name, ex in errors.items(): if isinstance(ex, rospkg.ResourceNotFound): - print("ERROR[%s]: resource not found [%s]"%(package_name, ex.args[0]), file=sys.stderr) + print('ERROR[%s]: resource not found [%s]' % (package_name, ex.args[0]), file=sys.stderr) else: - print("ERROR[%s]: %s"%(package_name, ex), file=sys.stderr) + print('ERROR[%s]: %s' % (package_name, ex), file=sys.stderr) if uninstalled: return 1 else: return 0 + def error_to_human_readable(error): if isinstance(error, rospkg.ResourceNotFound): - return "Missing resource %s"%(error,) + return 'Missing resource %s' % (error,) elif isinstance(error, ResolutionError): - return "%s"%(error.args[0],) + return '%s' % (error.args[0],) else: - return "%s"%(error,) - + return '%s' % (error,) + + def command_install(lookup, packages, options): # map options install_options = dict(interactive=not options.default_yes, verbose=options.verbose, @@ -655,62 +672,49 @@ if options.reinstall: if options.verbose: - print("reinstall is true, resolving all dependencies") + print('reinstall is true, resolving all dependencies') try: uninstalled, errors = lookup.resolve_all(packages, installer_context, implicit=options.recursive) except InvalidData as e: - print("ERROR: unable to process all dependencies:\n\t%s"%(e), file=sys.stderr) + print('ERROR: unable to process all dependencies:\n\t%s' % (e), file=sys.stderr) return 1 else: uninstalled, errors = installer.get_uninstalled(packages, implicit=options.recursive, verbose=options.verbose) if options.verbose: uninstalled_dependencies = normalize_uninstalled_to_list(uninstalled) - print("uninstalled dependencies are: [%s]" % ', '.join(uninstalled_dependencies)) + print('uninstalled dependencies are: [%s]' % ', '.join(uninstalled_dependencies)) if errors: - err_msg = ("ERROR: the following packages/stacks could not have their " - "rosdep keys resolved\nto system dependencies") + err_msg = ('ERROR: the following packages/stacks could not have their ' + 'rosdep keys resolved\nto system dependencies') if rospkg.distro.current_distro_codename() is None: err_msg += ( - " (ROS distro is not set. " - "Make sure `ROS_DISTRO` environment variable is set, or use " - "`--rosdistro` option to specify the distro, " - "e.g. `--rosdistro indigo`)" + ' (ROS distro is not set. ' + 'Make sure `ROS_DISTRO` environment variable is set, or use ' + '`--rosdistro` option to specify the distro, ' + 'e.g. `--rosdistro indigo`)' ) - print(err_msg + ":", file=sys.stderr) + print(err_msg + ':', file=sys.stderr) for rosdep_key, error in errors.items(): - print("%s: %s"%(rosdep_key, error_to_human_readable(error)), file=sys.stderr) + print('%s: %s' % (rosdep_key, error_to_human_readable(error)), file=sys.stderr) if options.robust: - print("Continuing to install resolvable dependencies...") + print('Continuing to install resolvable dependencies...') else: return 1 try: installer.install(uninstalled, **install_options) if not options.simulate: - print("#All required rosdeps installed successfully") + print('#All required rosdeps installed successfully') return 0 except KeyError as e: raise RosdepInternalError(e) except InstallFailed as e: - print("ERROR: the following rosdeps failed to install", file=sys.stderr) - print('\n'.join([" %s: %s"%(k, m) for k,m in e.failures]), file=sys.stderr) + print('ERROR: the following rosdeps failed to install', file=sys.stderr) + print('\n'.join([' %s: %s' % (k, m) for k, m in e.failures]), file=sys.stderr) return 1 -def _compute_depdb_output(lookup, packages, options): - installer_context = create_default_installer_context(verbose=options.verbose) - os_name, os_version = _detect_os(installer_context, options) - - output = "Rosdep dependencies for operating system %s version %s "%(os_name, os_version) - for stack_name in stacks: - output += "\nSTACK: %s\n"%(stack_name) - view = lookup.get_stack_rosdep_view(stack_name) - for rosdep in view.keys(): - definition = view.lookup(rosdep) - resolved = resolve_definition(definition, os_name, os_version) - output = output + "<<<< %s -> %s >>>>\n"%(rosdep, resolved) - return output - + def command_db(options): # exact same setup logic as command_resolve, should possibly combine lookup = _get_default_RosdepLookup(options) @@ -724,10 +728,10 @@ raise UnsupportedOs(os_name, installer_context.get_os_keys()) installer = installer_context.get_installer(default_key) - print("OS NAME: %s"%os_name) - print("OS VERSION: %s"%os_version) + print('OS NAME: %s' % os_name) + print('OS VERSION: %s' % os_version) errors = [] - print("DB [key -> resolution]") + print('DB [key -> resolution]') # db does not leverage the resource-based API view = lookup.get_rosdep_view(DEFAULT_VIEW_KEY, verbose=options.verbose) for rosdep_name in view.keys(): @@ -737,25 +741,27 @@ if options.filter_for_installers and inst_key not in options.filter_for_installers: continue resolved = installer.resolve(rule) - resolved_str = " ".join(resolved) - print ("%s -> %s"%(rosdep_name, resolved_str)) + resolved_str = ' '.join([str(r) for r in resolved]) + print('%s -> %s' % (rosdep_name, resolved_str)) except ResolutionError as e: errors.append(e) - #TODO: add command-line option for users to be able to see this. - #This is useful for platform bringup, but useless for most users - #as the rosdep db contains numerous, platform-specific keys. - if 0: + # TODO: add command-line option for users to be able to see this. + # This is useful for platform bringup, but useless for most users + # as the rosdep db contains numerous, platform-specific keys. + if 0: for error in errors: - print("WARNING: %s"%(error_to_human_readable(error)), file=sys.stderr) + print('WARNING: %s' % (error_to_human_readable(error)), file=sys.stderr) + def _print_lookup_errors(lookup): for error in lookup.get_errors(): if isinstance(error, rospkg.ResourceNotFound): - print("WARNING: unable to locate resource %s"%(str(error.args[0])), file=sys.stderr) + print('WARNING: unable to locate resource %s' % (str(error.args[0])), file=sys.stderr) else: - print("WARNING: %s"%(str(error)), file=sys.stderr) - + print('WARNING: %s' % (str(error)), file=sys.stderr) + + def command_what_needs(args, options): lookup = _get_default_RosdepLookup(options) packages = [] @@ -764,7 +770,8 @@ _print_lookup_errors(lookup) print('\n'.join(set(packages))) - + + def command_where_defined(args, options): lookup = _get_default_RosdepLookup(options) locations = [] @@ -777,21 +784,22 @@ origin = location[1] print(origin) else: - print("ERROR: cannot find definition(s) for [%s]"%(', '.join(args)), file=sys.stderr) + print('ERROR: cannot find definition(s) for [%s]' % (', '.join(args)), file=sys.stderr) return 1 + def command_resolve(args, options): lookup = _get_default_RosdepLookup(options) installer_context = create_default_installer_context(verbose=options.verbose) configure_installer_context(installer_context, options) installer, installer_keys, default_key, \ - os_name, os_version = get_default_installer(installer_context=installer_context, - verbose=options.verbose) + os_name, os_version = get_default_installer(installer_context=installer_context, + verbose=options.verbose) invalid_key_errors = [] for rosdep_name in args: if len(args) > 1: - print("#ROSDEP[%s]"%rosdep_name) + print('#ROSDEP[%s]' % rosdep_name) view = lookup.get_rosdep_view(DEFAULT_VIEW_KEY, verbose=options.verbose) try: @@ -803,17 +811,18 @@ installer = installer_context.get_installer(rule_installer) resolved = installer.resolve(rule) - print("#%s"%(rule_installer)) - print (" ".join([str(r) for r in resolved])) + print('#%s' % (rule_installer)) + print(' '.join([str(r) for r in resolved])) for error in invalid_key_errors: - print("ERROR: no rosdep rule for %s"%(error), file=sys.stderr) + print('ERROR: no rosdep rule for %s' % (error), file=sys.stderr) for error in lookup.get_errors(): - print("WARNING: %s"%(error_to_human_readable(error)), file=sys.stderr) + print('WARNING: %s' % (error_to_human_readable(error)), file=sys.stderr) if invalid_key_errors: - return 1 # error exit code + return 1 # error exit code + def command_fix_permissions(options): import os @@ -848,15 +857,16 @@ except Exception: import traceback traceback.print_exc() - print("Failed to walk directory. Try with sudo?") + print('Failed to walk directory. Try with sudo?') else: if failed: - print("Failed to change ownership for:") + print('Failed to change ownership for:') for p, e in failed: - print("{0} --> {1}".format(p, e)) - print("Try with sudo?") + print('{0} --> {1}'.format(p, e)) + print('Try with sudo?') else: - print("Done.") + print('Done.') + command_handlers = { 'db': command_db, @@ -873,8 +883,8 @@ # backwards compat 'what_needs': command_what_needs, 'where_defined': command_where_defined, - 'depdb': command_db, - } + 'depdb': command_db, +} # commands that accept rosdep names as args _command_rosdep_args = ['what-needs', 'what_needs', 'where-defined', 'where_defined', 'resolve'] diff -Nru ros-rosdep-0.11.8/src/rosdep2/model.py ros-rosdep-0.12.2/src/rosdep2/model.py --- ros-rosdep-0.11.8/src/rosdep2/model.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/model.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -38,11 +38,12 @@ into a combined view on which queries can be made. """ + class RosdepDatabaseEntry(object): """ Stores rosdep data and metadata for a single view. """ - + def __init__(self, rosdep_data, view_dependencies, origin): """ :param rosdep_data: raw rosdep dictionary map for view @@ -53,14 +54,15 @@ self.rosdep_data = rosdep_data self.view_dependencies = view_dependencies self.origin = origin - + + class RosdepDatabase(object): """ Stores loaded rosdep data for multiple views. """ - + def __init__(self): - self._rosdep_db = {} # {view_name: RosdepDatabaseEntry} + self._rosdep_db = {} # {view_name: RosdepDatabaseEntry} def is_loaded(self, view_name): """ @@ -77,7 +79,7 @@ :param view_name: name of view to mark as loaded """ self.set_view_data(view_name, {}, [], None) - + def set_view_data(self, view_name, rosdep_data, view_dependencies, origin): """ Set data associated with view. This will create a new @@ -94,7 +96,7 @@ :returns: list of view names that are loaded into this database. """ return self._rosdep_db.keys() - + def get_view_data(self, view_name): """ :returns: :class:`RosdepDatabaseEntry` of given view. @@ -102,7 +104,7 @@ :raises: :exc:`KeyError` if no entry for *view_name* """ return self._rosdep_db[view_name] - + def get_view_dependencies(self, view_name): """ :raises: :exc:`KeyError` if *view_name* is not an entry, or if @@ -117,6 +119,6 @@ # make unique preserving order unique_deps = [] for d in dependencies: - if not d in unique_deps: + if d not in unique_deps: unique_deps.append(d) return unique_deps diff -Nru ros-rosdep-0.11.8/src/rosdep2/platforms/arch.py ros-rosdep-0.12.2/src/rosdep2/platforms/arch.py --- ros-rosdep-0.11.8/src/rosdep2/platforms/arch.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/platforms/arch.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,10 +1,10 @@ #!/usr/bin/env python # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -13,7 +13,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -36,20 +36,25 @@ ARCH_OS_NAME = 'arch' PACMAN_INSTALLER = 'pacman' + def register_installers(context): context.set_installer(PACMAN_INSTALLER, PacmanInstaller()) + def register_platforms(context): context.add_os_installer_key(ARCH_OS_NAME, SOURCE_INSTALLER) context.add_os_installer_key(ARCH_OS_NAME, PACMAN_INSTALLER) context.set_default_os_installer_key(ARCH_OS_NAME, lambda self: PACMAN_INSTALLER) + def pacman_detect_single(p): return not subprocess.call(['pacman', '-T', p], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + def pacman_detect(packages): return [p for p in packages if pacman_detect_single(p)] + class PacmanInstaller(PackageManagerInstaller): def __init__(self): @@ -60,7 +65,7 @@ if not packages: return [] - command = ['pacman', '-S'] + command = ['pacman', '-S'] if not interactive: command.append('--noconfirm') diff -Nru ros-rosdep-0.11.8/src/rosdep2/platforms/cygwin.py ros-rosdep-0.12.2/src/rosdep2/platforms/cygwin.py --- ros-rosdep-0.11.8/src/rosdep2/platforms/cygwin.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/platforms/cygwin.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,10 +1,10 @@ #!/usr/bin/env python # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -13,7 +13,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -39,21 +39,26 @@ APT_CYG_INSTALLER = 'apt-cyg' + def register_installers(context): context.set_installer(APT_CYG_INSTALLER, AptCygInstaller()) - + + def register_platforms(context): context.add_os_installer_key(OS_CYGWIN, SOURCE_INSTALLER) context.add_os_installer_key(OS_CYGWIN, APT_CYG_INSTALLER) context.set_default_os_installer_key(OS_CYGWIN, lambda self: APT_CYG_INSTALLER) + def cygcheck_detect_single(p): std_out = read_stdout(['cygcheck', '-c', p]) - return std_out.count("OK") > 0 + return std_out.count('OK') > 0 + def cygcheck_detect(packages): return [p for p in packages if cygcheck_detect_single(p)] + class AptCygInstaller(PackageManagerInstaller): """ An implementation of the :class:`Installer` for use on @@ -66,12 +71,13 @@ self.sudo_command = 'cygstart --action=runas' def get_install_command(self, resolved, interactive=True, reinstall=False, quiet=False): - packages = self.get_packages_to_install(resolved, reinstall=reinstall) - #TODO: interactive + packages = self.get_packages_to_install(resolved, reinstall=reinstall) + # TODO: interactive if not packages: return [] else: - return [self.elevate_priv(['apt-cyg', '-m', 'ftp://sourceware.org/pub/cygwinports', 'install'])+packages] + return [self.elevate_priv(['apt-cyg', '-m', 'ftp://sourceware.org/pub/cygwinports', 'install']) + packages] + if __name__ == '__main__': - print("test cygcheck_detect(true)", cygcheck_detect('cygwin')) + print('test cygcheck_detect(true)', cygcheck_detect('cygwin')) diff -Nru ros-rosdep-0.11.8/src/rosdep2/platforms/debian.py ros-rosdep-0.12.2/src/rosdep2/platforms/debian.py --- ros-rosdep-0.11.8/src/rosdep2/platforms/debian.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/platforms/debian.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,10 +1,10 @@ #!/usr/bin/env python # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -13,7 +13,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,7 +31,6 @@ from __future__ import print_function import subprocess import sys -import re from rospkg.os_detect import OS_DEBIAN, OS_LINARO, OS_UBUNTU, OS_ELEMENTARY, OsDetect @@ -42,18 +41,20 @@ from ..shell_utils import read_stdout # apt package manager key -APT_INSTALLER='apt' +APT_INSTALLER = 'apt' def register_installers(context): context.set_installer(APT_INSTALLER, AptInstaller()) + def register_platforms(context): register_debian(context) register_linaro(context) register_ubuntu(context) register_elementary(context) - + + def register_debian(context): context.add_os_installer_key(OS_DEBIAN, APT_INSTALLER) context.add_os_installer_key(OS_DEBIAN, PIP_INSTALLER) @@ -61,21 +62,28 @@ context.add_os_installer_key(OS_DEBIAN, SOURCE_INSTALLER) context.set_default_os_installer_key(OS_DEBIAN, lambda self: APT_INSTALLER) context.set_os_version_type(OS_DEBIAN, OsDetect.get_codename) - + + def register_linaro(context): - # Linaro is an alias for Ubuntu. If linaro is detected and it's not set as an override force ubuntu. + # Linaro is an alias for Ubuntu. If linaro is detected and it's not set as + # an override force ubuntu. (os_name, os_version) = context.get_os_name_and_version() if os_name == OS_LINARO and not context.os_override: - print("rosdep detected OS: [%s] aliasing it to: [%s]" % (OS_LINARO, OS_UBUNTU), file=sys.stderr) + print('rosdep detected OS: [%s] aliasing it to: [%s]' % + (OS_LINARO, OS_UBUNTU), file=sys.stderr) context.set_os_override(OS_UBUNTU, context.os_detect.get_codename()) + def register_elementary(context): - # Elementary is an alias for Ubuntu. If elementary is detected and it's not set as an override force ubuntu. + # Elementary is an alias for Ubuntu. If elementary is detected and it's + # not set as an override force ubuntu. (os_name, os_version) = context.get_os_name_and_version() if os_name == OS_ELEMENTARY and not context.os_override: - print("rosdep detected OS: [%s] aliasing it to: [%s]" % (OS_ELEMENTARY, OS_UBUNTU), file=sys.stderr) + print('rosdep detected OS: [%s] aliasing it to: [%s]' % + (OS_ELEMENTARY, OS_UBUNTU), file=sys.stderr) context.set_os_override(OS_UBUNTU, context.os_detect.get_codename()) + def register_ubuntu(context): context.add_os_installer_key(OS_UBUNTU, APT_INSTALLER) context.add_os_installer_key(OS_UBUNTU, PIP_INSTALLER) @@ -85,70 +93,60 @@ context.set_os_version_type(OS_UBUNTU, OsDetect.get_codename) -# detect that apt show indicates that the package is virtual -APT_PURELY_VIRTUAL_RE = re.compile( - r'as it is purely virtual', - flags=re.DOTALL) -# detect what lines in apt-cache showpkg show the packages providing a virtual -# package -APT_CACHE_REVERSE_PROVIDE_START_RE = re.compile( - r'^Reverse Provides:') -# format of a 'Reverse Provides' line in the apt-cache showpkg output -APT_CACHE_PROVIDER_RE = re.compile('^(.*?) (.*)$') - - -def _is_installed_as_virtual_package(package, exec_fn=None): - ''' - Check whether this is a virtual package and a package providing this - virtual package is installed. - +def _read_apt_cache_showpkg(packages, exec_fn=None): + """ + Output whether these packages are virtual package list providing package. + If one package was not found, it gets returned as non-virtual. :param exec_fn: see `dpkg_detect`; make sure that exec_fn supports a second, boolean, parameter. - ''' -# Note: This can be done much more concise when adding python-apt as a dependency: -# -# import apt -# cache = apt.Cache() -# if cache.is_virtual_package(package): -# for provider in cache.get_providing_packages(package): -# if cache[provider].is_installed: -# print('Virtual package {} is provided by {}'.format( -# package, provider.name)) -# return True -# return False -# - # check output of `apt show package' for whether it's a virtual - # package and if so use `apt-cache showpkg package' to get the providing - # packages. Then check if one of those is installed. - cmd = ['apt-cache', 'show', package] + """ + + cmd = ['apt-cache', 'showpkg'] + packages if exec_fn is None: exec_fn = read_stdout - std_out, std_err = exec_fn(cmd, True) # use stderr as well to hide error message ... not too nice, but hopefully cautious - if APT_PURELY_VIRTUAL_RE.search(std_out): - print('Package {} seems to be virtual; try to specify a providing package in your rosdep config.'.format(package)) - cmd = ['apt-cache', 'showpkg', package] - std_out = exec_fn(cmd) - is_provider = False # true when parsed line contains a povider - for line in std_out.split('\n'): - if is_provider: - match = APT_CACHE_PROVIDER_RE.match(line) - if not match: - print('WARNING: The output of {} is strange; unable to determine providers of virtual package {}'.format( - cmd[0] + ' ' + cmd[1], package)) - else: - provider_name, provider_version = match.groups() - # now that we have the name of the provider, finaly check - # whether the package is provided - if dpkg_detect([provider_name]): - print('Virtual package {} is provided by {}'.format(package, provider_name)) - return True - if APT_CACHE_REVERSE_PROVIDE_START_RE.match(line): - is_provider = True - # Note: Set this _after_ possibly parsing the current line to - # not parse the line containing - # APT_CACHE_REVERSE_PROVIDE_START_RE - return False # unable to find a provider that was installed + std_out = exec_fn(cmd).splitlines() + + starts = [] + notfound = set() + for p in packages: + last_start = starts[-1] if len(starts) > 0 else 0 + try: + starts.append(std_out.index('Package: %s' % p, last_start)) + except ValueError: + notfound.add(p) + starts.append(None) + + for p in packages: + if p in notfound: + yield p, False, None + continue + start = starts.pop(0) + lines = iter(std_out[start:starts[0]]) + + header = 'Package: %s' % p + # proceed to Package header + while next(lines) != header: + pass + + # proceed to versions section + while next(lines) != 'Versions: ': + pass + + # virtual packages don't have versions + if next(lines) != '': + yield p, False, None + continue + + # proceed to reserve provides section + while next(lines) != 'Reverse Provides: ': + pass + + pr = [line.split(' ', 2)[0] for line in lines] + if pr: + yield p, True, pr + else: + yield p, False, None def dpkg_detect(pkgs, exec_fn=None): @@ -175,30 +173,46 @@ if exec_fn is None: exec_fn = read_stdout - std_out = exec_fn(cmd) - std_out = std_out.replace('\'','') + std_out, std_err = exec_fn(cmd, True) + std_out = std_out.replace('\'', '') pkg_list = std_out.split('\n') for pkg in pkg_list: pkg_row = pkg.split() - if len(pkg_row) == 4 and (pkg_row[3] =='installed'): - ret_list.append( pkg_row[0]) + if len(pkg_row) == 4 and (pkg_row[3] == 'installed'): + ret_list.append(pkg_row[0]) installed_packages = [version_lock_map[r] for r in ret_list] # now for the remaining packages check, whether they are installed as # virtual packages - for rem in set(pkgs) - set(installed_packages): - if _is_installed_as_virtual_package(rem): - installed_packages.append(rem) + remaining = _read_apt_cache_showpkg(list(p for p in pkgs if p not in installed_packages)) + virtual = [n for (n, v, pr) in remaining if v and len(dpkg_detect(pr)) > 0] + + return installed_packages + virtual - return installed_packages +def _iterate_packages(packages, reinstall): + for entry in _read_apt_cache_showpkg(packages): + p, is_virtual, providers = entry + if is_virtual: + installed = [] + if reinstall: + installed = dpkg_detect(providers) + if len(installed) > 0: + for i in installed: + yield i + continue # don't ouput providers + yield providers + else: + yield p class AptInstaller(PackageManagerInstaller): + """ An implementation of the Installer for use on debian style systems. """ + def __init__(self): super(AptInstaller, self).__init__(dpkg_detect) @@ -207,15 +221,26 @@ version = output.splitlines()[0].split(' ')[1] return ['apt-get {}'.format(version)] + def _get_install_commands_for_package(self, base_cmd, package_or_list): + def pkg_command(p): + return self.elevate_priv(base_cmd + [p]) + + if isinstance(package_or_list, list): + return [pkg_command(p) for p in package_or_list] + else: + return pkg_command(package_or_list) + def get_install_command(self, resolved, interactive=True, reinstall=False, quiet=False): packages = self.get_packages_to_install(resolved, reinstall=reinstall) if not packages: return [] if not interactive and quiet: - return [self.elevate_priv(['apt-get', 'install', '-y', '-qq', p]) for p in packages] + base_cmd = ['apt-get', 'install', '-y', '-qq'] elif quiet: - return [self.elevate_priv(['apt-get', 'install', '-qq', p]) for p in packages] + base_cmd = ['apt-get', 'install', '-qq'] if not interactive: - return [self.elevate_priv(['apt-get', 'install', '-y', p]) for p in packages] + base_cmd = ['apt-get', 'install', '-y'] else: - return [self.elevate_priv(['apt-get', 'install', p]) for p in packages] + base_cmd = ['apt-get', 'install'] + + return [self._get_install_commands_for_package(base_cmd, p) for p in _iterate_packages(packages, reinstall)] diff -Nru ros-rosdep-0.11.8/src/rosdep2/platforms/freebsd.py ros-rosdep-0.12.2/src/rosdep2/platforms/freebsd.py --- ros-rosdep-0.11.8/src/rosdep2/platforms/freebsd.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/platforms/freebsd.py 2018-03-21 23:40:00.000000000 +0000 @@ -28,60 +28,54 @@ # Original from cygwin.py by Tingfan Wu tingfan@gmail.com # Modified for FreeBSD by Rene Ladan rene@freebsd.org - -import os -import subprocess +# Updated for FreeBSD with pkg by Trenton Schulz trentonw@ifi.uio.no from rospkg.os_detect import OS_FREEBSD -from .source import SOURCE_INSTALLER -from ..installers import Installer +from .pip import PIP_INSTALLER +from ..installers import PackageManagerInstaller +from ..shell_utils import read_stdout + +PKG_INSTALLER = 'pkg' -PKG_ADD_INSTALLER = 'pkg_add' def register_installers(context): - context.set_installer(PKG_ADD_INSTALLER, PkgAddInstaller()) - + context.set_installer(PKG_INSTALLER, PkgInstaller()) + + def register_platforms(context): - context.add_os_installer_key(OS_FREEBSD, SOURCE_INSTALLER) - context.add_os_installer_key(OS_FREEBSD, PKG_ADD_INSTALLER) - context.set_default_os_installer_key(OS_FREEBSD, lambda self: PKG_ADD_INSTALLER) + context.add_os_installer_key(OS_FREEBSD, PKG_INSTALLER) + context.add_os_installer_key(OS_FREEBSD, PIP_INSTALLER) + context.set_default_os_installer_key(OS_FREEBSD, lambda self: PKG_INSTALLER) -def pkg_info_detect_single(p): + +def pkg_detect_single(p, exec_fn): if p == "builtin": return True - # The next code is a lot of hassle, but there is no - # better way in FreeBSD using just the base tools - portname = p - if p == "gtk20": - portname = "gtk-2.\*" - elif p == "py-gtk2": - portname = "py27-gtk-2.\*" - elif p[:9] in ["autoconf2", "automake1"]: - portname = p[:8] + "-" + p[8] + "." + p[9:] + "\*" - elif p[:3] == "py-": - portname = "py27-" + p[3:] + "\*" - else: - portname = p + "-\*" - pop = subprocess.Popen("/usr/sbin/pkg_info -qE " + portname, shell=True) - return os.waitpid(pop.pid, 0)[1] == 0 # pkg_info -E returns 0 if pkg installed, 1 if not -def pkg_info_detect(packages): - return [p for p in packages if pkg_info_detect_single(p)] + cmd = ['/usr/sbin/pkg', 'query', '%n', p] + std_out = exec_fn(cmd) + return std_out.split() != [] + + +def pkg_detect(packages, exec_fn=None): + if exec_fn is None: + exec_fn = read_stdout + return [p for p in packages if pkg_detect_single(p, exec_fn)] + -class PkgAddInstaller(Installer): +class PkgInstaller(PackageManagerInstaller): """ An implementation of the Installer for use on FreeBSD-style systems. """ def __init__(self): - super(PkgAddInstaller, self).__init__(pkg_info_detect) + super(PkgInstaller, self).__init__(pkg_detect) def get_install_command(self, resolved, interactive=True, reinstall=False, quiet=False): - packages = self.get_packages_to_install(resolved, reinstall=reinstall) + packages = self.get_packages_to_install(resolved, reinstall=reinstall) if not packages: return [] else: - #pkg_add does not have a non-interactive command - return [self.elevate_priv(['/usr/sbin/pkg_add', '-r'])+packages] + return [self.elevate_priv(['/usr/sbin/pkg', 'install', '-y']) + packages] diff -Nru ros-rosdep-0.11.8/src/rosdep2/platforms/gem.py ros-rosdep-0.12.2/src/rosdep2/platforms/gem.py --- ros-rosdep-0.11.8/src/rosdep2/platforms/gem.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/platforms/gem.py 2018-03-21 23:40:00.000000000 +0000 @@ -2,10 +2,10 @@ # Copyright (c) 2009, Willow Garage, Inc. # Copyright (c) 2012, Intermodalics, BVBA. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -14,7 +14,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -40,9 +40,11 @@ # gem package manager key GEM_INSTALLER = 'gem' + def register_installers(context): context.set_installer(GEM_INSTALLER, GemInstaller()) + def is_gem_installed(): try: subprocess.Popen(['gem'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() @@ -50,8 +52,9 @@ except OSError: return False + def gem_detect(pkgs, exec_fn=None): - """ + """ Given a list of package, return the list of installed packages. :param exec_fn: function to execute Popen and read stdout (for testing) @@ -62,13 +65,14 @@ ret_list = [] for pkg in pkg_list: - pkg_row = pkg.split(" ") + pkg_row = pkg.split(' ') if pkg_row[0] in pkgs: - ret_list.append( pkg_row[0]) + ret_list.append(pkg_row[0]) return ret_list + class GemInstaller(PackageManagerInstaller): - """ + """ :class:`Installer` support for gem. """ @@ -81,10 +85,9 @@ def get_install_command(self, resolved, interactive=True, reinstall=False, quiet=False): if not is_gem_installed(): - raise InstallFailed((GEM_INSTALLER, "gem is not installed")) + raise InstallFailed((GEM_INSTALLER, 'gem is not installed')) packages = self.get_packages_to_install(resolved, reinstall=reinstall) if not packages: return [] else: return [self.elevate_priv(['gem', 'install', p]) for p in packages] - diff -Nru ros-rosdep-0.11.8/src/rosdep2/platforms/gentoo.py ros-rosdep-0.12.2/src/rosdep2/platforms/gentoo.py --- ros-rosdep-0.11.8/src/rosdep2/platforms/gentoo.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/platforms/gentoo.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,10 +1,10 @@ #!/usr/bin/env python # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -13,7 +13,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -28,11 +28,11 @@ # # Author Murph Finnicum/murph@murph.cc -### A word on atoms ### +# A word on atoms # We'll be using 'atoms' instead of 'packages' for the majority of the gentoo installer. -# Atoms can specify a package version (either exactly, or min/max version), flags it has +# Atoms can specify a package version (either exactly, or min/max version), flags it has # to be built with, and even repositories it has to come from -# +# # Here are some valid atoms and their meanings: # sed // A package named 'sed' # sys-apps/sed // sed from the category 'sys-apps'. There can be collisions otherwise. @@ -50,19 +50,23 @@ PORTAGE_INSTALLER = 'portage' + def register_installers(context): context.set_installer(PORTAGE_INSTALLER, PortageInstaller()) + def register_platforms(context): context.add_os_installer_key(OS_GENTOO, PORTAGE_INSTALLER) context.add_os_installer_key(OS_GENTOO, SOURCE_INSTALLER) context.set_default_os_installer_key(OS_GENTOO, lambda self: PORTAGE_INSTALLER) # Determine whether an atom is already satisfied -def portage_detect_single(atom, exec_fn = read_stdout ): - """ + + +def portage_detect_single(atom, exec_fn=read_stdout): + """ Check if a given atom is installed. - + :param exec_fn: function to execute Popen and read stdout (for testing) """ @@ -72,7 +76,8 @@ # Also, todo, figure out if just returning true if two packages are returned is cool.. return len(std_out) >= 1 -def portage_detect(atoms, exec_fn = read_stdout): + +def portage_detect(atoms, exec_fn=read_stdout): """ Given a list of atoms, return a list of which are already installed. @@ -83,15 +88,17 @@ # TODO: make testing better to not need this if isinstance(atoms, list): atoms.sort() - + return [a for a in atoms if portage_detect_single(a, exec_fn)] # Check portage and needed tools for existence and compatibility + + def portage_available(): - if not os.path.exists("/usr/bin/portageq"): + if not os.path.exists('/usr/bin/portageq'): return False - if not os.path.exists("/usr/bin/emerge"): + if not os.path.exists('/usr/bin/emerge'): return False # We only use standard, defined portage features. @@ -101,14 +108,14 @@ return True + class PortageInstaller(PackageManagerInstaller): def __init__(self): super(PortageInstaller, self).__init__(portage_detect) - - + def get_install_command(self, resolved, interactive=True, reinstall=False, quiet=False): - atoms = self.get_packages_to_install(resolved, reinstall=reinstall) + atoms = self.get_packages_to_install(resolved, reinstall=reinstall) cmd = self.elevate_priv(['emerge']) if not atoms: @@ -120,5 +127,3 @@ cmd.extend(atoms) return [cmd] - - diff -Nru ros-rosdep-0.11.8/src/rosdep2/platforms/opensuse.py ros-rosdep-0.12.2/src/rosdep2/platforms/opensuse.py --- ros-rosdep-0.11.8/src/rosdep2/platforms/opensuse.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/platforms/opensuse.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -35,16 +35,19 @@ from ..installers import PackageManagerInstaller # zypper package manager key -ZYPPER_INSTALLER='zypper' +ZYPPER_INSTALLER = 'zypper' + def register_installers(context): context.set_installer(ZYPPER_INSTALLER, ZypperInstaller()) + def register_platforms(context): context.add_os_installer_key(OS_OPENSUSE, SOURCE_INSTALLER) context.add_os_installer_key(OS_OPENSUSE, ZYPPER_INSTALLER) context.set_default_os_installer_key(OS_OPENSUSE, lambda self: ZYPPER_INSTALLER) - + + def rpm_detect(packages): installed = [] for p in packages: @@ -52,6 +55,7 @@ installed.append(p) return installed + class ZypperInstaller(PackageManagerInstaller): """ This class provides the functions for installing using zypper. @@ -65,6 +69,6 @@ if not packages: return [] if not interactive: - return [self.elevate_priv(['zypper', 'install', '-yl'])+packages] + return [self.elevate_priv(['zypper', 'install', '-yl']) + packages] else: - return [self.elevate_priv(['zypper', 'install'])+packages] + return [self.elevate_priv(['zypper', 'install']) + packages] diff -Nru ros-rosdep-0.11.8/src/rosdep2/platforms/osx.py ros-rosdep-0.12.2/src/rosdep2/platforms/osx.py --- ros-rosdep-0.11.8/src/rosdep2/platforms/osx.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/platforms/osx.py 2018-03-21 23:40:00.000000000 +0000 @@ -47,16 +47,18 @@ BREW_INSTALLER = 'homebrew' MACPORTS_INSTALLER = 'macports' -#py3k +# py3k try: _basestring = basestring except NameError: _basestring = str + def register_installers(context): context.set_installer(MACPORTS_INSTALLER, MacportsInstaller()) context.set_installer(BREW_INSTALLER, HomebrewInstaller()) + def register_platforms(context): context.add_os_installer_key(OS_OSX, BREW_INSTALLER) context.add_os_installer_key(OS_OSX, MACPORTS_INSTALLER) @@ -65,6 +67,7 @@ context.set_default_os_installer_key(OS_OSX, lambda self: BREW_INSTALLER) context.set_os_version_type(OS_OSX, OsDetect.get_codename) + def is_port_installed(): try: subprocess.Popen(['port'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() @@ -72,19 +75,21 @@ except OSError: return False + def port_detect(pkgs, exec_fn=None): ret_list = [] if not is_port_installed(): return ret_list if exec_fn is None: exec_fn = read_stdout - std_out = exec_fn(['port', 'installed']+pkgs) + std_out = exec_fn(['port', 'installed'] + pkgs) for pkg in std_out.split('\n'): pkg_row = pkg.split() - if len(pkg_row) == 3 and pkg_row[0] in pkgs and pkg_row[2] =='(active)': + if len(pkg_row) == 3 and pkg_row[0] in pkgs and pkg_row[2] == '(active)': ret_list.append(pkg_row[0]) return ret_list + class MacportsInstaller(PackageManagerInstaller): """ An implementation of the :class:`Installer` API for use on @@ -112,9 +117,10 @@ if not packages: return [] else: - #TODO: interactive + # TODO: interactive return [self.elevate_priv(['port', 'install', p]) for p in packages] + def is_brew_installed(): try: subprocess.Popen(['brew'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() @@ -143,8 +149,8 @@ def __eq__(self, other): return other.package == self.package and \ - other.install_flags == self.install_flags and \ - other.options == self.options + other.install_flags == self.install_flags and \ + other.options == self.options def __hash__(self): return hash(( @@ -166,7 +172,7 @@ :returns: Unqualified package name. E.g. 'foo-pkg' for input 'ros/hydro/foo-pkg' """ - if not isinstance(package, str): # package is a bytes object + if not isinstance(package, str): # package is a bytes object package = package.decode() return package.split('/')[-1] @@ -211,7 +217,7 @@ * Output of `brew info {0} --json=v1`: {1} * Error while parsing: - {2}""".format(r.package, std_out, "".join(traceback.format_exception(e_type, e, tb)))) + {2}""".format(r.package, std_out, ''.join(traceback.format_exception(e_type, e, tb)))) if set(r.options) <= set(installed_options): return True @@ -291,7 +297,7 @@ def handle_options(options): # if only one package is specified we allow a flat list of options - if len(packages) == 1 and options and not isinstance(options[0],list): + if len(packages) == 1 and options and not isinstance(options[0], list): options = [options] else: options = list(map(coerce_to_list, options)) @@ -319,8 +325,8 @@ options = [] install_flags = [] if type(rosdep_args) == dict: - options = coerce_to_list(rosdep_args.get("options", [])) - install_flags = coerce_to_list(rosdep_args.get("install_flags", [])) + options = coerce_to_list(rosdep_args.get('options', [])) + install_flags = coerce_to_list(rosdep_args.get('install_flags', [])) options = handle_options(options) install_flags = handle_options(install_flags) diff -Nru ros-rosdep-0.11.8/src/rosdep2/platforms/pip.py ros-rosdep-0.12.2/src/rosdep2/platforms/pip.py --- ros-rosdep-0.11.8/src/rosdep2/platforms/pip.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/platforms/pip.py 2018-03-21 23:40:00.000000000 +0000 @@ -67,7 +67,7 @@ ret_list = [] for pkg in pkg_list: - pkg_row = pkg.split("==") + pkg_row = pkg.split('==') if pkg_row[0] in pkgs: ret_list.append(pkg_row[0]) @@ -112,7 +112,7 @@ def get_install_command(self, resolved, interactive=True, reinstall=False, quiet=False): if not is_pip_installed(): - raise InstallFailed((PIP_INSTALLER, "pip is not installed")) + raise InstallFailed((PIP_INSTALLER, 'pip is not installed')) packages = self.get_packages_to_install(resolved, reinstall=reinstall) if not packages: return [] diff -Nru ros-rosdep-0.11.8/src/rosdep2/platforms/redhat.py ros-rosdep-0.12.2/src/rosdep2/platforms/redhat.py --- ros-rosdep-0.11.8/src/rosdep2/platforms/redhat.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/platforms/redhat.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,10 +1,10 @@ #!/usr/bin/env python # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -13,7 +13,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -39,19 +39,22 @@ from ..shell_utils import read_stdout # dnf package manager key -DNF_INSTALLER='dnf' +DNF_INSTALLER = 'dnf' # yum package manager key -YUM_INSTALLER='yum' +YUM_INSTALLER = 'yum' + def register_installers(context): context.set_installer(DNF_INSTALLER, DnfInstaller()) context.set_installer(YUM_INSTALLER, YumInstaller()) + def register_platforms(context): register_fedora(context) register_rhel(context) - + + def register_fedora(context): context.add_os_installer_key(OS_FEDORA, PIP_INSTALLER) context.add_os_installer_key(OS_FEDORA, DNF_INSTALLER) @@ -60,12 +63,14 @@ context.set_default_os_installer_key(OS_FEDORA, lambda self: DNF_INSTALLER if self.get_version().isdigit() and int(self.get_version()) > 21 else YUM_INSTALLER) context.set_os_version_type(OS_FEDORA, lambda self: self.get_version() if self.get_version().isdigit() and int(self.get_version()) > 20 else self.get_codename()) + def register_rhel(context): context.add_os_installer_key(OS_RHEL, PIP_INSTALLER) context.add_os_installer_key(OS_RHEL, YUM_INSTALLER) context.add_os_installer_key(OS_RHEL, SOURCE_INSTALLER) context.set_default_os_installer_key(OS_RHEL, lambda self: YUM_INSTALLER) + def rpm_detect_py(packages): ret_list = [] import rpm @@ -77,6 +82,7 @@ ret_list += [raw_req] return ret_list + def rpm_detect_cmd(raw_packages, exec_fn=None): ret_list = [] @@ -89,25 +95,33 @@ cmd.extend(packages) std_out = exec_fn(cmd) - out_lines = std_out.split() + out_lines = std_out.split('\n') for index, package in enumerate(packages): if package in out_lines: ret_list.append(raw_packages[index]) return ret_list + def rpm_detect(packages, exec_fn=None): try: return rpm_detect_py(packages) except ImportError: + rd_debug('Failed to import rpm module, falling back to slow method') return rpm_detect_cmd(packages, exec_fn) + def rpm_expand_py(macro): import rpm + if '%' not in macro: + return macro expanded = rpm.expandMacro(macro) rd_debug('Expanded rpm macro in \'%s\' to \'%s\'' % (macro, expanded)) return expanded + def rpm_expand_cmd(macro, exec_fn=None): + if '%' not in macro: + return macro cmd = ['rpm', '-E', macro] if exec_fn is None: @@ -117,14 +131,14 @@ rd_debug('Expanded rpm macro in \'%s\' to \'%s\'' % (macro, expanded)) return expanded + def rpm_expand(package, exec_fn=None): - if not '%' in package: - return package try: return rpm_expand_py(package) except ImportError: return rpm_expand_cmd(package, exec_fn) + class DnfInstaller(PackageManagerInstaller): """ This class provides the functions for installing using dnf diff -Nru ros-rosdep-0.11.8/src/rosdep2/platforms/slackware.py ros-rosdep-0.12.2/src/rosdep2/platforms/slackware.py --- ros-rosdep-0.11.8/src/rosdep2/platforms/slackware.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/platforms/slackware.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,10 +1,10 @@ #!/usr/bin/env python # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -13,7 +13,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -45,7 +45,8 @@ def register_installers(context): context.set_installer(SBOTOOLS_INSTALLER, SbotoolsInstaller()) context.set_installer(SLACKPKG_INSTALLER, SlackpkgInstaller()) - + + def register_platforms(context): context.add_os_installer_key(SLACKWARE_OS_NAME, SBOTOOLS_INSTALLER) context.add_os_installer_key(SLACKWARE_OS_NAME, PIP_INSTALLER) @@ -53,20 +54,24 @@ context.add_os_installer_key(SLACKWARE_OS_NAME, SLACKPKG_INSTALLER) context.set_default_os_installer_key(SLACKWARE_OS_NAME, lambda self: SBOTOOLS_INSTALLER) + def sbotools_available(): - if not os.path.exists("/usr/sbin/sboinstall"): + if not os.path.exists('/usr/sbin/sboinstall'): return False return True + def sbotools_detect_single(p): pkg_list = read_stdout(['ls', '/var/log/packages']) p = subprocess.Popen(['grep', '-i', '^' + p], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p.communicate(pkg_list) return not p.returncode + def sbotools_detect(packages): return [p for p in packages if sbotools_detect_single(p)] + class SbotoolsInstaller(PackageManagerInstaller): def __init__(self): @@ -74,30 +79,31 @@ def get_install_command(self, resolved, interactive=True, reinstall=False, quiet=False): if not sbotools_available(): - raise InstallFailed((SBOTOOLS_INSTALLER, "sbotools is not installed")) + raise InstallFailed((SBOTOOLS_INSTALLER, 'sbotools is not installed')) - packages = self.get_packages_to_install(resolved, reinstall=reinstall) + packages = self.get_packages_to_install(resolved, reinstall=reinstall) if not packages: return [] cmd = ['sboinstall'] - if not interactive: - cmd.append('-r') + return [self.elevate_priv(cmd + [p] + ['-j']) for p in packages] - return [self.elevate_priv(cmd + [p]) for p in packages] def slackpkg_available(): - if not os.path.exists("/usr/sbin/slackpkg"): + if not os.path.exists('/usr/sbin/slackpkg'): return False return True + def slackpkg_detect_single(p): - return not subprocess.call(['slackpkg', 'search', p], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return not subprocess.call(['slackpkg', 'search', p], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + def slackpkg_detect(packages): return [p for p in packages if slackpkg_detect_single(p)] + class SlackpkgInstaller(PackageManagerInstaller): def __init__(self): @@ -105,7 +111,7 @@ def get_install_command(self, resolved, interactive=True, reinstall=False, quiet=False): # slackpkg does not provide non-interactive mode - packages = self.get_packages_to_install(resolved, reinstall=reinstall) + packages = self.get_packages_to_install(resolved, reinstall=reinstall) if not packages: return [] else: diff -Nru ros-rosdep-0.11.8/src/rosdep2/platforms/source.py ros-rosdep-0.12.2/src/rosdep2/platforms/source.py --- ros-rosdep-0.11.8/src/rosdep2/platforms/source.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/platforms/source.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -46,27 +46,31 @@ from ..installers import PackageManagerInstaller, InstallFailed from ..shell_utils import create_tempfile_from_string_and_execute -SOURCE_INSTALLER='source' +SOURCE_INSTALLER = 'source' + def register_installers(context): context.set_installer(SOURCE_INSTALLER, SourceInstaller()) + class InvalidRdmanifest(Exception): """ rdmanifest format is invalid. """ pass + class DownloadFailed(Exception): """ File download failed either due to i/o issues or md5sum validation. """ pass + def _sub_fetch_file(url, md5sum=None): """ Sub-routine of _fetch_file - + :raises: :exc:`DownloadFailed` """ contents = '' @@ -74,21 +78,23 @@ fh = urlopen(url) contents = fh.read() if md5sum is not None: - filehash = hashlib.md5(contents).hexdigest() + filehash = hashlib.md5(contents).hexdigest() if md5sum and filehash != md5sum: - raise DownloadFailed("md5sum didn't match for %s. Expected %s got %s"%(url, md5sum, filehash)) + raise DownloadFailed("md5sum didn't match for %s. Expected %s got %s" % (url, md5sum, filehash)) except URLError as ex: raise DownloadFailed(str(ex)) - return contents + return contents + def get_file_hash(filename): md5 = hashlib.md5() - with open(filename,'rb') as f: + with open(filename, 'rb') as f: for chunk in iter(lambda: f.read(8192), b''): md5.update(chunk) return md5.hexdigest() + def fetch_file(url, md5sum=None): """ Download file. Optionally validate with md5sum @@ -102,10 +108,11 @@ if not isinstance(contents, str): contents = contents.decode('utf-8') except DownloadFailed as e: - rd_debug("Download of file %s failed"%(url)) + rd_debug('Download of file %s failed' % (url)) error = str(e) return contents, error + def load_rdmanifest(contents): """ :raises: :exc:`InvalidRdmanifest` @@ -113,8 +120,9 @@ try: return yaml.load(contents) except yaml.scanner.ScannerError as ex: - raise InvalidRdmanifest("Failed to parse yaml in %s: Error: %s"%(contents, ex)) - + raise InvalidRdmanifest('Failed to parse yaml in %s: Error: %s' % (contents, ex)) + + def download_rdmanifest(url, md5sum, alt_url=None): """ :param url: URL to download rdmanifest from @@ -128,11 +136,11 @@ """ # fetch the manifest download_url = url - error_prefix = "Failed to load a rdmanifest from %s: "%(url) + error_prefix = 'Failed to load a rdmanifest from %s: ' % (url) contents, error = fetch_file(download_url, md5sum) # - try the backup url - if not contents and alt_url: - error_prefix = "Failed to load a rdmanifest from either %s or %s: "%(url, alt_url) + if not contents and alt_url: + error_prefix = 'Failed to load a rdmanifest from either %s or %s: ' % (url, alt_url) download_url = alt_url contents, error = fetch_file(download_url, md5sum) if not contents: @@ -140,7 +148,9 @@ manifest = load_rdmanifest(contents) return manifest, download_url -#TODO: create SourceInstall instance objects +# TODO: create SourceInstall instance objects + + class SourceInstall(object): def __init__(self): @@ -150,42 +160,47 @@ self.tarball = self.alternate_tarball = None self.tarball_md5sum = None self.dependencies = None - + @staticmethod def from_manifest(manifest, manifest_url): r = SourceInstall() r.manifest = manifest r.manifest_url = manifest_url - rd_debug("Loading manifest:\n{{{%s\n}}}\n"%manifest) - - r.install_command = manifest.get("install-script", '') - r.check_presence_command = manifest.get("check-presence-script", '') + rd_debug('Loading manifest:\n{{{%s\n}}}\n' % manifest) + + r.install_command = manifest.get('install-script', '') + r.check_presence_command = manifest.get('check-presence-script', '') - r.exec_path = manifest.get("exec-path", ".") + r.exec_path = manifest.get('exec-path', '.') try: - r.tarball = manifest["uri"] + r.tarball = manifest['uri'] except KeyError: - raise InvalidRdmanifest("uri required for source rosdeps") - r.alternate_tarball = manifest.get("alternate-uri") - r.tarball_md5sum = manifest.get("md5sum") - r.dependencies = manifest.get("depends", []) + raise InvalidRdmanifest('uri required for source rosdeps') + r.alternate_tarball = manifest.get('alternate-uri') + r.tarball_md5sum = manifest.get('md5sum') + r.dependencies = manifest.get('depends', []) return r def __str__(self): - return "source: %s"%(self.manifest_url) - + return 'source: %s' % (self.manifest_url) + + __repr__ = __str__ + + def is_source_installed(source_item, exec_fn=None): return create_tempfile_from_string_and_execute(source_item.check_presence_command, exec_fn=exec_fn) - + + def source_detect(pkgs, exec_fn=None): return [x for x in pkgs if is_source_installed(x, exec_fn=exec_fn)] + class SourceInstaller(PackageManagerInstaller): def __init__(self): super(SourceInstaller, self).__init__(source_detect, supports_depends=True) self._rdmanifest_cache = {} - + def resolve(self, rosdep_args): """ :raises: :exc:`InvalidData` If format invalid or unable @@ -193,11 +208,11 @@ :returns: [SourceInstall] instances. """ try: - url = rosdep_args["uri"] + url = rosdep_args['uri'] except KeyError: - raise InvalidData("'uri' key required for source rosdeps") - alt_url = rosdep_args.get("alternate-uri", None) - md5sum = rosdep_args.get("md5sum", None) + raise InvalidData("'uri' key required for source rosdeps") + alt_url = rosdep_args.get('alternate-uri', None) + md5sum = rosdep_args.get('md5sum', None) # load manifest from cache or from web manifest = None @@ -206,14 +221,14 @@ elif alt_url in self._rdmanifest_cache: return self._rdmanifest_cache[alt_url] try: - rd_debug("Downloading manifest [%s], mirror [%s]"%(url, alt_url)) + rd_debug('Downloading manifest [%s], mirror [%s]' % (url, alt_url)) manifest, download_url = download_rdmanifest(url, md5sum, alt_url) resolved = SourceInstall.from_manifest(manifest, download_url) self._rdmanifest_cache[download_url] = [resolved] return [resolved] except DownloadFailed as ex: # not sure this should be masked this way - raise InvalidData(str(ex)) + raise InvalidData(str(ex)) except InvalidRdmanifest as ex: raise InvalidData(str(ex)) @@ -229,31 +244,34 @@ commands.append(['rosdep-source', 'install', p.manifest_url]) return commands - def get_depends(self, rosdep_args): + def get_depends(self, rosdep_args): deps = rosdep_args.get('depends', []) for r in self.resolve(rosdep_args): deps.extend(r.dependencies) return deps + def install_from_file(rdmanifest_file): with open(rdmanifest_file, 'r') as f: contents = f.read() manifest = load_rdmanifest(contents) install_source(SourceInstall.from_manifest(manifest, rdmanifest_file)) - + + def install_from_url(rdmanifest_url): manifest, download_url = download_rdmanifest(rdmanifest_url, None, None) install_source(SourceInstall.from_manifest(manifest, download_url)) + def install_source(resolved): import shutil import tarfile import tempfile tempdir = tempfile.mkdtemp() - rd_debug("created tmpdir [%s]"%(tempdir)) + rd_debug('created tmpdir [%s]' % (tempdir)) - rd_debug("Fetching tarball %s"%resolved.tarball) + rd_debug('Fetching tarball %s' % resolved.tarball) # compute desired download path filename = os.path.join(tempdir, os.path.basename(resolved.tarball)) @@ -261,41 +279,39 @@ assert f[0] == filename if resolved.tarball_md5sum: - rd_debug("checking md5sum on tarball") + rd_debug('checking md5sum on tarball') hash1 = get_file_hash(filename) if resolved.tarball_md5sum != hash1: - #try backup tarball if it is defined + # try backup tarball if it is defined if resolved.alternate_tarball: f = urlretrieve(resolved.alternate_tarball) filename = f[0] hash2 = get_file_hash(filename) if resolved.tarball_md5sum != hash2: - failure = (SOURCE_INSTALLER, "md5sum check on %s and %s failed. Expected %s got %s and %s"%(resolved.tarball, resolved.alternate_tarball, resolved.tarball_md5sum, hash1, hash2)) + failure = (SOURCE_INSTALLER, 'md5sum check on %s and %s failed. Expected %s got %s and %s' % (resolved.tarball, resolved.alternate_tarball, resolved.tarball_md5sum, hash1, hash2)) raise InstallFailed(failure=failure) else: - raise InstallFailed((SOURCE_INSTALLER, "md5sum check on %s failed. Expected %s got %s "%(resolved.tarball, resolved.tarball_md5sum, hash1))) + raise InstallFailed((SOURCE_INSTALLER, 'md5sum check on %s failed. Expected %s got %s ' % (resolved.tarball, resolved.tarball_md5sum, hash1))) else: - rd_debug("No md5sum defined for tarball, not checking.") + rd_debug('No md5sum defined for tarball, not checking.') try: # This is a bit hacky. Basically, don't unpack dmg files as # we are currently using source rosdeps for Nvidia Cg. if not filename.endswith('.dmg'): - rd_debug("Extracting tarball") + rd_debug('Extracting tarball') tarf = tarfile.open(filename) tarf.extractall(tempdir) else: - rd_debug("Bypassing tarball extraction as it is a dmg") - rd_debug("Running installation script") + rd_debug('Bypassing tarball extraction as it is a dmg') + rd_debug('Running installation script') success = create_tempfile_from_string_and_execute(resolved.install_command, os.path.join(tempdir, resolved.exec_path)) if success: - rd_debug("successfully executed script") + rd_debug('successfully executed script') else: - raise InstallFailed((SOURCE_INSTALLER, "installation script returned with error code")) + raise InstallFailed((SOURCE_INSTALLER, 'installation script returned with error code')) finally: - rd_debug("cleaning up tmpdir [%s]"%(tempdir)) + rd_debug('cleaning up tmpdir [%s]' % (tempdir)) shutil.rmtree(tempdir) - - diff -Nru ros-rosdep-0.11.8/src/rosdep2/rep3.py ros-rosdep-0.12.2/src/rosdep2/rep3.py --- ros-rosdep-0.11.8/src/rosdep2/rep3.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/rep3.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2012, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -38,9 +38,10 @@ # location of targets file for processing gbpdistro files REP3_TARGETS_URL = 'https://raw.github.com/ros/rosdistro/master/releases/targets.yaml' -#seconds to wait before aborting download of gbpdistro data +# seconds to wait before aborting download of gbpdistro data DOWNLOAD_TIMEOUT = 15.0 + def download_targets_data(targets_url=None): """ Download REP 3 targets file and unmarshal from YAML. @@ -53,7 +54,7 @@ :raises: :exc:`DownloadFailure` :raises: :exc:`InvalidData` If targets file does not pass cursory validation checks. """ - warnings.warn("deprecated, use rosdistro instead", PreRep137Warning) + warnings.warn('deprecated, use rosdistro instead', PreRep137Warning) if targets_url is None: targets_url = REP3_TARGETS_URL @@ -63,7 +64,7 @@ f.close() targets_data = yaml.safe_load(text) except Exception as e: - raise DownloadFailure("Failed to download target platform data for gbpdistro:\n\t%s"%(str(e))) + raise DownloadFailure('Failed to download target platform data for gbpdistro:\n\t%s' % (str(e))) if type(targets_data) == list: # convert to dictionary new_targets_data = {} diff -Nru ros-rosdep-0.11.8/src/rosdep2/rospack.py ros-rosdep-0.12.2/src/rosdep2/rospack.py --- ros-rosdep-0.11.8/src/rosdep2/rospack.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/rospack.py 2018-03-21 23:40:00.000000000 +0000 @@ -51,6 +51,7 @@ def init_rospack_interface(): class Options(object): + def __init__(self): self.os_override = None self.sources_cache_dir = get_sources_cache_dir() diff -Nru ros-rosdep-0.11.8/src/rosdep2/rospkg_loader.py ros-rosdep-0.12.2/src/rosdep2/rospkg_loader.py --- ros-rosdep-0.11.8/src/rosdep2/rospkg_loader.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/rospkg_loader.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -42,7 +42,7 @@ # Default view key is the view that packages that are not in stacks # see. It is the root of all dependencies. It is superceded by an # explicit underlay_key. -DEFAULT_VIEW_KEY='*default*' +DEFAULT_VIEW_KEY = '*default*' # Implementation details: this API was originally conceived under the # rosdep 1 design. It has since been retrofitted for the rosdep 2 @@ -54,8 +54,9 @@ # resources and SourcesListLoader would build a *single* view that was # no longer resource-dependent. + class RosPkgLoader(RosdepLoader): - + def __init__(self, rospack=None, rosstack=None, underlay_key=None): """ :param underlay_key: If set, all views loaded by this loader @@ -70,7 +71,7 @@ self._rosstack = rosstack self._rosdep_yaml_cache = {} self._underlay_key = underlay_key - + # cache computed list of loadable resources self._loadable_resource_cache = None self._catkin_packages_cache = None @@ -90,12 +91,12 @@ """ if rosdep_db.is_loaded(view_name): return - if not view_name in self.get_loadable_views(): + if view_name not in self.get_loadable_views(): raise rospkg.ResourceNotFound(view_name) elif view_name == 'invalid': - raise rospkg.ResourceNotFound("FOUND"+ view_name+str(self.get_loadable_views())) + raise rospkg.ResourceNotFound('FOUND' + view_name + str(self.get_loadable_views())) if verbose: - print("loading view [%s] with rospkg loader"%(view_name)) + print('loading view [%s] with rospkg loader' % (view_name)) # chain into underlay if set if self._underlay_key: view_dependencies = [self._underlay_key] @@ -130,7 +131,7 @@ def get_rosdeps(self, resource_name, implicit=True): """ If *resource_name* is a stack, returns an empty list. - + :raises: :exc:`rospkg.ResourceNotFound` if *resource_name* cannot be found. """ @@ -149,7 +150,7 @@ def is_metapackage(self, resource_name): if resource_name in self._rosstack.list(): m = self._rosstack.get_manifest(resource_name) - return m.is_catkin; + return m.is_catkin return False def get_view_key(self, resource_name): @@ -159,8 +160,10 @@ :raises: :exc:`rospkg.ResourceNotFound` """ - if (resource_name in self.get_catkin_paths() or - resource_name in self.get_loadable_resources()): + if ( + resource_name in self.get_catkin_paths() or + resource_name in self.get_loadable_resources() + ): return DEFAULT_VIEW_KEY else: raise rospkg.ResourceNotFound(resource_name) diff -Nru ros-rosdep-0.11.8/src/rosdep2/shell_utils.py ros-rosdep-0.12.2/src/rosdep2/shell_utils.py --- ros-rosdep-0.11.8/src/rosdep2/shell_utils.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/shell_utils.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -37,7 +37,7 @@ from .core import rd_debug -if sys.hexversion > 0x03000000: #Python3 +if sys.hexversion > 0x03000000: # Python3 python3 = True else: python3 = False @@ -45,8 +45,9 @@ env = dict(os.environ) env['LANG'] = 'C' + def read_stdout(cmd, capture_stderr=False): - ''' + """ Execute given command and return stdout and if requested also stderr. :param cmd: command in a form that Popen understands (list of strings or one string) @@ -56,7 +57,7 @@ the program as string (Note: stderr will be printed to the running terminal). If it evaluates to True, tuple of strings: stdout output and standard error output each as string. - ''' + """ if capture_stderr: p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) std_out, std_err = p.communicate() @@ -66,7 +67,7 @@ return std_out, std_err else: p = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=env) - std_out, std_err = p.communicate() # ignore stderr + std_out, std_err = p.communicate() # ignore stderr if python3: return std_out.decode() else: @@ -80,25 +81,24 @@ """ if path is None: path = tempfile.gettempdir() - + result = 1 try: fh = tempfile.NamedTemporaryFile('w', delete=False) fh.write(string_script) fh.close() - print("Executing script below with cwd=%s\n{{{\n%s\n}}}\n"%(path, string_script)) + print('Executing script below with cwd=%s\n{{{\n%s\n}}}\n' % (path, string_script)) try: os.chmod(fh.name, stat.S_IRWXU) if exec_fn is None: result = subprocess.call(fh.name, cwd=path) else: - result = exec_fn(fh.name, cwd=path) + result = exec_fn(fh.name, cwd=path) except OSError as ex: - print("Execution failed with OSError: %s"%(ex)) + print('Execution failed with OSError: %s' % (ex)) finally: if os.path.exists(fh.name): os.remove(fh.name) - - rd_debug("Return code was: %s"%(result)) - return result == 0 + rd_debug('Return code was: %s' % (result)) + return result == 0 diff -Nru ros-rosdep-0.11.8/src/rosdep2/sources_list.py ros-rosdep-0.12.2/src/rosdep2/sources_list.py --- ros-rosdep-0.11.8/src/rosdep2/sources_list.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/sources_list.py 2018-03-21 23:40:00.000000000 +0000 @@ -51,7 +51,7 @@ try: import urlparse except ImportError: - import urllib.parse as urlparse #py3k + import urllib.parse as urlparse # py3k try: import httplib @@ -68,7 +68,7 @@ # rosdep DEFAULT_SOURCES_LIST_URL = 'https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/sources.list.d/20-default.list' -#seconds to wait before aborting download of rosdep data +# seconds to wait before aborting download of rosdep data DOWNLOAD_TIMEOUT = 15.0 SOURCES_LIST_DIR = 'sources.list.d' @@ -109,13 +109,16 @@ else: return sys_sources_list_dir + def get_default_sources_list_file(): return os.path.join(get_sources_list_dir(), '20-default.list') + def get_sources_cache_dir(): ros_home = rospkg.get_ros_home() return os.path.join(ros_home, 'rosdep', SOURCES_CACHE_DIR) + # Default rosdep.yaml format. For now this is the only valid type and # is specified for future compatibility. TYPE_YAML = 'yaml' @@ -123,6 +126,7 @@ TYPE_GBPDISTRO = 'gbpdistro' VALID_TYPES = [TYPE_YAML, TYPE_GBPDISTRO] + class DataSource(object): def __init__(self, type_, url, tags, origin=None): @@ -139,13 +143,13 @@ :raises: :exc:`ValueError` if parameters do not validate """ # validate inputs - if not type_ in VALID_TYPES: - raise ValueError("type must be one of [%s]"%(','.join(VALID_TYPES))) + if type_ not in VALID_TYPES: + raise ValueError('type must be one of [%s]' % (','.join(VALID_TYPES))) parsed = urlparse.urlparse(url) if not parsed.scheme or (parsed.scheme != 'file' and not parsed.netloc) or parsed.path in ('', '/'): - raise ValueError("url must be a fully-specified URL with scheme, hostname, and path: %s"%(str(url))) + raise ValueError('url must be a fully-specified URL with scheme, hostname, and path: %s' % (str(url))) if not type(tags) == list: - raise ValueError("tags must be a list: %s"%(str(tags))) + raise ValueError('tags must be a list: %s' % (str(tags))) self.type = type_ self.tags = tags @@ -155,21 +159,23 @@ def __eq__(self, other): return isinstance(other, DataSource) and \ - self.type == other.type and \ - self.tags == other.tags and \ - self.url == other.url and \ - self.origin == other.origin + self.type == other.type and \ + self.tags == other.tags and \ + self.url == other.url and \ + self.origin == other.origin def __str__(self): if self.origin: - return "[%s]:\n%s %s %s"%(self.origin, self.type, self.url, ' '.join(self.tags)) + return '[%s]:\n%s %s %s' % (self.origin, self.type, self.url, ' '.join(self.tags)) else: - return "%s %s %s"%(self.type, self.url, ' '.join(self.tags)) + return '%s %s %s' % (self.type, self.url, ' '.join(self.tags)) def __repr__(self): return repr((self.type, self.url, self.tags, self.origin)) + class RosDistroSource(DataSource): + def __init__(self, distro): self.type = TYPE_GBPDISTRO self.tags = [distro] @@ -180,6 +186,8 @@ # create function we can pass in as model to parse_source_data. The # function emulates the CachedDataSource constructor but does the # necessary full filepath calculation and loading of data. + + def cache_data_source_loader(sources_cache_dir, verbose=False): def create_model(type_, uri, tags, origin=None): # compute the filename has from the URL @@ -188,12 +196,12 @@ pickle_filepath = filepath + PICKLE_CACHE_EXT if os.path.exists(pickle_filepath): if verbose: - print("loading cached data source:\n\t%s\n\t%s"%(uri, pickle_filepath), file=sys.stderr) + print('loading cached data source:\n\t%s\n\t%s' % (uri, pickle_filepath), file=sys.stderr) with open(pickle_filepath, 'rb') as f: rosdep_data = pickle.loads(f.read()) elif os.path.exists(filepath): if verbose: - print("loading cached data source:\n\t%s\n\t%s"%(uri, filepath), file=sys.stderr) + print('loading cached data source:\n\t%s\n\t%s' % (uri, filepath), file=sys.stderr) with open(filepath) as f: rosdep_data = yaml.load(f.read()) else: @@ -201,6 +209,7 @@ return CachedDataSource(type_, uri, tags, rosdep_data, origin=filepath) return create_model + class CachedDataSource(object): def __init__(self, type_, url, tags, rosdep_data, origin=None): @@ -216,35 +225,37 @@ def __eq__(self, other): try: return self.source == other.source and \ - self.rosdep_data == other.rosdep_data + self.rosdep_data == other.rosdep_data except AttributeError: return False def __str__(self): - return "%s\n%s"%(self.source, self.rosdep_data) + return '%s\n%s' % (self.source, self.rosdep_data) def __repr__(self): return repr((self.type, self.url, self.tags, self.rosdep_data, self.origin)) - @property def type(self): """ :returns: data source type """ return self.source.type + @property def url(self): """ :returns: data source URL """ return self.source.url + @property def tags(self): """ :returns: data source tags """ return self.source.tags + @property def origin(self): """ @@ -252,6 +263,7 @@ """ return self.source.origin + class DataSourceMatcher(object): def __init__(self, tags): @@ -264,7 +276,7 @@ :param rosdep_data_source: :class:`DataSource` """ # all of the rosdep_data_source tags must be in our matcher tags - return not any(set(rosdep_data_source.tags)-set(self.tags)) + return not any(set(rosdep_data_source.tags) - set(self.tags)) @staticmethod def create_default(os_override=None): @@ -285,6 +297,7 @@ tags = [t for t in (distro_name, os_name, os_codename) if t] return DataSourceMatcher(tags) + def download_rosdep_data(url): """ :raises: :exc:`DownloadFailure` If data cannot be @@ -296,13 +309,14 @@ f.close() data = yaml.safe_load(text) if type(data) != dict: - raise DownloadFailure('rosdep data from [%s] is not a YAML dictionary'%(url)) + raise DownloadFailure('rosdep data from [%s] is not a YAML dictionary' % (url)) return data except (URLError, httplib.HTTPException) as e: raise DownloadFailure(str(e) + ' (%s)' % url) except yaml.YAMLError as e: raise DownloadFailure(str(e)) + def download_default_sources_list(url=DEFAULT_SOURCES_LIST_URL): """ Download (and validate) contents of default sources list. @@ -321,16 +335,18 @@ data = f.read().decode() f.close() if not data: - raise DownloadFailure("cannot download defaults file from %s : empty contents" % url) + raise DownloadFailure('cannot download defaults file from %s : empty contents' % url) # parse just for validation try: parse_sources_data(data) except InvalidData as e: - raise DownloadFailure("The content downloaded from %s failed to pass validation." - " It is likely that the source is invalid unless the data was corrupted during the download." - " The contents were:{{{%s}}} The error raised was: %s" % (url, data, e)) + raise DownloadFailure( + 'The content downloaded from %s failed to pass validation.' + ' It is likely that the source is invalid unless the data was corrupted during the download.' + ' The contents were:{{{%s}}} The error raised was: %s' % (url, data, e)) return data + def parse_sources_data(data, origin='', model=None): """ Parse sources file format (tags optional):: @@ -362,16 +378,17 @@ continue splits = line.split(' ') if len(splits) < 2: - raise InvalidData("invalid line:\n%s"%(line), origin=origin) + raise InvalidData('invalid line:\n%s' % (line), origin=origin) type_ = splits[0] url = splits[1] tags = splits[2:] try: sources.append(model(type_, url, tags, origin=origin)) except ValueError as e: - raise InvalidData("line:\n\t%s\n%s"%(line, e), origin=origin) + raise InvalidData('line:\n\t%s\n%s' % (line, e), origin=origin) return sources + def parse_sources_file(filepath): """ Parse file on disk @@ -384,7 +401,8 @@ with open(filepath, 'r') as f: return parse_sources_data(f.read(), origin=filepath) except IOError as e: - raise InvalidData("I/O error reading sources file: %s"%(str(e)), origin=filepath) + raise InvalidData('I/O error reading sources file: %s' % (str(e)), origin=filepath) + def parse_sources_list(sources_list_dir=None): """ @@ -486,11 +504,12 @@ data = "#autogenerated by rosdep, do not edit. use 'rosdep update' instead\n" for source in sources: url = _generate_key_from_urls(source.url) - data += "yaml %s %s\n" % (url, ' '.join(source.tags)) + data += 'yaml %s %s\n' % (url, ' '.join(source.tags)) write_atomic(cache_index, data) # mainly for debugging and testing return retval + def load_cached_sources_list(sources_cache_dir=None, verbose=False): """ Load cached data based on the sources list. @@ -505,7 +524,7 @@ cache_index = os.path.join(sources_cache_dir, 'index') if not os.path.exists(cache_index): if verbose: - print("no cache index present, not loading cached sources", file=sys.stderr) + print('no cache index present, not loading cached sources', file=sys.stderr) return [] with open(cache_index, 'r') as f: cache_data = f.read() @@ -540,7 +559,7 @@ try: write_atomic(filepath + PICKLE_CACHE_EXT, pickle.dumps(rosdep_data, -1), True) except OSError as e: - raise CachePermissionError("Failed to write cache file: " + str(e)) + raise CachePermissionError('Failed to write cache file: ' + str(e)) try: os.unlink(filepath) except OSError: @@ -575,6 +594,7 @@ except OSError: os.unlink(filepath_tmp) + class SourcesListLoader(RosdepLoader): """ SourcesList loader implements the general RosdepLoader API. This @@ -608,14 +628,14 @@ if matcher is None: matcher = DataSourceMatcher.create_default(os_override=os_override) if verbose: - print("using matcher with tags [%s]"%(', '.join(matcher.tags)), file=sys.stderr) + print('using matcher with tags [%s]' % (', '.join(matcher.tags)), file=sys.stderr) sources = load_cached_sources_list(sources_cache_dir=sources_cache_dir, verbose=verbose) if verbose: - print("loaded %s sources"%(len(sources)), file=sys.stderr) + print('loaded %s sources' % (len(sources)), file=sys.stderr) sources = [x for x in sources if matcher.matches(x)] if verbose: - print("%s sources match current tags"%(len(sources)), file=sys.stderr) + print('%s sources match current tags' % (len(sources)), file=sys.stderr) return SourcesListLoader(sources) def load_view(self, view_name, rosdep_db, verbose=False): @@ -632,7 +652,7 @@ return source = self.get_source(view_name) if verbose: - print("loading view [%s] with sources.list loader"%(view_name), file=sys.stderr) + print('loading view [%s] with sources.list loader' % (view_name), file=sys.stderr) view_dependencies = self.get_view_dependencies(view_name) rosdep_db.set_view_data(view_name, source.rosdep_data, view_dependencies, view_name) diff -Nru ros-rosdep-0.11.8/src/rosdep2/_version.py ros-rosdep-0.12.2/src/rosdep2/_version.py --- ros-rosdep-0.11.8/src/rosdep2/_version.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/src/rosdep2/_version.py 2018-03-21 23:40:00.000000000 +0000 @@ -1 +1 @@ -__version__ = '0.11.8' +__version__ = '0.12.2' diff -Nru ros-rosdep-0.11.8/stdeb.cfg ros-rosdep-0.12.2/stdeb.cfg --- ros-rosdep-0.11.8/stdeb.cfg 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/stdeb.cfg 2018-03-21 23:40:00.000000000 +0000 @@ -1,7 +1,7 @@ [DEFAULT] Depends: ca-certificates, python-rospkg (>= 1.0.37), python-yaml, python-catkin-pkg, python-rosdistro (>= 0.4.0) Depends3: ca-certificates, python3-rospkg (>= 1.0.37), python3-yaml, python3-catkin-pkg, python3-rosdistro (>= 0.4.0) -Conflicts: python3-rosdep -Conflicts3: python-rosdep -Suite: oneiric precise quantal raring saucy trusty utopic vivid wily xenial yakkety zesty artful wheezy jessie stretch +Conflicts: python3-rosdep, python-rosdep2, python3-rosdep2 +Conflicts3: python-rosdep, python-rosdep2, python3-rosdep2 +Suite: oneiric precise quantal raring saucy trusty utopic vivid wily xenial yakkety zesty artful bionic wheezy jessie stretch buster X-Python3-Version: >= 3.2 diff -Nru ros-rosdep-0.11.8/test/debian/showpkg-curl-wget-libcurl-dev ros-rosdep-0.12.2/test/debian/showpkg-curl-wget-libcurl-dev --- ros-rosdep-0.11.8/test/debian/showpkg-curl-wget-libcurl-dev 1970-01-01 00:00:00.000000000 +0000 +++ ros-rosdep-0.12.2/test/debian/showpkg-curl-wget-libcurl-dev 2018-03-21 23:40:00.000000000 +0000 @@ -0,0 +1,362 @@ +Package: curl +Versions: +7.47.0-1ubuntu2.4 (/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial-updates_main_binary-amd64_Packages.lz4) (/var/lib/apt/lists/security.ubuntu.com_ubuntu_dists_xenial-security_main_binary-amd64_Packages.lz4) + Description Language: + File: /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial_main_binary-amd64_Packages.lz4 + MD5: f83293d10df083ae6f7bb7d01642913c + Description Language: + File: /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial-updates_main_binary-amd64_Packages.lz4 + MD5: f83293d10df083ae6f7bb7d01642913c + +7.47.0-1ubuntu2 (/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial_main_binary-amd64_Packages.lz4) + Description Language: + File: /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial_main_binary-amd64_Packages.lz4 + MD5: f83293d10df083ae6f7bb7d01642913c + Description Language: + File: /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial-updates_main_binary-amd64_Packages.lz4 + MD5: f83293d10df083ae6f7bb7d01642913c + + +Reverse Depends: + plowshare,curl 7.24 + playonlinux,curl + google-perftools,curl + drupal7,curl + ceph-test,curl + pollinate,curl + pciutils,curl + imagemagick-6.q16,curl + ttytter,curl + playonlinux,curl + ec2-ami-tools,curl + bgoffice-dict-downloader,curl + astrometry-data-2mass-08-19,curl + astrometry-data-2mass-07,curl + astrometry-data-2mass-06,curl + astrometry-data-2mass-05,curl + astrometry-data-2mass-04,curl + astrometry-data-2mass-03,curl + astrometry-data-2mass-02,curl + astrometry-data-2mass-01,curl + astrometry-data-2mass-00,curl + zescrow-client,curl + youtube-dl,curl + yorick,curl + wsl,curl + wsl,curl + wmget,curl + wakeup,curl + vagrant,curl + umegaya,curl + uhd-host,curl + twittering-mode,curl + twidge,curl + tdiary-contrib,curl + sylpheed,curl + surfraw,curl + surf,curl + solr-common,curl + smokeping,curl + scamp,curl + s3curl,curl + ruby-build,curl + rkhunter,curl + python-curtin,curl + pybit-svn,curl + prey,curl + pp-popularity-contest,curl + podracer,curl + gotmail,curl 7.9.0 + phablet-tools,curl + perlbrew,curl + origami,curl + openstreetmap-carto-common,curl + openstack-resource-agents,curl + openssh-known-hosts,curl + opennebula-flow,curl + opam,curl + nomnom,curl + myrepos,curl + linuxbrew-wrapper,curl + libguestfs0,curl + libguestfs-tools,curl + kino,curl + jhbuild,curl + jenkins-debian-glue-buildenv,curl + ifupdown-extra,curl + hydra,curl + html2text,curl + gwhois,curl + groonga-httpd,curl + debian-goodies,curl + google-perftools,curl + git-remote-gcrypt,curl + git-ftp,curl + git-annex,curl + getlive,curl + freeipa-client,curl + freedombox-setup,curl + foomatic-db-engine,curl + elastichosts-utils,curl + drush,curl + drupal7,curl + dracut-network,curl + dpatch,curl + djvulibre-bin,curl + diaspora-common,curl + di-netboot-assistant,curl + dgit,curl + debmake,curl + debian-cd,curl + dbab,curl + cpanminus,curl + clamav-unofficial-sigs,curl + ceph-test,curl + cairo-dock-plug-ins,curl + bosixnet-webui,curl + bosixnet-daemon,curl + bibledit-xiphos,curl + bibledit-gtk,curl + bibledit-bibletime,curl + ben,curl + awesome-extra,curl + atheist,curl + astrometry.net,curl + arno-iptables-firewall,curl + apt-file,curl + approx,curl + ansiweather,curl + anc-api-tools,curl + ubuntu-server,curl + spamassassin,curl + python3-curtin,curl + pollinate,curl + plainbox-provider-checkbox,curl + pciutils,curl + imagemagick-6.q16,curl + ieee-data,curl + gettext,curl + devscripts,curl +Dependencies: +7.47.0-1ubuntu2.4 - libc6 (2 2.17) libcurl3-gnutls (5 7.47.0-1ubuntu2.4) zlib1g (2 1:1.1.4) +7.47.0-1ubuntu2 - libc6 (2 2.17) libcurl3-gnutls (5 7.47.0-1ubuntu2) zlib1g (2 1:1.1.4) +Provides: +7.47.0-1ubuntu2.4 - +7.47.0-1ubuntu2 - +Reverse Provides: +Package: wget +Versions: +1.17.1-1ubuntu1.3 (/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial-updates_main_binary-amd64_Packages.lz4) (/var/lib/apt/lists/security.ubuntu.com_ubuntu_dists_xenial-security_main_binary-amd64_Packages.lz4) + Description Language: + File: /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial_main_binary-amd64_Packages.lz4 + MD5: 63a4a740bcd9e8e94bf661e4f1806e02 + Description Language: + File: /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial-updates_main_binary-amd64_Packages.lz4 + MD5: 63a4a740bcd9e8e94bf661e4f1806e02 + +1.17.1-1ubuntu1 (/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial_main_binary-amd64_Packages.lz4) + Description Language: + File: /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial_main_binary-amd64_Packages.lz4 + MD5: 63a4a740bcd9e8e94bf661e4f1806e02 + Description Language: + File: /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_xenial-updates_main_binary-amd64_Packages.lz4 + MD5: 63a4a740bcd9e8e94bf661e4f1806e02 + + +Reverse Depends: + ttf-root-installer,wget 1.9.1-4 + virtualbox-ext-pack,wget + playonlinux,wget + pepperflashplugin-nonfree,wget + mythtv-backend,wget + flashplugin-installer,wget + xtables-addons-common,wget + sbuild,wget + python-curtin,wget + ubiquity,wget + python3-curtin,wget + pciutils,wget + maas-rack-controller,wget + debootstrap,wget + virtualbox-ext-pack,wget + usbutils,wget 1.8.1-6 + susv4,wget + susv3,wget + susv2,wget + snmp-mibs-downloader,wget + sdic-gene95,wget + rocksndiamonds,wget + quake3-data,wget + publicfile-installer,wget + primesense-nite-nonfree,wget + playonlinux,wget + pepperflashplugin-nonfree,wget + mythtv-backend,wget + libdvd-pkg,wget + kinect-audio-setup,wget + hyperspec,wget + googleearth-package,wget + google-android-sdk-docs-installer,wget + geoip-database-contrib,wget + flashplugin-installer,wget + firmware-b43legacy-installer,wget + firmware-b43-installer,wget + cltl,wget + zomg,wget + youtube-dl,wget + xtables-addons-common,wget + xdeb,wget + wsl,wget 1.13 + wotsap,wget + wmfrog,wget + winetricks,wget + util-vserver,wget + urlview,wget + uck,wget + ubuntu-touch,wget + testdrive-common,wget + svn-buildpackage,wget + surfraw,wget + spacefm-gtk3,wget + spacefm,wget + simple-cdd,wget + shorewall6-lite,wget + shorewall-lite,wget + screenbin,wget + sbuild,wget + rrdweather,wget + rkhunter,wget + rinse,wget + rfcdiff,wget + qalc,wget + q4wine,wget + pyxplot,wget + python-curtin,wget + prism2-usb-firmware-installer,wget + podget,wget + plait,wget + phablet-tools-citrain,wget + phablet-tools,wget + petitboot-twin,wget + petitboot,wget + perlbrew,wget + osmctools,wget + origami,wget + openrocket,wget + opennebula,wget + opam,wget + oinkmaster,wget + nrss,wget + neurodebian,wget + mirmon,wget + mh-e,wget + madison-lite,wget + luarocks,wget + ltsp-client,wget + live-config,wget + live-boot,wget + liquidsoap,wget + libcupt4-1-downloadmethod-wget,wget + ktoblzcheck,wget + jigdo-file,wget + jhbuild,wget + inn2,wget + hydra,wget + html2text,wget + gnuhtml2latex,wget + gkrellweather,wget + gkrellkam,wget + git-annex,wget + geographiclib-tools,wget + freedombox-setup,wget + foomatic-db-engine,wget + fiaif,wget + fex-utils,wget + fex,wget + e2wm,wget + drush,wget + dpkg-dev-el,wget + dphys-config,wget + dokuwiki,wget + disc-cover,wget + dillo,wget + diaspora-installer,wget + di-netboot-assistant,wget + debmake,wget + debian-el,wget + dahdi-dkms,wget + cpl-plugin-xshoo-calib,wget + cpl-plugin-visir-calib,wget + cpl-plugin-vimos-calib,wget + cpl-plugin-uves-calib,wget + cpl-plugin-sinfo-calib,wget + cpl-plugin-naco-calib,wget + cpl-plugin-muse-calib,wget + cpl-plugin-kmos-calib,wget + cpl-plugin-hawki-calib,wget + cpl-plugin-giraf-calib,wget + cpl-plugin-fors-calib,wget + cpl-plugin-amber-calib,wget + cpanminus,wget + collabtive,wget + cloud-utils-euca,wget + cdebootstrap-static,wget + cairo-dock-plug-ins,wget + bmt,wget + bladerf-fpga-hostedx40,wget + bladerf-fpga-hostedx115,wget + bladerf-firmware-fx3,wget + avfs,wget + auto-apt,wget + apt-mirror,wget + apf-firewall,wget + adzapper,wget + abcde,wget + cloud-image-utils,wget + ubuntu-standard,wget + ubiquity,wget + ssh-import-id,wget + python3-curtin,wget + printer-driver-foo2zjs,wget + pciutils,wget + pbuilder,wget + maas-rack-controller,wget + maas-enlist,wget + jigit,wget + ieee-data,wget + hplip,wget + gettext,wget + emacs-goodies-el,wget + devscripts,wget + debootstrap,wget +Dependencies: +1.17.1-1ubuntu1.3 - libc6 (2 2.17) libidn11 (2 1.13) libpcre3 (0 (null)) libssl1.0.0 (2 1.0.1) libuuid1 (2 2.16) zlib1g (2 1:1.1.4) wget-ssl (0 (null)) ca-certificates (0 (null)) +1.17.1-1ubuntu1 - libc6 (2 2.17) libidn11 (2 1.13) libpcre3 (0 (null)) libssl1.0.0 (2 1.0.1) libuuid1 (2 2.16) zlib1g (2 1:1.1.4) wget-ssl (0 (null)) ca-certificates (0 (null)) +Provides: +1.17.1-1ubuntu1.3 - +1.17.1-1ubuntu1 - +Reverse Provides: +Package: libcurl-dev +Versions: + +Reverse Depends: + libdap-dev,libcurl-dev + libnxml0-dev,libcurl-dev + libglyr-dev,libcurl-dev +Dependencies: +Provides: +Reverse Provides: +libcurl4-openssl-dev 7.47.0-1ubuntu2.4 (= ) +libcurl4-nss-dev 7.47.0-1ubuntu2.4 (= ) +libcurl4-gnutls-dev 7.47.0-1ubuntu2.4 (= ) +libcurl4-openssl-dev 7.47.0-1ubuntu2 (= ) +libcurl4-nss-dev 7.47.0-1ubuntu2 (= ) +libcurl4-gnutls-dev 7.47.0-1ubuntu2 (= ) +Package: ros-kinetic-rc-genicam-api +Versions: + +Reverse Depends: + ros-kinetic-rc-visard-driver,ros-kinetic-rc-genicam-api +Dependencies: +Provides: +Reverse Provides: diff -Nru ros-rosdep-0.11.8/test/redhat/rpm-E-fedora ros-rosdep-0.12.2/test/redhat/rpm-E-fedora --- ros-rosdep-0.11.8/test/redhat/rpm-E-fedora 1970-01-01 00:00:00.000000000 +0000 +++ ros-rosdep-0.12.2/test/redhat/rpm-E-fedora 2018-03-21 23:40:00.000000000 +0000 @@ -0,0 +1 @@ +27 diff -Nru ros-rosdep-0.11.8/test/redhat/rpm-q-rpm ros-rosdep-0.12.2/test/redhat/rpm-q-rpm --- ros-rosdep-0.11.8/test/redhat/rpm-q-rpm 1970-01-01 00:00:00.000000000 +0000 +++ ros-rosdep-0.12.2/test/redhat/rpm-q-rpm 2018-03-21 23:40:00.000000000 +0000 @@ -0,0 +1,3 @@ +config(rpm) +rpm +rpm(x86-64) diff -Nru ros-rosdep-0.11.8/test/redhat/rpm-q-tinyxml-dev ros-rosdep-0.12.2/test/redhat/rpm-q-tinyxml-dev --- ros-rosdep-0.11.8/test/redhat/rpm-q-tinyxml-dev 1970-01-01 00:00:00.000000000 +0000 +++ ros-rosdep-0.12.2/test/redhat/rpm-q-tinyxml-dev 2018-03-21 23:40:00.000000000 +0000 @@ -0,0 +1 @@ +no package provides tinyxml-dev diff -Nru ros-rosdep-0.11.8/test/test_flake8.py ros-rosdep-0.12.2/test/test_flake8.py --- ros-rosdep-0.11.8/test/test_flake8.py 1970-01-01 00:00:00.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_flake8.py 2018-03-21 23:40:00.000000000 +0000 @@ -0,0 +1,67 @@ +# Copyright 2018 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import print_function + +import os +import sys + +# flake8 doesn't support Python < 2.7 anymore +if sys.version_info[0] > 2 or sys.version_info[1] >= 7: + from flake8.api.legacy import get_style_guide +else: + get_style_guide = None + + +def test_flake8(): + if get_style_guide is None: + # skip test on Python 2.6 and older + return + + style_guide = get_style_guide( + exclude=['conf.py'], + ignore=[ + 'C402', # ignore presence of unnecessary generators + 'C405', # ignore presence of unnecessary literals + 'C407', # ignore presence of unnecessary comprehensions + 'C408', # ignore presence of unnecessary tuple/list/dict + 'D', # ignore documentation related warnings + 'F401', # ignore presence of unused imports + 'F841', # ignore presence of unused variables + 'I', # ignore import order related warnings + 'N802', # ignore presence of upper case in function names + ], + max_line_length=200, + max_complexity=10, + show_source=True, + ) + + stdout = sys.stdout + sys.stdout = sys.stderr + # implicitly calls report_errors() + report = style_guide.check_files([ + os.path.dirname(os.path.dirname(__file__)), + ]) + sys.stdout = stdout + + if report.total_errors: + # output summary with per-category counts + print() + report._application.formatter.show_statistics(report._stats) + print( + 'flake8 reported {report.total_errors} errors' + .format_map(locals()), file=sys.stderr) + + assert not report.total_errors, \ + 'flake8 reported {report.total_errors} errors'.format_map(locals()) diff -Nru ros-rosdep-0.11.8/test/test_rosdep_arch.py ros-rosdep-0.12.2/test/test_rosdep_arch.py --- ros-rosdep-0.11.8/test/test_rosdep_arch.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_arch.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,10 +31,12 @@ import traceback from mock import Mock, patch + def get_test_dir(): # not used yet return os.path.abspath(os.path.join(os.path.dirname(__file__), 'arch')) + def test_PacmanInstaller(): from rosdep2.platforms.arch import PacmanInstaller @@ -57,4 +59,3 @@ except AssertionError: traceback.print_exc() raise - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_catkin_packages.py ros-rosdep-0.12.2/test/test_rosdep_catkin_packages.py --- ros-rosdep-0.11.8/test/test_rosdep_catkin_packages.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_catkin_packages.py 2018-03-21 23:40:00.000000000 +0000 @@ -41,4 +41,4 @@ create_package_xml('src/baz', '0.2.0') pkgs = find_catkin_packages_in('src') assert sorted(pkgs) == sorted(['foo', 'bar', 'baz']), \ - 'actually: ' + str(sorted(pkgs)) + 'actually: ' + str(sorted(pkgs)) diff -Nru ros-rosdep-0.11.8/test/test_rosdep_core.py ros-rosdep-0.12.2/test/test_rosdep_core.py --- ros-rosdep-0.11.8/test/test_rosdep_core.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_core.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -27,6 +27,7 @@ import os + def test_RosdepInternalError(): from rosdep2.core import RosdepInternalError try: @@ -34,13 +35,15 @@ except Exception as e: ex = RosdepInternalError(e) assert e == ex.error - + + def test_rd_debug(): # just tripwire/coverage from rosdep2.core import rd_debug rd_debug('foo') os.environ['ROSDEP_DEBUG'] = '1' - rd_debug('foo') + rd_debug('foo') + def test_InvalidData(): from rosdep2.core import InvalidData @@ -48,4 +51,3 @@ raise InvalidData('hi') except InvalidData as ex: assert 'hi' in str(ex) - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_cygwin.py ros-rosdep-0.12.2/test/test_rosdep_cygwin.py --- ros-rosdep-0.11.8/test/test_rosdep_cygwin.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_cygwin.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,10 +31,12 @@ import traceback from mock import patch + def get_test_dir(): # not used yet return os.path.abspath(os.path.join(os.path.dirname(__file__), 'cygwin')) + def test_AptCygInstaller(): from rosdep2.platforms.cygwin import AptCygInstaller @@ -57,4 +59,3 @@ except AssertionError: traceback.print_exc() raise - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_debian.py ros-rosdep-0.12.2/test/test_rosdep_debian.py --- ros-rosdep-0.11.8/test/test_rosdep_debian.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_debian.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -29,47 +29,104 @@ import os import traceback -from mock import Mock, patch +from mock import Mock, patch, call + def get_test_dir(): return os.path.abspath(os.path.join(os.path.dirname(__file__), 'debian')) + def test_dpkg_detect(): from rosdep2.platforms.debian import dpkg_detect - - m = Mock() - m.return_value = '' - val = dpkg_detect([], exec_fn=m) - assert val == [], val - - val = dpkg_detect(['tinyxml-dev'], exec_fn=m) - assert val == [], val - #assert m.assert_called_with(['dpkg-query', '-W', '-f=\'${Package} ${Status}\n\'']) + + with patch('rosdep2.platforms.debian.read_stdout') as mock_read_stdout: + mock_read_stdout.side_effect = [('', ''), ''] + val = dpkg_detect([]) + assert val == [], val + assert mock_read_stdout.call_count == 2 + assert mock_read_stdout.call_args_list[0] == call(['dpkg-query', '-W', "-f='${Package} ${Status}\n'"], True) + assert mock_read_stdout.call_args_list[1] == call(['apt-cache', 'showpkg']) + + with patch('rosdep2.platforms.debian.read_stdout') as mock_read_stdout: + mock_read_stdout.side_effect = [('', ''), ''] + val = dpkg_detect(['tinyxml-dev']) + assert val == [], val + assert mock_read_stdout.call_count == 2 + assert mock_read_stdout.call_args_list[0] == call(['dpkg-query', '-W', "-f='${Package} ${Status}\n'", + 'tinyxml-dev'], True) + assert mock_read_stdout.call_args_list[1] == call(['apt-cache', 'showpkg', 'tinyxml-dev']) with open(os.path.join(get_test_dir(), 'dpkg-python-apt'), 'r') as f: - m.return_value = f.read() - val = dpkg_detect(['apt', 'tinyxml-dev', 'python'], exec_fn=m) - assert val == ['apt', 'python'], val + dpkg_python_apt_test_content = f.read() + + with patch('rosdep2.platforms.debian.read_stdout') as mock_read_stdout: + mock_read_stdout.side_effect = [(dpkg_python_apt_test_content, ''), ''] + val = dpkg_detect(['apt', 'tinyxml-dev', 'python']) + assert val == ['apt', 'python'], val + assert mock_read_stdout.call_count == 2 + print(mock_read_stdout.call_args_list[0]) + assert mock_read_stdout.call_args_list[1] == call(['apt-cache', 'showpkg', 'tinyxml-dev']) # test version lock code (should be filtered out w/o validation) - val = dpkg_detect(['apt=1.8', 'tinyxml-dev', 'python=2.7'], exec_fn=m) - assert val == ['apt=1.8', 'python=2.7'], val + with patch('rosdep2.platforms.debian.read_stdout') as mock_read_stdout: + mock_read_stdout.side_effect = [(dpkg_python_apt_test_content, ''), ''] + val = dpkg_detect(['apt=1.8', 'tinyxml-dev', 'python=2.7']) + assert val == ['apt=1.8', 'python=2.7'], val + assert mock_read_stdout.call_count == 2 + assert mock_read_stdout.call_args_list[1] == call(['apt-cache', 'showpkg', 'tinyxml-dev']) + + +def test_read_apt_cache_showpkg(): + from rosdep2.platforms.debian import _read_apt_cache_showpkg + + m = Mock() + with open(os.path.join(get_test_dir(), 'showpkg-curl-wget-libcurl-dev'), 'r') as f: + m.return_value = f.read() + pkgs = ['curl', 'wget', '_not_existing', 'libcurl-dev', 'ros-kinetic-rc-genicam-api'] + results = list(_read_apt_cache_showpkg(pkgs, exec_fn=m)) + assert len(results) == len(pkgs), results + + package, virtual, providers = results[0] + assert package == 'curl', package + assert not virtual + assert providers is None, providers + + package, virtual, providers = results[1] + assert package == 'wget', package + assert not virtual + assert providers is None, providers + + package, virtual, providers = results[2] + assert package == '_not_existing', package + assert not virtual + assert providers is None, providers + + package, virtual, providers = results[3] + assert package == 'libcurl-dev', package + assert virtual, providers + + package, virtual, providers = results[4] + assert package == 'ros-kinetic-rc-genicam-api', package + assert not virtual + assert providers is None, providers def test_AptInstaller(): from rosdep2.platforms.debian import AptInstaller + @patch('rosdep2.platforms.debian.read_stdout') @patch.object(AptInstaller, 'get_packages_to_install') - def test(mock_method): + def test(mock_get_packages_to_install, mock_read_stdout): installer = AptInstaller() - mock_method.return_value = [] + mock_get_packages_to_install.return_value = [] + mock_read_stdout.return_value = '' assert [] == installer.get_install_command(['fake']) - mock_method.return_value = ['a', 'b'] + mock_get_packages_to_install.return_value = ['a', 'b'] expected = [['sudo', '-H', 'apt-get', 'install', '-y', 'a'], ['sudo', '-H', 'apt-get', 'install', '-y', 'b']] val = installer.get_install_command(['whatever'], interactive=False) - print("VAL", val) + print('VAL', val) assert val == expected, val expected = [['sudo', '-H', 'apt-get', 'install', 'a'], ['sudo', '-H', 'apt-get', 'install', 'b']] @@ -80,4 +137,3 @@ except AssertionError: traceback.print_exc() raise - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_dependency_graph.py ros-rosdep-0.12.2/test/test_rosdep_dependency_graph.py --- ros-rosdep-0.11.8/test/test_rosdep_dependency_graph.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_dependency_graph.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2012, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -27,145 +27,151 @@ # Author William Woodall/wjwwood@gmail.com + def test_DependencyGraph_Linear(): - from rosdep2.dependency_graph import DependencyGraph - # Normal A-B-C - dg = DependencyGraph() - dg['A']['installer_key'] = 'a_installer' - dg['A']['install_keys'] = ['a'] - dg['A']['dependencies'] = ['B'] - dg['B']['installer_key'] = 'b_installer' - dg['B']['install_keys'] = ['b'] - dg['B']['dependencies'] = ['C'] - dg['C']['installer_key'] = 'c_installer' - dg['C']['install_keys'] = ['c'] - dg['C']['dependencies'] = [] - result = dg.get_ordered_dependency_list() - expected = [('c_installer', ['c']), ('b_installer', ['b']), ('a_installer', ['a'])] - assert result == expected, "Results did not match expectations: %s == %s"%(str(result),str(expected)) + from rosdep2.dependency_graph import DependencyGraph + # Normal A-B-C + dg = DependencyGraph() + dg['A']['installer_key'] = 'a_installer' + dg['A']['install_keys'] = ['a'] + dg['A']['dependencies'] = ['B'] + dg['B']['installer_key'] = 'b_installer' + dg['B']['install_keys'] = ['b'] + dg['B']['dependencies'] = ['C'] + dg['C']['installer_key'] = 'c_installer' + dg['C']['install_keys'] = ['c'] + dg['C']['dependencies'] = [] + result = dg.get_ordered_dependency_list() + expected = [('c_installer', ['c']), ('b_installer', ['b']), ('a_installer', ['a'])] + assert result == expected, 'Results did not match expectations: %s == %s' % (str(result), str(expected)) + def test_DependencyGraph_Cycle(): - from rosdep2.dependency_graph import DependencyGraph - # Full Loop A-B-C-A-... - dg = DependencyGraph() - dg['A']['installer_key'] = 'a_installer' - dg['A']['install_keys'] = ['a'] - dg['A']['dependencies'] = ['B'] - dg['B']['installer_key'] = 'b_installer' - dg['B']['install_keys'] = ['b'] - dg['B']['dependencies'] = ['C'] - dg['C']['installer_key'] = 'c_installer' - dg['C']['install_keys'] = ['c'] - dg['C']['dependencies'] = ['A'] - try: - result = dg.get_ordered_dependency_list() - assert False, "Doesn't fail, it should fail with an AssertionError because of the cycle." - except AssertionError as e: - if not str(e).startswith("A cycle in the dependency graph occurred with key"): - assert False, "Throws AssertionError, but with the wrong message. Error was: %s: %s"%(type(e),str(e)) - except Exception as e: - assert False, "Throws and Exception, but not an AssertionError. Error was: %s: %s"%(type(e),str(e)) + from rosdep2.dependency_graph import DependencyGraph + # Full Loop A-B-C-A-... + dg = DependencyGraph() + dg['A']['installer_key'] = 'a_installer' + dg['A']['install_keys'] = ['a'] + dg['A']['dependencies'] = ['B'] + dg['B']['installer_key'] = 'b_installer' + dg['B']['install_keys'] = ['b'] + dg['B']['dependencies'] = ['C'] + dg['C']['installer_key'] = 'c_installer' + dg['C']['install_keys'] = ['c'] + dg['C']['dependencies'] = ['A'] + try: + result = dg.get_ordered_dependency_list() + assert False, "Doesn't fail, it should fail with an AssertionError because of the cycle." + except AssertionError as e: + if not str(e).startswith('A cycle in the dependency graph occurred with key'): + assert False, 'Throws AssertionError, but with the wrong message. Error was: %s: %s' % (type(e), str(e)) + except Exception as e: + assert False, 'Throws and Exception, but not an AssertionError. Error was: %s: %s' % (type(e), str(e)) + def test_DependencyGraph_Short_Cycle(): - from rosdep2.dependency_graph import DependencyGraph - # Short cycle A-B-C-D-B-C-D-... - dg = DependencyGraph() - dg['A']['installer_key'] = 'a_installer' - dg['A']['install_keys'] = ['a'] - dg['A']['dependencies'] = ['B'] - dg['B']['installer_key'] = 'b_installer' - dg['B']['install_keys'] = ['b'] - dg['B']['dependencies'] = ['C'] - dg['C']['installer_key'] = 'c_installer' - dg['C']['install_keys'] = ['c'] - dg['C']['dependencies'] = ['D'] - dg['D']['installer_key'] = 'd_installer' - dg['D']['install_keys'] = ['d'] - dg['D']['dependencies'] = ['B'] - try: - result = dg.get_ordered_dependency_list() - assert False, "Doesn't fail, it should fail with an AssertionError because of the cycle." - except AssertionError as e: - if not str(e).startswith("A cycle in the dependency graph occurred with key"): - assert False, "Throws AssertionError, but with the wrong message. Error was: %s: %s"%(type(e),str(e)) - except Exception as e: - assert False, "Throws and Exception, but not an AssertionError. Error was: %s: %s"%(type(e),str(e)) + from rosdep2.dependency_graph import DependencyGraph + # Short cycle A-B-C-D-B-C-D-... + dg = DependencyGraph() + dg['A']['installer_key'] = 'a_installer' + dg['A']['install_keys'] = ['a'] + dg['A']['dependencies'] = ['B'] + dg['B']['installer_key'] = 'b_installer' + dg['B']['install_keys'] = ['b'] + dg['B']['dependencies'] = ['C'] + dg['C']['installer_key'] = 'c_installer' + dg['C']['install_keys'] = ['c'] + dg['C']['dependencies'] = ['D'] + dg['D']['installer_key'] = 'd_installer' + dg['D']['install_keys'] = ['d'] + dg['D']['dependencies'] = ['B'] + try: + result = dg.get_ordered_dependency_list() + assert False, "Doesn't fail, it should fail with an AssertionError because of the cycle." + except AssertionError as e: + if not str(e).startswith('A cycle in the dependency graph occurred with key'): + assert False, 'Throws AssertionError, but with the wrong message. Error was: %s: %s' % (type(e), str(e)) + except Exception as e: + assert False, 'Throws and Exception, but not an AssertionError. Error was: %s: %s' % (type(e), str(e)) + def test_DependencyGraph_Invalid_Key(): - from rosdep2.dependency_graph import DependencyGraph - # Invalid graph A-B-C where C doesn't exist - dg = DependencyGraph() - dg['A']['installer_key'] = 'a_installer' - dg['A']['install_keys'] = ['a'] - dg['A']['dependencies'] = ['B'] - dg['B']['installer_key'] = 'b_installer' - dg['B']['install_keys'] = ['b'] - dg['B']['dependencies'] = ['C'] - try: - result = dg.get_ordered_dependency_list() - assert False, "Doesn't fail, it should fail with an KeyError because of the invalid rosdep key." - except KeyError as e: - if not str(e).endswith("does not exist in the dictionary of resolutions.'"): - assert False, "Throws KeyError, but with the wrong message. Error was: %s: %s"%(type(e),str(e)) - except Exception as e: - assert False, "Throws and Exception, but not an KeyError. Error was: %s: %s"%(type(e),str(e)) + from rosdep2.dependency_graph import DependencyGraph + # Invalid graph A-B-C where C doesn't exist + dg = DependencyGraph() + dg['A']['installer_key'] = 'a_installer' + dg['A']['install_keys'] = ['a'] + dg['A']['dependencies'] = ['B'] + dg['B']['installer_key'] = 'b_installer' + dg['B']['install_keys'] = ['b'] + dg['B']['dependencies'] = ['C'] + try: + result = dg.get_ordered_dependency_list() + assert False, "Doesn't fail, it should fail with an KeyError because of the invalid rosdep key." + except KeyError as e: + if not str(e).endswith("does not exist in the dictionary of resolutions.'"): + assert False, 'Throws KeyError, but with the wrong message. Error was: %s: %s' % (type(e), str(e)) + except Exception as e: + assert False, 'Throws and Exception, but not an KeyError. Error was: %s: %s' % (type(e), str(e)) + def test_DependencyGraph_Invalid_Key2(): - from rosdep2.dependency_graph import DependencyGraph - # Invalid graph A-B-C where B doesn't exist - dg = DependencyGraph() - dg['A']['installer_key'] = 'a_installer' - dg['A']['install_keys'] = ['a'] - dg['A']['dependencies'] = ['B'] - dg['C']['installer_key'] = 'c_installer' - dg['C']['install_keys'] = ['c'] - dg['C']['dependencies'] = [] - try: - result = dg.get_ordered_dependency_list() - assert False, "Doesn't fail, it should fail with an KeyError because of the invalid rosdep key." - except KeyError as e: - if not str(e).endswith("does not exist in the dictionary of resolutions.'"): - assert False, "Throws KeyError, but with the wrong message. Error was: %s: %s"%(type(e),str(e)) - except Exception as e: - assert False, "Throws and Exception, but not an KeyError. Error was: %s: %s"%(type(e),str(e)) + from rosdep2.dependency_graph import DependencyGraph + # Invalid graph A-B-C where B doesn't exist + dg = DependencyGraph() + dg['A']['installer_key'] = 'a_installer' + dg['A']['install_keys'] = ['a'] + dg['A']['dependencies'] = ['B'] + dg['C']['installer_key'] = 'c_installer' + dg['C']['install_keys'] = ['c'] + dg['C']['dependencies'] = [] + try: + result = dg.get_ordered_dependency_list() + assert False, "Doesn't fail, it should fail with an KeyError because of the invalid rosdep key." + except KeyError as e: + if not str(e).endswith("does not exist in the dictionary of resolutions.'"): + assert False, 'Throws KeyError, but with the wrong message. Error was: %s: %s' % (type(e), str(e)) + except Exception as e: + assert False, 'Throws and Exception, but not an KeyError. Error was: %s: %s' % (type(e), str(e)) + def test_DependencyGraph_Multi_Root(): - from rosdep2.dependency_graph import DependencyGraph - # Multi root, shared dependency: A-B-C, D-C - dg = DependencyGraph() - dg['A']['installer_key'] = 'a_installer' - dg['A']['install_keys'] = ['a'] - dg['A']['dependencies'] = ['B'] - dg['B']['installer_key'] = 'b_installer' - dg['B']['install_keys'] = ['b'] - dg['B']['dependencies'] = ['C'] - dg['C']['installer_key'] = 'c_installer' - dg['C']['install_keys'] = ['c'] - dg['C']['dependencies'] = [] - dg['D']['installer_key'] = 'd_installer' - dg['D']['install_keys'] = ['d'] - dg['D']['dependencies'] = ['C'] - result = dg.get_ordered_dependency_list() - # TODO: The expected might also have a different order, for example it might be: - # [('c_installer', ['c']), ('d_installer', ['d']), ('b_installer', ['b']), ('a_installer', ['a'])] - # But that wont invalidate the order from a dependency graph stand point - expected = [ - [('c_installer', ['c']), ('b_installer', ['b']), ('a_installer', ['a']), ('d_installer', ['d'])], - [('c_installer', ['c']), ('d_installer', ['d']), ('b_installer', ['b']), ('a_installer', ['a'])], - ] - assert result in expected, "Results did not match expectations: %s == %s"%(str(result),str(expected)) + from rosdep2.dependency_graph import DependencyGraph + # Multi root, shared dependency: A-B-C, D-C + dg = DependencyGraph() + dg['A']['installer_key'] = 'a_installer' + dg['A']['install_keys'] = ['a'] + dg['A']['dependencies'] = ['B'] + dg['B']['installer_key'] = 'b_installer' + dg['B']['install_keys'] = ['b'] + dg['B']['dependencies'] = ['C'] + dg['C']['installer_key'] = 'c_installer' + dg['C']['install_keys'] = ['c'] + dg['C']['dependencies'] = [] + dg['D']['installer_key'] = 'd_installer' + dg['D']['install_keys'] = ['d'] + dg['D']['dependencies'] = ['C'] + result = dg.get_ordered_dependency_list() + # TODO: The expected might also have a different order, for example it might be: + # [('c_installer', ['c']), ('d_installer', ['d']), ('b_installer', ['b']), ('a_installer', ['a'])] + # But that wont invalidate the order from a dependency graph stand point + expected = [ + [('c_installer', ['c']), ('b_installer', ['b']), ('a_installer', ['a']), ('d_installer', ['d'])], + [('c_installer', ['c']), ('d_installer', ['d']), ('b_installer', ['b']), ('a_installer', ['a'])], + ] + assert result in expected, 'Results did not match expectations: %s == %s' % (str(result), str(expected)) -def test_DependencyGraph_Realworld(): - from rosdep2.dependency_graph import DependencyGraph - # Real world example - dg = DependencyGraph() - dg['python-matplotlib']['installer_key'] = 'pip' - dg['python-matplotlib']['install_keys'] = ['matplotlib'] - dg['python-matplotlib']['dependencies'] = ['pkg-config'] - dg['pkg-config']['installer_key'] = 'homebrew' - dg['pkg-config']['install_keys'] = ['pkg-config'] - dg['pkg-config']['dependencies'] = [] - result = dg.get_ordered_dependency_list() - expected = [('homebrew', ['pkg-config']), ('pip', ['matplotlib'])] - assert result == expected, "Results did not match expectations: %s == %s"%(str(result),str(expected)) +def test_DependencyGraph_Realworld(): + from rosdep2.dependency_graph import DependencyGraph + # Real world example + dg = DependencyGraph() + dg['python-matplotlib']['installer_key'] = 'pip' + dg['python-matplotlib']['install_keys'] = ['matplotlib'] + dg['python-matplotlib']['dependencies'] = ['pkg-config'] + dg['pkg-config']['installer_key'] = 'homebrew' + dg['pkg-config']['install_keys'] = ['pkg-config'] + dg['pkg-config']['dependencies'] = [] + result = dg.get_ordered_dependency_list() + expected = [('homebrew', ['pkg-config']), ('pip', ['matplotlib'])] + assert result == expected, 'Results did not match expectations: %s == %s' % (str(result), str(expected)) diff -Nru ros-rosdep-0.11.8/test/test_rosdep_freebsd.py ros-rosdep-0.12.2/test/test_rosdep_freebsd.py --- ros-rosdep-0.11.8/test/test_rosdep_freebsd.py 1970-01-01 00:00:00.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_freebsd.py 2018-03-21 23:40:00.000000000 +0000 @@ -0,0 +1,75 @@ +# Copyright (c) 2011, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# Copied from test_rosdep_suse.py by Author Ken Conley/kwc@willowgarage.com +# Converted to FreeBSD by Trenton Schulz/trentonw@ifi.uio.no + +import os +import traceback +from mock import patch, Mock + + +def get_test_dir(): + # not used yet + return os.path.abspath(os.path.join(os.path.dirname(__file__), 'freebsd')) + + +def test_pkg_detect(): + from rosdep2.platforms.freebsd import pkg_detect + + m = Mock() + m.return_value = '' + + val = pkg_detect([], exec_fn=m) + assert val == [], val + + val = pkg_detect(['tinyxml'], exec_fn=m) + assert val == [], val + + +def test_PkgInstaller(): + from rosdep2.platforms.freebsd import PkgInstaller + + @patch.object(PkgInstaller, 'get_packages_to_install') + def test(mock_method): + installer = PkgInstaller() + mock_method.return_value = [] + assert [] == installer.get_install_command(['fake']) + + # no interactive option with YUM + mock_method.return_value = ['a', 'b'] + expected = [['sudo', '-H', '/usr/sbin/pkg', 'install', '-y', 'a', 'b']] + val = installer.get_install_command(['whatever'], interactive=False) + assert val == expected, val + expected = [['sudo', '-H', '/usr/sbin/pkg', 'install', '-y', 'a', 'b']] + val = installer.get_install_command(['whatever'], interactive=True) + assert val == expected, val + try: + test() + except AssertionError: + traceback.print_exc() + raise diff -Nru ros-rosdep-0.11.8/test/test_rosdep_gbpdistro_support.py ros-rosdep-0.12.2/test/test_rosdep_gbpdistro_support.py --- ros-rosdep-0.11.8/test/test_rosdep_gbpdistro_support.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_gbpdistro_support.py 2018-03-21 23:40:00.000000000 +0000 @@ -40,19 +40,19 @@ def test_url_constants(): from rosdep2.gbpdistro_support import FUERTE_GBPDISTRO_URL for url_name, url in [ - ('FUERTE_GBPDISTRO_URL', FUERTE_GBPDISTRO_URL)]: + ('FUERTE_GBPDISTRO_URL', FUERTE_GBPDISTRO_URL)]: try: f = urlopen(url) f.read() f.close() - except: - assert False, "URL [%s][%s] failed to download" % (url_name, url) + except Exception: + assert False, 'URL [%s][%s] failed to download' % (url_name, url) def test_get_gbprepo_as_rosdep_data(): from rosdep2.rosdistrohelper import get_index from rosdep2.gbpdistro_support import get_gbprepo_as_rosdep_data - distro = list(get_index().distributions.keys())[0] + distro = sorted(get_index().distributions.keys())[0] data = get_gbprepo_as_rosdep_data(distro) for k in ['ros', 'catkin', 'genmsg']: assert k in data, data @@ -60,7 +60,7 @@ try: get_gbprepo_as_rosdep_data('fooNonExistantDistro') - assert False, "should have raised" + assert False, 'should have raised' except RuntimeError: pass @@ -80,15 +80,16 @@ # try with bad url to trigger exception handling try: # override targets URL with bad URL - download_gbpdistro_as_rosdep_data(FUERTE_GBPDISTRO_URL, + download_gbpdistro_as_rosdep_data( + FUERTE_GBPDISTRO_URL, targets_url='http://bad.ros.org/foo.yaml') - assert False, "should have raised" + assert False, 'should have raised' except DownloadFailure: pass try: # use targets URL, which should have a bad format download_gbpdistro_as_rosdep_data(REP3_TARGETS_URL) - assert False, "should have raised" + assert False, 'should have raised' except DownloadFailure: pass @@ -103,7 +104,7 @@ # test bad data try: gbprepo_to_rosdep_data(simple_gbpdistro, [targets]) - assert False, "should have raised" + assert False, 'should have raised' except InvalidData: pass try: @@ -111,12 +112,12 @@ 'targets': 1, 'repositories': [], 'type': 'gbp'}, targets) - assert False, "should have raised" + assert False, 'should have raised' except InvalidData: pass try: gbprepo_to_rosdep_data([], targets) - assert False, "should have raised" + assert False, 'should have raised' except InvalidData: pass # release-name must be in targets @@ -125,7 +126,7 @@ 'release-name': 'barte', 'repositories': [], 'type': 'gbp'}, targets) - assert False, "should have raised" + assert False, 'should have raised' except InvalidData: pass # gbp-distros must be list of dicts @@ -134,7 +135,7 @@ 'release-name': 'foorte', 'repositories': [1], 'type': 'gbp'}, targets) - assert False, "should have raised" + assert False, 'should have raised' except InvalidData: pass # gbp-distro target must be 'all' or a list of strings @@ -146,7 +147,7 @@ 'release-name': 'foorte', 'repositories': [bad_example], 'type': 'gbp'}, targets) - assert False, "should have raised" + assert False, 'should have raised' except InvalidData: pass @@ -163,22 +164,23 @@ assert rosdep_data is not None assert {} == rosdep_data - gbpdistro_data = {'release-name': 'foorte', - 'repositories': { - 'common_msgs': dict( - target='all', - url='git://github.com/wg-debs/common_msgs.git', - packages={ 'foo': 'subdir/foo', 'bar': 'subdir/bar' }), - 'gazebo': dict( - target=['lucid', 'natty'], - url='git://github.com/wg-debs/gazebo.git'), - 'foo-bar': dict( - target=['precise'], - url='git://github.com/wg-debs/gazebo.git', - packages={ 'foo-bar': None }), - }, - 'type': 'gbp', - } + gbpdistro_data = { + 'release-name': 'foorte', + 'repositories': { + 'common_msgs': dict( + target='all', + url='git://github.com/wg-debs/common_msgs.git', + packages={'foo': 'subdir/foo', 'bar': 'subdir/bar'}), + 'gazebo': dict( + target=['lucid', 'natty'], + url='git://github.com/wg-debs/gazebo.git'), + 'foo-bar': dict( + target=['precise'], + url='git://github.com/wg-debs/gazebo.git', + packages={'foo-bar': None}), + }, + 'type': 'gbp', + } rosdep_data = gbprepo_to_rosdep_data(gbpdistro_data, targets) for k in ['foo', 'bar', 'gazebo', 'foo-bar']: @@ -220,11 +222,10 @@ empty_url = '' assert get_owner_name(empty_url) == 'ros', 'url: ' + empty_url https_test_url = 'https://github.com/' \ - + 'ros/rosdistro/raw/master/releases/fuerte.yaml' + 'ros/rosdistro/raw/master/releases/fuerte.yaml' assert get_owner_name(https_test_url) == 'ros', 'url: ' + https_test_url user_test_url = 'https://github.com/' \ - + 'zklapow/rosdistro/raw/master/releases/fuerte.yaml' + 'zklapow/rosdistro/raw/master/releases/fuerte.yaml' assert get_owner_name(user_test_url) == 'zklapow', 'url: ' + user_test_url non_github_url = 'https://ros.org/files/releases/fuerte.yaml' assert get_owner_name(non_github_url) == 'ros', 'url: ' + non_github_url - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_gem.py ros-rosdep-0.12.2/test/test_rosdep_gem.py --- ros-rosdep-0.11.8/test/test_rosdep_gem.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_gem.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,10 +1,10 @@ # Copyright (c) 2011, Willow Garage, Inc. # Copyright (c) 2012, Intermodalics, BVBA # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -13,7 +13,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,12 +33,14 @@ import traceback from mock import Mock, patch + def get_test_dir(): return os.path.abspath(os.path.join(os.path.dirname(__file__), 'gem')) + def test_gem_detect(): from rosdep2.platforms.gem import gem_detect - + m = Mock() # test behavior with empty freeze @@ -64,7 +66,8 @@ from rosdep2.platforms.gem import GemInstaller installer = GemInstaller() assert ['foo'] == installer.get_depends(dict(depends=['foo'])) - + + def test_GemInstaller(): from rosdep2 import InstallFailed from rosdep2.platforms.gem import GemInstaller @@ -75,11 +78,12 @@ try: installer = GemInstaller() installer.get_install_command(['whatever']) - assert False, "should have raised" - except InstallFailed: pass - + assert False, 'should have raised' + except InstallFailed: + pass + test_no_gem() - + @patch('rosdep2.platforms.gem.is_gem_installed') @patch.object(GemInstaller, 'get_packages_to_install') def test(mock_method, mock_is_gem_installed): @@ -103,4 +107,3 @@ except AssertionError: traceback.print_exc() raise - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_gentoo.py ros-rosdep-0.12.2/test/test_rosdep_gentoo.py --- ros-rosdep-0.11.8/test/test_rosdep_gentoo.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_gentoo.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,49 +33,54 @@ import rospkg.os_detect + def is_gentoo(): return rospkg.os_detect.Gentoo().is_os() + def get_test_dir(): # not used yet return os.path.abspath(os.path.join(os.path.dirname(__file__), 'gentoo')) # Requires 2.7 @unittest.skipIf(not rospkg.os_detect.Gentoo().is_os(), "not running Gentoo") + + def test_portage_available(): if not is_gentoo(): - print("Skipping not Gentoo") - return + print('Skipping not Gentoo') + return from rosdep2.platforms.gentoo import portage_available original_exists = os.path.exists path_overrides = {} + def mock_path(path): if path in path_overrides: return path_overrides[path] - else: + else: return original_exists(path) m = Mock(side_effect=mock_path) os.path.exists = m - #Test with portageq missing + # Test with portageq missing m.reset_mock() path_overrides = {} path_overrides['/usr/bin/portageq'] = False path_overrides['/usr/bin/emerge'] = True val = portage_available() - assert val==False, "Portage should not be available without portageq" + assert not val, 'Portage should not be available without portageq' - #Test with emerge missing + # Test with emerge missing m.reset_mock() path_overrides = {} path_overrides['/usr/bin/portageq'] = True path_overrides['/usr/bin/emerge'] = False val = portage_available() - assert val==False, "Portage should not be available without emerge" + assert not val, 'Portage should not be available without emerge' # Test with nothing missing m.reset_mock() @@ -84,16 +89,17 @@ path_overrides['/usr/bin/emerge'] = True val = portage_available() - assert val==True, "Portage should be available" - + assert val, 'Portage should be available' + os.path.exists = original_exists # This actually tests portage_detect_single and portage_detect + def test_portage_detect(): if not is_gentoo(): - print("Skipping not Gentoo") - return + print('Skipping not Gentoo') + return from rosdep2.platforms.gentoo import portage_detect @@ -102,69 +108,70 @@ val = portage_detect([], exec_fn=m) assert val == [], val - + # Test checking for a package that we do not have installed - m = Mock(return_value = []) + m = Mock(return_value=[]) val = portage_detect(['tinyxml[stl]'], exec_fn=m) - assert val == [], "Result was actually: %s" % val + assert val == [], 'Result was actually: %s' % val m.assert_called_with(['portageq', 'match', '/', 'tinyxml[stl]']) # Test checking for a package that we do have installed - m = Mock(return_value = ['dev-libs/tinyxml-2.6.2-r1']) + m = Mock(return_value=['dev-libs/tinyxml-2.6.2-r1']) val = portage_detect(['tinyxml[stl]'], exec_fn=m) - assert val == ['tinyxml[stl]'], "Result was actually: %s" % val + assert val == ['tinyxml[stl]'], 'Result was actually: %s' % val m.assert_called_with(['portageq', 'match', '/', 'tinyxml[stl]']) - + # Test checking for two packages that we have installed - m = Mock(side_effect = [['sys-devel/gcc-4.5.3-r2'], ['dev-libs/tinyxml-2.6.2-r1']]) + m = Mock(side_effect=[['sys-devel/gcc-4.5.3-r2'], ['dev-libs/tinyxml-2.6.2-r1']]) val = portage_detect(['tinyxml[stl]', 'gcc'], exec_fn=m) - assert val == ['gcc', 'tinyxml[stl]'], "Result was actually: %s" % val - m.assert_any_call(['portageq', 'match', '/', 'tinyxml[stl]']) + assert val == ['gcc', 'tinyxml[stl]'], 'Result was actually: %s' % val + m.assert_any_call(['portageq', 'match', '/', 'tinyxml[stl]']) m.assert_any_call(['portageq', 'match', '/', 'gcc']) - + # Test checking for two missing packages - m = Mock(side_effect = [[],[]]) + m = Mock(side_effect=[[], []]) val = portage_detect(['tinyxml[stl]', 'gcc'], exec_fn=m) - assert val == [], "Result was actually: %s" % val - m.assert_any_call(['portageq', 'match', '/', 'tinyxml[stl]']) + assert val == [], 'Result was actually: %s' % val + m.assert_any_call(['portageq', 'match', '/', 'tinyxml[stl]']) m.assert_any_call(['portageq', 'match', '/', 'gcc']) # Test checking for one missing, one installed package - m = Mock(side_effect = [['sys-devel/gcc-4.5.3-r2'], []]) + m = Mock(side_effect=[['sys-devel/gcc-4.5.3-r2'], []]) val = portage_detect(['tinyxml[stl]', 'gcc'], exec_fn=m) - assert val == ['gcc'], "Result was actually: %s" % val - m.assert_any_call(['portageq', 'match', '/', 'tinyxml[stl]']) + assert val == ['gcc'], 'Result was actually: %s' % val + m.assert_any_call(['portageq', 'match', '/', 'tinyxml[stl]']) m.assert_any_call(['portageq', 'match', '/', 'gcc']) # Test checking for one installed, one missing package (reverse order) - m = Mock(side_effect = [[], ['dev-libs/tinyxml-2.6.2-r1']]) + m = Mock(side_effect=[[], ['dev-libs/tinyxml-2.6.2-r1']]) val = portage_detect(['tinyxml[stl]', 'gcc'], exec_fn=m) - assert val == ['tinyxml[stl]'], "Result was actually: %s" % val - m.assert_any_call(['portageq', 'match', '/', 'tinyxml[stl]']) + assert val == ['tinyxml[stl]'], 'Result was actually: %s' % val + m.assert_any_call(['portageq', 'match', '/', 'tinyxml[stl]']) m.assert_any_call(['portageq', 'match', '/', 'gcc']) # Test duplicates (requesting the same package twice) - #TODO what's the desired behavior here - m = Mock(side_effect = [['dev-libs/tinyxml-2.6.2-r1'],['dev-libs/tinyxml-2.6.2-r1']]) + # TODO what's the desired behavior here + m = Mock(side_effect=[['dev-libs/tinyxml-2.6.2-r1'], ['dev-libs/tinyxml-2.6.2-r1']]) val = portage_detect(['tinyxml[stl]', 'tinyxml[stl]'], exec_fn=m) - assert val == ['tinyxml[stl]','tinyxml[stl]'], "Result was actually: %s" % val - m.assert_any_call(['portageq', 'match', '/', 'tinyxml[stl]']) + assert val == ['tinyxml[stl]', 'tinyxml[stl]'], 'Result was actually: %s' % val + m.assert_any_call(['portageq', 'match', '/', 'tinyxml[stl]']) # and a second of the same, but any_call won't show that. # Test packages with multiple slot - m = Mock(side_effect = [['dev-lang/python-2.7.2-r3','dev-lang/python-3.2.2']]) + m = Mock(side_effect=[['dev-lang/python-2.7.2-r3', 'dev-lang/python-3.2.2']]) val = portage_detect(['python'], exec_fn=m) - assert val == ['python'], "Result was actually: %s" % val - m.assert_any_call(['portageq', 'match', '/', 'python']) + assert val == ['python'], 'Result was actually: %s' % val + m.assert_any_call(['portageq', 'match', '/', 'python']) + def test_PortageInstaller(): if not is_gentoo(): - print("Skipping not Gentoo") - return + print('Skipping not Gentoo') + return from rosdep2.platforms.gentoo import PortageInstaller @@ -175,7 +182,7 @@ assert [] == installer.get_install_command(['fake']) mock_method.return_value = ['a', 'b'] - + expected = [['sudo', '-H', 'emerge', 'a'], ['sudo', '-H', 'emerge', 'b']] val = installer.get_install_command(['whatever'], interactive=False) @@ -185,10 +192,9 @@ ['sudo', '-H', 'emerge', '-a', 'b']] val = installer.get_install_command(['whatever'], interactive=True) assert val == expected, val - + try: test() except AssertionError: traceback.print_exc() raise - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_installers.py ros-rosdep-0.12.2/test/test_rosdep_installers.py --- ros-rosdep-0.11.8/test/test_rosdep_installers.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_installers.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -27,6 +27,7 @@ from __future__ import print_function +from contextlib import contextmanager import os import sys try: @@ -36,21 +37,26 @@ from rospkg import RosPack, RosStack + def get_test_dir(): return os.path.abspath(os.path.dirname(__file__)) + def get_cache_dir(): p = os.path.join(get_test_dir(), 'sources_cache') assert os.path.isdir(p) return p + def create_test_SourcesListLoader(): from rosdep2.sources_list import SourcesListLoader return SourcesListLoader.create_default(sources_cache_dir=get_cache_dir(), verbose=True) + def get_test_tree_dir(): return os.path.abspath(os.path.join(os.path.dirname(__file__), 'tree')) + def get_test_rospkgs(): test_dir = get_test_tree_dir() ros_root = os.path.join(test_dir, 'ros') @@ -60,6 +66,7 @@ rosstack = RosStack(ros_paths=ros_paths) return rospack, rosstack + def test_InstallerContext_ctor(): from rosdep2.installers import InstallerContext from rospkg.os_detect import OsDetect @@ -78,7 +85,8 @@ assert context.get_os_detect() == detect assert len(context.get_installer_keys()) == 0 assert len(context.get_os_keys()) == 0 - + + def test_InstallerContext_get_os_version_type(): from rospkg.os_detect import OS_UBUNTU, OsDetect from rosdep2.installers import InstallerContext @@ -86,14 +94,15 @@ try: context.set_os_version_type(OS_UBUNTU, 'bad') - assert False, "should check type" + assert False, 'should check type' except ValueError: pass assert OsDetect.get_version == context.get_os_version_type(OS_UBUNTU) context.set_os_version_type(OS_UBUNTU, OsDetect.get_codename) assert OsDetect.get_codename == context.get_os_version_type(OS_UBUNTU) - + + def test_InstallerContext_os_version_and_name(): from rospkg.os_detect import OsDetect from rosdep2.installers import InstallerContext @@ -102,13 +111,12 @@ os_name, os_version = context.get_os_name_and_version() assert os_name is not None assert os_version is not None - - val = ("fakeos", "blah") + + val = ('fakeos', 'blah') context.set_os_override(*val) assert val == context.get_os_name_and_version() from mock import Mock - from rospkg.os_detect import OsDetect os_detect_mock = Mock(spec=OsDetect) os_detect_mock.get_name.return_value = 'fakeos' os_detect_mock.get_version.return_value = 'fakeos-version' @@ -123,7 +131,8 @@ os_name, os_version = context.get_os_name_and_version() assert os_name == 'fakeos', os_name assert os_version == 'fakeos-version', os_version - + + def test_InstallerContext_installers(): from rosdep2.installers import InstallerContext, Installer from rospkg.os_detect import OsDetect @@ -134,29 +143,36 @@ key = 'fake-apt' try: installer = context.get_installer(key) - assert False, "should have raised: %s"%(installer) - except KeyError: pass + assert False, 'should have raised: %s' % (installer) + except KeyError: + pass + + class Foo: + pass - class Foo: pass class FakeInstaller(Installer): pass + class FakeInstaller2(Installer): pass # test TypeError on set_installer try: context.set_installer(key, 1) - assert False, "should have raised" - except TypeError: pass + assert False, 'should have raised' + except TypeError: + pass try: context.set_installer(key, Foo()) - assert False, "should have raised" - except TypeError: pass + assert False, 'should have raised' + except TypeError: + pass try: # must be instantiated context.set_installer(key, FakeInstaller) - assert False, "should have raised" - except TypeError: pass + assert False, 'should have raised' + except TypeError: + pass installer = FakeInstaller() installer2 = FakeInstaller2() @@ -173,7 +189,7 @@ context.set_installer(key, installer2) assert context.get_installer(key) == installer2 assert list(context.get_installer_keys()) == [key] - + # repeat with new key key2 = 'fake-port' context.set_installer(key2, installer2) @@ -193,6 +209,7 @@ pass assert set(context.get_installer_keys()) == set([key, key2]) + def test_InstallerContext_os_installers(): from rosdep2.installers import InstallerContext, Installer from rospkg.os_detect import OsDetect @@ -203,35 +220,41 @@ os_key = 'ubuntu' try: context.get_os_installer_keys(os_key) - assert False, "should have raised" + assert False, 'should have raised' except KeyError: pass try: context.get_default_os_installer_key(os_key) - assert False, "should have raised" + assert False, 'should have raised' except KeyError: pass try: context.add_os_installer_key(os_key, 'fake-key') - assert False, "should have raised" - except KeyError: pass + assert False, 'should have raised' + except KeyError: + pass try: context.set_default_os_installer_key(os_key, 'non-method') - assert False, "should have raised" - except KeyError: pass + assert False, 'should have raised' + except KeyError: + pass try: context.set_default_os_installer_key(os_key, lambda self: 'fake-key') - assert False, "should have raised" - except KeyError: pass + assert False, 'should have raised' + except KeyError: + pass try: context.get_default_os_installer_key('bad-os') - assert False, "should have raised" - except KeyError: pass - + assert False, 'should have raised' + except KeyError: + pass + installer_key1 = 'fake1' installer_key2 = 'fake2' + class FakeInstaller(Installer): pass + class FakeInstaller2(Installer): pass @@ -246,7 +269,7 @@ # retest set_default_os_installer_key, now with installer_key not configured on os try: context.set_default_os_installer_key(os_key, lambda self: installer_key2) - assert False, "should have raised" + assert False, 'should have raised' except KeyError as e: assert 'add_os_installer' in str(e), e @@ -255,7 +278,7 @@ assert set(context.get_os_installer_keys(os_key)) == set([installer_key1, installer_key2]) # test default - assert None == context.get_default_os_installer_key(os_key) + assert context.get_default_os_installer_key(os_key) is None context.set_default_os_installer_key(os_key, lambda self: installer_key1) assert installer_key1 == context.get_default_os_installer_key(os_key) context.set_default_os_installer_key(os_key, lambda self: installer_key2) @@ -264,8 +287,9 @@ # retest set_default_os_installer_key, now with invalid os try: context.set_default_os_installer_key('bad-os', lambda self: installer_key1) - assert False, "should have raised" - except KeyError: pass + assert False, 'should have raised' + except KeyError: + pass def test_Installer_tripwire(): @@ -273,26 +297,35 @@ try: Installer().is_installed('foo') assert False - except NotImplementedError: pass + except NotImplementedError: + pass try: Installer().get_install_command('foo') assert False - except NotImplementedError: pass + except NotImplementedError: + pass try: Installer().resolve({}) assert False - except NotImplementedError: pass + except NotImplementedError: + pass try: Installer().unique([]) assert False - except NotImplementedError: pass + except NotImplementedError: + pass assert Installer().get_depends({}) == [] + def detect_fn_empty(packages): return [] + + def detect_fn_all(packages): return packages # return any packages that are string length 1 + + def detect_fn_single(packages): return [p for p in packages if len(p) == 1] @@ -302,7 +335,9 @@ try: PackageManagerInstaller(detect_fn_all).get_install_command(['foo']) assert False - except NotImplementedError: pass + except NotImplementedError: + pass + def test_PackageManagerInstaller_resolve(): from rosdep2 import InvalidData @@ -312,21 +347,23 @@ assert ['baz'] == installer.resolve(dict(depends=['foo', 'bar'], packages=['baz'])) assert ['baz', 'bar'] == installer.resolve(dict(packages=['baz', 'bar'])) - #test string logic + # test string logic assert ['baz'] == installer.resolve(dict(depends=['foo', 'bar'], packages='baz')) assert ['baz', 'bar'] == installer.resolve(dict(packages='baz bar')) assert ['baz'] == installer.resolve('baz') assert ['baz', 'bar'] == installer.resolve('baz bar') - #test list logic + # test list logic assert ['baz'] == installer.resolve(['baz']) assert ['baz', 'bar'] == installer.resolve(['baz', 'bar']) # test invalid data try: installer.resolve(0) - assert False, "should have raised" - except InvalidData: pass + assert False, 'should have raised' + except InvalidData: + pass + def test_PackageManagerInstaller_depends(): from rosdep2.installers import PackageManagerInstaller @@ -336,6 +373,7 @@ installer = PackageManagerInstaller(detect_fn_all, supports_depends=False) assert [] == installer.get_depends(dict(depends=['foo', 'bar'], packages=['baz'])) + def test_PackageManagerInstaller_unique(): from rosdep2.installers import PackageManagerInstaller @@ -348,18 +386,20 @@ assert ['a'] == installer.unique(['a'], [], ['a']) assert set(['a', 'b', 'c']) == set(installer.unique(['a', 'b', 'c'], ['a', 'b', 'c'])) assert set(['a', 'b', 'c']) == set(installer.unique(['a'], ['b'], ['c'])) - assert set(['a', 'b', 'c']) == set(installer.unique(['a', 'b'], ['c'])) - assert set(['a', 'b', 'c']) == set(installer.unique(['a', 'b'], ['c', 'a'])) + assert set(['a', 'b', 'c']) == set(installer.unique(['a', 'b'], ['c'])) + assert set(['a', 'b', 'c']) == set(installer.unique(['a', 'b'], ['c', 'a'])) + def test_PackageManagerInstaller_is_installed(): from rosdep2.installers import PackageManagerInstaller installer = PackageManagerInstaller(detect_fn_all) for r in ['a', 'b', 'c']: - assert True == installer.is_installed(r), installer.is_installed(r) + assert installer.is_installed(r), installer.is_installed(r) installer = PackageManagerInstaller(detect_fn_empty) for r in ['a', 'b', 'c']: - assert False == installer.is_installed(r), installer.is_installed(r) + assert not installer.is_installed(r), installer.is_installed(r) + def test_PackageManagerInstaller_get_packages_to_install(): from rosdep2.installers import PackageManagerInstaller @@ -368,13 +408,14 @@ assert [] == installer.get_packages_to_install([]) assert [] == installer.get_packages_to_install(['a', 'b', 'c']) assert set(['a', 'b', 'c']) == set(installer.get_packages_to_install(['a', 'b', 'c'], reinstall=True)) - + installer = PackageManagerInstaller(detect_fn_empty) assert set(['a', 'b', 'c']) == set(installer.get_packages_to_install(['a', 'b', 'c'])) assert set(['a', 'b', 'c']) == set(installer.get_packages_to_install(['a', 'b', 'c'], reinstall=True)) installer = PackageManagerInstaller(detect_fn_single) assert set(['baba', 'cada']) == set(installer.get_packages_to_install(['a', 'baba', 'b', 'cada', 'c'])) - + + def test_RosdepInstaller_ctor(): # tripwire/coverage from rosdep2 import create_default_installer_context @@ -384,17 +425,17 @@ context = create_default_installer_context() installer = RosdepInstaller(context, lookup) assert lookup == installer.lookup - assert context == installer.installer_context + assert context == installer.installer_context + def test_RosdepInstaller_get_uninstalled(): from rosdep2 import create_default_installer_context from rosdep2.lookup import RosdepLookup from rosdep2.installers import RosdepInstaller from rosdep2.platforms.debian import APT_INSTALLER - - from rosdep2.lookup import RosdepLookup + rospack, rosstack = get_test_rospkgs() - + # create our test fixture. use most of the default toolchain, but # replace the apt installer with one that we can have more fun # with. we will do all tests with ubuntu lucid keys -- other @@ -404,7 +445,7 @@ context = create_default_installer_context() context.set_os_override('ubuntu', 'lucid') installer = RosdepInstaller(context, lookup) - + # in this first test, detect_fn detects everything as installed fake_apt = get_fake_apt(lambda x: x) context.set_installer(APT_INSTALLER, fake_apt) @@ -450,11 +491,13 @@ assert apt_uninstalled == expected, uninstalled assert not errors + def get_fake_apt(detect_fn): # mainly did this to keep coverage results from rosdep2.installers import PackageManagerInstaller + class FakeAptInstaller(PackageManagerInstaller): - """ + """ An implementation of the Installer for use on debian style systems. """ @@ -465,15 +508,15 @@ return [[resolved, interactive, reinstall]] return FakeAptInstaller() + def test_RosdepInstaller_get_uninstalled_unconfigured(): from rosdep2 import create_default_installer_context, RosdepInternalError from rosdep2.lookup import RosdepLookup, ResolutionError from rosdep2.installers import RosdepInstaller, PackageManagerInstaller from rosdep2.platforms.debian import APT_INSTALLER - - from rosdep2.lookup import RosdepLookup + rospack, rosstack = get_test_rospkgs() - + sources_loader = create_test_SourcesListLoader() # create our test fixture. we want to setup a fixture that cannot resolve the rosdep data in order to test error conditions lookup = RosdepLookup.create_from_rospkg(rospack=rospack, rosstack=rosstack, sources_loader=sources_loader) @@ -501,31 +544,32 @@ # fake/bad installer to test that we re-cast general installer issues class BadInstaller(PackageManagerInstaller): + def __init__(self): super(BadInstaller, self).__init__(lambda x: x) + def get_packages_to_install(*args): - raise Exception("deadbeef") + raise Exception('deadbeef') context.set_installer(APT_INSTALLER, BadInstaller()) try: installer.get_uninstalled(['roscpp_fake']) - assert False, "should have raised" + assert False, 'should have raised' except RosdepInternalError as e: assert 'apt' in str(e) - + # annoying mock to test generally impossible error condition from mock import Mock lookup = Mock(spec=RosdepLookup) lookup.resolve_all.return_value = ([('bad-key', ['stuff'])], []) - + installer = RosdepInstaller(context, lookup) try: installer.get_uninstalled(['roscpp_fake']) - assert False, "should have raised" + assert False, 'should have raised' except RosdepInternalError: pass -from contextlib import contextmanager @contextmanager def fakeout(): realstdout = sys.stdout @@ -538,15 +582,15 @@ sys.stdout = realstdout sys.stderr = realstderr + def test_RosdepInstaller_install_resolved(): from rosdep2 import create_default_installer_context from rosdep2.lookup import RosdepLookup from rosdep2.installers import RosdepInstaller from rosdep2.platforms.debian import APT_INSTALLER - - from rosdep2.lookup import RosdepLookup + rospack, rosstack = get_test_rospkgs() - + # create our test fixture. use most of the default toolchain, but # replace the apt installer with one that we can have more fun # with. we will do all tests with ubuntu lucid keys -- other @@ -556,13 +600,13 @@ context = create_default_installer_context() context.set_os_override('ubuntu', 'lucid') installer = RosdepInstaller(context, lookup) - + with fakeout() as (stdout, stderr): installer.install_resolved(APT_INSTALLER, [], simulate=True, verbose=False) with fakeout() as (stdout, stderr): installer.install_resolved(APT_INSTALLER, [], simulate=True, verbose=True) assert stdout.getvalue().strip() == '#No packages to install' - with fakeout() as (stdout, stderr): + with fakeout() as (stdout, stderr): try: installer.install_resolved(APT_INSTALLER, ['rosdep-fake1', 'rosdep-fake2'], simulate=True, verbose=True) except OSError as e: diff -Nru ros-rosdep-0.11.8/test/test_rosdep_issue30.py ros-rosdep-0.12.2/test/test_rosdep_issue30.py --- ros-rosdep-0.11.8/test/test_rosdep_issue30.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_issue30.py 2018-03-21 23:40:00.000000000 +0000 @@ -5,13 +5,15 @@ from rosdep2 import main as rdmain + class Issue30TestCase(unittest.TestCase): + def testIssue30(self): return True d = make_temp_dir() try: cd(d) - script = '''#!/bin/bash + script = """#!/bin/bash mkdir ws mkdir ws/src mkdir ws/build @@ -22,33 +24,37 @@ cmake ../src > /dev/null cd ../src git clone -b groovy-devel git://github.com/ros-drivers/joystick_drivers.git > /dev/null -''' +""" run_script('commands.bash', script) source('ws/build/devel/setup.sh') lookup = make_lookup() keys = rdmain.get_keys(lookup, ['spacenav_node'], recursive=True) - expected = ''' + expected = """ geometry_msgs libspnav-dev libx11-dev roscpp sensor_msgs spacenavd - '''.split() + """.split() self.assertEqual(expected, sorted(keys)) finally: sp.call(['rm', '-rf', d]) + def make_temp_dir(): return tempfile.mkdtemp() + def cd(d): os.chdir(d) + def write_file(filename, contents): with open(filename, 'w') as f: f.write(contents) + def run_script(filename, contents): """ Creates a script with the given filename and contents, runs it @@ -61,15 +67,18 @@ return p.stdout.read() # http://pythonwise.blogspot.com/2010/04/sourcing-shell-script.html + + def source(script): """ Sources a shell script at a given path, updating the environment. """ - pipe = sp.Popen(". %s; env" % script, stdout=sp.PIPE, shell=True) + pipe = sp.Popen('. %s; env' % script, stdout=sp.PIPE, shell=True) data = pipe.communicate()[0] - env = dict((line.split("=", 1) for line in data.splitlines())) + env = dict((line.split('=', 1) for line in data.splitlines())) os.environ.update(env) + def make_lookup(): """ Creates a RosdepLookup object. @@ -81,6 +90,6 @@ verbose=True) return rdl.RosdepLookup.create_from_rospkg(sources_loader=sources_loader) + if __name__ == '__main__': unittest.main() - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_loader.py ros-rosdep-0.12.2/test/test_rosdep_loader.py --- ros-rosdep-0.11.8/test/test_rosdep_loader.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_loader.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -27,27 +27,33 @@ from mock import Mock + def test_RosdepLoader(): - #tripwire tests + # tripwire tests from rosdep2.loader import RosdepLoader loader = RosdepLoader() try: loader.load_view('foo', Mock()) - assert False, "should have raised NotImplemented" - except NotImplementedError: pass + assert False, 'should have raised NotImplemented' + except NotImplementedError: + pass try: loader.get_loadable_resources() - assert False, "should have raised NotImplementedError" - except NotImplementedError: pass + assert False, 'should have raised NotImplementedError' + except NotImplementedError: + pass try: loader.get_loadable_views() - assert False, "should have raised NotImplementedError" - except NotImplementedError: pass + assert False, 'should have raised NotImplementedError' + except NotImplementedError: + pass try: loader.get_view_key('foo') - assert False, "should have raised NotImplementedError" - except NotImplementedError: pass + assert False, 'should have raised NotImplementedError' + except NotImplementedError: + pass try: loader.get_rosdeps('foo', implicit=False) - assert False, "should have raised NotImplementedError" - except NotImplementedError: pass + assert False, 'should have raised NotImplementedError' + except NotImplementedError: + pass diff -Nru ros-rosdep-0.11.8/test/test_rosdep_lookup.py ros-rosdep-0.12.2/test/test_rosdep_lookup.py --- ros-rosdep-0.11.8/test/test_rosdep_lookup.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_lookup.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -35,33 +35,40 @@ BASE_URL = 'https://github.com/ros/rosdistro/raw/master/rosdep/base.yaml' PYTHON_URL = 'https://github.com/ros/rosdistro/raw/master/rosdep/python.yaml' + def get_test_dir(): return os.path.abspath(os.path.dirname(__file__)) + def get_test_tree_dir(): return os.path.abspath(os.path.join(os.path.dirname(__file__), 'tree')) + def get_cache_dir(): p = os.path.join(get_test_dir(), 'sources_cache') assert os.path.isdir(p) return p + def create_test_SourcesListLoader(): from rosdep2.sources_list import SourcesListLoader return SourcesListLoader.create_default(sources_cache_dir=get_cache_dir(), verbose=True) - + + def get_cache_raw(): cache_rosdep_path = os.path.join(get_cache_dir(), '0a12d6e7b0d47be9b76e7726720e4cb79528cbaa') with open(cache_rosdep_path) as f: cache_raw = yaml.load(f.read()) return cache_raw + def get_cache_raw_python(): cache_rosdep_path = os.path.join(get_cache_dir(), 'f6f4ef95664e373cd4754501337fa217f5b55d91') with open(cache_rosdep_path) as f: cache_raw = yaml.load(f.read()) return cache_raw + def get_test_rospkgs(): test_dir = get_test_tree_dir() ros_root = os.path.join(test_dir, 'ros') @@ -72,6 +79,7 @@ rosstack = RosStack(ros_paths=ros_paths) return rospack, rosstack + FAKE_TINYXML_RULE = """testtinyxml: ubuntu: lucid: @@ -86,6 +94,7 @@ yum: packages: tinyxml-devel""" + def test_RosdepDefinition(): from rosdep2.lookup import RosdepDefinition, ResolutionError, InvalidData d = dict(a=1, b=2, c=3) @@ -101,16 +110,19 @@ # - test w/invalid data try: RosdepDefinition('dbad', 'foo', 'bad.txt').get_rule_for_platform('ubuntu', 'hardy', ['apt'], 'apt') - assert False, "should have failed" - except InvalidData: pass + assert False, 'should have failed' + except InvalidData: + pass try: RosdepDefinition('dbad', {'ubuntu': 1}, 'bad2.txt').get_rule_for_platform('ubuntu', 'hardy', ['apt'], 'apt') - assert False, "should have failed" - except InvalidData: pass + assert False, 'should have failed' + except InvalidData: + pass try: RosdepDefinition('dbad', {'ubuntu': {'hardy': 1}}, 'bad2.txt').get_rule_for_platform('ubuntu', 'hardy', ['apt'], 'apt') - assert False, "should have failed" - except InvalidData: pass + assert False, 'should have failed' + except InvalidData: + pass # - test w/valid data d2 = yaml.load(FAKE_TINYXML_RULE)['testtinyxml'] @@ -120,7 +132,7 @@ val = definition.get_rule_for_platform('fedora', 'fake-version', ['yum', 'source', 'pip'], 'yum') assert val == ('yum', dict(packages='tinyxml-devel')), val - + val = definition.get_rule_for_platform('debian', 'sid', ['apt', 'source', 'pip'], 'apt') assert val == ('apt', 'libtinyxml-dev') @@ -133,7 +145,7 @@ # test bad resolutions try: val = definition.get_rule_for_platform('ubuntu', 'hardy', ['apt', 'source', 'pip'], 'apt') - assert False, "should have raised: %s"%(str(val)) + assert False, 'should have raised: %s' % (str(val)) except ResolutionError as e: assert e.rosdep_key == 'd2' assert e.rosdep_data == d2 @@ -144,7 +156,7 @@ try: val = definition.get_rule_for_platform('fakeos', 'fakeversion', ['apt', 'source', 'pip'], 'apt') - assert False, "should have raised: %s"%(str(val)) + assert False, 'should have raised: %s' % (str(val)) except ResolutionError as e: assert e.rosdep_key == 'd2' assert e.rosdep_data == d2 @@ -153,6 +165,23 @@ # tripwire str(e) + definition = RosdepDefinition('testtinyxml', {'ubuntu': {'lucid': None, 'precise': ['libtinyxml-dev'], '*': ['libtinyxml2-dev']}}, 'wildcard.txt') + try: + val = definition.get_rule_for_platform('ubuntu', 'lucid', ['apt', 'source', 'pip'], 'apt') + assert False, 'should have raised: %s' % (str(val)) + except ResolutionError as e: + assert e.rosdep_key == 'testtinyxml' + assert e.os_name == 'ubuntu' + assert e.os_version == 'lucid' + # tripwire + str(e) + + val = definition.get_rule_for_platform('ubuntu', 'precise', ['apt', 'source', 'pip'], 'apt') + assert val == ('apt', ['libtinyxml-dev']), val + + val = definition.get_rule_for_platform('ubuntu', 'trusty', ['apt', 'source', 'pip'], 'apt') + assert val == ('apt', ['libtinyxml2-dev']), val + # test reverse merging OS things (first is default) definition = RosdepDefinition('test', {'debian': 'libtest-dev'}, 'fake-1.txt') # rule should work as expected before reverse-merge @@ -160,7 +189,7 @@ assert val == ('apt', 'libtest-dev'), val try: val = definition.get_rule_for_platform('ubuntu', 'precise', ['apt', 'source', 'pip'], 'apt') - assert False, "should have failed" + assert False, 'should have failed' except ResolutionError as e: assert e.rosdep_key == 'test' assert e.os_name == 'ubuntu' @@ -173,13 +202,14 @@ val = definition.get_rule_for_platform('debian', 'sid', ['apt', 'source', 'pip'], 'apt') assert val == ('apt', 'libtest-dev'), val + def test_RosdepView_merge(): from rosdep2.model import RosdepDatabaseEntry from rosdep2.lookup import RosdepView - + # rosdep data must be dictionary of dictionaries data = dict(a=dict(x=1), b=dict(y=2), c=dict(z=3)) - + # create empty view and test view = RosdepView('common') assert len(view.keys()) == 0 @@ -189,17 +219,17 @@ # make sure lookups fail if not found try: view.lookup('notfound') - assert False, "should have raised KeyError" + assert False, 'should have raised KeyError' except KeyError as e: assert 'notfound' in str(e) - + # merge into empty view d = RosdepDatabaseEntry(data, [], 'origin') view.merge(d) assert set(view.keys()) == set(data.keys()) for k, v in data.items(): - assert view.lookup(k).data == v, "%s vs. %s"%(view.lookup(k), v) - + assert view.lookup(k).data == v, '%s vs. %s' % (view.lookup(k), v) + # merge exact same data d2 = RosdepDatabaseEntry(data, [], 'origin2') view.merge(d2) @@ -225,7 +255,7 @@ assert view.lookup('c').data == dict(z=3) assert view.lookup('d').data == dict(o=4) assert view.lookup('e').data == dict(p=5) - + # - now w/ override view.merge(d4, override=True) assert view.lookup('a').data == dict(x=2) @@ -237,11 +267,12 @@ # - tripwire str(view) + def test_RosdepLookup_get_rosdeps(): from rosdep2.loader import RosdepLoader from rosdep2.lookup import RosdepLookup rospack, rosstack = get_test_rospkgs() - + sources_loader = create_test_SourcesListLoader() lookup = RosdepLookup.create_from_rospkg(rospack=rospack, rosstack=rosstack, sources_loader=sources_loader) @@ -252,63 +283,66 @@ try: assert lookup.get_rosdeps('not a resource') == [] - assert False, "should have raised" + assert False, 'should have raised' except ResourceNotFound: pass - + print(lookup.get_rosdeps('stack1_p1')) assert set(lookup.get_rosdeps('stack1_p1')) == set(['stack1_dep1', 'stack1_p1_dep1', 'stack1_p1_dep2']) assert set(lookup.get_rosdeps('stack1_p1', implicit=False)) == set(['stack1_dep1', 'stack1_p1_dep1', 'stack1_p1_dep2']) - + print(lookup.get_rosdeps('stack1_p2')) assert set(lookup.get_rosdeps('stack1_p2', implicit=False)) == set(['stack1_dep1', 'stack1_dep2', 'stack1_p2_dep1']), set(lookup.get_rosdeps('stack1_p2')) - assert set(lookup.get_rosdeps('stack1_p2', implicit=True)) == set(['stack1_dep1', 'stack1_dep2', 'stack1_p1_dep1', 'stack1_p1_dep2', 'stack1_p2_dep1']), set(lookup.get_rosdeps('stack1_p2')) - + assert set(lookup.get_rosdeps('stack1_p2', implicit=True)) == set(['stack1_dep1', 'stack1_dep2', 'stack1_p1_dep1', 'stack1_p1_dep2', 'stack1_p2_dep1']), set(lookup.get_rosdeps('stack1_p2')) + # catkin print(lookup.get_rosdeps('simple_catkin_package')) - assert set(lookup.get_rosdeps('simple_catkin_package')) == set(['catkin', 'testboost' ]) + assert set(lookup.get_rosdeps('simple_catkin_package')) == set(['catkin', 'testboost']) assert set(lookup.get_rosdeps('simple_catkin_package', implicit=False)) == set(['catkin', 'testboost']) print(lookup.get_rosdeps('another_catkin_package')) - assert set(lookup.get_rosdeps('another_catkin_package')) == set(['catkin', 'simple_catkin_package' ]) # implicit deps won't get included + assert set(lookup.get_rosdeps('another_catkin_package')) == set(['catkin', 'simple_catkin_package']) # implicit deps won't get included assert set(lookup.get_rosdeps('another_catkin_package', implicit=False)) == set(['catkin', 'simple_catkin_package']) print(lookup.get_rosdeps('metapackage_with_deps')) - assert set(lookup.get_rosdeps('metapackage_with_deps')) == set(['catkin', 'simple_catkin_package', 'another_catkin_package']) # implicit deps won't get included + assert set(lookup.get_rosdeps('metapackage_with_deps')) == set(['catkin', 'simple_catkin_package', 'another_catkin_package']) # implicit deps won't get included assert set(lookup.get_rosdeps('metapackage_with_deps', implicit=False)) == set(['catkin', 'simple_catkin_package', 'another_catkin_package']) + def test_RosdepLookup_get_resources_that_need(): from rosdep2.lookup import RosdepLookup rospack, rosstack = get_test_rospkgs() - + sources_loader = create_test_SourcesListLoader() lookup = RosdepLookup.create_from_rospkg(rospack=rospack, rosstack=rosstack, sources_loader=sources_loader) - assert lookup.get_resources_that_need('fake') == [] - assert set(lookup.get_resources_that_need('stack1_dep1')) == set(['stack1_p1', 'stack1_p2']) - assert lookup.get_resources_that_need('stack1_dep2') == ['stack1_p2'] - assert lookup.get_resources_that_need('stack1_p1_dep1') == ['stack1_p1'] - + assert lookup.get_resources_that_need('fake') == [] + assert set(lookup.get_resources_that_need('stack1_dep1')) == set(['stack1_p1', 'stack1_p2']) + assert lookup.get_resources_that_need('stack1_dep2') == ['stack1_p2'] + assert lookup.get_resources_that_need('stack1_p1_dep1') == ['stack1_p1'] + + def test_RosdepLookup_create_from_rospkg(): from rosdep2.lookup import RosdepLookup rospack, rosstack = get_test_rospkgs() # these are just tripwire, can't actually test as it depends on external env lookup = RosdepLookup.create_from_rospkg() - + lookup = RosdepLookup.create_from_rospkg(rospack=rospack) assert rospack == lookup.loader._rospack - + lookup = RosdepLookup.create_from_rospkg(rospack=rospack, rosstack=rosstack) assert rospack == lookup.loader._rospack assert rosstack == lookup.loader._rosstack - + + def test_RosdepLookup_get_rosdep_view_for_resource(): from rosdep2.lookup import RosdepLookup from rosdep2.rospkg_loader import DEFAULT_VIEW_KEY, RosPkgLoader rospack, rosstack = get_test_rospkgs() - + sources_loader = create_test_SourcesListLoader() lookup = RosdepLookup.create_from_rospkg(rospack=rospack, rosstack=rosstack, sources_loader=sources_loader) @@ -327,13 +361,17 @@ assert PYTHON_URL == python.origin assert py_cache_raw['testpython'] == python.data - # package not in stack, should return + # package not in stack, should return assert lookup.get_rosdep_view_for_resource('just_a_package').name is DEFAULT_VIEW_KEY - + + # meta-packages should return default view as well + assert lookup.get_rosdep_view_for_resource('metapackage_with_deps').name is DEFAULT_VIEW_KEY + + def test_RosdepLookup_get_rosdep_view(): from rosdep2.lookup import RosdepLookup rospack, rosstack = get_test_rospkgs() - + sources_loader = create_test_SourcesListLoader() lookup = RosdepLookup.create_from_rospkg(rospack=rospack, rosstack=rosstack, sources_loader=sources_loader) @@ -355,19 +393,20 @@ libtool = ros_view.lookup('testlibtool') assert BASE_URL == libtool.origin assert cache_raw['testlibtool'] == libtool.data - + # depends on ros stack1_view = lookup.get_rosdep_view('stack1') stack1_rosdep_path = os.path.join(rosstack.get_path('stack1'), 'rosdep.yaml') - - # - make sure ros data is available + + # - make sure ros data is available libtool = stack1_view.lookup('testlibtool') assert BASE_URL == libtool.origin assert cache_raw['testlibtool'] == libtool.data python = stack1_view.lookup('testpython') assert PYTHON_URL == python.origin assert py_cache_raw['testpython'] == python.data - + + def test_RosdepLookup_get_errors(): from rosdep2.lookup import RosdepLookup rospack, rosstack = get_test_rospkgs() @@ -381,10 +420,11 @@ # force errors lookup._load_all_views(lookup.loader) - - #TODO: force errors. Previous tests relied on bad stack views. - #Now we need a bad sources cache. - + + # TODO: force errors. Previous tests relied on bad stack views. + # Now we need a bad sources cache. + + def test_RosdepLookup_get_views_that_define(): from rosdep2.lookup import RosdepLookup rospack, rosstack = get_test_rospkgs() @@ -402,7 +442,8 @@ assert len(val) == 1 entry = val[0] assert entry == (PYTHON_URL, PYTHON_URL), entry - + + def test_RosdepLookup_resolve_all_errors(): from rosdep2.installers import InstallerContext from rosdep2.lookup import RosdepLookup, ResolutionError @@ -420,11 +461,12 @@ resolutions, errors = lookup.resolve_all(['not_a_resource'], installer_context) assert 'not_a_resource' in errors, errors + def test_RosdepLookup_resolve_errors(): from rosdep2.installers import InstallerContext from rosdep2.lookup import RosdepLookup, ResolutionError rospack, rosstack = get_test_rospkgs() - + sources_loader = create_test_SourcesListLoader() lookup = RosdepLookup.create_from_rospkg(rospack=rospack, rosstack=rosstack, sources_loader=sources_loader) @@ -434,21 +476,22 @@ try: lookup.resolve('testtinyxml', 'rospack_fake', installer_context) - assert False, "should have raised" + assert False, 'should have raised' except ResolutionError as e: - assert "Unsupported OS" in str(e), str(e) + assert 'Unsupported OS' in str(e), str(e) try: lookup.resolve('fakedep', 'rospack_fake', installer_context) - assert False, "should have raised" + assert False, 'should have raised' except ResolutionError as e: - assert "Cannot locate rosdep definition" in str(e), str(e) + assert 'Cannot locate rosdep definition' in str(e), str(e) + def test_RosdepLookup_resolve(): from rosdep2 import create_default_installer_context from rosdep2.lookup import RosdepLookup rospack, rosstack = get_test_rospkgs() - + sources_loader = create_test_SourcesListLoader() lookup = RosdepLookup.create_from_rospkg(rospack=rospack, rosstack=rosstack, sources_loader=sources_loader) @@ -477,7 +520,7 @@ from rosdep2 import create_default_installer_context from rosdep2.lookup import RosdepLookup rospack, rosstack = get_test_rospkgs() - + sources_loader = create_test_SourcesListLoader() lookup = RosdepLookup.create_from_rospkg(rospack=rospack, rosstack=rosstack, sources_loader=sources_loader) @@ -496,4 +539,3 @@ if k == 'apt': apt_resolutions.extend(v) assert set(apt_resolutions) == set(['libtinyxml-dev', 'libboost1.40-all-dev', 'libtool', 'libltdl-dev']), set(apt_resolutions) - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_main.py ros-rosdep-0.12.2/test/test_rosdep_main.py --- ros-rosdep-0.11.8/test/test_rosdep_main.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_main.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2012, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -25,6 +25,7 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from contextlib import contextmanager import os import sys try: @@ -40,25 +41,33 @@ from mock import patch from mock import DEFAULT +from rosdep2 import main +from rosdep2.main import rosdep_main +from rosdep2.main import setup_proxy_opener + + GITHUB_BASE_URL = 'https://github.com/ros/rosdistro/raw/master/rosdep/base.yaml' GITHUB_PYTHON_URL = 'https://github.com/ros/rosdistro/raw/master/rosdep/python.yaml' + def get_test_dir(): return os.path.abspath(os.path.dirname(__file__)) + def get_test_tree_dir(): return os.path.abspath(os.path.join(get_test_dir(), 'tree')) + +def get_test_catkin_tree_dir(): + return os.path.abspath(os.path.join(get_test_tree_dir(), 'catkin')) + + def get_cache_dir(): p = os.path.join(get_test_dir(), 'sources_cache') assert os.path.isdir(p) return p -from rosdep2 import main -from rosdep2.main import rosdep_main -from rosdep2.main import setup_proxy_opener -from contextlib import contextmanager @contextmanager def fakeout(): realstdout = sys.stdout @@ -70,10 +79,13 @@ yield fakestdout, fakestderr sys.stdout = realstdout sys.stderr = realstderr - + # the goal of these tests is only to test that we are wired into the # APIs. More exhaustive tests are at the unit level. + + class TestRosdepMain(unittest.TestCase): + def setUp(self): if 'ROSDEP_DEBUG' in os.environ: del os.environ['ROSDEP_DEBUG'] @@ -96,79 +108,111 @@ ['check', 'rospack_fake', '--os', 'ubuntulucid'], ]: try: - rosdep_main(commands+cmd_extras) - assert False, "system exit should have occurred" + rosdep_main(commands + cmd_extras) + assert False, 'system exit should have occurred' except SystemExit: pass - + def test_check(self): sources_cache = get_cache_dir() cmd_extras = ['-c', sources_cache] with fakeout() as b: try: - rosdep_main(['check', 'python_dep']+cmd_extras) + rosdep_main(['check', 'python_dep'] + cmd_extras) except SystemExit: - assert False, "system exit occurred: %s\n%s"%(b[0].getvalue(), b[1].getvalue()) + assert False, 'system exit occurred: %s\n%s' % (b[0].getvalue(), b[1].getvalue()) stdout, stderr = b - assert stdout.getvalue().strip() == "All system dependencies have been satisified", stdout.getvalue() + assert stdout.getvalue().strip() == 'All system dependencies have been satisified', stdout.getvalue() assert not stderr.getvalue(), stderr.getvalue() try: osd = rospkg.os_detect.OsDetect() - override = "%s:%s"%(osd.get_name(), osd.get_codename()) + override = '%s:%s' % (osd.get_name(), osd.get_codename()) with fakeout() as b: - rosdep_main(['check', 'python_dep', '--os', override]+cmd_extras) + rosdep_main(['check', 'python_dep', '--os', override] + cmd_extras) stdout, stderr = b - assert stdout.getvalue().strip() == "All system dependencies have been satisified" + assert stdout.getvalue().strip() == 'All system dependencies have been satisified' assert not stderr.getvalue(), stderr.getvalue() except SystemExit: - assert False, "system exit occurred" + assert False, 'system exit occurred' # this used to abort, but now rosdep assumes validity for even empty stack args try: with fakeout() as b: - rosdep_main(['check', 'packageless']+cmd_extras) + rosdep_main(['check', 'packageless'] + cmd_extras) stdout, stderr = b - assert stdout.getvalue().strip() == "All system dependencies have been satisified" + assert stdout.getvalue().strip() == 'All system dependencies have been satisified' assert not stderr.getvalue(), stderr.getvalue() except SystemExit: - assert False, "system exit occurred" + assert False, 'system exit occurred' try: - rosdep_main(['check', 'nonexistent']+cmd_extras) - assert False, "system exit should have occurred" + rosdep_main(['check', 'nonexistent'] + cmd_extras) + assert False, 'system exit should have occurred' except SystemExit: pass - def test_install(self): + @patch('rosdep2.platforms.debian.read_stdout') + def test_install(self, mock_read_stdout): sources_cache = get_cache_dir() cmd_extras = ['-c', sources_cache] + catkin_tree = get_test_catkin_tree_dir() + + def read_stdout(cmd, capture_stderr=False): + if cmd[0] == 'apt-cache' and cmd[1] == 'showpkg': + result = '' + elif cmd[0] == 'dpkg-query': + if cmd[-1] == 'python-dev': + result = '\'python-dev install ok installed\n\'' + else: + result = '\n'.join(["dpkg-query: no packages found matching %s" % f for f in cmd[3:]]) + + if capture_stderr: + return result, '' + return result try: + mock_read_stdout.side_effect = read_stdout # python must have already been installed with fakeout() as b: - rosdep_main(['install', 'python_dep']+cmd_extras) + rosdep_main(['install', 'python_dep'] + cmd_extras) + stdout, stderr = b + assert 'All required rosdeps installed' in stdout.getvalue(), stdout.getvalue() + assert not stderr.getvalue(), stderr.getvalue() + with fakeout() as b: + rosdep_main(['install', 'python_dep', '-r'] + cmd_extras) stdout, stderr = b - assert "All required rosdeps installed" in stdout.getvalue(), stdout.getvalue() + assert 'All required rosdeps installed' in stdout.getvalue(), stdout.getvalue() assert not stderr.getvalue(), stderr.getvalue() with fakeout() as b: - rosdep_main(['install', 'python_dep', '-r']+cmd_extras) + rosdep_main([ + 'install', '-s', '-i', + '--os', 'ubuntu:lucid', + '--rosdistro', 'fuerte', + '--from-paths', catkin_tree + ] + cmd_extras) stdout, stderr = b - assert "All required rosdeps installed" in stdout.getvalue(), stdout.getvalue() + expected = [ + '#[apt] Installation commands:', + ' sudo -H apt-get install ros-fuerte-catkin', + ' sudo -H apt-get install libboost1.40-all-dev' + ] + lines = stdout.getvalue().splitlines() + assert set(lines) == set(expected), lines assert not stderr.getvalue(), stderr.getvalue() except SystemExit: - assert False, "system exit occurred: "+b[1].getvalue() + assert False, 'system exit occurred: ' + b[1].getvalue() try: - rosdep_main(['check', 'nonexistent']) - assert False, "system exit should have occurred" + rosdep_main(['install', 'nonexistent']) + assert False, 'system exit should have occurred' except SystemExit: pass def test_where_defined(self): try: sources_cache = get_cache_dir() - expected = GITHUB_PYTHON_URL + expected = GITHUB_PYTHON_URL for command in (['where_defined', 'testpython'], ['where_defined', 'testpython']): with fakeout() as b: # set os to ubuntu so this test works on different platforms @@ -177,26 +221,26 @@ output = stdout.getvalue().strip() assert output == expected, output except SystemExit: - assert False, "system exit occurred" - + assert False, 'system exit occurred' + def test_what_needs(self): try: sources_cache = get_cache_dir() cmd_extras = ['-c', sources_cache] expected = ['python_dep'] with fakeout() as b: - rosdep_main(['what-needs', 'testpython']+cmd_extras) + rosdep_main(['what-needs', 'testpython'] + cmd_extras) stdout, stderr = b output = stdout.getvalue().strip() assert output.split('\n') == expected expected = ['python_dep'] with fakeout() as b: - rosdep_main(['what_needs', 'testpython', '--os', 'ubuntu:lucid', '--verbose']+cmd_extras) + rosdep_main(['what_needs', 'testpython', '--os', 'ubuntu:lucid', '--verbose'] + cmd_extras) stdout, stderr = b output = stdout.getvalue().strip() assert output.split('\n') == expected except SystemExit: - assert False, "system exit occurred" + assert False, 'system exit occurred' def test_keys(self): sources_cache = get_cache_dir() @@ -204,19 +248,19 @@ try: with fakeout() as b: - rosdep_main(['keys', 'rospack_fake']+cmd_extras) + rosdep_main(['keys', 'rospack_fake'] + cmd_extras) stdout, stderr = b - assert stdout.getvalue().strip() == "testtinyxml", stdout.getvalue() + assert stdout.getvalue().strip() == 'testtinyxml', stdout.getvalue() assert not stderr.getvalue(), stderr.getvalue() with fakeout() as b: - rosdep_main(['keys', 'rospack_fake', '--os', 'ubuntu:lucid', '--verbose']+cmd_extras) + rosdep_main(['keys', 'rospack_fake', '--os', 'ubuntu:lucid', '--verbose'] + cmd_extras) stdout, stderr = b - assert stdout.getvalue().strip() == "testtinyxml", stdout.getvalue() + assert stdout.getvalue().strip() == 'testtinyxml', stdout.getvalue() except SystemExit: - assert False, "system exit occurred" + assert False, 'system exit occurred' try: - rosdep_main(['keys', 'nonexistent']+cmd_extras) - assert False, "system exit should have occurred" + rosdep_main(['keys', 'nonexistent'] + cmd_extras) + assert False, 'system exit should have occurred' except SystemExit: pass diff -Nru ros-rosdep-0.11.8/test/test_rosdep_model.py ros-rosdep-0.12.2/test/test_rosdep_model.py --- ros-rosdep-0.11.8/test/test_rosdep_model.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_model.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -25,6 +25,7 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. + def test_RosdepDatabaseEntry(): # not muich to test with container from rosdep2.model import RosdepDatabaseEntry @@ -33,6 +34,7 @@ assert d.view_dependencies == [] assert d.origin == 'foo' + def test_RosdepDatabase(): from rosdep2.model import RosdepDatabase @@ -41,7 +43,7 @@ data = {'a': 1} db.set_view_data('foo', data, [], 'origin1') - assert db.is_loaded('foo') + assert db.is_loaded('foo') entry = db.get_view_data('foo') assert entry.rosdep_data == data assert entry.origin == 'origin1' @@ -49,10 +51,10 @@ # make sure data is copy data['a'] = 2 assert entry.rosdep_data != data - + data = {'b': 2} db.set_view_data('bar', data, ['foo'], 'origin2') - assert db.is_loaded('bar') + assert db.is_loaded('bar') entry = db.get_view_data('bar') assert entry.rosdep_data == data assert entry.origin == 'origin2' @@ -60,21 +62,21 @@ # override entry for bar data = {'b': 3} - assert db.is_loaded('bar') + assert db.is_loaded('bar') db.set_view_data('bar', data, ['baz', 'blah'], 'origin3') - assert db.is_loaded('bar') + assert db.is_loaded('bar') entry = db.get_view_data('bar') assert entry.rosdep_data == data assert entry.origin == 'origin3' assert set(entry.view_dependencies) == set(['baz', 'blah']) - + def test_RosdepDatabase_get_view_dependencies(): from rosdep2.model import RosdepDatabase data = {'a': 1} db = RosdepDatabase() - + db.set_view_data('foo', data, [], 'origin') assert [] == db.get_view_dependencies('foo') @@ -82,7 +84,7 @@ assert ['foo'] == db.get_view_dependencies('bar') db.set_view_data('baz', data, ['bar'], 'origin') - assert ['foo', 'bar'] == db.get_view_dependencies('baz') + assert ['foo', 'bar'] == db.get_view_dependencies('baz') db.set_view_data('rad', data, [], 'origin') db.set_view_data('fad', data, ['baz', 'rad'], 'origin') diff -Nru ros-rosdep-0.11.8/test/test_rosdep_opensuse.py ros-rosdep-0.12.2/test/test_rosdep_opensuse.py --- ros-rosdep-0.11.8/test/test_rosdep_opensuse.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_opensuse.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,10 +31,12 @@ import traceback from mock import patch + def get_test_dir(): # not used yet return os.path.abspath(os.path.join(os.path.dirname(__file__), 'opensuse')) + def test_ZypperInstaller(): from rosdep2.platforms.opensuse import ZypperInstaller @@ -57,4 +59,3 @@ except AssertionError: traceback.print_exc() raise - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_osx.py ros-rosdep-0.12.2/test/test_rosdep_osx.py --- ros-rosdep-0.11.8/test/test_rosdep_osx.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_osx.py 2018-03-21 23:40:00.000000000 +0000 @@ -64,15 +64,15 @@ def brew_command(command): - if command[1] == "list": + if command[1] == 'list': with open(os.path.join(get_test_dir(), 'brew-list-output'), 'r') as f: return f.read() - elif command[1] == "info": + elif command[1] == 'info': pkg = command[2] with open(os.path.join(get_test_dir(), 'brew-info-output'), 'r') as f: output = f.readlines() for line in output: - res = line.split(":", 1) + res = line.split(':', 1) if res[0] == pkg: return res[1] return '' @@ -147,14 +147,14 @@ except SyntaxError: # Python 3.2, u'...' is not allowed, but string literals are unicode mock_get_packages_to_install.return_value = make_resolutions_options( - [('subversion', ['f´´ßß', 'öäö'], []), ('bazaar', [], ["tüü"])]) + [('subversion', ['f´´ßß', 'öäö'], []), ('bazaar', [], ['tüü'])]) mock_remove_duplicate_dependencies.return_value = mock_get_packages_to_install.return_value try: expected = eval("[['brew', 'install', 'subversion', u'f´´ßß', u'öäö'], ['brew', 'install', 'bazaar', u'tüü']]") except SyntaxError: # Python 3.2, u'...' is not allowed, but string literals are unicode expected = [['brew', 'install', 'subversion', 'f´´ßß', 'öäö'], - ['brew', 'install', 'bazaar', "tüü"]] + ['brew', 'install', 'bazaar', 'tüü']] val = installer.get_install_command(['whatever']) assert val == expected, val try: diff -Nru ros-rosdep-0.11.8/test/test_rosdep_pip.py ros-rosdep-0.12.2/test/test_rosdep_pip.py --- ros-rosdep-0.11.8/test/test_rosdep_pip.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_pip.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,12 +31,14 @@ import traceback from mock import Mock, patch + def get_test_dir(): return os.path.abspath(os.path.join(os.path.dirname(__file__), 'pip')) + def test_pip_detect(): from rosdep2.platforms.pip import pip_detect - + m = Mock() # test behavior with empty freeze @@ -62,7 +64,8 @@ from rosdep2.platforms.pip import PipInstaller installer = PipInstaller() assert ['foo'] == installer.get_depends(dict(depends=['foo'])) - + + def test_PipInstaller(): from rosdep2 import InstallFailed from rosdep2.platforms.pip import PipInstaller @@ -73,11 +76,12 @@ try: installer = PipInstaller() installer.get_install_command(['whatever']) - assert False, "should have raised" - except InstallFailed: pass - + assert False, 'should have raised' + except InstallFailed: + pass + test_no_pip() - + @patch('rosdep2.platforms.pip.is_pip_installed') @patch.object(PipInstaller, 'get_packages_to_install') def test(mock_method, mock_is_pip_installed): @@ -101,4 +105,3 @@ except AssertionError: traceback.print_exc() raise - diff -Nru ros-rosdep-0.11.8/test/test_rosdep.py ros-rosdep-0.12.2/test/test_rosdep.py --- ros-rosdep-0.11.8/test/test_rosdep.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -30,6 +30,7 @@ import os import sys + def test_create_default_installer_context(): import rosdep2 @@ -38,11 +39,9 @@ assert context is not None assert isinstance(context, rosdep2.InstallerContext) - #this is just tripwire as we actual value will change over time + # this is just tripwire as we actual value will change over time from rospkg.os_detect import OS_UBUNTU, OsDetect assert OS_UBUNTU in context.get_os_keys() assert context.get_installer('apt') is not None assert 'apt' in context.get_os_installer_keys(OS_UBUNTU) assert OsDetect.get_codename == context.get_os_version_type(OS_UBUNTU) - - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_redhat.py ros-rosdep-0.12.2/test/test_rosdep_redhat.py --- ros-rosdep-0.11.8/test/test_rosdep_redhat.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_redhat.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,10 +31,29 @@ import traceback from mock import patch, Mock + def get_test_dir(): # not used yet return os.path.abspath(os.path.join(os.path.dirname(__file__), 'redhat')) + +def test_rpm_expand(): + from rosdep2.platforms.redhat import rpm_expand + + m = Mock() + m.return_value = '' + + # Non-macro test, should return the string unmodified + val = rpm_expand('test-string', exec_fn=m) + assert val == 'test-string', val + + # Macro test, should return expanded rpm tag + with open(os.path.join(get_test_dir(), 'rpm-E-fedora'), 'r') as f: + m.return_value = f.read() + val = rpm_expand('%fedora', exec_fn=m) + assert val == '27', val + + def test_rpm_detect(): from rosdep2.platforms.redhat import rpm_detect @@ -44,9 +63,19 @@ val = rpm_detect([], exec_fn=m) assert val == [], val + # Negitive case test. rpms use devel, rather than dev + with open(os.path.join(get_test_dir(), 'rpm-q-tinyxml-dev'), 'r') as f: + m.return_value = f.read() val = rpm_detect(['tinyxml-dev'], exec_fn=m) assert val == [], val + # Positive case test. rpm should always be installed if you're attempting to detect rpms + with open(os.path.join(get_test_dir(), 'rpm-q-rpm'), 'r') as f: + m.return_value = f.read() + val = rpm_detect(['rpm'], exec_fn=m) + assert val == ['rpm'], val + + def test_DnfInstaller(): from rosdep2.platforms.redhat import DnfInstaller @@ -76,6 +105,7 @@ traceback.print_exc() raise + def test_YumInstaller(): from rosdep2.platforms.redhat import YumInstaller @@ -105,6 +135,7 @@ traceback.print_exc() raise + def test_Fedora_variable_installer_key(): from rosdep2 import InstallerContext from rosdep2.platforms import pip, redhat, source @@ -131,6 +162,7 @@ os_detect_mock.get_version.return_value = '22' assert DNF_INSTALLER == context.get_default_os_installer_key(OS_FEDORA) + def test_Fedora_variable_lookup_key(): from rosdep2 import InstallerContext from rosdep2.platforms import pip, redhat, source diff -Nru ros-rosdep-0.11.8/test/test_rosdep_rep3.py ros-rosdep-0.12.2/test/test_rosdep_rep3.py --- ros-rosdep-0.11.8/test/test_rosdep_rep3.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_rep3.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2012, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,9 +31,11 @@ except ImportError: from urllib2 import urlopen + def get_test_dir(): return os.path.abspath(os.path.join(os.path.dirname(__file__), 'sources.list.d')) + def test_url_constants(): from rosdep2.rep3 import REP3_TARGETS_URL for url_name, url in [('REP3_TARGETS_URL', REP3_TARGETS_URL), @@ -42,8 +44,9 @@ f = urlopen(url) f.read() f.close() - except: - assert False, "URL [%s][%s] failed to download"%(url_name, url) + except Exception: + assert False, 'URL [%s][%s] failed to download' % (url_name, url) + def test_download_targets_data(): from rosdep2.rep3 import download_targets_data, REP3_TARGETS_URL @@ -57,6 +60,6 @@ try: download_targets_data(targets_url='http://bad.ros.org/foo.yaml') - assert False, "should have raised" + assert False, 'should have raised' except DownloadFailure: pass diff -Nru ros-rosdep-0.11.8/test/test_rosdep_rospkg_loader.py ros-rosdep-0.12.2/test/test_rosdep_rospkg_loader.py --- ros-rosdep-0.11.8/test/test_rosdep_rospkg_loader.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_rospkg_loader.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,9 +33,11 @@ from mock import Mock from rospkg import RosPack, RosStack + def get_test_dir(): return os.path.abspath(os.path.join(os.path.dirname(__file__), 'tree')) - + + def get_rospkg(): # configure inside of the test tree test_dir = get_test_dir() @@ -46,16 +48,17 @@ rosstack = RosStack(ros_paths=ros_paths) return rospack, rosstack + def test_RosPkgLoader(): from rospkg import ResourceNotFound from rosdep2.model import RosdepDatabase from rosdep2.rospkg_loader import RosPkgLoader, DEFAULT_VIEW_KEY from rosdep2.loader import InvalidData - + # Due to rosdep 2/REP 125 changes, this test is a bit overbuilt. # All stacks return the same. - + # tripwire loader = RosPkgLoader() assert loader._rospack is not None @@ -66,7 +69,7 @@ ros_root = rosstack.get_path('ros') loader = RosPkgLoader(rospack, rosstack) assert loader._rospack == rospack - assert loader._rosstack == rosstack + assert loader._rosstack == rosstack # test with mock db rosdep_db = Mock(spec=RosdepDatabase) @@ -80,15 +83,15 @@ # test invalid stack try: loader.load_view('does not exist', rosdep_db) - assert False, "should have raised" + assert False, 'should have raised' except ResourceNotFound as e: pass # Test with default view key loader.load_view(DEFAULT_VIEW_KEY, rosdep_db) rosdep_db.set_view_data.assert_called_with(DEFAULT_VIEW_KEY, {}, [], '') - - # test with complicated ros stack. + + # test with complicated ros stack. loader.load_view('ros', rosdep_db) rosdep_db.is_loaded.assert_called_with('ros') rosdep_db.set_view_data.assert_called_with('ros', {}, [], '') @@ -105,22 +108,24 @@ assert loader.get_view_key('stackless') == DEFAULT_VIEW_KEY try: loader.get_view_key('fake') - assert False, "should error" - except ResourceNotFound: pass - + assert False, 'should error' + except ResourceNotFound: + pass + + def test_RosPkgLoader_with_underlay_key(): from rospkg import ResourceNotFound from rosdep2.model import RosdepDatabase from rosdep2.rospkg_loader import RosPkgLoader, DEFAULT_VIEW_KEY from rosdep2.loader import InvalidData - + # configure inside of the test tree rospack, rosstack = get_rospkg() ros_root = rosstack.get_path('ros') loader = RosPkgLoader(rospack, rosstack, underlay_key='underlay-key') assert loader._rospack == rospack - assert loader._rosstack == rosstack + assert loader._rosstack == rosstack # test with mock db rosdep_db = Mock(spec=RosdepDatabase) @@ -134,11 +139,11 @@ # test invalid stack try: loader.load_view('does not exist', rosdep_db) - assert False, "should have raised" + assert False, 'should have raised' except ResourceNotFound as e: pass - # test with complicated ros stack. + # test with complicated ros stack. loader.load_view('ros', rosdep_db) rosdep_db.is_loaded.assert_called_with('ros') rosdep_db.set_view_data.assert_called_with('ros', {}, ['underlay-key'], '') @@ -155,22 +160,22 @@ assert loader.get_view_key('stackless') == DEFAULT_VIEW_KEY try: loader.get_view_key('fake') - assert False, "should error" - except ResourceNotFound: pass + assert False, 'should error' + except ResourceNotFound: + pass + def test_RosPkgLoader_get_loadable(): from rosdep2.rospkg_loader import RosPkgLoader - + rospack, rosstack = get_rospkg() loader = RosPkgLoader(rospack, rosstack) assert loader._rospack == rospack - assert loader._rosstack == rosstack + assert loader._rosstack == rosstack keys = loader.get_loadable_resources() for p in ['stack1_p1', 'stack1_p2', 'stack1_p3']: assert p in keys - keys = loader.get_loadable_views() + keys = loader.get_loadable_views() for s in ['ros', 'empty', 'invalid', 'stack1']: assert s in keys - - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_shell_utils.py ros-rosdep-0.12.2/test/test_rosdep_shell_utils.py --- ros-rosdep-0.11.8/test/test_rosdep_shell_utils.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_shell_utils.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -25,12 +25,14 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. + def test_create_tempfile_from_string_and_execute(): # not sure how to test this just yet, for now just a tripwire from rosdep2.shell_utils import create_tempfile_from_string_and_execute - assert create_tempfile_from_string_and_execute('#!/bin/sh\necho "hello"'), "ls command failed" - assert not create_tempfile_from_string_and_execute('bad'), "bad command did not fail" + assert create_tempfile_from_string_and_execute('#!/bin/sh\necho "hello"'), 'ls command failed' + assert not create_tempfile_from_string_and_execute('bad'), 'bad command did not fail' + def test_read_stdout(): from rosdep2.shell_utils import read_stdout diff -Nru ros-rosdep-0.11.8/test/test_rosdep_slackware.py ros-rosdep-0.12.2/test/test_rosdep_slackware.py --- ros-rosdep-0.11.8/test/test_rosdep_slackware.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_slackware.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,54 +33,58 @@ import rospkg.os_detect + def is_slackware(): return rospkg.os_detect.Slackware().is_os() + def get_test_dir(): # not used yet return os.path.abspath(os.path.join(os.path.dirname(__file__), 'slackware')) + def test_sbotools_available(): if not is_slackware(): - print("Skipping not Slackware") - return + print('Skipping not Slackware') + return from rosdep2.platforms.slackware import sbotools_available original_exists = os.path.exists path_overrides = {} + def mock_path(path): if path in path_overrides: return path_overrides[path] - else: + else: return original_exists(path) m = Mock(side_effect=mock_path) os.path.exists = m - #Test with sbotools missing + # Test with sbotools missing m.reset_mock() path_overrides = {} path_overrides['/usr/sbin/sboinstall'] = False val = sbotools_available() - assert val==False, "Sbotools should not be available" + assert not val, 'Sbotools should not be available' - #Test with sbotools installed + # Test with sbotools installed m.reset_mock() path_overrides = {} path_overrides['/usr/sbin/sboinstall'] = True val = sbotools_available() - assert val==True, "Sbotools should be available" + assert val, 'Sbotools should be available' os.path.exists = original_exists def test_SbotoolsInstaller(): if not is_slackware(): - print("Skipping not Slackware") - return + print('Skipping not Slackware') + return from rosdep2.platforms.slackware import SbotoolsInstaller @@ -91,7 +95,7 @@ assert [] == installer.get_install_command(['fake']) mock_method.return_value = ['a', 'b'] - + expected = [['sudo', '-H', 'sboinstall', '-r', 'a'], ['sudo', '-H', 'sboinstall', '-r', 'b']] val = installer.get_install_command(['whatever'], interactive=False) @@ -101,53 +105,56 @@ ['sudo', '-H', 'sboinstall', 'b']] val = installer.get_install_command(['whatever'], interactive=True) assert val == expected, val - + try: test() except AssertionError: traceback.print_exc() raise - + + def test_slackpkg_available(): if not is_slackware(): - print("Skipping not Slackware") - return + print('Skipping not Slackware') + return from rosdep2.platforms.slackware import slackpkg_available original_exists = os.path.exists path_overrides = {} + def mock_path(path): if path in path_overrides: return path_overrides[path] - else: + else: return original_exists(path) m = Mock(side_effect=mock_path) os.path.exists = m - #Test with sbotools missing + # Test with sbotools missing m.reset_mock() path_overrides = {} path_overrides['/usr/sbin/slackpkg'] = False val = slackpkg_available() - assert val==False, "Slackpkg should not be available" + assert not val, 'Slackpkg should not be available' - #Test with sbotools installed + # Test with sbotools installed m.reset_mock() path_overrides = {} path_overrides['/usr/sbin/slackpkg'] = True val = slackpkg_available() - assert val==True, "Slackpkg should be available" + assert val, 'Slackpkg should be available' os.path.exists = original_exists + def test_SlackpkgInstaller(): if not is_slackware(): - print("Skipping not Slackware") - return + print('Skipping not Slackware') + return from rosdep2.platforms.slackware import SlackpkgInstaller @@ -158,7 +165,7 @@ assert [] == installer.get_install_command(['fake']) mock_method.return_value = ['a', 'b'] - + expected = [['sudo', '-H', 'slackpkg', 'install', 'a'], ['sudo', '-H', 'slackpkg', 'install', 'b']] val = installer.get_install_command(['whatever'], interactive=False) @@ -168,10 +175,9 @@ ['sudo', '-H', 'slackpkg', 'install', 'b']] val = installer.get_install_command(['whatever'], interactive=True) assert val == expected, val - + try: test() except AssertionError: traceback.print_exc() raise - diff -Nru ros-rosdep-0.11.8/test/test_rosdep_source.py ros-rosdep-0.12.2/test/test_rosdep_source.py --- ros-rosdep-0.11.8/test/test_rosdep_source.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_source.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -51,9 +51,11 @@ REP112_MD5SUM = '57cb9faf930e9c4f0822be8b27798248' + def get_test_dir(): return os.path.abspath(os.path.join(os.path.dirname(__file__), 'source')) + def _subtest_rep112_rdmanifest(resolved): test_dir = get_test_dir() path = os.path.join(test_dir, 'rep112-example.rdmanifest') @@ -64,17 +66,18 @@ assert resolved.install_command == rep122_install_command assert resolved.check_presence_command == rep122_check_presence_command - assert len(resolved.check_presence_command) == len(rep122_check_presence_command), "%s %s"%(len(resolved.check_presence_command), len(rep122_check_presence_command)) + assert len(resolved.check_presence_command) == len(rep122_check_presence_command), '%s %s' % (len(resolved.check_presence_command), len(rep122_check_presence_command)) assert resolved.exec_path == 'yaml-cpp-0.2.5' assert resolved.tarball == 'http://download.ros.org/downloads/yaml-cpp-0.2.5.tar.gz' - assert resolved.alternate_tarball == None + assert resolved.alternate_tarball is None assert resolved.tarball_md5sum == 'b17dc36055cd2259c88b2602601415d9' + def test_SourceInstall(): from rosdep2.platforms.source import InvalidRdmanifest, SourceInstall - #tripwire + # tripwire SourceInstall() # test unpacking of dict @@ -86,7 +89,7 @@ 'uri': 'http://ros.org/', 'alternate-uri': 'http://turtlebot.com/', 'depends': ['foo', 'bar'], - } + } resolved = SourceInstall.from_manifest(manifest, 'fake-url') assert resolved.manifest == manifest assert resolved.manifest_url == 'fake-url' @@ -103,7 +106,7 @@ resolved = SourceInstall.from_manifest(manifest, path) _subtest_rep112_rdmanifest(resolved) - #TODO: test depends + # TODO: test depends # test with bad dicts manifest = { @@ -113,23 +116,24 @@ 'check-presence-script': 'hello there', 'alternate-uri': 'http://turtlebot.com/', 'depends': ['foo', 'bar'], - } + } # uri is required try: SourceInstall.from_manifest(manifest, 'foo') - assert False, "should have raised" + assert False, 'should have raised' except InvalidRdmanifest as e: pass - + # test defaults manifest = dict(uri='http://ros.org/') resolved = SourceInstall.from_manifest(manifest, 'foo') assert resolved.exec_path == '.' assert resolved.install_command == '' - assert resolved.check_presence_command == '' + assert resolved.check_presence_command == '' assert resolved.alternate_tarball is None assert resolved.tarball_md5sum is None + def test_is_installed(): from rosdep2.platforms.source import SourceInstaller, SourceInstall resolved = SourceInstall() @@ -138,7 +142,8 @@ """ installer = SourceInstaller() assert installer.is_installed(resolved) - + + def test_source_detect(): from rosdep2.platforms.source import source_detect, SourceInstall resolved = SourceInstall() @@ -148,17 +153,21 @@ assert [] == source_detect([]) assert [resolved] == source_detect([resolved]) - def yes(*args, **kwds): return 0 - def no(*args, **kwds): return 1 + def yes(*args, **kwds): + return 0 + + def no(*args, **kwds): + return 1 resolved = [SourceInstall(), SourceInstall(), SourceInstall(), SourceInstall()] for r in resolved: r.check_presence_command = '' - + retval = source_detect(resolved, exec_fn=yes) assert resolved == retval, retval assert [] == source_detect(resolved, exec_fn=no) - + + def test_SourceInstaller_get_install_command(): from rosdep2.platforms.source import SourceInstaller, SourceInstall installer = SourceInstaller() @@ -179,7 +188,8 @@ """ commands = installer.get_install_command([resolved]) assert not(commands) - + + def test_SourceInstaller_resolve(): from rosdep2.platforms.source import SourceInstaller, InvalidData test_dir = get_test_dir() @@ -191,21 +201,21 @@ installer = SourceInstaller() try: installer.resolve({}) - assert False, "should have raised" + assert False, 'should have raised' except InvalidData: pass try: installer.resolve(dict(uri=url, md5sum=md5sum_bad)) - assert False, "should have raised" + assert False, 'should have raised' except InvalidData: pass resolved = installer.resolve(dict(uri=url, md5sum=md5sum_good)) - + assert type(resolved) == list assert len(resolved) == 1 # test for reinstall (to check the depends in rdmanifest) dependencies = installer.get_depends(dict(uri=url, md5sum=md5sum_good)) - assert dependencies == ['checkinstall'], "Dependencies should resolve to checkinstall listed in the rdmanifest." + assert dependencies == ['checkinstall'], 'Dependencies should resolve to checkinstall listed in the rdmanifest.' resolved = resolved[0] assert resolved.install_command == rep122_install_command @@ -213,13 +223,13 @@ # test again to activate caching resolved = installer.resolve(dict(uri=url, md5sum=md5sum_good)) - assert type(resolved) == list, "Cache should also return a list" + assert type(resolved) == list, 'Cache should also return a list' assert len(resolved) == 1 resolved = resolved[0] assert resolved.install_command == rep122_install_command assert resolved.check_presence_command == rep122_check_presence_command - + def test_load_rdmanifest(): from rosdep2.platforms.source import load_rdmanifest, InvalidRdmanifest # load_rdmanifest is just a YAML unmarshaller with an exception change @@ -228,15 +238,17 @@ try: load_rdmanifest(';lkajsdf;klj ;l: a;kljdf;: asdf\n ;asdfl;kj') - assert False, "should have raised" + assert False, 'should have raised' except InvalidRdmanifest as e: pass + def test_get_file_hash(): from rosdep2.platforms.source import get_file_hash path = os.path.join(get_test_dir(), 'rep112-example.rdmanifest') assert REP112_MD5SUM == get_file_hash(path) - + + def test_fetch_file(): test_dir = get_test_dir() with open(os.path.join(test_dir, 'rep112-example.rdmanifest')) as f: @@ -249,13 +261,14 @@ assert contents == expected contents, error = fetch_file(url, 'badmd5') - assert bool(error), "should have errored" + assert bool(error), 'should have errored' assert not contents contents, error = fetch_file('http://badhostname.willowgarage.com', 'md5sum') assert not contents - assert bool(error), "should have errored" - + assert bool(error), 'should have errored' + + def test_download_rdmanifest(): test_dir = get_test_dir() with open(os.path.join(test_dir, 'rep112-example.rdmanifest')) as f: @@ -275,23 +288,24 @@ # test md5sum validate try: contents, error = download_rdmanifest(url, 'badmd5') - assert False, "should have errored" + assert False, 'should have errored' except DownloadFailed: pass # test download verify try: contents, error = download_rdmanifest('http://badhostname.willowgarage.com', 'fakemd5') - assert False, "should have errored" + assert False, 'should have errored' except DownloadFailed: pass - + def test_install_from_file(): from rosdep2.platforms.source import install_from_file f = os.path.join(get_test_dir(), 'noop-not-installed.rdmanifest') install_from_file(f) + def test_install_source(): from rosdep2.platforms.source import install_source, SourceInstall resolved = SourceInstall() diff -Nru ros-rosdep-0.11.8/test/test_rosdep_sources_list.py ros-rosdep-0.12.2/test/test_rosdep_sources_list.py --- ros-rosdep-0.11.8/test/test_rosdep_sources_list.py 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/test/test_rosdep_sources_list.py 2018-03-21 23:40:00.000000000 +0000 @@ -1,9 +1,9 @@ # Copyright (c) 2012, Willow Garage, Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright @@ -12,7 +12,7 @@ # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -40,19 +40,18 @@ GITHUB_BASE_URL = 'https://raw.github.com/ros/rosdistro/master/rosdep/base.yaml' + def get_test_dir(): return os.path.abspath(os.path.join(os.path.dirname(__file__), 'sources.list.d')) + def test_get_sources_list_dir(): assert rosdep2.sources_list.get_sources_list_dir() + def test_get_sources_cache_dir(): assert rosdep2.sources_list.get_sources_cache_dir() -def test_parse_sources_data(): - from rosdep2.sources_list import parse_sources_data - - parse_sources_data def test_url_constants(): from rosdep2.sources_list import DEFAULT_SOURCES_LIST_URL @@ -61,19 +60,21 @@ f = urlopen(url) f.read() f.close() - except: - assert False, "URL [%s][%s] failed to download"%(url_name, url) + except Exception: + assert False, 'URL [%s][%s] failed to download' % (url_name, url) + def test_download_default_sources_list(): from rosdep2.sources_list import download_default_sources_list data = download_default_sources_list() - assert 'http' in data, data # sanity check, all sources files have urls + assert 'http' in data, data # sanity check, all sources files have urls try: download_default_sources_list(url='http://bad.ros.org/foo.yaml') - assert False, "should not have succeeded/valdiated" + assert False, 'should not have succeeded/valdiated' except URLError: pass - + + def test_CachedDataSource(): from rosdep2.sources_list import CachedDataSource, DataSource, TYPE_GBPDISTRO, TYPE_YAML type_ = TYPE_GBPDISTRO @@ -100,8 +101,9 @@ assert tags[0] in str(cds) assert tags[0] in repr(cds) assert 'key' in str(cds) - assert 'key' in repr(cds) - + assert 'key' in repr(cds) + + def test_DataSource(): from rosdep2.sources_list import DataSource data_source = DataSource('yaml', 'http://fake/url', ['tag1', 'tag2']) @@ -115,30 +117,31 @@ assert data_source_foo != data_source assert data_source_foo.origin == 'foo' assert '[foo]:\nyaml http://fake/url tag1 tag2' == str(data_source_foo), str(data_source_foo) - + assert repr(data_source) try: rosdep2.sources_list.DataSource('yaml', 'http://fake/url', 'tag1', origin='foo') - assert False, "should have raised" + assert False, 'should have raised' except ValueError: pass try: rosdep2.sources_list.DataSource('yaml', 'non url', ['tag1'], origin='foo') - assert False, "should have raised" + assert False, 'should have raised' except ValueError: pass try: rosdep2.sources_list.DataSource('bad', 'http://fake/url', ['tag1'], origin='foo') - assert False, "should have raised" + assert False, 'should have raised' except ValueError: pass try: rosdep2.sources_list.DataSource('yaml', 'http://host.no.path/', ['tag1'], origin='foo') - assert False, "should have raised" + assert False, 'should have raised' except ValueError: pass + def test_parse_sources_file(): from rosdep2.sources_list import parse_sources_file from rosdep2 import InvalidData @@ -151,14 +154,15 @@ sources = parse_sources_file('bad') except InvalidData: pass - + + def test_parse_sources_list(): from rosdep2.sources_list import parse_sources_list from rosdep2 import InvalidData # test with non-existent dir, should return with empty list as # directory is not required to exist. assert [] == parse_sources_list(sources_list_dir='/not/a/real/path') - + # test with real dir path = get_test_dir() sources_list = parse_sources_list(sources_list_dir=get_test_dir()) @@ -168,11 +172,12 @@ assert sources_list[0].origin.endswith('20-default.list') assert sources_list[1].origin.endswith('20-default.list') assert sources_list[2].origin.endswith('30-nonexistent.list') - + # tripwire -- we don't know what the actual return value is, but # should not error on a correctly configured test system. parse_sources_list() + def test_write_cache_file(): from rosdep2.sources_list import write_cache_file, compute_filename_hash, PICKLE_CACHE_EXT try: @@ -180,13 +185,14 @@ except ImportError: import pickle tempdir = tempfile.mkdtemp() - - filepath = write_cache_file(tempdir, 'foo', {'data': 1}) + PICKLE_CACHE_EXT + + filepath = write_cache_file(tempdir, 'foo', {'data': 1}) + PICKLE_CACHE_EXT computed_path = os.path.join(tempdir, compute_filename_hash('foo')) + PICKLE_CACHE_EXT assert os.path.samefile(filepath, computed_path) with open(filepath, 'rb') as f: assert {'data': 1} == pickle.loads(f.read()) - + + def test_update_sources_list(): from rosdep2.sources_list import update_sources_list, InvalidData, compute_filename_hash, PICKLE_CACHE_EXT try: @@ -197,7 +203,7 @@ from urllib.request import pathname2url except ImportError: from urllib import pathname2url - sources_list_dir=get_test_dir() + sources_list_dir = get_test_dir() index_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'rosdistro', 'index.yaml')) index_url = 'file://' + pathname2url(index_path) os.environ['ROSDISTRO_INDEX_URL'] = index_url @@ -206,6 +212,7 @@ tempdir = os.path.join(tempdir, 'newdir') errors = [] + def error_handler(loc, e): errors.append((loc, e)) retval = update_sources_list(sources_list_dir=sources_list_dir, @@ -221,8 +228,8 @@ hash1 = compute_filename_hash(GITHUB_URL) hash2 = compute_filename_hash(BADHOSTNAME_URL) filepath = os.path.join(tempdir, hash1) - assert filepath == path0, "%s vs %s"%(filepath, path0) - with open(filepath+PICKLE_CACHE_EXT, 'rb') as f: + assert filepath == path0, '%s vs %s' % (filepath, path0) + with open(filepath + PICKLE_CACHE_EXT, 'rb') as f: data = pickle.loads(f.read()) assert 'cmake' in data @@ -232,10 +239,11 @@ with open(os.path.join(tempdir, 'index'), 'r') as f: index = f.read().strip() expected = "#autogenerated by rosdep, do not edit. use 'rosdep update' instead\n"\ - "yaml %s \n"\ - "yaml %s python\n"\ - "yaml %s ubuntu"%(GITHUB_URL, GITHUB_PYTHON_URL, BADHOSTNAME_URL) - assert expected == index, "\n[%s]\nvs\n[%s]"%(expected, index) + 'yaml %s \n'\ + 'yaml %s python\n'\ + 'yaml %s ubuntu' % (GITHUB_URL, GITHUB_PYTHON_URL, BADHOSTNAME_URL) + assert expected == index, '\n[%s]\nvs\n[%s]' % (expected, index) + def test_load_cached_sources_list(): from rosdep2.sources_list import load_cached_sources_list, update_sources_list @@ -243,28 +251,29 @@ # test behavior on empty cache assert [] == load_cached_sources_list(sources_cache_dir=tempdir) - + # pull in cache data - sources_list_dir=get_test_dir() + sources_list_dir = get_test_dir() retval = update_sources_list(sources_list_dir=sources_list_dir, sources_cache_dir=tempdir, error_handler=None) assert retval - + # now test with cached data retval = load_cached_sources_list(sources_cache_dir=tempdir) - assert len(retval) == 3, '%s != %s' % ([source0, source1, source2], retval[0:3]) + assert len(retval) == 3, 'len(%s) != 3' % retval source0 = retval[0] source1 = retval[1] source2 = retval[2] - + # this should be the 'default' source assert 'python' in source1.rosdep_data assert not source0.tags - + # this should be the 'non-existent' source assert source2.rosdep_data == {} assert source2.tags == ['ubuntu'] + def test_DataSourceMatcher(): empty_data_source = rosdep2.sources_list.DataSource('yaml', 'http://fake/url', []) assert empty_data_source == rosdep2.sources_list.DataSource('yaml', 'http://fake/url', []) @@ -286,48 +295,52 @@ matcher = rosdep2.sources_list.DataSourceMatcher(['tag1']) assert not matcher.matches(data_source) + def test_download_rosdep_data(): from rosdep2.sources_list import download_rosdep_data from rosdep2 import DownloadFailure url = GITHUB_BASE_URL data = download_rosdep_data(url) - assert 'boost' in data #sanity check + assert 'boost' in data # sanity check # try with a bad URL try: data = download_rosdep_data('http://badhost.willowgarage.com/rosdep.yaml') - assert False, "should have raised" + assert False, 'should have raised' except DownloadFailure as e: pass # try to trigger both non-dict clause and YAMLError clause for url in [ 'https://code.ros.org/svn/release/trunk/distros/', 'https://code.ros.org/svn/release/trunk/distros/manifest.xml', - ]: + ]: try: data = download_rosdep_data(url) - assert False, "should have raised" + assert False, 'should have raised' except DownloadFailure as e: pass - + + BADHOSTNAME_URL = 'https://badhostname.willowgarage.com/rosdep.yaml' GITHUB_URL = 'https://github.com/ros/rosdistro/raw/master/rosdep/base.yaml' GITHUB_PYTHON_URL = 'https://github.com/ros/rosdistro/raw/master/rosdep/python.yaml' GITHUB_FUERTE_URL = 'https://raw.github.com/ros-infrastructure/rosdep_rules/master/rosdep_fuerte.yaml' -EXAMPLE_SOURCES_DATA_BAD_TYPE = "YAML %s"%(GITHUB_URL) -EXAMPLE_SOURCES_DATA_BAD_URL = "yaml not-a-url tag1 tag2" -EXAMPLE_SOURCES_DATA_BAD_LEN = "yaml" -EXAMPLE_SOURCES_DATA_NO_TAGS = "yaml %s"%(GITHUB_URL) -EXAMPLE_SOURCES_DATA = "yaml %s fuerte ubuntu"%(GITHUB_URL) +EXAMPLE_SOURCES_DATA_BAD_TYPE = 'YAML %s' % (GITHUB_URL) +EXAMPLE_SOURCES_DATA_BAD_URL = 'yaml not-a-url tag1 tag2' +EXAMPLE_SOURCES_DATA_BAD_LEN = 'yaml' +EXAMPLE_SOURCES_DATA_NO_TAGS = 'yaml %s' % (GITHUB_URL) +EXAMPLE_SOURCES_DATA = 'yaml %s fuerte ubuntu' % (GITHUB_URL) EXAMPLE_SOURCES_DATA_MULTILINE = """ # this is a comment, above and below are empty lines yaml %s yaml %s fuerte ubuntu -"""%(GITHUB_URL, GITHUB_FUERTE_URL) +""" % (GITHUB_URL, GITHUB_FUERTE_URL) + + def test_parse_sources_data(): from rosdep2.sources_list import parse_sources_data, TYPE_YAML, InvalidData - + retval = parse_sources_data(EXAMPLE_SOURCES_DATA, origin='foo') assert len(retval) == 1 sd = retval[0] @@ -335,7 +348,7 @@ assert sd.url == GITHUB_URL assert sd.tags == ['fuerte', 'ubuntu'] assert sd.origin == 'foo' - + retval = parse_sources_data(EXAMPLE_SOURCES_DATA_NO_TAGS) assert len(retval) == 1 sd = retval[0] @@ -350,21 +363,22 @@ assert sd.type == TYPE_YAML assert sd.url == GITHUB_URL assert sd.tags == [] - + sd = retval[1] assert sd.type == TYPE_YAML assert sd.url == GITHUB_FUERTE_URL assert sd.tags == ['fuerte', 'ubuntu'] - + for bad in [EXAMPLE_SOURCES_DATA_BAD_URL, EXAMPLE_SOURCES_DATA_BAD_TYPE, EXAMPLE_SOURCES_DATA_BAD_LEN]: try: parse_sources_data(bad) - assert False, "should have raised: %s"%(bad) + assert False, 'should have raised: %s' % (bad) except InvalidData as e: pass - + + def test_DataSourceMatcher_create_default(): distro_name = rospkg.distro.current_distro_codename() os_detect = rospkg.os_detect.OsDetect() @@ -379,7 +393,7 @@ # matches against current os os_data_source = rosdep2.sources_list.DataSource('yaml', 'http://fake/url', [os_name, os_codename]) assert matcher.matches(os_data_source) - + # matches against current distro distro_data_source = rosdep2.sources_list.DataSource('yaml', 'http://fake/url', [distro_name]) assert matcher.matches(distro_data_source) @@ -388,35 +402,36 @@ matcher = rosdep2.sources_list.DataSourceMatcher.create_default(os_override=('fubuntu', 'flucid')) assert not matcher.matches(os_data_source) data_source = rosdep2.sources_list.DataSource('yaml', 'http://fake/url', ['fubuntu']) - assert matcher.matches(data_source) + assert matcher.matches(data_source) data_source = rosdep2.sources_list.DataSource('yaml', 'http://fake/url', ['flucid']) - assert matcher.matches(data_source) + assert matcher.matches(data_source) data_source = rosdep2.sources_list.DataSource('yaml', 'http://fake/url', ['flucid', 'fubuntu']) - assert matcher.matches(data_source) + assert matcher.matches(data_source) data_source = rosdep2.sources_list.DataSource('yaml', 'http://fake/url', ['kubuntu', 'lucid']) - assert not matcher.matches(data_source) - + assert not matcher.matches(data_source) + + def test_SourcesListLoader_create_default(): from rosdep2.sources_list import update_sources_list, SourcesListLoader, DataSourceMatcher # create temp dir for holding sources cache tempdir = tempfile.mkdtemp() # pull in cache data - sources_list_dir=get_test_dir() + sources_list_dir = get_test_dir() retval = update_sources_list(sources_list_dir=sources_list_dir, sources_cache_dir=tempdir, error_handler=None) assert retval - + # now test with cached data matcher = rosdep2.sources_list.DataSourceMatcher(['ubuntu', 'lucid']) loader = SourcesListLoader.create_default(matcher, sources_cache_dir=tempdir) assert loader.sources sources0 = loader.sources assert not any([s for s in loader.sources if not matcher.matches(s)]) - + loader = SourcesListLoader.create_default(matcher, sources_cache_dir=tempdir) assert sources0 == loader.sources - + # now test with different matcher matcher2 = rosdep2.sources_list.DataSourceMatcher(['python']) loader2 = SourcesListLoader.create_default(matcher2, sources_cache_dir=tempdir) @@ -430,20 +445,23 @@ # very simple, always raises RNF try: loader.get_rosdeps('foo') - except rospkg.ResourceNotFound: pass + except rospkg.ResourceNotFound: + pass try: loader.get_view_key('foo') - except rospkg.ResourceNotFound: pass + except rospkg.ResourceNotFound: + pass assert [] == loader.get_loadable_resources() all_sources = [x.url for x in loader.sources] assert all_sources == loader.get_loadable_views() - + # test get_source early to make sure model matches expected try: loader.get_source('foo') - assert False, "should have raised" - except rospkg.ResourceNotFound: pass + assert False, 'should have raised' + except rospkg.ResourceNotFound: + pass s = loader.get_source(GITHUB_URL) assert s.url == GITHUB_URL @@ -451,7 +469,7 @@ # - loader doesn't new view name, so assume everything assert all_sources == loader.get_view_dependencies('foo') # - actual views don't depend on anything - assert [] == loader.get_view_dependencies(GITHUB_URL) + assert [] == loader.get_view_dependencies(GITHUB_URL) # load_view from rosdep2.model import RosdepDatabase diff -Nru ros-rosdep-0.11.8/.travis/install.sh ros-rosdep-0.12.2/.travis/install.sh --- ros-rosdep-0.11.8/.travis/install.sh 1970-01-01 00:00:00.000000000 +0000 +++ ros-rosdep-0.12.2/.travis/install.sh 2018-03-21 23:40:00.000000000 +0000 @@ -0,0 +1,29 @@ +#!/bin/bash + +do_install() +{ + set -e + + if [[ $TRAVIS_OS_NAME == 'osx' && $PYTHON_INSTALLER == 'pyenv' ]]; then + brew install pyenv-virtualenv + pyenv versions + eval "$(pyenv init -)" + pyenv install $TRAVIS_PYTHON_VERSION + PYTHON_ENV_NAME=virtual-env-$TRAVIS_PYTHON_VERSION + pyenv virtualenv $TRAVIS_PYTHON_VERSION $PYTHON_ENV_NAME + pyenv activate $PYTHON_ENV_NAME + + elif [[ $TRAVIS_OS_NAME == 'osx' && $PYTHON_INSTALLER == 'brew' ]]; then + # nose 1.3.7 creates /usr/local/man dir if it does not exist. + # The operation fails because current user does not own /usr/local. Create the dir manually instead. + sudo mkdir /usr/local/man + sudo chown -R $(whoami) $(brew --prefix)/* + + export PATH=$(pwd)/.travis/shim:$PATH + + mkdir -p ~/Library/Python/2.7/lib/python/site-packages + echo "$(brew --prefix)/lib/python2.7/site-packages" >> ~/Library/Python/2.7/lib/python/site-packages/homebrew.pth + fi +} + +do_install diff -Nru ros-rosdep-0.11.8/.travis/shim/pip ros-rosdep-0.12.2/.travis/shim/pip --- ros-rosdep-0.11.8/.travis/shim/pip 1970-01-01 00:00:00.000000000 +0000 +++ ros-rosdep-0.12.2/.travis/shim/pip 2018-03-21 23:40:00.000000000 +0000 @@ -0,0 +1,6 @@ +#!/bin/sh +# This wrapper allows installation to call pip and it actually be +# the pip2 that's part of brewed Python, rather than the missing +# system pip. +pip2 $@ +exit $? diff -Nru ros-rosdep-0.11.8/.travis.yml ros-rosdep-0.12.2/.travis.yml --- ros-rosdep-0.11.8/.travis.yml 2017-08-12 07:24:25.000000000 +0000 +++ ros-rosdep-0.12.2/.travis.yml 2018-03-21 23:40:00.000000000 +0000 @@ -1,16 +1,33 @@ language: python -python: - - "2.6" - - "2.7" - - "3.4" +matrix: + include: + - os: linux + python: 2.6 + - os: linux + python: 2.7 + - os: linux + python: 3.4 + - os: osx + language: generic + env: PYTHON_INSTALLER=brew + - os: osx + language: generic + env: PYTHON_INSTALLER=pyenv TRAVIS_PYTHON_VERSION=2.7.14 + - os: osx + language: generic + env: PYTHON_INSTALLER=pyenv TRAVIS_PYTHON_VERSION=3.6.4 + # command to install dependencies install: -# develop seems to be required by travis since 02/2013 + - source .travis/install.sh + - python --version - pip install PyYAML argparse rospkg vcstools catkin_pkg python-dateutil rosdistro - - python setup.py build develop - - pip install nose coverage + - pip install -e . + - pip install nose coverage flake8 mock codecov # command to run tests script: - nosetests --with-coverage --cover-package=rosdep2 --with-xunit test +after_script: + - codecov notifications: email: false