diff options
author | John T. Wodder II <git@varonathe.org> | 2019-04-27 19:21:50 +0000 |
---|---|---|
committer | John T. Wodder II <git@varonathe.org> | 2020-05-15 18:49:43 +0000 |
commit | 6de971f158553c47ce11e7be9d38d268e0398193 (patch) | |
tree | b827f272f5f4aa0daf4d9b2a5af0c09b28b55de0 | |
parent | 9887350aa500b86feea0859eebe057d56a060d67 (diff) | |
download | external_python_setuptools-6de971f158553c47ce11e7be9d38d268e0398193.tar.gz external_python_setuptools-6de971f158553c47ce11e7be9d38d268e0398193.tar.bz2 external_python_setuptools-6de971f158553c47ce11e7be9d38d268e0398193.zip |
Implement a "literal_attr:" config directive
-rw-r--r-- | setuptools/config.py | 62 | ||||
-rw-r--r-- | setuptools/tests/test_config.py | 64 |
2 files changed, 117 insertions, 9 deletions
diff --git a/setuptools/config.py b/setuptools/config.py index 9b9a0c45..d1456cac 100644 --- a/setuptools/config.py +++ b/setuptools/config.py @@ -1,4 +1,5 @@ from __future__ import absolute_import, unicode_literals +import ast import io import os import sys @@ -316,15 +317,22 @@ class ConfigHandler: Examples: attr: package.attr attr: package.module.attr + literal_attr: package.attr + literal_attr: package.module.attr :param str value: :rtype: str """ attr_directive = 'attr:' - if not value.startswith(attr_directive): + literal_attr_directive = 'literal_attr:' + if value.startswith(attr_directive): + directive = attr_directive + elif value.startswith(literal_attr_directive): + directive = literal_attr_directive + else: return value - attrs_path = value.replace(attr_directive, '').strip().split('.') + attrs_path = value.replace(directive, '').strip().split('.') attr_name = attrs_path.pop() module_name = '.'.join(attrs_path) @@ -344,13 +352,49 @@ class ConfigHandler: elif '' in package_dir: # A custom parent directory was specified for all root modules parent_path = os.path.join(os.getcwd(), package_dir['']) - sys.path.insert(0, parent_path) - try: - module = import_module(module_name) - value = getattr(module, attr_name) - - finally: - sys.path = sys.path[1:] + if directive == attr_directive: + sys.path.insert(0, parent_path) + try: + module = import_module(module_name) + value = getattr(module, attr_name) + finally: + sys.path = sys.path[1:] + + elif directive == literal_attr_directive: + fpath = os.path.join(parent_path, *module_name.split('.')) + if os.path.exists(fpath + '.py'): + fpath += '.py' + elif os.path.isdir(fpath): + fpath = os.path.join(fpath, '__init__.py') + else: + raise DistutilsOptionError( + 'Could not find module ' + module_name + ) + with open(fpath, 'rb') as fp: + src = fp.read() + found = False + top_level = ast.parse(src) + for statement in top_level.body: + if isinstance(statement, ast.Assign): + for target in statement.targets: + if isinstance(target, ast.Name) \ + and target.id == attr_name: + value = ast.literal_eval(statement.value) + found = True + elif isinstance(target, ast.Tuple) \ + and any(isinstance(t, ast.Name) and t.id==attr_name + for t in target.elts): + stmnt_value = ast.literal_eval(statement.value) + for t,v in zip(target.elts, stmnt_value): + if isinstance(t, ast.Name) \ + and t.id == attr_name: + value = v + found = True + if not found: + raise DistutilsOptionError( + 'No literal assignment to {!r} found in file' + .format(attr_name) + ) return value diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py index 2fa0b374..03e6916b 100644 --- a/setuptools/tests/test_config.py +++ b/setuptools/tests/test_config.py @@ -300,6 +300,37 @@ class TestMetadata: with get_dist(tmpdir) as dist: assert dist.metadata.version == '2016.11.26' + def test_literal_version(self, tmpdir): + + _, config = fake_env( + tmpdir, + '[metadata]\n' + 'version = literal_attr: fake_package.VERSION\n' + ) + with get_dist(tmpdir) as dist: + assert dist.metadata.version == '1.2.3' + + config.write( + '[metadata]\n' + 'version = literal_attr: fake_package.VERSION_MAJOR\n' + ) + with get_dist(tmpdir) as dist: + assert dist.metadata.version == '1' + + subpack = tmpdir.join('fake_package').mkdir('subpackage') + subpack.join('__init__.py').write('') + subpack.join('submodule.py').write( + 'import third_party_module\n' + 'VERSION = (2016, 11, 26)' + ) + + config.write( + '[metadata]\n' + 'version = attr: fake_package.subpackage.submodule.VERSION\n' + ) + with get_dist(tmpdir) as dist: + assert dist.metadata.version == '2016.11.26' + def test_version_file(self, tmpdir): _, config = fake_env( @@ -332,6 +363,17 @@ class TestMetadata: with get_dist(tmpdir) as dist: assert dist.metadata.version == '1.2.3' + config.write( + '[metadata]\n' + 'version = literal_attr: fake_package_simple.VERSION\n' + '[options]\n' + 'package_dir =\n' + ' = src\n' + ) + + with get_dist(tmpdir) as dist: + assert dist.metadata.version == '1.2.3' + def test_version_with_package_dir_rename(self, tmpdir): _, config = fake_env( @@ -347,6 +389,17 @@ class TestMetadata: with get_dist(tmpdir) as dist: assert dist.metadata.version == '1.2.3' + config.write( + '[metadata]\n' + 'version = literal_attr: fake_package_rename.VERSION\n' + '[options]\n' + 'package_dir =\n' + ' fake_package_rename = fake_dir\n' + ) + + with get_dist(tmpdir) as dist: + assert dist.metadata.version == '1.2.3' + def test_version_with_package_dir_complex(self, tmpdir): _, config = fake_env( @@ -362,6 +415,17 @@ class TestMetadata: with get_dist(tmpdir) as dist: assert dist.metadata.version == '1.2.3' + config.write( + '[metadata]\n' + 'version = literal_attr: fake_package_complex.VERSION\n' + '[options]\n' + 'package_dir =\n' + ' fake_package_complex = src/fake_dir\n' + ) + + with get_dist(tmpdir) as dist: + assert dist.metadata.version == '1.2.3' + def test_unknown_meta_item(self, tmpdir): fake_env( |