From 29a12eb86aee706082f344a25d2e563984b9aa1a Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Sat, 12 Feb 2022 04:34:06 -0700 Subject: [PATCH] package/python-flit-core: new package/infrastructure This adds pep517(needed for flit-core to build itself) and flit python package types. We need to add an installer script and pass it appropriate options for installing pep517 wheels generated by python-pypa-build during the build stage. Unfortunately it seems pep517 does not support builds without using the wheel format. We also need to add a patch fixing the version parser in flit-core. Signed-off-by: James Hilliard [Arnout: - fix indentation in pkg-python.mk (tabs, not spaces); - use the new _CMD variables instead of duplicating the entire _CMDS definitions; - no need to filter dependencies (they're not self-referencing); - _NEEDS_HOST_PYTHON no longer exists; - host-python-pypa-build gets added to DEPENDENCIES automatically. ] Signed-off-by: Arnout Vandecappelle (Essensium/Mind) --- package/pkg-python.mk | 59 +++++++++++++- ...sion-parser-for-multiple-assignments.patch | 80 +++++++++++++++++++ .../python-flit-core/python-flit-core.hash | 3 + package/python-flit-core/python-flit-core.mk | 13 +++ support/scripts/pyinstaller.py | 69 ++++++++++++++++ 5 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 package/python-flit-core/0001-Fix-ast-version-parser-for-multiple-assignments.patch create mode 100644 package/python-flit-core/python-flit-core.hash create mode 100644 package/python-flit-core/python-flit-core.mk create mode 100755 support/scripts/pyinstaller.py diff --git a/package/pkg-python.mk b/package/pkg-python.mk index 61f0dd6ec2..0c5577362f 100644 --- a/package/pkg-python.mk +++ b/package/pkg-python.mk @@ -103,6 +103,47 @@ HOST_PKG_PYTHON_SETUPTOOLS_INSTALL_OPTS = \ --root=/ \ --single-version-externally-managed +# Target pep517-based packages +PKG_PYTHON_PEP517_ENV = \ + _PYTHON_SYSCONFIGDATA_NAME="$(PKG_PYTHON_SYSCONFIGDATA_NAME)" \ + PATH=$(BR_PATH) \ + $(TARGET_CONFIGURE_OPTS) \ + PYTHONPATH="$(PYTHON3_PATH)" \ + PYTHONNOUSERSITE=1 \ + _python_sysroot=$(STAGING_DIR) \ + _python_prefix=/usr \ + _python_exec_prefix=/usr + +PKG_PYTHON_PEP517_INSTALL_TARGET_OPTS = \ + --interpreter=/usr/bin/python \ + --script-kind=posix \ + --purelib=$(TARGET_DIR)/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages \ + --headers=$(TARGET_DIR)/usr/include/python$(PYTHON3_VERSION_MAJOR) \ + --scripts=$(TARGET_DIR)/usr/bin \ + --data=$(TARGET_DIR)/usr + +PKG_PYTHON_PEP517_INSTALL_STAGING_OPTS = \ + --interpreter=/usr/bin/python \ + --script-kind=posix \ + --purelib=$(STAGING_DIR)/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages \ + --headers=$(STAGING_DIR)/usr/include/python$(PYTHON3_VERSION_MAJOR) \ + --scripts=$(STAGING_DIR)/usr/bin \ + --data=$(STAGING_DIR)/usr + +# Host pep517-based packages +HOST_PKG_PYTHON_PEP517_ENV = \ + PATH=$(BR_PATH) \ + PYTHONNOUSERSITE=1 \ + $(HOST_CONFIGURE_OPTS) + +HOST_PKG_PYTHON_PEP517_INSTALL_OPTS = \ + --interpreter=/usr/bin/python \ + --script-kind=posix \ + --purelib=$(HOST_DIR)/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages \ + --headers=$(HOST_DIR)/usr/include/python$(PYTHON3_VERSION_MAJOR) \ + --scripts=$(HOST_DIR)/usr/bin \ + --data=$(HOST_DIR)/usr + ################################################################################ # inner-python-package -- defines how the configuration, compilation # and installation of a Python package should be done, implements a @@ -152,8 +193,19 @@ $(2)_BASE_ENV = $$(HOST_PKG_PYTHON_SETUPTOOLS_ENV) $(2)_BASE_BUILD_CMD = setup.py build $(2)_BASE_INSTALL_CMD = setup.py install $$(HOST_PKG_PYTHON_SETUPTOOLS_INSTALL_OPTS) endif +else ifneq ($$(filter flit pep517,$$($(2)_SETUP_TYPE)),) +ifeq ($(4),target) +$(2)_BASE_ENV = $$(PKG_PYTHON_PEP517_ENV) +$(2)_BASE_BUILD_CMD = -m build -n -w +$(2)_BASE_INSTALL_TARGET_CMD = $(TOPDIR)/support/scripts/pyinstaller.py dist/* $$(PKG_PYTHON_PEP517_INSTALL_TARGET_OPTS) +$(2)_BASE_INSTALL_STAGING_CMD = $(TOPDIR)/support/scripts/pyinstaller.py dist/* $$(PKG_PYTHON_PEP517_INSTALL_STAGING_OPTS) else -$$(error "Invalid $(2)_SETUP_TYPE. Valid options are 'distutils' or 'setuptools'") +$(2)_BASE_ENV = $$(HOST_PKG_PYTHON_PEP517_ENV) +$(2)_BASE_BUILD_CMD = -m build -n -w +$(2)_BASE_INSTALL_CMD = $(TOPDIR)/support/scripts/pyinstaller.py dist/* $$(HOST_PKG_PYTHON_PEP517_INSTALL_OPTS) +endif +else +$$(error "Invalid $(2)_SETUP_TYPE. Valid options are 'distutils', 'setuptools', 'pep517' or 'flit'.") endif # Target packages need both the python interpreter on the target (for @@ -172,6 +224,11 @@ endif # ($(4),target) # ifeq ($$($(2)_SETUP_TYPE),setuptools) $(2)_DEPENDENCIES += $$(if $$(filter host-python-setuptools,$(1)),,host-python-setuptools) +else ifneq ($$(filter flit pep517,$$($(2)_SETUP_TYPE)),) +$(2)_DEPENDENCIES += host-python-pypa-build host-python-installer +ifeq ($$($(2)_SETUP_TYPE),flit) +$(2)_DEPENDENCIES += host-python-flit-core +endif endif # SETUP_TYPE # Python interpreter to use for building the package. diff --git a/package/python-flit-core/0001-Fix-ast-version-parser-for-multiple-assignments.patch b/package/python-flit-core/0001-Fix-ast-version-parser-for-multiple-assignments.patch new file mode 100644 index 0000000000..5a94e1dcab --- /dev/null +++ b/package/python-flit-core/0001-Fix-ast-version-parser-for-multiple-assignments.patch @@ -0,0 +1,80 @@ +From 2cd8b5708be88b90ea2fa0fb35407a5ec2038c8e Mon Sep 17 00:00:00 2001 +From: James Hilliard +Date: Sat, 27 Nov 2021 02:36:15 -0700 +Subject: [PATCH] Fix ast version parser for multiple assignments + +Signed-off-by: James Hilliard +[Upstream status: +https://github.com/takluyver/flit/pull/474] +--- + flit_core/common.py | 21 +++++++++++-------- + .../tests/samples/moduleunimportabledouble.py | 8 +++++++ + flit_core/tests/test_common.py | 5 +++++ + 3 files changed, 25 insertions(+), 9 deletions(-) + create mode 100644 flit_core/tests/samples/moduleunimportabledouble.py + +diff --git a/flit_core/common.py b/flit_core/common.py +index f1f378f..86bcf4b 100644 +--- a/flit_core/common.py ++++ b/flit_core/common.py +@@ -132,15 +132,18 @@ def get_docstring_and_version_via_ast(target): + for child in node.body: + # Only use the version from the given module if it's a simple + # string assignment to __version__ +- is_version_str = ( +- isinstance(child, ast.Assign) +- and len(child.targets) == 1 +- and isinstance(child.targets[0], ast.Name) +- and child.targets[0].id == "__version__" +- and isinstance(child.value, ast.Str) +- ) +- if is_version_str: +- version = child.value.s ++ if isinstance(child, ast.Assign): ++ for target in child.targets: ++ is_version_str = ( ++ isinstance(target, ast.Name) ++ and target.id == "__version__" ++ and isinstance(child.value, ast.Str) ++ ) ++ if is_version_str: ++ version = child.value.s ++ break ++ else: ++ continue + break + else: + version = None +diff --git a/flit_core/tests/samples/moduleunimportabledouble.py b/flit_core/tests/samples/moduleunimportabledouble.py +new file mode 100644 +index 0000000..42d51f3 +--- /dev/null ++++ b/flit_core/tests/samples/moduleunimportabledouble.py +@@ -0,0 +1,8 @@ ++ ++""" ++A sample unimportable module with double assignment ++""" ++ ++raise ImportError() ++ ++VERSION = __version__ = "0.1" +diff --git a/flit_core/tests/test_common.py b/flit_core/tests/test_common.py +index 02cfab7..42e230b 100644 +--- a/flit_core/tests/test_common.py ++++ b/flit_core/tests/test_common.py +@@ -70,6 +70,11 @@ class ModuleTests(TestCase): + 'version': '0.1'} + ) + ++ info = get_info_from_module(Module('moduleunimportabledouble', samples_dir)) ++ self.assertEqual(info, {'summary': 'A sample unimportable module with double assignment', ++ 'version': '0.1'} ++ ) ++ + info = get_info_from_module(Module('module1', samples_dir / 'constructed_version')) + self.assertEqual(info, {'summary': 'This module has a __version__ that requires runtime interpretation', + 'version': '1.2.3'} +-- +2.33.1 + diff --git a/package/python-flit-core/python-flit-core.hash b/package/python-flit-core/python-flit-core.hash new file mode 100644 index 0000000000..bd47fd4f6b --- /dev/null +++ b/package/python-flit-core/python-flit-core.hash @@ -0,0 +1,3 @@ +# md5, sha256 from https://pypi.org/pypi/flit_core/json +md5 82143536b81f148851a0213305838e53 flit_core-3.6.0.tar.gz +sha256 5892962ab8b8ea945835b3a288fe9dd69316f1903d5288c3f5cafdcdd04756ad flit_core-3.6.0.tar.gz diff --git a/package/python-flit-core/python-flit-core.mk b/package/python-flit-core/python-flit-core.mk new file mode 100644 index 0000000000..8971223d1f --- /dev/null +++ b/package/python-flit-core/python-flit-core.mk @@ -0,0 +1,13 @@ +################################################################################ +# +# python-flit-core +# +################################################################################ + +PYTHON_FLIT_CORE_VERSION = 3.6.0 +PYTHON_FLIT_CORE_SOURCE = flit_core-$(PYTHON_FLIT_CORE_VERSION).tar.gz +PYTHON_FLIT_CORE_SITE = https://files.pythonhosted.org/packages/08/e9/0653f7783ba2ec2f954f19442878427f1d5bfccb01842d354453c2809b22 +PYTHON_FLIT_CORE_LICENSE = BSD-3-Clause +PYTHON_FLIT_CORE_SETUP_TYPE = pep517 + +$(eval $(host-python-package)) diff --git a/support/scripts/pyinstaller.py b/support/scripts/pyinstaller.py new file mode 100755 index 0000000000..6dd9242327 --- /dev/null +++ b/support/scripts/pyinstaller.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 + +import argparse +import glob + +from installer import install +from installer.destinations import SchemeDictionaryDestination +from installer.sources import WheelFile + + +def main(): + """Entry point for CLI.""" + ap = argparse.ArgumentParser("python pyinstaller.py") + ap.add_argument("wheel_file", help="Path to a .whl file to install") + + ap.add_argument( + "--interpreter", required=True, help="Interpreter path to be used in scripts" + ) + ap.add_argument( + "--script-kind", + required=True, + choices=["posix", "win-ia32", "win-amd64", "win-arm", "win-arm64"], + help="Kind of launcher to create for each script", + ) + + dest_args = ap.add_argument_group("Destination directories") + dest_args.add_argument( + "--purelib", + required=True, + help="Directory for platform-independent Python modules", + ) + dest_args.add_argument( + "--platlib", + help="Directory for platform-dependent Python modules (same as purelib " + "if not specified)", + ) + dest_args.add_argument( + "--headers", required=True, help="Directory for C header files" + ) + dest_args.add_argument( + "--scripts", required=True, help="Directory for executable scripts" + ) + dest_args.add_argument( + "--data", required=True, help="Directory for external data files" + ) + args = ap.parse_args() + + destination = SchemeDictionaryDestination( + { + "purelib": args.purelib, + "platlib": args.platlib if args.platlib is not None else args.purelib, + "headers": args.headers, + "scripts": args.scripts, + "data": args.data, + }, + interpreter=args.interpreter, + script_kind=args.script_kind, + ) + + with WheelFile.open(glob.glob(args.wheel_file)[0]) as source: + install( + source=source, + destination=destination, + additional_metadata={}, + ) + + +if __name__ == "__main__": + main()