forked from ports/contrib
437 lines
11 KiB
Diff
437 lines
11 KiB
Diff
From 5bfaee154cd713252adae4b12e7a6ec83c7ae6c0 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= <mgorny@gentoo.org>
|
|
Date: Mon, 17 May 2021 19:29:48 +0200
|
|
Subject: [PATCH] Add support for PEP 621 metadata in flit
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Closes: https://github.com/mgorny/pyproject2setuppy/issues/16
|
|
Signed-off-by: Michał Górny <mgorny@gentoo.org>
|
|
---
|
|
pyproject2setuppy/flit.py | 83 +++++++----
|
|
tests/test_flit_pep621.py | 305 ++++++++++++++++++++++++++++++++++++++
|
|
2 files changed, 356 insertions(+), 32 deletions(-)
|
|
create mode 100644 tests/test_flit_pep621.py
|
|
|
|
diff --git a/pyproject2setuppy/flit.py b/pyproject2setuppy/flit.py
|
|
index 72418fd..08e0fff 100644
|
|
--- a/pyproject2setuppy/flit.py
|
|
+++ b/pyproject2setuppy/flit.py
|
|
@@ -1,6 +1,6 @@
|
|
# pyproject2setup.py -- flit support
|
|
# vim:se fileencoding=utf-8 :
|
|
-# (c) 2019-2020 Michał Górny
|
|
+# (c) 2019-2021 Michał Górny
|
|
# 2-clause BSD license
|
|
|
|
from __future__ import absolute_import
|
|
@@ -13,6 +13,7 @@
|
|
import sys
|
|
|
|
from pyproject2setuppy.common import auto_find_packages
|
|
+from pyproject2setuppy.pep621 import get_pep621_metadata
|
|
|
|
|
|
def handle_flit(data):
|
|
@@ -21,39 +22,57 @@ def handle_flit(data):
|
|
system.
|
|
"""
|
|
|
|
- topdata = data['tool']['flit']
|
|
- metadata = topdata['metadata']
|
|
- modname = metadata['module']
|
|
- sys.path.insert(0, '.')
|
|
- mod = importlib.import_module(modname, '')
|
|
-
|
|
- entry_points = defaultdict(list)
|
|
- if 'scripts' in topdata:
|
|
- for name, content in topdata['scripts'].items():
|
|
- entry_points['console_scripts'].append(
|
|
- '{} = {}'.format(name, content)
|
|
- )
|
|
-
|
|
- if 'entrypoints' in topdata:
|
|
- for group_name, group_content in topdata['entrypoints'].items():
|
|
- for name, path in group_content.items():
|
|
- entry_points[group_name].append(
|
|
- '{} = {}'.format(name, path)
|
|
+ # try PEP 621 first
|
|
+ setup_metadata = get_pep621_metadata(data, ['version', 'description'])
|
|
+ if setup_metadata is not None:
|
|
+ if 'flit' in data.get('tool', {}):
|
|
+ raise ValueError('[project] and [tool.flit] cannot be present '
|
|
+ 'simultaneously')
|
|
+ else:
|
|
+ # tool.flit fallback
|
|
+ topdata = data['tool']['flit']
|
|
+ metadata = topdata['metadata']
|
|
+
|
|
+ entry_points = defaultdict(list)
|
|
+ if 'scripts' in topdata:
|
|
+ for name, content in topdata['scripts'].items():
|
|
+ entry_points['console_scripts'].append(
|
|
+ '{} = {}'.format(name, content)
|
|
)
|
|
|
|
- package_args = auto_find_packages(modname)
|
|
-
|
|
- setup(name=modname,
|
|
- version=mod.__version__,
|
|
- description=mod.__doc__.strip(),
|
|
- author=metadata['author'],
|
|
- author_email=metadata['author-email'],
|
|
- url=metadata.get('home-page'),
|
|
- classifiers=metadata.get('classifiers', []),
|
|
- entry_points=dict(entry_points),
|
|
- # hack stolen from flit
|
|
- package_data={'': ['*']},
|
|
- **package_args)
|
|
+ if 'entrypoints' in topdata:
|
|
+ for group_name, group_content in topdata['entrypoints'].items():
|
|
+ for name, path in group_content.items():
|
|
+ entry_points[group_name].append(
|
|
+ '{} = {}'.format(name, path)
|
|
+ )
|
|
+
|
|
+ setup_metadata = {
|
|
+ 'name': metadata['module'],
|
|
+ # use None to match PEP 621 return value for dynamic
|
|
+ 'version': None,
|
|
+ 'description': None,
|
|
+ 'author': metadata['author'],
|
|
+ 'author_email': metadata['author-email'],
|
|
+ 'url': metadata.get('home-page'),
|
|
+ 'classifiers': metadata.get('classifiers', []),
|
|
+ 'entry_points': dict(entry_points),
|
|
+ }
|
|
+
|
|
+ # handle dynamic metadata if necessary
|
|
+ modname = setup_metadata['name']
|
|
+ if None in [setup_metadata[x] for x in ('version', 'description')]:
|
|
+ sys.path.insert(0, '.')
|
|
+ mod = importlib.import_module(modname, '')
|
|
+ if setup_metadata['version'] is None:
|
|
+ setup_metadata['version'] = mod.__version__
|
|
+ if setup_metadata['description'] is None:
|
|
+ setup_metadata['description'] = mod.__doc__.strip()
|
|
+
|
|
+ setup_metadata.update(auto_find_packages(modname))
|
|
+
|
|
+ setup(package_data={'': ['*']}, # hack stolen from flit
|
|
+ **setup_metadata)
|
|
|
|
|
|
def handle_flit_thyself(data):
|
|
diff --git a/tests/test_flit_pep621.py b/tests/test_flit_pep621.py
|
|
new file mode 100644
|
|
index 0000000..ad3852e
|
|
--- /dev/null
|
|
+++ b/tests/test_flit_pep621.py
|
|
@@ -0,0 +1,305 @@
|
|
+# vim:se fileencoding=utf-8 :
|
|
+# (c) 2019-2021 Michał Górny
|
|
+# 2-clause BSD license
|
|
+
|
|
+import unittest
|
|
+
|
|
+from pyproject2setuppy.flit import handle_flit, handle_flit_thyself
|
|
+
|
|
+from tests.base import BuildSystemTestCase
|
|
+
|
|
+
|
|
+class FlitTestCase(BuildSystemTestCase):
|
|
+ """
|
|
+ Tests for the flit build system.
|
|
+ """
|
|
+
|
|
+ toml_base = '''
|
|
+[build-system]
|
|
+requires = ["flit"]
|
|
+build-backend = "flit.buildapi"
|
|
+
|
|
+[project]
|
|
+name = "test_module"
|
|
+authors = [
|
|
+ {name="Some Guy", email="guy@example.com"},
|
|
+]
|
|
+dynamic = ["version", "description"]
|
|
+'''
|
|
+
|
|
+ expected_base = {
|
|
+ 'name': 'test_module',
|
|
+ 'version': '0',
|
|
+ 'description': 'documentation.',
|
|
+ 'author': 'Some Guy',
|
|
+ 'author_email': 'guy@example.com',
|
|
+ 'classifiers': [],
|
|
+ 'entry_points': {},
|
|
+ 'package_data': {'': ['*']},
|
|
+ }
|
|
+
|
|
+ package_files = ['test_module.py']
|
|
+
|
|
+ handler = staticmethod(handle_flit)
|
|
+
|
|
+ def make_package(self):
|
|
+ """
|
|
+ Make a flit-compatible packags. Adds docstring and version
|
|
+ to the first .py file in package_files.
|
|
+ """
|
|
+
|
|
+ d = super(FlitTestCase, self).make_package()
|
|
+ with open(self.package_files[0], 'w') as f:
|
|
+ f.write('''
|
|
+""" documentation. """
|
|
+__version__ = '0'
|
|
+''')
|
|
+ return d
|
|
+
|
|
+
|
|
+class FlitBasicTest(unittest.TestCase, FlitTestCase):
|
|
+ """
|
|
+ Test handling a simple flit package.
|
|
+ """
|
|
+
|
|
+ expected_extra = {
|
|
+ 'py_modules': ['test_module'],
|
|
+ }
|
|
+
|
|
+
|
|
+class FlitVersionTest(unittest.TestCase, FlitTestCase):
|
|
+ """
|
|
+ Test handling a package with non-dynamic version.
|
|
+ """
|
|
+
|
|
+ toml_base = '''
|
|
+[build-system]
|
|
+requires = ["flit"]
|
|
+build-backend = "flit.buildapi"
|
|
+
|
|
+[project]
|
|
+name = "test_module"
|
|
+version = "0"
|
|
+authors = [
|
|
+ {name="Some Guy", email="guy@example.com"},
|
|
+]
|
|
+dynamic = ["description"]
|
|
+'''
|
|
+
|
|
+ expected_extra = {
|
|
+ 'py_modules': ['test_module'],
|
|
+ }
|
|
+
|
|
+
|
|
+class FlitDescriptionTest(unittest.TestCase, FlitTestCase):
|
|
+ """
|
|
+ Test handling a package with non-dynamic description.
|
|
+ """
|
|
+
|
|
+ toml_base = '''
|
|
+[build-system]
|
|
+requires = ["flit"]
|
|
+build-backend = "flit.buildapi"
|
|
+
|
|
+[project]
|
|
+name = "test_module"
|
|
+description = "documentation."
|
|
+authors = [
|
|
+ {name="Some Guy", email="guy@example.com"},
|
|
+]
|
|
+dynamic = ["version"]
|
|
+'''
|
|
+
|
|
+ expected_extra = {
|
|
+ 'py_modules': ['test_module'],
|
|
+ }
|
|
+
|
|
+
|
|
+class FlitVersionDescriptionTest(unittest.TestCase, FlitTestCase):
|
|
+ """
|
|
+ Test handling a package with non-dynamic version and description.
|
|
+ """
|
|
+
|
|
+ toml_base = '''
|
|
+[build-system]
|
|
+requires = ["flit"]
|
|
+build-backend = "flit.buildapi"
|
|
+
|
|
+[project]
|
|
+name = "test_module"
|
|
+version = "0"
|
|
+description = "documentation."
|
|
+authors = [
|
|
+ {name="Some Guy", email="guy@example.com"},
|
|
+]
|
|
+'''
|
|
+
|
|
+ expected_extra = {
|
|
+ 'py_modules': ['test_module'],
|
|
+ }
|
|
+
|
|
+
|
|
+class FlitClassifiersTest(unittest.TestCase, FlitTestCase):
|
|
+ """
|
|
+ Test handling a flit package with trove classifiers.
|
|
+ """
|
|
+
|
|
+ toml_extra = '''
|
|
+classifiers = [
|
|
+ "License :: OSI Approved :: MIT License",
|
|
+ "Programming Language :: Python :: 2",
|
|
+ "Programming Language :: Python :: 3"
|
|
+]
|
|
+'''
|
|
+
|
|
+ expected_extra = {
|
|
+ 'py_modules': ['test_module'],
|
|
+ 'classifiers': [
|
|
+ "License :: OSI Approved :: MIT License",
|
|
+ "Programming Language :: Python :: 2",
|
|
+ "Programming Language :: Python :: 3"
|
|
+ ],
|
|
+ }
|
|
+
|
|
+
|
|
+class FlitPackageTest(unittest.TestCase, FlitTestCase):
|
|
+ """
|
|
+ Test handling a flit package containing a package instead of module.
|
|
+ """
|
|
+
|
|
+ package_files = ['test_module/__init__.py']
|
|
+
|
|
+ expected_extra = {
|
|
+ 'packages': ['test_module']
|
|
+ }
|
|
+
|
|
+
|
|
+class FlitExtraFilesTest(unittest.TestCase, FlitTestCase):
|
|
+ """
|
|
+ Test handling a flit package with non-python files.
|
|
+ """
|
|
+
|
|
+ package_files = ['test_module/__init__.py',
|
|
+ 'test_module/VERSION']
|
|
+
|
|
+ expected_extra = {
|
|
+ 'packages': ['test_module'],
|
|
+ }
|
|
+ expected_extra_files = [
|
|
+ 'test_module/VERSION',
|
|
+ ]
|
|
+
|
|
+
|
|
+class FlitNestedPackageTest(unittest.TestCase, FlitTestCase):
|
|
+ """
|
|
+ Test handling a flit package containing nested packages.
|
|
+ """
|
|
+
|
|
+ package_files = [
|
|
+ 'test_module/__init__.py',
|
|
+ 'test_module/sub_module/__init__.py',
|
|
+ 'test_module/sub_module/subsub/__init__.py',
|
|
+ ]
|
|
+
|
|
+ expected_extra = {
|
|
+ 'packages': [
|
|
+ 'test_module',
|
|
+ 'test_module.sub_module',
|
|
+ 'test_module.sub_module.subsub',
|
|
+ ]
|
|
+ }
|
|
+
|
|
+
|
|
+class FlitCoreTest(FlitTestCase):
|
|
+ """Test for using flit_core backend"""
|
|
+
|
|
+ toml_base = '''
|
|
+[build-system]
|
|
+requires = ["flit_core"]
|
|
+build-backend = "flit_core.buildapi"
|
|
+
|
|
+[project]
|
|
+name = "test_module"
|
|
+authors = [
|
|
+ {name="Some Guy", email="guy@example.com"},
|
|
+]
|
|
+dynamic = ["version", "description"]
|
|
+'''
|
|
+
|
|
+
|
|
+class FlitScriptsTest(unittest.TestCase, FlitTestCase):
|
|
+ """Test handling scripts"""
|
|
+
|
|
+ toml_extra = '''
|
|
+[project.scripts]
|
|
+test-tool = "testlib:main"
|
|
+'''
|
|
+
|
|
+ expected_extra = {
|
|
+ 'entry_points': {
|
|
+ 'console_scripts': [
|
|
+ 'test-tool = testlib:main',
|
|
+ ]
|
|
+ },
|
|
+ 'py_modules': ['test_module'],
|
|
+ }
|
|
+
|
|
+
|
|
+class FlitGUIScriptsTest(unittest.TestCase, FlitTestCase):
|
|
+ """Test handling scripts"""
|
|
+
|
|
+ toml_extra = '''
|
|
+[project.gui-scripts]
|
|
+test-tool = "testlib:main"
|
|
+'''
|
|
+
|
|
+ expected_extra = {
|
|
+ 'entry_points': {
|
|
+ 'gui_scripts': [
|
|
+ 'test-tool = testlib:main',
|
|
+ ]
|
|
+ },
|
|
+ 'py_modules': ['test_module'],
|
|
+ }
|
|
+
|
|
+
|
|
+class FlitEntryPointsTest(unittest.TestCase, FlitTestCase):
|
|
+ """Test handling entry points"""
|
|
+
|
|
+ toml_extra = '''
|
|
+[project.entrypoints."blogtool.parsers"]
|
|
+".rst" = "some_module:SomeClass"
|
|
+'''
|
|
+
|
|
+ expected_extra = {
|
|
+ 'entry_points': {
|
|
+ 'blogtool.parsers': [
|
|
+ '.rst = some_module:SomeClass',
|
|
+ ]
|
|
+ },
|
|
+ 'py_modules': ['test_module'],
|
|
+ }
|
|
+
|
|
+
|
|
+class FlitPluginsAndScriptsTest(unittest.TestCase, FlitTestCase):
|
|
+ """Test handling plugins and scripts"""
|
|
+
|
|
+ toml_extra = '''
|
|
+[project.scripts]
|
|
+test-tool = "testlib:main"
|
|
+
|
|
+[project.entrypoints."blogtool.parsers"]
|
|
+".rst" = "some_module:SomeClass"
|
|
+'''
|
|
+
|
|
+ expected_extra = {
|
|
+ 'entry_points': {
|
|
+ 'console_scripts': [
|
|
+ 'test-tool = testlib:main',
|
|
+ ],
|
|
+ 'blogtool.parsers': [
|
|
+ '.rst = some_module:SomeClass',
|
|
+ ]
|
|
+ },
|
|
+ 'py_modules': ['test_module'],
|
|
+ }
|