Python dependency generators live in python-rpm-generators now (#1444925)

This commit is contained in:
Panu Matilainen 2017-05-23 12:21:52 +03:00
parent 0123653c89
commit 7bc220d2a2
10 changed files with 7 additions and 488 deletions

View File

@ -1,20 +0,0 @@
--- rpm-4.13.0-rc1/scripts/Makefile.am.orig 2015-09-01 19:45:43.896822977 +0200
+++ rpm-4.13.0-rc1/scripts/Makefile.am 2016-06-13 15:46:34.281390084 +0200
@@ -11,7 +11,7 @@
check-files check-prereqs \
check-buildroot check-rpaths check-rpaths-worker \
find-debuginfo.sh find-lang.sh \
- perl.prov perl.req pythondeps.sh \
+ perl.prov perl.req pythondeps.sh pythondistdeps.py \
rpmdb_loadcvt rpm.daily rpm.log rpm.supp rpm2cpio.sh \
tgpg vpkg-provides.sh \
find-requires find-provides \
@@ -30,7 +30,7 @@
check-files check-prereqs \
check-buildroot check-rpaths check-rpaths-worker \
find-lang.sh find-requires find-provides \
- perl.prov perl.req pythondeps.sh \
+ perl.prov perl.req pythondeps.sh pythondistdeps.py \
mono-find-requires mono-find-provides \
pkgconfigdeps.sh libtooldeps.sh \
ocaml-find-requires.sh ocaml-find-provides.sh \

View File

@ -1,9 +0,0 @@
--- rpm-4.13.0-rc1/fileattrs/python.attr.orig 2016-06-13 15:49:10.072832164 +0200
+++ rpm-4.13.0-rc1/fileattrs/python.attr 2016-06-13 15:50:46.687106846 +0200
@@ -1,4 +1,4 @@
-%__python_provides %{_rpmconfigdir}/pythondeps.sh --provides
+%__python_provides %{_rpmconfigdir}/pythondistdeps.py --provides --majorver-provides
%__python_requires %{_rpmconfigdir}/pythondeps.sh --requires
-%__python_path ^((/usr/lib(64)?/python[[:digit:]]\\.[[:digit:]]/.*\\.(py[oc]?|so))|(%{_bindir}/python[[:digit:]]\\.[[:digit:]]))$
+%__python_path ^((/usr/lib(64)?/python[[:digit:]]\\.[[:digit:]]/.*))|(%{_bindir}/python[[:digit:]]\\.[[:digit:]]))$
%__python_magic [Pp]ython.*(executable|byte-compiled)

View File

@ -1,9 +0,0 @@
diff -uNr rpm-4.13.0.orig/scripts/pythondistdeps.py rpm-4.13.0/scripts/pythondistdeps.py
--- rpm-4.13.0.orig/scripts/pythondistdeps.py 2016-12-18 12:25:21.287632679 +0100
+++ rpm-4.13.0/scripts/pythondistdeps.py 2016-12-18 12:25:48.857479226 +0100
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Copyright 2010 Per Øyvind Karlsen <proyvind@moondrake.org>

View File

@ -1,229 +0,0 @@
diff --git a/scripts/pythondistdeps.py b/scripts/pythondistdeps.py
new file mode 100755
index 0000000..8a2f43d
--- /dev/null
+++ b/scripts/pythondistdeps.py
@@ -0,0 +1,223 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2010 Per Øyvind Karlsen <proyvind@moondrake.org>
+# Copyright 2015 Neal Gompa <ngompa13@gmail.com>
+#
+# This program is free software. It may be redistributed and/or modified under
+# the terms of the LGPL version 2.1 (or later).
+#
+# RPM python dependency generator, using .egg-info/.egg-link/.dist-info data
+#
+
+from __future__ import print_function
+from getopt import getopt
+from os.path import basename, dirname, isdir, sep
+from sys import argv, stdin, version
+from distutils.sysconfig import get_python_lib
+
+
+opts, args = getopt(
+ argv[1:], 'hPRrCEMLl:',
+ ['help', 'provides', 'requires', 'recommends', 'conflicts', 'extras', 'majorver-provides', 'legacy-provides' , 'legacy'])
+
+Provides = False
+Requires = False
+Recommends = False
+Conflicts = False
+Extras = False
+Provides_PyMajorVer_Variant = False
+legacy_Provides = False
+legacy = False
+
+for o, a in opts:
+ if o in ('-h', '--help'):
+ print('-h, --help\tPrint help')
+ print('-P, --provides\tPrint Provides')
+ print('-R, --requires\tPrint Requires')
+ print('-r, --recommends\tPrint Recommends')
+ print('-C, --conflicts\tPrint Conflicts')
+ print('-E, --extras\tPrint Extras ')
+ print('-M, --majorver-provides\tPrint extra Provides with Python major version only')
+ print('-L, --legacy-provides\tPrint extra legacy pythonegg Provides')
+ print('-l, --legacy\tPrint legacy pythonegg Provides/Requires instead')
+ exit(1)
+ elif o in ('-P', '--provides'):
+ Provides = True
+ elif o in ('-R', '--requires'):
+ Requires = True
+ elif o in ('-r', '--recommends'):
+ Recommends = True
+ elif o in ('-C', '--conflicts'):
+ Conflicts = True
+ elif o in ('-E', '--extras'):
+ Extras = True
+ elif o in ('-M', '--majorver-provides'):
+ Provides_PyMajorVer_Variant = True
+ elif o in ('-L', '--legacy-provides'):
+ legacy_Provides = True
+ elif o in ('-l', '--legacy'):
+ legacy = True
+
+if Requires:
+ py_abi = True
+else:
+ py_abi = False
+py_deps = {}
+if args:
+ files = args
+else:
+ files = stdin.readlines()
+
+for f in files:
+ f = f.strip()
+ lower = f.lower()
+ name = 'python(abi)'
+ # add dependency based on path, versioned if within versioned python directory
+ if py_abi and (lower.endswith('.py') or lower.endswith('.pyc') or lower.endswith('.pyo')):
+ if name not in py_deps:
+ py_deps[name] = []
+ purelib = get_python_lib(standard_lib=1, plat_specific=0).split(version[:3])[0]
+ platlib = get_python_lib(standard_lib=1, plat_specific=1).split(version[:3])[0]
+ for lib in (purelib, platlib):
+ if lib in f:
+ spec = ('==', f.split(lib)[1].split(sep)[0])
+ if spec not in py_deps[name]:
+ py_deps[name].append(spec)
+
+ # XXX: hack to workaround RPM internal dependency generator not passing directories
+ lower_dir = dirname(lower)
+ if lower_dir.endswith('.egg') or \
+ lower_dir.endswith('.egg-info') or \
+ lower_dir.endswith('.egg-link') or \
+ lower_dir.endswith('.dist-info'):
+ lower = lower_dir
+ f = dirname(f)
+ # Determine provide, requires, conflicts & recommends based on egg/dist metadata
+ if lower.endswith('.egg') or \
+ lower.endswith('.egg-info') or \
+ lower.endswith('.egg-link') or \
+ lower.endswith('.dist-info'):
+ # This import is very slow, so only do it if needed
+ from pkg_resources import Distribution, FileMetadata, PathMetadata
+ dist_name = basename(f)
+ if isdir(f):
+ path_item = dirname(f)
+ metadata = PathMetadata(path_item, f)
+ else:
+ path_item = f
+ metadata = FileMetadata(f)
+ dist = Distribution.from_location(path_item, dist_name, metadata)
+ if (Provides_PyMajorVer_Variant or legacy_Provides or legacy) and Provides:
+ # Get the Python major version
+ pyver_major = dist.py_version.split('.')[0]
+ if Provides:
+ # If egg/dist metadata says package name is python, we provide python(abi)
+ if dist.key == 'python':
+ name = 'python(abi)'
+ if name not in py_deps:
+ py_deps[name] = []
+ py_deps[name].append(('==', dist.py_version))
+ if not legacy:
+ name = 'python{}dist({})'.format(dist.py_version, dist.key)
+ if name not in py_deps:
+ py_deps[name] = []
+ if Provides_PyMajorVer_Variant:
+ pymajor_name = 'python{}dist({})'.format(pyver_major, dist.key)
+ if pymajor_name not in py_deps:
+ py_deps[pymajor_name] = []
+ if legacy or legacy_Provides:
+ legacy_name = 'pythonegg({})({})'.format(pyver_major, dist.key)
+ if legacy_name not in py_deps:
+ py_deps[legacy_name] = []
+ if dist.version:
+ spec = ('==', dist.version)
+ if spec not in py_deps[name]:
+ if not legacy:
+ py_deps[name].append(spec)
+ if Provides_PyMajorVer_Variant:
+ py_deps[pymajor_name].append(spec)
+ if legacy or legacy_Provides:
+ py_deps[legacy_name].append(spec)
+ if Requires or (Recommends and dist.extras):
+ name = 'python(abi)'
+ # If egg/dist metadata says package name is python, we don't add dependency on python(abi)
+ if dist.key == 'python':
+ py_abi = False
+ if name in py_deps:
+ py_deps.pop(name)
+ elif py_abi and dist.py_version:
+ if name not in py_deps:
+ py_deps[name] = []
+ spec = ('==', dist.py_version)
+ if spec not in py_deps[name]:
+ py_deps[name].append(spec)
+ deps = dist.requires()
+ if Recommends:
+ depsextras = dist.requires(extras=dist.extras)
+ if not Requires:
+ for dep in reversed(depsextras):
+ if dep in deps:
+ depsextras.remove(dep)
+ deps = depsextras
+ # add requires/recommends based on egg/dist metadata
+ for dep in deps:
+ if legacy:
+ name = 'pythonegg({})({})'.format(pyver_major, dep.key)
+ else:
+ name = 'python{}dist({})'.format(dist.py_version, dep.key)
+ for spec in dep.specs:
+ if spec[0] != '!=':
+ if name not in py_deps:
+ py_deps[name] = []
+ if spec not in py_deps[name]:
+ py_deps[name].append(spec)
+ if not dep.specs:
+ py_deps[name] = []
+ # Unused, for automatic sub-package generation based on 'extras' from egg/dist metadata
+ # TODO: implement in rpm later, or...?
+ if Extras:
+ deps = dist.requires()
+ extras = dist.extras
+ print(extras)
+ for extra in extras:
+ print('%%package\textras-{}'.format(extra))
+ print('Summary:\t{} extra for {} python package'.format(extra, dist.key))
+ print('Group:\t\tDevelopment/Python')
+ depsextras = dist.requires(extras=[extra])
+ for dep in reversed(depsextras):
+ if dep in deps:
+ depsextras.remove(dep)
+ deps = depsextras
+ for dep in deps:
+ for spec in dep.specs:
+ if spec[0] == '!=':
+ print('Conflicts:\t{} {} {}'.format(dep.key, '==', spec[1]))
+ else:
+ print('Requires:\t{} {} {}'.format(dep.key, spec[0], spec[1]))
+ print('%%description\t{}'.format(extra))
+ print('{} extra for {} python package'.format(extra, dist.key))
+ print('%%files\t\textras-{}\n'.format(extra))
+ if Conflicts:
+ # Should we really add conflicts for extras?
+ # Creating a meta package per extra with recommends on, which has
+ # the requires/conflicts in stead might be a better solution...
+ for dep in dist.requires(extras=dist.extras):
+ name = dep.key
+ for spec in dep.specs:
+ if spec[0] == '!=':
+ if name not in py_deps:
+ py_deps[name] = []
+ spec = ('==', spec[1])
+ if spec not in py_deps[name]:
+ py_deps[name].append(spec)
+names = list(py_deps.keys())
+names.sort()
+for name in names:
+ if py_deps[name]:
+ # Print out versioned provides, requires, recommends, conflicts
+ for spec in py_deps[name]:
+ print('{} {} {}'.format(name, spec[0], spec[1]))
+ else:
+ # Print out unversioned provides, requires, recommends, conflicts
+ print(name)

View File

@ -1,34 +0,0 @@
From 30d472c8af086df077e6cf047a87fdaf93c9b21b Mon Sep 17 00:00:00 2001
From: Igor Gnatenko <ignatenko@redhat.com>
Date: Wed, 24 Aug 2016 15:37:16 +0200
Subject: [PATCH] pythondistdeps.py: add forgotten import
Signed-off-by: Igor Gnatenko <ignatenko@redhat.com>
---
scripts/pythondistdeps.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/pythondistdeps.py b/scripts/pythondistdeps.py
index 76017f3..e4b99e2 100755
--- a/scripts/pythondistdeps.py
+++ b/scripts/pythondistdeps.py
@@ -15,6 +15,7 @@ from getopt import getopt
from os.path import basename, dirname, isdir, sep
from sys import argv, stdin, version
from distutils.sysconfig import get_python_lib
+from warnings import warn
opts, args = getopt(
@@ -108,7 +109,7 @@ for f in files:
dist = Distribution.from_location(path_item, dist_name, metadata)
# Check if py_version is defined in the file
if not dist.py_version:
- warnings.warn("Version for {!r} has not been found".format(dist), RuntimeWarning)
+ warn("Version for {!r} has not been found".format(dist), RuntimeWarning)
continue
if (Provides_PyMajorVer_Variant or legacy_Provides or legacy) and Provides:
# Get the Python major version
--
2.9.3

View File

@ -1,43 +0,0 @@
From ff395f4a820497a443baa6cd0198c49b06207c3f Mon Sep 17 00:00:00 2001
From: Tomas Orsava <torsava@redhat.com>
Date: Thu, 16 Feb 2017 11:36:29 +0100
Subject: [PATCH] Fix pythondistdeps.py --provides for Python wheels
As Python wheels do not contain targetted Python version in the directory/file
name of their metadata like Python eggs do, and since the Python version is not
contained in the metadata either, it is necessary to get it from elsewhere.
Here it is parsed from the path the metadata resides at
(e.g. /usr/lib/pythonX.Y/site-packages/...)
---
scripts/pythondistdeps.py | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/scripts/pythondistdeps.py b/scripts/pythondistdeps.py
index e4b99e2..d44210c 100644
--- a/scripts/pythondistdeps.py
+++ b/scripts/pythondistdeps.py
@@ -107,10 +107,17 @@ for f in files:
path_item = f
metadata = FileMetadata(f)
dist = Distribution.from_location(path_item, dist_name, metadata)
- # Check if py_version is defined in the file
+ # Check if py_version is defined in the metadata file/directory name
if not dist.py_version:
- warn("Version for {!r} has not been found".format(dist), RuntimeWarning)
- continue
+ # Try to parse the Python version from the path the metadata
+ # resides at (e.g. /usr/lib/pythonX.Y/site-packages/...)
+ import re
+ res = re.search(r"/python(?P<pyver>\d+\.\d)/", path_item)
+ if res:
+ dist.py_version = res.group('pyver')
+ else:
+ warn("Version for {!r} has not been found".format(dist), RuntimeWarning)
+ continue
if (Provides_PyMajorVer_Variant or legacy_Provides or legacy) and Provides:
# Get the Python major version
pyver_major = dist.py_version.split('.')[0]
--
2.11.0

View File

@ -1,29 +0,0 @@
From 2f51022e1586a9b3ac8036b23995074b00910475 Mon Sep 17 00:00:00 2001
From: Igor Gnatenko <ignatenko@redhat.com>
Date: Mon, 22 Aug 2016 12:55:50 +0200
Subject: [PATCH 2/3] pythondistdeps.py: show warning if version is not found
in metadata
In 49197c930bb6090d0fca4089ea75ec9d10e62f99 we introduced skipping
metadata which has no version, but it's better to show some warning.
Signed-off-by: Igor Gnatenko <ignatenko@redhat.com>
---
scripts/pythondistdeps.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/scripts/pythondistdeps.py b/scripts/pythondistdeps.py
index 54905c3..d7226e0 100755
--- a/scripts/pythondistdeps.py
+++ b/scripts/pythondistdeps.py
@@ -110,6 +110,7 @@ for f in files:
dist = Distribution.from_location(path_item, dist_name, metadata)
# Check if py_version is defined in the file
if not dist.py_version:
+ warnings.warn("Version for {!r} has not been found".format(dist), RuntimeWarning)
continue
if (Provides_PyMajorVer_Variant or legacy_Provides or legacy) and Provides:
# Get the Python major version
--
2.9.3

View File

@ -1,50 +0,0 @@
From 83e4d44b802d39dfbd407488c0d9f629799b809c Mon Sep 17 00:00:00 2001
From: Igor Gnatenko <ignatenko@redhat.com>
Date: Mon, 22 Aug 2016 12:56:05 +0200
Subject: [PATCH 3/3] pythondistdeps.py: skip .egg-link files
From setuptools's documentation:
These files are not eggs, strictly speaking. They simply provide a way
to reference an egg that is not physically installed in the desired
location. They exist primarily as a cross-platform alternative to
symbolic links, to support "installing" code that is being developed in
a different location than the desired installation location.
If we read .egg-link using pkg_resources.Distribution it will
never have version as it is just list of directories which should be
taken into account.
We could change into that directories and add eggs from those locations
for parsing, but RPM's dependency generator already passing all files
from built RPM so it just does not make any sense to traverse those
directories.
After all written above, let's just ignore .egg-link files.
Signed-off-by: Igor Gnatenko <ignatenko@redhat.com>
---
scripts/pythondistdeps.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/scripts/pythondistdeps.py b/scripts/pythondistdeps.py
index d7226e0..76017f3 100755
--- a/scripts/pythondistdeps.py
+++ b/scripts/pythondistdeps.py
@@ -89,14 +89,12 @@ for f in files:
lower_dir = dirname(lower)
if lower_dir.endswith('.egg') or \
lower_dir.endswith('.egg-info') or \
- lower_dir.endswith('.egg-link') or \
lower_dir.endswith('.dist-info'):
lower = lower_dir
f = dirname(f)
# Determine provide, requires, conflicts & recommends based on egg/dist metadata
if lower.endswith('.egg') or \
lower.endswith('.egg-info') or \
- lower.endswith('.egg-link') or \
lower.endswith('.dist-info'):
# This import is very slow, so only do it if needed
from pkg_resources import Distribution, FileMetadata, PathMetadata
--
2.9.3

View File

@ -1,44 +0,0 @@
From 49197c930bb6090d0fca4089ea75ec9d10e62f99 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Neal=20Gompa=20=28=E3=83=8B=E3=83=BC=E3=83=AB=E3=83=BB?=
=?UTF-8?q?=E3=82=B3=E3=82=99=E3=83=B3=E3=83=8F=E3=82=9A=29?=
<ngompa13@gmail.com>
Date: Sat, 20 Aug 2016 11:01:06 -0400
Subject: [PATCH 1/3] pythondistdeps.py: skip distribution metadata if there is
no version
For example, reading .egg-link using pkg_resources.Distribution returns
actual metadata, but it does not contain version. It returns traceback like:
File "/usr/lib/rpm/pythondistdeps.py", line 113, in <module>
pyver_major = dist.py_version.split('.')[0]
AttributeError: 'NoneType' object has no attribute 'split'
Traceback (most recent call last):
File "/usr/lib/rpm/pythondistdeps.py", line 113, in <module>
pyver_major = dist.py_version.split('.')[0]
AttributeError: 'NoneType' object has no attribute 'split'
Let's just skip such errors as we can't do much about that.
Reference: https://bugzilla.redhat.com/show_bug.cgi?id=1368673
Reported-and-tested-by: Igor Gnatenko <ignatenko@redhat.com>
---
scripts/pythondistdeps.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/scripts/pythondistdeps.py b/scripts/pythondistdeps.py
index 8a2f43d..54905c3 100755
--- a/scripts/pythondistdeps.py
+++ b/scripts/pythondistdeps.py
@@ -108,6 +108,9 @@ for f in files:
path_item = f
metadata = FileMetadata(f)
dist = Distribution.from_location(path_item, dist_name, metadata)
+ # Check if py_version is defined in the file
+ if not dist.py_version:
+ continue
if (Provides_PyMajorVer_Variant or legacy_Provides or legacy) and Provides:
# Get the Python major version
pyver_major = dist.py_version.split('.')[0]
--
2.9.3

View File

@ -33,7 +33,7 @@
Summary: The RPM package management system
Name: rpm
Version: %{rpmver}
Release: %{?snapver:0.%{snapver}.}21%{?dist}
Release: %{?snapver:0.%{snapver}.}22%{?dist}
Group: System Environment/Base
Url: http://www.rpm.org/
Source0: http://ftp.rpm.org/releases/%{srcdir}/%{name}-%{srcver}.tar.bz2
@ -58,22 +58,9 @@ Patch5: rpm-4.12.0-rpm2cpio-hack.patch
# Patches already upstream:
Patch100: rpm-4.13.0-python-rpmsign.patch
Patch133: rpm-4.13.x-pythondistdeps.patch
Patch134: rpm-4.13.x-pythondistdeps-Makefile.patch
Patch135: rpm-4.13.x-pythondistdeps-fileattr.patch
Patch136: rpm-4.13.x-pythondistdeps.py-skip-distribution-metadata-if-ther.patch
Patch137: rpm-4.13.x-pythondistdeps.py-show-warning-if-version-is-not-fou.patch
Patch138: rpm-4.13.x-pythondistdeps.py-skip-.egg-link-files.patch
Patch139: rpm-4.13.x-pythondistdeps.py-add-forgotten-import.patch
Patch140: rpm-4.13.x-brp-python-bytecompile-Python3-only.patch
# Upstream PR: https://github.com/rpm-software-management/rpm/pull/154
# rhbz#1421776
Patch141: rpm-4.13.x-pythondistdeps.py-fix-processing-wheels.patch
Patch142: rpm-4.13.x-fix-refcount-for-spec_type.patch
# Fedora-specific (python3) patch (RHBZ #1405483)
Patch200: rpm-4.13.x-pythondistdeps-python3.patch
# debuginfo backports (#1427970)
Patch250: 0001-Add-build-id-links-to-rpm-for-all-ELF-files.patch
Patch251: 0002-Make-it-possible-to-have-unique-build-ids-across-bui.patch
@ -248,10 +235,6 @@ Requires: /usr/bin/gdb-add-index
# "just work" while allowing for alternatives, depend on a virtual
# provide, typically coming from redhat-rpm-config.
Requires: system-rpm-config
# Techincally rpmbuild doesn't require python3 (and setuptools), but
# pythondistdeps generator expects it.
# See: https://bugzilla.redhat.com/show_bug.cgi?id=1410631
Requires: python3-setuptools
%description build
The rpm-build package contains the scripts and executable programs
@ -457,9 +440,9 @@ done
find $RPM_BUILD_ROOT -name "*.la"|xargs rm -f
# These live in perl-generators now
rm -f $RPM_BUILD_ROOT/%{rpmhome}/{perldeps.pl,perl.*}
rm -f $RPM_BUILD_ROOT/%{_fileattrsdir}/perl*
# These live in perl-generators and python-rpm-generators now
rm -f $RPM_BUILD_ROOT/%{rpmhome}/{perldeps.pl,perl.*,python*}
rm -f $RPM_BUILD_ROOT/%{_fileattrsdir}/{perl*,python*}
# Axe unused cruft
rm -f $RPM_BUILD_ROOT/%{rpmhome}/{tcl.req,osgideps.pl}
@ -610,6 +593,9 @@ exit 0
%doc doc/librpm/html/*
%changelog
* Tue May 23 2017 Panu Matilainen <pmatilai@redhat.com> - 4.13.0.1-22
- Python dependency generators live in python-rpm-generators now (#1444925)
* Tue May 23 2017 Panu Matilainen <pmatilai@redhat.com> - 4.13.0.1-21
- Fix rpmsign python module import failing (#1393659)