Add %pyproject_buildrequires

This commit is contained in:
Miro Hrončok 2019-07-02 16:53:05 +02:00
parent d81f3dfe39
commit fdf511644e
6 changed files with 198 additions and 26 deletions

View File

@ -5,8 +5,6 @@ This is a provisional implementation of pyproject RPM macros for Fedora 30+.
These macros are useful for packaging Python projects that use the [PEP 517] `pyproject.toml` file, which specifies the package's build dependencies (including the build system, such as setuptools, flit or poetry).
[PEP 517]: https://www.python.org/dev/peps/pep-0517/
Usage
-----
@ -17,12 +15,20 @@ If your upstream sources include `pyproject.toml` and you want to use these macr
This will bring in python3-devel, so you don't need to require python3-devel explicitly.
Then, build a wheel in %build:
In order to get automatic build dependencies on Fedora 31+, run `%pyproject_buildrequires` in the `%generate_buildrequires` section:
%generate_buildrequires
%pyproject_buildrequires
Only build dependencies according to [PEP 517] and [PEP 518] will be added.
All other build dependencies (such as non-Python libraries or test dependencies) still need to be specified manually.
Then, build a wheel in `%build` with `%pyproject_wheel`:
%build
%pyproject_wheel
And install the wheel in %install:
And install the wheel in `%install` with `%pyproject_install`:
%install
%pyproject_install
@ -33,8 +39,12 @@ Limitations
`%pyproject_install` currently installs all wheels in `$PWD`. We are working on a more explicit solution.
This macro changes shebang lines of every Python script in `%{buildroot}%{_bindir}` to `#! %{__python3} %{py3_shbang_opt}` (`#! /usr/bin/python -s`).
We plan to preserve exisiting Python flags in shebangs, but the work is not yet finished.
This macro changes shebang lines of every Python script in `%{buildroot}%{_bindir}` to `#! %{__python3} %{py3_shbang_opt}` (`#! /usr/bin/python3 -s`).
We plan to preserve existing Python flags in shebangs, but the work is not yet finished.
Currently, the macros do not automatically generate BuildRequires. We are working on that as well.
The PEPs don't (yet) define a way to specify test dependencies and test runners.
That means you still need to handle test dependencies and `%check` on your own.
[PEP 517]: https://www.python.org/dev/peps/pep-0517/
[PEP 518]: https://www.python.org/dev/peps/pep-0518/

View File

@ -6,13 +6,23 @@
%pyproject_install() %{expand:\\\
%{__python3} -m pip install --root %{buildroot} --strip-file-prefix %{buildroot} --no-deps --disable-pip-version-check --progress-bar off --verbose --ignore-installed --no-warn-script-location ./*.whl
if [ -e %{buildroot}%{_bindir} ]; then
if [ -d %{buildroot}%{_bindir} ]; then
pathfix.py -pni "%{__python3} %{py3_shbang_opts}" %{buildroot}%{_bindir}/*
fi
if [ -e %{buildroot}%{python3_sitelib}]; then
sed -i -e 's/pip/rpm/g' %{buildroot}%{python3_sitelib}/*.dist-info/INSTALLER
if [ -d %{buildroot}%{python3_sitelib} ]; then
sed -i 's/pip/rpm/' %{buildroot}%{python3_sitelib}/*.dist-info/INSTALLER
fi
if [ -e %{buildroot}{python3_sitearch}]; then
sed -i -e 's/pip/rpm/g' %{buildroot}%{python3_sitearch}/*.dist-info/INSTALLER
if [ -d %{buildroot}%{python3_sitearch} ]; then
sed -i 's/pip/rpm/' %{buildroot}%{python3_sitearch}/*.dist-info/INSTALLER
fi
}
%pyproject_buildrequires() %{expand:\\\
echo 'python3-devel'
echo 'python3dist(packaging)'
echo 'python3dist(pip) >= 19'
echo 'python3dist(pytoml)'
if [ -f %{__python3} ]; then
%{__python3} -I %{_rpmconfigdir}/redhat/pyproject_buildrequires.py
fi
}

View File

@ -1,24 +1,35 @@
Name: pyproject-rpm-macros
Version: 0
Release: 2%{?dist}
License: MIT
Source0: macros.pyproject
Source1: README.md
Source2: LICENSE
URL: https://src.fedoraproject.org/rpms/pyproject-rpm-macros
BuildArch: noarch
Summary: RPM macros for PEP 517 Python packages
License: MIT
# Keep the version at zero and increment only release
Version: 0
Release: 3%{?dist}
Source0: macros.pyproject
Source1: pyproject_buildrequires.py
Source8: README.md
Source9: LICENSE
URL: https://src.fedoraproject.org/rpms/pyproject-rpm-macros
BuildArch: noarch
# We keep them here for now to avoid one loop of %%generate_buildrequires
# And to allow the other macros without %%pyproject_buildrequires (e.g. on Fedora 30)
# But those are also always in the output of %%generate_buildrequires
# in order to be removable in the future
Requires: python3-pip >= 19
Requires: python3-devel
%description
This is a provisional implementation of pyproject RPM macros for Fedora 30+.
These macros are useful for packaging Python projects that use the PEP 517
pyproject.toml file, which specifies the package's build dependencies
(including the build system, such as setuptools, flit or poetry).
%prep
# Not strictly necessary but allows working on file names instead
# of source numbers in install section
@ -29,16 +40,22 @@ cp -p %{sources} .
# nothing to do, sources are not buildable
%install
mkdir -p %{buildroot}/%{_rpmmacrodir}
install -m 644 macros.pyproject %{buildroot}/%{_rpmmacrodir}/
mkdir -p %{buildroot}%{_rpmmacrodir}
mkdir -p %{buildroot}%{_rpmconfigdir}/redhat
install -m 644 macros.pyproject %{buildroot}%{_rpmmacrodir}/
install -m 644 pyproject_buildrequires.py %{buildroot}%{_rpmconfigdir}/redhat/
%files
%{_rpmmacrodir}/macros.pyproject
%{_rpmconfigdir}/redhat/pyproject_buildrequires.py
%doc README.md
%license LICENSE
%changelog
* Tue Jul 02 2019 Miro Hrončok <mhroncok@redhat.com> - 0-3
- Add %%pyproject_buildrequires
* Tue Jul 02 2019 Miro Hrončok <mhroncok@redhat.com> - 0-2
- Fix shell syntax errors in %%pyproject_install
- Drop PATH warning in %%pyproject_install

View File

@ -0,0 +1,89 @@
import sys
try:
import pytoml
from packaging.requirements import Requirement, InvalidRequirement
from packaging.utils import canonicalize_name, canonicalize_version
except ImportError:
# already echoed by the %pyproject_buildrequires macro
sys.exit(0)
try:
with open("pyproject.toml") as f:
pyproject_data = pytoml.load(f)
except FileNotFoundError:
pyproject_data = {}
except Exception as e:
sys.exit(e)
else:
import importlib
try:
backend = importlib.import_module(
pyproject_data["build-system"]["build-backend"]
)
except KeyError:
try:
import setuptools.build_meta
except ImportError:
print("python3dist(setuptools) >= 40.8")
print("python3dist(wheel)")
sys.exit(0)
backend = setuptools.build_meta
except ImportError:
backend = None
requirements = set()
rpm_requirements = set()
def add_requirement(requirement):
try:
requirements.add(Requirement(requirement))
except InvalidRequirement as e:
print(
f"WARNING: Skipping invalid requirement: {requirement}\n {e}",
file=sys.stderr,
)
if "requires" in pyproject_data.get("build-system", {}):
try:
for requirement in pyproject_data["build-system"]["requires"]:
add_requirement(requirement)
except Exception as e:
sys.exit(e)
if hasattr(backend, "get_requires_for_build_wheel"):
try:
for requirement in backend.get_requires_for_build_wheel():
add_requirement(requirement)
except Exception as e:
sys.exit(e)
for requirement in requirements:
name = canonicalize_name(requirement.name)
if requirement.marker is not None and not requirement.marker.evaluate():
continue
together = []
for specifier in requirement.specifier:
version = canonicalize_version(specifier.version)
if specifier.operator == "!=":
together.append(
f"(python3dist({name}) < {version} or python3dist({name}) >= {version}.0)"
)
else:
together.append(f"python3dist({name}) {specifier.operator} {version}")
if len(together) == 0:
rpm_requirements.add(f"python3dist({name})")
if len(together) == 1:
rpm_requirements.add(together[0])
elif len(together) > 1:
rpm_requirements.add(f"({' and '.join(together)})")
print(*sorted(rpm_requirements), sep="\n")

View File

@ -0,0 +1,46 @@
%global pypi_name entrypoints
Name: python-%{pypi_name}
Version: 0.3
Release: 0%{?dist}
Summary: Discover and load entry points from installed packages
License: MIT
URL: https://entrypoints.readthedocs.io/
Source0: %{pypi_source}
BuildArch: noarch
BuildRequires: pyproject-rpm-macros
%description
Discover and load entry points from installed packages.
%package -n python3-%{pypi_name}
Summary: %{summary}
%{?python_provide:%python_provide python3-%{pypi_name}}
%description -n python3-%{pypi_name}
Discover and load entry points from installed packages.
%prep
%autosetup -p1 -n %{pypi_name}-%{version}
%generate_buildrequires
%pyproject_buildrequires
%build
%pyproject_wheel
%install
%pyproject_install
%files -n python3-%{pypi_name}
%doc README.rst
%license LICENSE
%{python3_sitelib}/entrypoints-*.dist-info/
%{python3_sitelib}/entrypoints.py
%{python3_sitelib}/__pycache__/entrypoints.*

View File

@ -1,6 +1,6 @@
%global pypi_name pytest
Name: python-%{pypi_name}
Version: 5.0.0
Version: 4.4.2
Release: 0%{?dist}
Summary: Simple powerful testing with Python
License: MIT