Skip to content

Commit 5d17a59

Browse files
committed
Rework Package identification tests
1 parent ee5d9bc commit 5d17a59

File tree

2 files changed

+184
-64
lines changed

2 files changed

+184
-64
lines changed

test/spell_check.words

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ deps
1616
descs
1717
getpid
1818
iterdir
19+
localhost
1920
lstrip
2021
mkdtemp
2122
nargs

test/test_package_identification_python.py

Lines changed: 183 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
# Copyright 2016-2018 Dirk Thomas
2+
# Copyright 2019 Rover Robotics
23
# Licensed under the Apache License, Version 2.0
3-
4-
from pathlib import Path
5-
from tempfile import TemporaryDirectory
4+
import re
65

76
from colcon_core.package_descriptor import PackageDescriptor
87
from colcon_core.package_identification.python \
@@ -12,69 +11,189 @@
1211
import pytest
1312

1413

15-
def test_identify():
14+
@pytest.fixture
15+
def package_descriptor(tmp_path):
16+
"""Create package descriptor and fail the test if its path changes."""
17+
desc = PackageDescriptor(tmp_path)
18+
yield desc
19+
assert str(desc.path) == str(tmp_path)
20+
21+
22+
@pytest.fixture
23+
def unchanged_empty_descriptor(package_descriptor):
24+
"""Create package descriptor and fail the test if it changes."""
25+
yield package_descriptor
26+
assert package_descriptor.name is None
27+
assert package_descriptor.type is None
28+
29+
30+
@pytest.mark.xfail
31+
def test_error_in_setup_py(unchanged_empty_descriptor):
32+
setup_py = unchanged_empty_descriptor.path / 'setup.py'
33+
error_text = 'My hovercraft is full of eels'
34+
setup_py.write_text('raise OverflowError({!r})'.format(error_text))
35+
36+
extension = PythonPackageIdentification()
37+
with pytest.raises(RuntimeError) as e:
38+
extension.identify(unchanged_empty_descriptor)
39+
40+
assert e.match('Failure when trying to run setup script')
41+
assert e.match(re.escape(str(setup_py)))
42+
43+
# details of the root cause should be in error string
44+
assert e.match('OverflowError')
45+
assert e.match(error_text)
46+
47+
48+
def test_missing_setup_py(unchanged_empty_descriptor):
49+
extension = PythonPackageIdentification()
50+
# should not raise
51+
extension.identify(unchanged_empty_descriptor)
52+
53+
54+
@pytest.mark.xfail
55+
def test_empty_setup_py(unchanged_empty_descriptor):
56+
extension = PythonPackageIdentification()
57+
(unchanged_empty_descriptor.path / 'setup.py').write_text('')
58+
with pytest.raises(RuntimeError) as e:
59+
extension.identify(unchanged_empty_descriptor)
60+
assert e.match('not a Distutils setup script')
61+
62+
63+
def test_re_identify_if_non_python_package(package_descriptor):
64+
package_descriptor.name = 'other-package'
65+
package_descriptor.type = 'other'
66+
extension = PythonPackageIdentification()
67+
extension.identify(package_descriptor)
68+
assert package_descriptor.name == 'other-package'
69+
assert package_descriptor.type == 'other'
70+
71+
72+
def test_re_identify_python_if_same_python_package(package_descriptor):
73+
package_descriptor.name = 'my-package'
74+
package_descriptor.type = 'python'
75+
76+
extension = PythonPackageIdentification()
77+
(package_descriptor.path / 'setup.py').write_text(
78+
'import setuptools; setuptools.setup(name="my-package")')
79+
80+
extension.identify(package_descriptor)
81+
assert package_descriptor.name == 'my-package'
82+
assert package_descriptor.type == 'python'
83+
84+
85+
@pytest.mark.xfail
86+
def test_re_identify_python_if_different_python_package(package_descriptor):
87+
package_descriptor.name = 'other-package'
88+
package_descriptor.type = 'python'
89+
90+
extension = PythonPackageIdentification()
91+
(package_descriptor.path / 'setup.py').write_text(
92+
'import setuptools; setuptools.setup(name="my-package")')
93+
94+
with pytest.raises(RuntimeError):
95+
extension.identify(package_descriptor)
96+
97+
assert package_descriptor.name == 'other-package'
98+
assert package_descriptor.type == 'python'
99+
100+
101+
def test_minimal_cfg(package_descriptor):
102+
extension = PythonPackageIdentification()
103+
104+
(package_descriptor.path / 'setup.py').write_text(
105+
'import setuptools; setuptools.setup()')
106+
(package_descriptor.path / 'setup.cfg').write_text(
107+
'[metadata]\nname = pkg-name')
108+
109+
extension.identify(package_descriptor)
110+
111+
# descriptor should be unchanged
112+
assert package_descriptor.name == 'pkg-name'
113+
assert package_descriptor.type == 'python'
114+
115+
116+
def test_requires(package_descriptor):
117+
extension = PythonPackageIdentification()
118+
119+
(package_descriptor.path / 'setup.py').write_text(
120+
'import setuptools; setuptools.setup()')
121+
122+
(package_descriptor.path / 'setup.cfg').write_text(
123+
'[metadata]\n'
124+
'name = pkg-name\n'
125+
'[options]\n'
126+
'setup_requires =\n'
127+
' setuptools; sys_platform != "imaginary_platform"\n'
128+
' imaginary-package; sys_platform == "imaginary_platform"\n'
129+
'install_requires =\n'
130+
' runA > 1.2.3\n'
131+
' runB\n'
132+
'tests_require = test == 2.0.0\n'
133+
# prevent trying to look for setup_requires in the Package Index
134+
'[easy_install]\n'
135+
'allow_hosts = localhost\n')
136+
137+
extension.identify(package_descriptor)
138+
assert package_descriptor.name == 'pkg-name'
139+
assert package_descriptor.type == 'python'
140+
assert package_descriptor.dependencies.keys() == {'build', 'run', 'test'}
141+
assert package_descriptor.dependencies == {
142+
'build': {'setuptools', 'imaginary-package'},
143+
'run': {'runA', 'runB'},
144+
'test': {'test'}
145+
}
146+
for dep in package_descriptor.dependencies['run']:
147+
if dep == 'runA':
148+
assert dep.metadata['version_gt'] == '1.2.3'
149+
150+
assert package_descriptor.dependencies['run']
151+
assert package_descriptor.dependencies['run'] == {'runA', 'runB'}
152+
153+
154+
def test_metadata_options(package_descriptor):
155+
(package_descriptor.path / 'setup.py').write_text(
156+
'import setuptools; setuptools.setup()')
157+
158+
(package_descriptor.path / 'setup.cfg').write_text(
159+
'[metadata]\n'
160+
'name = pkg-name\n'
161+
'[options]\n'
162+
'zip_safe = false\n'
163+
'packages = find:\n')
164+
165+
(package_descriptor.path / 'my_module').mkdir()
166+
(package_descriptor.path / 'my_module' / '__init__.py').touch()
167+
168+
extension = PythonPackageIdentification()
169+
extension.identify(package_descriptor)
170+
171+
options = package_descriptor.metadata['get_python_setup_options'](None)
172+
assert options['zip_safe'] is False
173+
assert options['packages'] == ['my_module']
174+
175+
176+
@pytest.mark.xfail
177+
def test_metadata_options_dynamic(package_descriptor):
178+
(package_descriptor.path / 'setup.py').write_text(
179+
'import setuptools; setuptools.setup()')
180+
(package_descriptor.path / 'version_helper.py').write_text(
181+
'import os; version = os.environ["version"]'
182+
)
183+
184+
(package_descriptor.path / 'setup.cfg').write_text(
185+
'[metadata]\n'
186+
'name = my-package\n'
187+
'version = attr: version_helper.version\n'
188+
)
189+
16190
extension = PythonPackageIdentification()
191+
extension.identify(package_descriptor)
17192

18-
with TemporaryDirectory(prefix='test_colcon_') as basepath:
19-
desc = PackageDescriptor(basepath)
20-
desc.type = 'other'
21-
assert extension.identify(desc) is None
22-
assert desc.name is None
23-
24-
desc.type = None
25-
assert extension.identify(desc) is None
26-
assert desc.name is None
27-
assert desc.type is None
28-
29-
basepath = Path(basepath)
30-
(basepath / 'setup.py').write_text('')
31-
assert extension.identify(desc) is None
32-
assert desc.name is None
33-
assert desc.type is None
34-
35-
(basepath / 'setup.cfg').write_text('')
36-
assert extension.identify(desc) is None
37-
assert desc.name is None
38-
assert desc.type is None
39-
40-
(basepath / 'setup.cfg').write_text(
41-
'[metadata]\n'
42-
'name = pkg-name\n')
43-
assert extension.identify(desc) is None
44-
assert desc.name == 'pkg-name'
45-
assert desc.type == 'python'
46-
47-
desc.name = 'other-name'
48-
with pytest.raises(RuntimeError) as e:
49-
extension.identify(desc)
50-
assert str(e.value).endswith(
51-
'Package name already set to different value')
52-
53-
(basepath / 'setup.cfg').write_text(
54-
'[metadata]\n'
55-
'name = other-name\n'
56-
'[options]\n'
57-
'setup_requires =\n'
58-
" build; sys_platform != 'win32'\n"
59-
" build-windows; sys_platform == 'win32'\n"
60-
'install_requires =\n'
61-
' runA > 1.2.3\n'
62-
' runB\n'
63-
'tests_require = test == 2.0.0\n'
64-
'zip_safe = false\n')
65-
assert extension.identify(desc) is None
66-
assert desc.name == 'other-name'
67-
assert desc.type == 'python'
68-
assert set(desc.dependencies.keys()) == {'build', 'run', 'test'}
69-
assert desc.dependencies['build'] == {'build', 'build-windows'}
70-
assert desc.dependencies['run'] == {'runA', 'runB'}
71-
dep = next(x for x in desc.dependencies['run'] if x == 'runA')
72-
assert dep.metadata['version_gt'] == '1.2.3'
73-
assert desc.dependencies['test'] == {'test'}
74-
75-
assert callable(desc.metadata['get_python_setup_options'])
76-
options = desc.metadata['get_python_setup_options'](None)
77-
assert 'zip_safe' in options
193+
for version in ('1.0', '1.1'):
194+
options = package_descriptor.metadata['get_python_setup_options'](
195+
{'version': version})
196+
assert options['metadata'].version == version
78197

79198

80199
def test_create_dependency_descriptor():

0 commit comments

Comments
 (0)