summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Fregtman <941331+darkvertex@users.noreply.github.com>2021-06-30 01:15:18 -0400
committerAlan Fregtman <941331+darkvertex@users.noreply.github.com>2021-06-30 01:15:18 -0400
commit36b4820f519d93bad998302141ae6de2cb15191c (patch)
tree3b2f12b454f27de4d837f106885216ea89d28347
parent2234e88b7b820c40f29d7ddadc182b0f130eaa1d (diff)
downloadpython-setuptools-git-36b4820f519d93bad998302141ae6de2cb15191c.tar.gz
Implement "glob:" directive for declarative "data_files" option.
-rw-r--r--docs/userguide/declarative_config.rst5
-rw-r--r--setuptools/config.py30
-rw-r--r--setuptools/tests/test_config.py35
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,