def test_magic_methods(): d1 = PackageDescriptor('/some/path') d1.type = 'custom-type' d1.name = 'custom-name' d2 = PackageDescriptor('/some/path') d2.type = 'custom-type' d2.name = 'other-name' assert d1 != d2 assert hash(d1) != hash(d2) d2.name = 'custom-name' assert d1 == d2 assert hash(d1) == hash(d2) d1.dependencies['build'].add('build-depend') d2.hooks.append('hook') d2.metadata['key'] = 'value' assert d1 == d2 assert hash(d1) == hash(d2) d2.type = 'other-type' assert d1 != d2 assert hash(d1) != hash(d2) d2.type = 'custom-type' assert d1 == d2 assert hash(d1) == hash(d2) d2.path = Path('/other/path') assert d1 != d2 # comparing with other types always returns False assert d1 != []
def test_identify(): extension = PythonPackageIdentification() with TemporaryDirectory(prefix='test_colcon_') as basepath: desc = PackageDescriptor(basepath) desc.type = 'other' assert extension.identify(desc) is None assert desc.name is None desc.type = None assert extension.identify(desc) is None assert desc.name is None assert desc.type is None basepath = Path(basepath) (basepath / 'setup.py').write_text('') assert extension.identify(desc) is None assert desc.name is None assert desc.type is None (basepath / 'setup.cfg').write_text('') assert extension.identify(desc) is None assert desc.name is None assert desc.type is None (basepath / 'setup.cfg').write_text('[metadata]\n' 'name = pkg-name\n') assert extension.identify(desc) is None assert desc.name == 'pkg-name' assert desc.type == 'python' desc.name = 'other-name' with pytest.raises(RuntimeError) as e: extension.identify(desc) assert str(e).endswith('Package name already set to different value') (basepath / 'setup.cfg').write_text( '[metadata]\n' 'name = other-name\n' '[options]\n' 'setup_requires =\n' " build; sys_platform != 'win32'\n" " build-windows; sys_platform == 'win32'\n" 'install_requires =\n' ' runA > 1.2.3\n' ' runB\n' 'tests_require = test == 2.0.0\n' 'zip_safe = false\n') assert extension.identify(desc) is None assert desc.name == 'other-name' assert desc.type == 'python' assert set(desc.dependencies.keys()) == {'build', 'run', 'test'} assert desc.dependencies['build'] == {'build', 'build-windows'} assert desc.dependencies['run'] == {'runA', 'runB'} dep = next(x for x in desc.dependencies['run'] if x == 'runA') assert dep.metadata['version_gt'] == '1.2.3' assert desc.dependencies['test'] == {'test'} assert callable(desc.metadata['get_python_setup_options']) options = desc.metadata['get_python_setup_options'](None) assert 'zip_safe' in options
def test_identifies_package(): d = PackageDescriptor('/some/path') assert not d.identifies_package() d.type = 'type' assert not d.identifies_package() d.type = None d.name = 'name' assert not d.identifies_package() d.type = 'type' assert d.identifies_package()
def test_build_package(): event_loop = new_event_loop() asyncio.set_event_loop(event_loop) try: with TemporaryDirectory(prefix='test_colcon_') as tmp_path_str: tmp_path = Path(tmp_path_str) python_build_task = PythonBuildTask() package = PackageDescriptor(tmp_path / 'src') package.name = 'test_package' package.type = 'python' context = TaskContext( pkg=package, args=SimpleNamespace( path=str(tmp_path / 'src'), build_base=str(tmp_path / 'build'), install_base=str(tmp_path / 'install'), symlink_install=False, ), dependencies={} ) python_build_task.set_context(context=context) pkg = python_build_task.context.pkg pkg.path.mkdir() (pkg.path / 'setup.py').write_text( 'from setuptools import setup\n' 'setup(\n' ' name="test_package",\n' ' packages=["my_module"],\n' ')\n' ) (pkg.path / 'my_module').mkdir() (pkg.path / 'my_module' / '__init__.py').touch() src_base = Path(python_build_task.context.args.path) source_files_before = set(src_base.rglob('*')) event_loop.run_until_complete(python_build_task.build()) source_files_after = set(src_base.rglob('*')) assert source_files_before == source_files_after build_base = Path(python_build_task.context.args.build_base) assert 1 == len(list(build_base.rglob('my_module/__init__.py'))) install_base = Path(python_build_task.context.args.install_base) assert 1 == len(list(install_base.rglob('my_module/__init__.py'))) pkg_info, = install_base.rglob('PKG-INFO') assert 'Name: test-package' in pkg_info.read_text().splitlines() finally: event_loop.close()
def test_pytest_match(): extension = PytestPythonTestingStep() env = {} desc = PackageDescriptor('/dev/null') context = TaskContext(pkg=desc, args=None, dependencies=None) desc.name = 'pkg-name' desc.type = 'python' # no test requirements desc.metadata['get_python_setup_options'] = lambda env: {} assert not extension.match(context, env, get_setup_data(desc, env)) # pytest not in tests_require desc.metadata['get_python_setup_options'] = lambda env: { 'tests_require': ['nose'], } assert not extension.match(context, env, get_setup_data(desc, env)) # pytest not in extras_require.test desc.metadata['get_python_setup_options'] = lambda env: { 'extras_require': { 'test': ['nose'] }, } assert not extension.match(context, env, get_setup_data(desc, env)) # pytest in tests_require desc.metadata['get_python_setup_options'] = lambda env: { 'tests_require': ['pytest'], } assert extension.match(context, env, get_setup_data(desc, env)) # pytest in extras_require.test desc.metadata['get_python_setup_options'] = lambda env: { 'extras_require': { 'test': ['pytest'] }, } assert extension.match(context, env, get_setup_data(desc, env))
def test_str(): d = PackageDescriptor('/some/path') d.type = 'custom-type' d.name = 'custom-name' d.dependencies['build'].add('build-depend') d.dependencies['run'].add('run-depend') d.hooks += ('hook-a', 'hook-b') d.metadata['key'] = 'value' s = str(d) assert s.startswith('{') assert s.endswith('}') assert 'path: ' in s assert '/some/path'.replace('/', os.sep) in s assert 'type: ' in s assert 'custom-type' in s assert 'name: ' in s assert 'custom-name' in s assert 'dependencies: ' in s assert 'build-depend' in s assert 'run-depend' in s assert 'hooks: ' in s assert 'hook-a' in s assert 'metadata: ' in s assert 'value' in s
def update_descriptor(desc: PackageDescriptor, data: dict, *, additional_argument_names=None): """ Update the package descriptor with additional information. For the keys `name` and `type` the values from `data` are set on the descriptor attributes with the same names. For the key `dependencies` the values are being added to the dependencies in each of the following categories: `build`, `run`, and `test`. For the keys `build_dependencies`, `run_dependencies`, and `test_dependencies` the values are being added to the dependencies in the category with the same name. For the key `hooks` the values are being added to the list of hooks. Any key-value pair not explicitly mentioned above is being used to update the metadata if the key is in the list of additional argument names. See :function:`update_metadata` for details how the metadata is updated. If the additional argument names is a list with the single value `*` all keys not explicitly mentioned above are being used to update the metadata. :param desc: the package descriptor :param data: The dictionary with additional information :param additional_argument_names: A dict of option names to destination names or a list of argument names """ # explicit key updates try: desc.name = data['name'] except KeyError: pass try: desc.type = data['type'] except KeyError: pass dep_types = ('build', 'run', 'test') # transfer generic dependencies to each specific type if 'dependencies' in data: for d in data['dependencies']: for dep_type in dep_types: desc.dependencies[dep_type].add(d) # transfer type specific dependencies for dep_type in dep_types: key = '{dep_type}-dependencies'.format_map(locals()) if key in data: for d in data[key]: desc.dependencies[dep_type].add(d) # transfer hooks if 'hooks' in data: for d in data['hooks']: desc.hooks.append(d) # transfer any other metadata if additional_argument_names == ['*']: additional_argument_names = [] # skip any of the already explicitly handled names ignored_names = ['name', 'type', 'dependencies', 'hooks'] for dep_type in dep_types: ignored_names.append('{dep_type}-dependencies'.format_map( locals())) for name in data.keys(): if name in ignored_names: continue additional_argument_names.append(name) if isinstance(additional_argument_names, list): additional_argument_names = OrderedDict([ (name, name) for name in additional_argument_names ]) for option, dest in (additional_argument_names or {}).items(): if option in data: update_metadata(desc, dest, data[option])
def test_identify(): extension = BazelPackageIdentification() with TemporaryDirectory(prefix='test_colcon_') as basepath: desc = PackageDescriptor(basepath) desc.type = 'other' assert extension.identify(desc) is None assert desc.name is None desc.type = None assert extension.identify(desc) is None assert desc.name is None assert desc.type is None basepath = Path(basepath) (basepath / 'BUILD.bazel').write_text('') assert extension.identify(desc) is None assert desc.name is not None assert desc.type is 'bazel' desc.name = None (basepath / 'BUILD').write_text('') assert extension.identify(desc) is None assert desc.name is not None assert desc.type is 'bazel' desc.name = None (basepath / 'BUILD.bazel').write_text( 'java_binary(\n' ' name = "pkg-name",\n' ')\n') assert extension.identify(desc) is None assert desc.name == 'pkg-name' assert desc.type == 'bazel' desc.name = 'other-name' with pytest.raises(RuntimeError) as einfo: extension.identify(desc) assert str(einfo.value).endswith('Package name already set to different value') (basepath / 'BUILD.bazel').write_text( 'java_binary(\n' ' name = "other-name",\n' ' deps = [":build-depA", ":build-depB"]\n' ' runtime_deps = [":run-depA", ":run-depB"]\n' ')\n' '\n' 'java_library(\n' ' name = "other-name-lib",\n' ' deps = [":lib-dep", "@log4j//jar", "other-name"]\n' ' runtime_deps = [":lib-run-dep"]\n' ')\n' '\n' 'java_test(\n' ' name = "other-name-test",\n' ' deps = [":test-dep"],\n' ' runtime_deps = [":test-run-dep"]\n' ')\n') assert extension.identify(desc) is None assert desc.name == 'other-name' assert desc.type == 'bazel' assert set(desc.dependencies.keys()) == {'build', 'run', 'test'} assert desc.dependencies['build'] == {'build-depA', 'build-depB', 'lib-dep'} assert desc.dependencies['run'] == {'run-depA', 'run-depB', 'lib-run-dep'} assert desc.dependencies['test'] == {'test-dep', 'test-run-dep'} desc.name = None (basepath / 'sub1/sub2/sub3').mkdir(parents=True, exist_ok=True) assert extension.identify(desc) is None assert desc.name == 'other-name' assert desc.type == 'bazel'