Exemple #1
0
    def identify(self, desc):  # noqa: D102
        # ignore packages which have been identified with a different type
        if desc.type is not None and desc.type != 'ros':
            return

        # skip paths with an ignore marker file
        if (desc.path / 'CATKIN_IGNORE').exists():
            raise IgnoreLocationException()
        if (desc.path / 'AMENT_IGNORE').exists():
            raise IgnoreLocationException()

        # parse package manifest and get build type
        pkg, build_type = get_package_with_build_type(str(desc.path))
        if not pkg or not build_type:
            # if it is not a wet ROS package check for a dry ROS package
            if (desc.path / 'manifest.xml').exists():
                # ignore location to avoid being identified as a CMake package
                raise IgnoreLocationException()
            return

        desc.type = 'ros.{build_type}'.format_map(locals())

        # use package name from manifest if not already set
        # e.g. from external configuration
        if desc.name is None:
            desc.name = pkg.name

        # get dependencies
        for d in pkg.build_depends + pkg.buildtool_depends:
            assert d.evaluated_condition is not None
            if d.evaluated_condition:
                desc.dependencies['build'].add(d.name)

        for d in (
            pkg.build_export_depends +
            pkg.buildtool_export_depends +
            pkg.exec_depends
        ):
            assert d.evaluated_condition is not None
            if d.evaluated_condition:
                desc.dependencies['run'].add(d.name)

        for d in pkg.test_depends:
            assert d.evaluated_condition is not None
            if d.evaluated_condition:
                desc.dependencies['test'].add(d.name)

        def getter(env):
            nonlocal desc
            return get_setup_arguments_with_context(
                str(desc.path / 'setup.py'), env)

        desc.metadata['get_python_setup_options'] = getter
Exemple #2
0
 def identify(self, desc):  # noqa: D102
     filenames = (
         '_order_isolated_packages.py',  # ament_tools
         '_setup_util.py',  # catkin
     )
     for filename in filenames:
         ignore = desc.path / filename
         if ignore.exists():
             raise IgnoreLocationException()
Exemple #3
0
def test_identify():
    path = '/some/path'
    context = EntryPointContext(extension1=Extension1,
                                extension2=Extension2,
                                extension3=Extension3,
                                extension4=Extension4)

    with context:
        # no identification
        desc = identify({}, path)
        assert desc is None

        # no complete identification
        extensions = get_package_identification_extensions()
        extensions[80]['extension1'].identify = Mock(side_effect=identify_name)
        desc = identify(extensions, path)
        assert desc is None

        # valid result combined across priority groups
        extensions = get_package_identification_extensions()
        extensions[100]['extension4'].identify = Mock(
            side_effect=identify_type)
        desc = identify(extensions, path)
        assert isinstance(desc, PackageDescriptor)
        assert str(desc.path) == '/some/path'.replace('/', os.sep)
        assert desc.name == 'name'
        assert desc.type == 'type'

        # skip location
        extensions = get_package_identification_extensions()
        extensions[90]['extension3'].identify = Mock(
            side_effect=IgnoreLocationException())
        with pytest.raises(IgnoreLocationException):
            identify(extensions, path)

        # valid result from first priority group
        # lower priority groups are not even invoked
        extensions = get_package_identification_extensions()
        extensions[100]['extension4'].identify.side_effect = \
            identify_name_and_type
        desc = identify(extensions, path)
        assert isinstance(desc, PackageDescriptor)
        assert str(desc.path) == '/some/path'.replace('/', os.sep)
        assert desc.name == 'name'
        assert desc.type == 'type'

    with context:
        # multiple different results result in skipping the location
        extensions = get_package_identification_extensions()
        extensions[100]['extension2'].identify = Mock(
            side_effect=identify_name)
        extensions[100]['extension4'].identify = Mock(
            side_effect=identify_type)
        with pytest.raises(IgnoreLocationException):
            identify(extensions, path)
Exemple #4
0
def test__identify():
    desc_path_only = PackageDescriptor('/some/path')
    with EntryPointContext(
            extension1=Extension1,
            extension2=Extension2,
            extension3=Extension3,
            extension4=Extension4,
    ):
        # valid result
        extensions = get_package_identification_extensions()[100]
        extensions['extension2'].identify = Mock()
        extensions['extension4'].identify = identify_name_and_type
        desc = _identify(extensions, desc_path_only)
        assert isinstance(desc, PackageDescriptor)
        assert str(desc.path) == '/some/path'.replace('/', os.sep)
        assert desc.name == 'name'
        assert desc.type == 'type'

        # no results
        extensions = get_package_identification_extensions()[100]
        extensions['extension2'].identify = Mock()
        extensions['extension4'].identify = Mock()
        desc = _identify(extensions, desc_path_only)
        assert desc is None

        # multiple different results
        extensions = get_package_identification_extensions()[100]
        extensions['extension2'].identify = identify_name
        extensions['extension4'].identify = identify_type
        with patch(
                'colcon_core.package_identification.logger.warning') as warn:
            desc = _identify(extensions, desc_path_only)
            assert desc is False
            # the raised exception is catched and results in a warn message
            assert warn.call_count == 1
            assert len(warn.call_args[0]) == 1
            assert 'multiple matches' in warn.call_args[0][0]

        # invalid return value
        extensions = get_package_identification_extensions()[90]
        extensions['extension3'].identify = Mock(return_value=True)
        with patch('colcon_core.package_identification.logger.error') as error:
            desc = _identify(extensions, desc_path_only)
            assert desc is None
            # the raised exception is catched and results in an error message
            assert error.call_count == 1
            assert len(error.call_args[0]) == 1
            assert error.call_args[0][0].startswith(
                "Exception in package identification extension 'extension3' "
                "in '/some/path': identify() should return None\n".replace(
                    '/', os.sep))

        # skip location
        extensions = get_package_identification_extensions()[90]
        extensions['extension3'].identify = Mock(
            side_effect=IgnoreLocationException())
        with pytest.raises(IgnoreLocationException):
            _identify(extensions, desc_path_only)

        # raise exception
        extensions = get_package_identification_extensions()[90]
        extensions['extension3'].identify = Mock(
            side_effect=RuntimeError('custom exception'))
        with patch('colcon_core.package_identification.logger.error') as error:
            desc = _identify(extensions, desc_path_only)
            assert desc is None
            # the raised exception is catched and results in an error message
            assert error.call_count == 1
            assert len(error.call_args[0]) == 1
            assert error.call_args[0][0].startswith(
                "Exception in package identification extension 'extension3' "
                "in '/some/path': custom exception\n".replace('/', os.sep))
Exemple #5
0
    def identify(self, desc):  # noqa: D102
        # ignore packages which have been identified with a different type
        if desc.type is not None and desc.type != 'ros':
            return

        # skip paths with an ignore marker file
        if (desc.path / 'CATKIN_IGNORE').exists():
            raise IgnoreLocationException()
        if (desc.path / 'AMENT_IGNORE').exists():
            raise IgnoreLocationException()

        # parse package manifest and get build type
        pkg, build_type = get_package_with_build_type(str(desc.path))
        if not pkg or not build_type:
            # if it is not a wet ROS package check for a dry ROS package
            if (desc.path / 'manifest.xml').exists():
                # ignore location to avoid being identified as a CMake package
                raise IgnoreLocationException()
            return

        # for Python build types ensure that a setup.py file exists
        if build_type == 'ament_python':
            setup_py = desc.path / 'setup.py'
            if not setup_py.is_file():
                logger.error(
                    "ROS package '{desc.path}' with build type '{build_type}' "
                    "has no 'setup.py' file".format_map(locals()))
                raise IgnoreLocationException()

        desc.type = 'ros.{build_type}'.format_map(locals())

        # use package name from manifest if not already set
        # e.g. from external configuration
        if desc.name is None:
            desc.name = pkg.name

        desc.metadata['version'] = pkg.version

        # get dependencies
        for d in pkg.build_depends + pkg.buildtool_depends:
            assert d.evaluated_condition is not None
            if d.evaluated_condition:
                desc.dependencies['build'].add(
                    DependencyDescriptor(d.name, metadata=_create_metadata(d)))

        for d in (pkg.build_export_depends + pkg.buildtool_export_depends +
                  pkg.exec_depends):
            assert d.evaluated_condition is not None
            if d.evaluated_condition:
                desc.dependencies['run'].add(
                    DependencyDescriptor(d.name, metadata=_create_metadata(d)))

        for d in pkg.test_depends:
            assert d.evaluated_condition is not None
            if d.evaluated_condition:
                desc.dependencies['test'].add(
                    DependencyDescriptor(d.name, metadata=_create_metadata(d)))

        # for Python build types ensure that a setup.py file exists
        if build_type == 'ament_python':
            setup_cfg = desc.path / 'setup.cfg'
            for _ in (1, ):
                # try to get information from setup.cfg file
                if setup_cfg.is_file():
                    if is_reading_cfg_sufficient(setup_py):
                        config = get_configuration(setup_cfg)
                        name = config.get('metadata', {}).get('name')
                        if name:
                            options = config.get('options', {})

                            def getter(env):
                                nonlocal options
                                return options

                            break
            else:
                # use information from setup.py file

                def getter(env):  # noqa: F811
                    nonlocal desc
                    return get_setup_information(desc.path / 'setup.py',
                                                 env=env)

            desc.metadata['get_python_setup_options'] = getter
Exemple #6
0
def identify(_, path):
    if path == os.path.realpath('/empty/path'):
        return None
    if path == os.path.realpath('/skip/path'):
        raise IgnoreLocationException()
    return PackageDescriptor(path)
Exemple #7
0
 def identify(self, desc):  # noqa: D102
     colcon_ignore = desc.path / IGNORE_MARKER
     if colcon_ignore.exists():
         raise IgnoreLocationException()