Skip to content

Use build rather than pep517 for building #2784

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 10 additions & 79 deletions pythonforandroid/pythonpackage.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,14 @@
import sys
import tarfile
import tempfile
import textwrap
import time
import zipfile
from io import open # needed for python 2
from urllib.parse import unquote as urlunquote
from urllib.parse import urlparse

import toml
from pep517.envbuild import BuildEnvironment
from pep517.wrappers import Pep517HookCaller
import build.util


def transform_dep_for_pip(dependency):
Expand Down Expand Up @@ -113,40 +111,7 @@ def extract_metainfo_files_from_package(
)
package = os.path.join(temp_folder, "package")

# Because PEP517 can be noisy and contextlib.redirect_* fails to
# contain it, we will run the actual analysis in a separate process:
try:
subprocess.check_output([
sys.executable,
"-c",
"import importlib\n"
"import json\n"
"import os\n"
"import sys\n"
"sys.path = [os.path.dirname(sys.argv[3])] + sys.path\n"
"m = importlib.import_module(\n"
" os.path.basename(sys.argv[3]).partition('.')[0]\n"
")\n"
"m._extract_metainfo_files_from_package_unsafe("
" sys.argv[1],"
" sys.argv[2],"
")",
package, output_folder, os.path.abspath(__file__)],
stderr=subprocess.STDOUT, # make sure stderr is muted.
cwd=os.path.join(os.path.dirname(__file__), "..")
)
except subprocess.CalledProcessError as e:
output = e.output.decode("utf-8", "replace")
if debug:
print("Got error obtaining meta info.")
print("Detail output:")
print(output)
print("End of Detail output.")
raise ValueError(
"failed to obtain meta info - "
"is '{}' a valid package? "
"Detailed output:\n{}".format(package, output)
)
_extract_metainfo_files_from_package_unsafe(package, output_folder)
finally:
shutil.rmtree(temp_folder)

Expand Down Expand Up @@ -461,51 +426,17 @@ def _extract_metainfo_files_from_package_unsafe(
clean_up_path = True

try:
build_requires = []
metadata_path = None

if path_type != "wheel":
# We need to process this first to get the metadata.

# Ensure pyproject.toml is available (pep517 expects it)
if not os.path.exists(os.path.join(path, "pyproject.toml")):
with open(os.path.join(path, "pyproject.toml"), "w") as f:
f.write(textwrap.dedent(u"""\
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
"""))

# Copy the pyproject.toml:
shutil.copyfile(
os.path.join(path, 'pyproject.toml'),
os.path.join(output_path, 'pyproject.toml')
)

# Get build backend and requirements from pyproject.toml:
with open(os.path.join(path, 'pyproject.toml')) as f:
build_sys = toml.load(f)['build-system']
backend = build_sys["build-backend"]
build_requires.extend(build_sys["requires"])

# Get a virtualenv with build requirements and get all metadata:
env = BuildEnvironment()
metadata = None
with env:
hooks = Pep517HookCaller(path, backend)
env.pip_install(
[transform_dep_for_pip(req) for req in build_requires]
)
reqs = hooks.get_requires_for_build_wheel({})
env.pip_install([transform_dep_for_pip(req) for req in reqs])
try:
metadata = hooks.prepare_metadata_for_build_wheel(path)
except Exception: # sadly, pep517 has no good error here
pass
if metadata is not None:
metadata_path = os.path.join(
path, metadata, "METADATA"
)
# Use a build helper function to fetch the metadata directly
metadata = build.util.project_wheel_metadata(path)
# And write it to a file
metadata_path = os.path.join(output_path, "built_metadata")
with open(metadata_path, 'w') as f:
for key in metadata.keys():
for value in metadata.get_all(key):
f.write("{}: {}\n".format(key, value))
else:
# This is a wheel, so metadata should be in *.dist-info folder:
metadata_path = os.path.join(
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
install_reqs = [
'appdirs', 'colorama>=0.3.3', 'jinja2',
'sh>=1.10, <2.0; sys_platform!="nt"',
'pep517', 'toml', 'packaging',
'build', 'toml', 'packaging',
]
# (pep517 and toml are used by pythonpackage.py)
# (build and toml are used by pythonpackage.py)


# By specifying every file manually, package_data will be able to
Expand Down
2 changes: 1 addition & 1 deletion tests/test_pythonpackage.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def test_get_package_dependencies():
if "MarkupSafe" in dep
]
# Check setuptools not being in non-recursive deps:
# (It will be in recursive ones due to p4a's pep517 dependency)
# (It will be in recursive ones due to p4a's build dependency)
assert "setuptools" not in deps_nonrecursive
# Check setuptools is present in non-recursive deps,
# if we also add build requirements:
Expand Down
13 changes: 5 additions & 8 deletions tests/test_pythonpackage_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def run__get_system_python_executable(self, pybin):
pybin,
"-c",
"import importlib\n"
"import json\n"
"import build.util\n"
"import os\n"
"import sys\n"
"sys.path = [os.path.dirname(sys.argv[1])] + sys.path\n"
Expand Down Expand Up @@ -273,8 +273,8 @@ def test_systemwide_python(self):
# Some deps may not be installed, so we just avoid to raise
# an exception here, as a missing dep should not make the test
# fail.
if "pep517" in str(e.args):
# System python probably doesn't have pep517 available!
if "build" in str(e.args):
# System python probably doesn't have build available!
pass
elif "toml" in str(e.args):
# System python probably doesn't have toml available!
Expand Down Expand Up @@ -304,11 +304,8 @@ def test_venv(self):
])
subprocess.check_output([
os.path.join(test_dir, "venv", "bin", "pip"),
"install", "-U", "pep517"
])
subprocess.check_output([
os.path.join(test_dir, "venv", "bin", "pip"),
"install", "-U", "toml"
"install", "-U", "build", "toml", "sh<2.0", "colorama",
"appdirs", "jinja2", "packaging"
])
sys_python_path = self.run__get_system_python_executable(
os.path.join(test_dir, "venv", "bin", "python")
Expand Down