summaryrefslogtreecommitdiffstats
path: root/flit_core/flit_core/tests/test_config.py
diff options
context:
space:
mode:
Diffstat (limited to 'flit_core/flit_core/tests/test_config.py')
-rw-r--r--flit_core/flit_core/tests/test_config.py165
1 files changed, 165 insertions, 0 deletions
diff --git a/flit_core/flit_core/tests/test_config.py b/flit_core/flit_core/tests/test_config.py
new file mode 100644
index 0000000..eafb7e9
--- /dev/null
+++ b/flit_core/flit_core/tests/test_config.py
@@ -0,0 +1,165 @@
+import logging
+from pathlib import Path
+import pytest
+
+from flit_core import config
+
+samples_dir = Path(__file__).parent / 'samples'
+
+def test_flatten_entrypoints():
+ r = config.flatten_entrypoints({'a': {'b': {'c': 'd'}, 'e': {'f': {'g': 'h'}}, 'i': 'j'}})
+ assert r == {'a': {'i': 'j'}, 'a.b': {'c': 'd'}, 'a.e.f': {'g': 'h'}}
+
+def test_load_toml():
+ inf = config.read_flit_config(samples_dir / 'module1-pkg.toml')
+ assert inf.module == 'module1'
+ assert inf.metadata['home_page'] == 'http://github.com/sirrobin/module1'
+
+def test_load_toml_ns():
+ inf = config.read_flit_config(samples_dir / 'ns1-pkg' / 'pyproject.toml')
+ assert inf.module == 'ns1.pkg'
+ assert inf.metadata['home_page'] == 'http://github.com/sirrobin/module1'
+
+def test_load_normalization():
+ inf = config.read_flit_config(samples_dir / 'normalization' / 'pyproject.toml')
+ assert inf.module == 'my_python_module'
+ assert inf.metadata['name'] == 'my-python-module'
+
+def test_load_pep621():
+ inf = config.read_flit_config(samples_dir / 'pep621' / 'pyproject.toml')
+ assert inf.module == 'module1a'
+ assert inf.metadata['name'] == 'module1'
+ assert inf.metadata['description_content_type'] == 'text/x-rst'
+ # Remove all whitespace from requirements so we don't check exact format:
+ assert {r.replace(' ', '') for r in inf.metadata['requires_dist']} == {
+ 'docutils',
+ 'requests>=2.18',
+ 'pytest;extra=="test"', # from [project.optional-dependencies]
+ 'mock;extra=="test"and(python_version<\'3.6\')',
+ }
+ assert inf.metadata['author_email'] == "Sir Röbin <robin@camelot.uk>"
+ assert inf.entrypoints['flit_test_example']['foo'] == 'module1:main'
+ assert set(inf.dynamic_metadata) == {'version', 'description'}
+
+def test_load_pep621_nodynamic():
+ inf = config.read_flit_config(samples_dir / 'pep621_nodynamic' / 'pyproject.toml')
+ assert inf.module == 'module1'
+ assert inf.metadata['name'] == 'module1'
+ assert inf.metadata['version'] == '0.3'
+ assert inf.metadata['summary'] == 'Statically specified description'
+ assert set(inf.dynamic_metadata) == set()
+
+ # Filling reqs_by_extra when dependencies were specified but no optional
+ # dependencies was a bug.
+ assert inf.reqs_by_extra == {'.none': ['requests >= 2.18', 'docutils']}
+
+def test_misspelled_key():
+ with pytest.raises(config.ConfigError) as e_info:
+ config.read_flit_config(samples_dir / 'misspelled-key.toml')
+
+ assert 'description-file' in str(e_info.value)
+
+def test_description_file():
+ info = config.read_flit_config(samples_dir / 'package1.toml')
+ assert info.metadata['description'] == \
+ "Sample description for test.\n"
+ assert info.metadata['description_content_type'] == 'text/x-rst'
+
+def test_missing_description_file():
+ with pytest.raises(config.ConfigError, match=r"Description file .* does not exist"):
+ config.read_flit_config(samples_dir / 'missing-description-file.toml')
+
+def test_bad_description_extension(caplog):
+ info = config.read_flit_config(samples_dir / 'bad-description-ext.toml')
+ assert info.metadata['description_content_type'] is None
+ assert any((r.levelno == logging.WARN and "Unknown extension" in r.msg)
+ for r in caplog.records)
+
+def test_extras():
+ info = config.read_flit_config(samples_dir / 'extras.toml')
+ requires_dist = set(info.metadata['requires_dist'])
+ assert requires_dist == {
+ 'toml',
+ 'pytest ; extra == "test"',
+ 'requests ; extra == "custom"',
+ }
+ assert set(info.metadata['provides_extra']) == {'test', 'custom'}
+
+def test_extras_dev_conflict():
+ with pytest.raises(config.ConfigError, match=r'dev-requires'):
+ config.read_flit_config(samples_dir / 'extras-dev-conflict.toml')
+
+def test_extras_dev_warning(caplog):
+ info = config.read_flit_config(samples_dir / 'requires-dev.toml')
+ assert '"dev-requires = ..." is obsolete' in caplog.text
+ assert set(info.metadata['requires_dist']) == {'apackage ; extra == "dev"'}
+
+def test_requires_extra_env_marker():
+ info = config.read_flit_config(samples_dir / 'requires-extra-envmark.toml')
+ assert info.metadata['requires_dist'][0].startswith('pathlib2 ;')
+
+@pytest.mark.parametrize(('erroneous', 'match'), [
+ ({'requires-extra': None}, r'Expected a dict for requires-extra field'),
+ ({'requires-extra': dict(dev=None)}, r'Expected a dict of lists for requires-extra field'),
+ ({'requires-extra': dict(dev=[1])}, r'Expected a string list for requires-extra'),
+])
+def test_faulty_requires_extra(erroneous, match):
+ metadata = {'module': 'mymod', 'author': '', 'author-email': ''}
+ with pytest.raises(config.ConfigError, match=match):
+ config._prep_metadata(dict(metadata, **erroneous), None)
+
+@pytest.mark.parametrize(('path', 'err_match'), [
+ ('../bar', 'out of the directory'),
+ ('foo/../../bar', 'out of the directory'),
+ ('/home', 'absolute path'),
+ ('foo:bar', 'bad character'),
+])
+def test_bad_include_paths(path, err_match):
+ toml_cfg = {'tool': {'flit': {
+ 'metadata': {'module': 'xyz', 'author': 'nobody'},
+ 'sdist': {'include': [path]}
+ }}}
+
+ with pytest.raises(config.ConfigError, match=err_match):
+ config.prep_toml_config(toml_cfg, None)
+
+@pytest.mark.parametrize(('proj_bad', 'err_match'), [
+ ({'version': 1}, r'\bstr\b'),
+ ({'license': {'fromage': 2}}, '[Uu]nrecognised'),
+ ({'license': {'file': 'LICENSE', 'text': 'xyz'}}, 'both'),
+ ({'license': {}}, 'required'),
+ ({'keywords': 'foo'}, 'list'),
+ ({'keywords': ['foo', 7]}, 'strings'),
+ ({'entry-points': {'foo': 'module1:main'}}, 'entry-point.*tables'),
+ ({'entry-points': {'group': {'foo': 7}}}, 'entry-point.*string'),
+ ({'entry-points': {'gui_scripts': {'foo': 'a:b'}}}, r'\[project\.gui-scripts\]'),
+ ({'scripts': {'foo': 7}}, 'scripts.*string'),
+ ({'gui-scripts': {'foo': 7}}, 'gui-scripts.*string'),
+ ({'optional-dependencies': {'test': 'requests'}}, 'list.*optional-dep'),
+ ({'optional-dependencies': {'test': [7]}}, 'string.*optional-dep'),
+ ({'dynamic': ['classifiers']}, 'dynamic'),
+ ({'dynamic': ['version']}, r'dynamic.*\[project\]'),
+ ({'authors': ['thomas']}, r'author.*\bdict'),
+ ({'maintainers': [{'title': 'Dr'}]}, r'maintainer.*title'),
+])
+def test_bad_pep621_info(proj_bad, err_match):
+ proj = {'name': 'module1', 'version': '1.0', 'description': 'x'}
+ proj.update(proj_bad)
+ with pytest.raises(config.ConfigError, match=err_match):
+ config.read_pep621_metadata(proj, samples_dir / 'pep621')
+
+@pytest.mark.parametrize(('readme', 'err_match'), [
+ ({'file': 'README.rst'}, 'required'),
+ ({'file': 'README.rst', 'content-type': 'text/x-python'}, 'content-type'),
+ ('/opt/README.rst', 'relative'),
+ ({'file': 'README.rst', 'text': '', 'content-type': 'text/x-rst'}, 'both'),
+ ({'content-type': 'text/x-rst'}, 'required'),
+ ({'file': 'README.rst', 'content-type': 'text/x-rst', 'a': 'b'}, '[Uu]nrecognised'),
+ (5, r'readme.*string'),
+])
+def test_bad_pep621_readme(readme, err_match):
+ proj = {
+ 'name': 'module1', 'version': '1.0', 'description': 'x', 'readme': readme
+ }
+ with pytest.raises(config.ConfigError, match=err_match):
+ config.read_pep621_metadata(proj, samples_dir / 'pep621')