Skip to content

Commit

Permalink
Rework Package identification tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rotu committed Sep 13, 2019
1 parent ee5d9bc commit 5d17a59
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 64 deletions.
1 change: 1 addition & 0 deletions test/spell_check.words
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ deps
descs
getpid
iterdir
localhost
lstrip
mkdtemp
nargs
Expand Down
247 changes: 183 additions & 64 deletions test/test_package_identification_python.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# Copyright 2016-2018 Dirk Thomas
# Copyright 2019 Rover Robotics
# Licensed under the Apache License, Version 2.0

from pathlib import Path
from tempfile import TemporaryDirectory
import re

from colcon_core.package_descriptor import PackageDescriptor
from colcon_core.package_identification.python \
Expand All @@ -12,69 +11,189 @@
import pytest


def test_identify():
@pytest.fixture
def package_descriptor(tmp_path):
"""Create package descriptor and fail the test if its path changes."""
desc = PackageDescriptor(tmp_path)
yield desc
assert str(desc.path) == str(tmp_path)


@pytest.fixture
def unchanged_empty_descriptor(package_descriptor):
"""Create package descriptor and fail the test if it changes."""
yield package_descriptor
assert package_descriptor.name is None
assert package_descriptor.type is None


@pytest.mark.xfail
def test_error_in_setup_py(unchanged_empty_descriptor):
setup_py = unchanged_empty_descriptor.path / 'setup.py'
error_text = 'My hovercraft is full of eels'
setup_py.write_text('raise OverflowError({!r})'.format(error_text))

extension = PythonPackageIdentification()
with pytest.raises(RuntimeError) as e:
extension.identify(unchanged_empty_descriptor)

assert e.match('Failure when trying to run setup script')
assert e.match(re.escape(str(setup_py)))

# details of the root cause should be in error string
assert e.match('OverflowError')
assert e.match(error_text)


def test_missing_setup_py(unchanged_empty_descriptor):
extension = PythonPackageIdentification()
# should not raise
extension.identify(unchanged_empty_descriptor)


@pytest.mark.xfail
def test_empty_setup_py(unchanged_empty_descriptor):
extension = PythonPackageIdentification()
(unchanged_empty_descriptor.path / 'setup.py').write_text('')
with pytest.raises(RuntimeError) as e:
extension.identify(unchanged_empty_descriptor)
assert e.match('not a Distutils setup script')


def test_re_identify_if_non_python_package(package_descriptor):
package_descriptor.name = 'other-package'
package_descriptor.type = 'other'
extension = PythonPackageIdentification()
extension.identify(package_descriptor)
assert package_descriptor.name == 'other-package'
assert package_descriptor.type == 'other'


def test_re_identify_python_if_same_python_package(package_descriptor):
package_descriptor.name = 'my-package'
package_descriptor.type = 'python'

extension = PythonPackageIdentification()
(package_descriptor.path / 'setup.py').write_text(
'import setuptools; setuptools.setup(name="my-package")')

extension.identify(package_descriptor)
assert package_descriptor.name == 'my-package'
assert package_descriptor.type == 'python'


@pytest.mark.xfail
def test_re_identify_python_if_different_python_package(package_descriptor):
package_descriptor.name = 'other-package'
package_descriptor.type = 'python'

extension = PythonPackageIdentification()
(package_descriptor.path / 'setup.py').write_text(
'import setuptools; setuptools.setup(name="my-package")')

with pytest.raises(RuntimeError):
extension.identify(package_descriptor)

assert package_descriptor.name == 'other-package'
assert package_descriptor.type == 'python'


def test_minimal_cfg(package_descriptor):
extension = PythonPackageIdentification()

(package_descriptor.path / 'setup.py').write_text(
'import setuptools; setuptools.setup()')
(package_descriptor.path / 'setup.cfg').write_text(
'[metadata]\nname = pkg-name')

extension.identify(package_descriptor)

# descriptor should be unchanged
assert package_descriptor.name == 'pkg-name'
assert package_descriptor.type == 'python'


def test_requires(package_descriptor):
extension = PythonPackageIdentification()

(package_descriptor.path / 'setup.py').write_text(
'import setuptools; setuptools.setup()')

(package_descriptor.path / 'setup.cfg').write_text(
'[metadata]\n'
'name = pkg-name\n'
'[options]\n'
'setup_requires =\n'
' setuptools; sys_platform != "imaginary_platform"\n'
' imaginary-package; sys_platform == "imaginary_platform"\n'
'install_requires =\n'
' runA > 1.2.3\n'
' runB\n'
'tests_require = test == 2.0.0\n'
# prevent trying to look for setup_requires in the Package Index
'[easy_install]\n'
'allow_hosts = localhost\n')

extension.identify(package_descriptor)
assert package_descriptor.name == 'pkg-name'
assert package_descriptor.type == 'python'
assert package_descriptor.dependencies.keys() == {'build', 'run', 'test'}
assert package_descriptor.dependencies == {
'build': {'setuptools', 'imaginary-package'},
'run': {'runA', 'runB'},
'test': {'test'}
}
for dep in package_descriptor.dependencies['run']:
if dep == 'runA':
assert dep.metadata['version_gt'] == '1.2.3'

assert package_descriptor.dependencies['run']
assert package_descriptor.dependencies['run'] == {'runA', 'runB'}


def test_metadata_options(package_descriptor):
(package_descriptor.path / 'setup.py').write_text(
'import setuptools; setuptools.setup()')

(package_descriptor.path / 'setup.cfg').write_text(
'[metadata]\n'
'name = pkg-name\n'
'[options]\n'
'zip_safe = false\n'
'packages = find:\n')

(package_descriptor.path / 'my_module').mkdir()
(package_descriptor.path / 'my_module' / '__init__.py').touch()

extension = PythonPackageIdentification()
extension.identify(package_descriptor)

options = package_descriptor.metadata['get_python_setup_options'](None)
assert options['zip_safe'] is False
assert options['packages'] == ['my_module']


@pytest.mark.xfail
def test_metadata_options_dynamic(package_descriptor):
(package_descriptor.path / 'setup.py').write_text(
'import setuptools; setuptools.setup()')
(package_descriptor.path / 'version_helper.py').write_text(
'import os; version = os.environ["version"]'
)

(package_descriptor.path / 'setup.cfg').write_text(
'[metadata]\n'
'name = my-package\n'
'version = attr: version_helper.version\n'
)

extension = PythonPackageIdentification()
extension.identify(package_descriptor)

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.value).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
for version in ('1.0', '1.1'):
options = package_descriptor.metadata['get_python_setup_options'](
{'version': version})
assert options['metadata'].version == version


def test_create_dependency_descriptor():
Expand Down

0 comments on commit 5d17a59

Please sign in to comment.