diff options
author | Alan Fregtman <941331+darkvertex@users.noreply.github.com> | 2021-06-30 01:15:18 -0400 |
---|---|---|
committer | Alan Fregtman <941331+darkvertex@users.noreply.github.com> | 2021-06-30 01:15:18 -0400 |
commit | 36b4820f519d93bad998302141ae6de2cb15191c (patch) | |
tree | 3b2f12b454f27de4d837f106885216ea89d28347 | |
parent | 2234e88b7b820c40f29d7ddadc182b0f130eaa1d (diff) | |
download | python-setuptools-git-36b4820f519d93bad998302141ae6de2cb15191c.tar.gz |
Implement "glob:" directive for declarative "data_files" option.
-rw-r--r-- | docs/userguide/declarative_config.rst | 5 | ||||
-rw-r--r-- | setuptools/config.py | 30 | ||||
-rw-r--r-- | setuptools/tests/test_config.py | 35 |
3 files changed, 68 insertions, 2 deletions
diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst index 128d9f97..dcab0b3a 100644 --- a/docs/userguide/declarative_config.rst +++ b/docs/userguide/declarative_config.rst @@ -68,6 +68,7 @@ boilerplate code in some cases. site.d/00_default.conf host.d/00_default.conf data = data/img/logo.png, data/svg/icon.svg + fonts = glob: data/fonts/*.ttf, glob: data/fonts/*.otf Metadata and options are set in the config sections of the same name. @@ -156,6 +157,8 @@ Special directives: The ``file:`` directive is sandboxed and won't reach anything outside the directory containing ``setup.py``. +* ``glob:`` - Value will be treated as a glob() pattern and expanded accordingly. + Metadata -------- @@ -225,7 +228,7 @@ package_data section [# exclude_package_data section namespace_packages list-comma py_modules list-comma -data_files dict 40.6.0 +data_files glob:, dict 40.6.0 ======================= =================================== =============== ========= **Notes**: diff --git a/setuptools/config.py b/setuptools/config.py index 44de7cf5..47109dad 100644 --- a/setuptools/config.py +++ b/setuptools/config.py @@ -9,6 +9,7 @@ import importlib from collections import defaultdict from functools import partial from functools import wraps +from glob import iglob import contextlib from distutils.errors import DistutilsOptionError, DistutilsFileError @@ -256,6 +257,33 @@ class ConfigHandler: return [chunk.strip() for chunk in value if chunk.strip()] @classmethod + def _parse_list_glob(cls, value, separator=','): + """Equivalent to _parse_list() but expands 'glob:' directives using glob(). + + However, unlike glob(), the resolved results stay relative paths. + + :param value: + :param separator: List items separator character. + :rtype: list + """ + directive = 'glob:' + values = cls._parse_list(value, separator=separator) + expanded_values = [] + for value in values: + trimmed_value = value.strip() + if trimmed_value.startswith(directive): + # take what is after "glob:" + value = trimmed_value.split(directive, 1)[-1].strip() + value = os.path.abspath(value) + # and expand it while keeping as a relative path: + value = sorted(os.path.relpath(path, os.getcwd()) for path in iglob(value)) + expanded_values.extend(value) + else: + expanded_values.append(value) + + return expanded_values + + @classmethod def _parse_dict(cls, value): """Represents value as a dict. @@ -711,5 +739,5 @@ class ConfigOptionsHandler(ConfigHandler): :param dict section_options: """ - parsed = self._parse_section_to_dict(section_options, self._parse_list) + parsed = self._parse_section_to_dict(section_options, self._parse_list_glob) self['data_files'] = [(k, v) for k, v in parsed.items()] diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py index 21f1becd..c86c8573 100644 --- a/setuptools/tests/test_config.py +++ b/setuptools/tests/test_config.py @@ -893,6 +893,41 @@ class TestOptions: ] assert sorted(dist.data_files) == sorted(expected) + def test_data_files_globby(self, tmpdir): + fake_env( + tmpdir, + '[options.data_files]\n' + 'cfg =\n' + ' a/b.conf\n' + ' c/d.conf\n' + 'data = glob: *.dat\n' + 'icons = \n' + ' glob: *.ico\n' + 'audio = \n' + ' glob:*.wav\n' + ' sounds.db\n' + ) + + # Create dummy files for glob()'s sake: + tmpdir.join('a.dat').write('') + tmpdir.join('b.dat').write('') + tmpdir.join('c.dat').write('') + tmpdir.join('a.ico').write('') + tmpdir.join('b.ico').write('') + tmpdir.join('c.ico').write('') + tmpdir.join('beep.wav').write('') + tmpdir.join('boop.wav').write('') + tmpdir.join('sounds.db').write('') + + with get_dist(tmpdir) as dist: + expected = [ + ('cfg', ['a/b.conf', 'c/d.conf']), + ('data', ['a.dat', 'b.dat', 'c.dat']), + ('icons', ['a.ico', 'b.ico', 'c.ico']), + ('audio', ['beep.wav', 'boop.wav', 'sounds.db']), + ] + assert sorted(dist.data_files) == sorted(expected) + def test_python_requires_simple(self, tmpdir): fake_env( tmpdir, |