Add %pyproject_buildrequires
This commit is contained in:
parent
d81f3dfe39
commit
fdf511644e
24
README.md
24
README.md
@ -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).
|
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
|
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.
|
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
|
%build
|
||||||
%pyproject_wheel
|
%pyproject_wheel
|
||||||
|
|
||||||
And install the wheel in %install:
|
And install the wheel in `%install` with `%pyproject_install`:
|
||||||
|
|
||||||
%install
|
%install
|
||||||
%pyproject_install
|
%pyproject_install
|
||||||
@ -33,8 +39,12 @@ Limitations
|
|||||||
|
|
||||||
`%pyproject_install` currently installs all wheels in `$PWD`. We are working on a more explicit solution.
|
`%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`).
|
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 exisiting Python flags in shebangs, but the work is not yet finished.
|
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/
|
||||||
|
@ -1,18 +1,28 @@
|
|||||||
%pyproject_wheel() %{expand:\\\
|
%pyproject_wheel() %{expand:\\\
|
||||||
CFLAGS="${CFLAGS:-${RPM_OPT_FLAGS}}" LDFLAGS="${LDFLAGS:-${RPM_LD_FLAGS}}" \\\
|
CFLAGS="${CFLAGS:-${RPM_OPT_FLAGS}}" LDFLAGS="${LDFLAGS:-${RPM_LD_FLAGS}}" \\\
|
||||||
%{__python3} -m pip wheel --no-deps --use-pep517 --no-build-isolation --disable-pip-version-check --progress-bar off --verbose .
|
%{__python3} -m pip wheel --no-deps --use-pep517 --no-build-isolation --disable-pip-version-check --progress-bar off --verbose .
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
%pyproject_install() %{expand:\\\
|
%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
|
%{__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}/*
|
pathfix.py -pni "%{__python3} %{py3_shbang_opts}" %{buildroot}%{_bindir}/*
|
||||||
fi
|
fi
|
||||||
if [ -e %{buildroot}%{python3_sitelib}]; then
|
if [ -d %{buildroot}%{python3_sitelib} ]; then
|
||||||
sed -i -e 's/pip/rpm/g' %{buildroot}%{python3_sitelib}/*.dist-info/INSTALLER
|
sed -i 's/pip/rpm/' %{buildroot}%{python3_sitelib}/*.dist-info/INSTALLER
|
||||||
fi
|
fi
|
||||||
if [ -e %{buildroot}{python3_sitearch}]; then
|
if [ -d %{buildroot}%{python3_sitearch} ]; then
|
||||||
sed -i -e 's/pip/rpm/g' %{buildroot}%{python3_sitearch}/*.dist-info/INSTALLER
|
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
|
fi
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,35 @@
|
|||||||
Name: pyproject-rpm-macros
|
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
|
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-pip >= 19
|
||||||
Requires: python3-devel
|
Requires: python3-devel
|
||||||
|
|
||||||
|
|
||||||
%description
|
%description
|
||||||
This is a provisional implementation of pyproject RPM macros for Fedora 30+.
|
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
|
These macros are useful for packaging Python projects that use the PEP 517
|
||||||
pyproject.toml file, which specifies the package's build dependencies
|
pyproject.toml file, which specifies the package's build dependencies
|
||||||
(including the build system, such as setuptools, flit or poetry).
|
(including the build system, such as setuptools, flit or poetry).
|
||||||
|
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
# Not strictly necessary but allows working on file names instead
|
# Not strictly necessary but allows working on file names instead
|
||||||
# of source numbers in install section
|
# of source numbers in install section
|
||||||
@ -29,16 +40,22 @@ cp -p %{sources} .
|
|||||||
# nothing to do, sources are not buildable
|
# nothing to do, sources are not buildable
|
||||||
|
|
||||||
%install
|
%install
|
||||||
mkdir -p %{buildroot}/%{_rpmmacrodir}
|
mkdir -p %{buildroot}%{_rpmmacrodir}
|
||||||
install -m 644 macros.pyproject %{buildroot}/%{_rpmmacrodir}/
|
mkdir -p %{buildroot}%{_rpmconfigdir}/redhat
|
||||||
|
install -m 644 macros.pyproject %{buildroot}%{_rpmmacrodir}/
|
||||||
|
install -m 644 pyproject_buildrequires.py %{buildroot}%{_rpmconfigdir}/redhat/
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%{_rpmmacrodir}/macros.pyproject
|
%{_rpmmacrodir}/macros.pyproject
|
||||||
|
%{_rpmconfigdir}/redhat/pyproject_buildrequires.py
|
||||||
|
|
||||||
%doc README.md
|
%doc README.md
|
||||||
%license LICENSE
|
%license LICENSE
|
||||||
|
|
||||||
%changelog
|
%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
|
* Tue Jul 02 2019 Miro Hrončok <mhroncok@redhat.com> - 0-2
|
||||||
- Fix shell syntax errors in %%pyproject_install
|
- Fix shell syntax errors in %%pyproject_install
|
||||||
- Drop PATH warning in %%pyproject_install
|
- Drop PATH warning in %%pyproject_install
|
||||||
|
89
pyproject_buildrequires.py
Normal file
89
pyproject_buildrequires.py
Normal 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")
|
46
tests/python-entrypoints.spec
Normal file
46
tests/python-entrypoints.spec
Normal 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.*
|
@ -1,6 +1,6 @@
|
|||||||
%global pypi_name pytest
|
%global pypi_name pytest
|
||||||
Name: python-%{pypi_name}
|
Name: python-%{pypi_name}
|
||||||
Version: 5.0.0
|
Version: 4.4.2
|
||||||
Release: 0%{?dist}
|
Release: 0%{?dist}
|
||||||
Summary: Simple powerful testing with Python
|
Summary: Simple powerful testing with Python
|
||||||
License: MIT
|
License: MIT
|
||||||
|
Loading…
Reference in New Issue
Block a user