Skip to content
Permalink
Browse files

Rename to pythonX.Ydist, read .dist-info, support legacy pythoneggs()()

Per the recommendation of Nick Coghlan and Toshio Kuratomi,
pythonXegg(M) is being renamed to pythonX.Ydist(M).

An option has also been added to add a pythonXdist(M)
Provides for distributions that may prefer to have it.
The option '--majorver-provides' is intended for use
if only one Python stack per major version will be
available at a given time, as unexpected results may
occur if there are multiple independent Python stacks
per major version available.

Consequently, it will not be on by default when using
the generator for generating Provides.

Additionally, .egg-info data is being replaced with
.dist-info data, so we need to handle that case, too.

See for more details:
https://lists.fedoraproject.org/archives/list/python-devel%40lists.fedoraproject.org/thread/SQBSAS4T25HK5YJBNBSFDD7KDQWDELL6/

Also, Thierry Vignaud brought up on rpm-maint that Mageia
currently uses "pythonegg(X)(M)" (e.g. "pythonegg(3)(rpm)"
for python3 rpm bindings package) in their Python packages
to pull in Python dependencies and requested a way to
not break Mageia.

After discussing with Florian Festi about it, Mageia's
pythonegg(X)(M) will be supported by adding '--legacy'
as a switch to generate legacy Provides/Requires to maintain
compatibility with Mageia's existing usage.

The '--legacy-provides' switch will enable pythonegg(X)(M)
Provides in addition to the new pythonX.Ydist(M) format to
allow for a easier transition.
  • Loading branch information
Conan-Kudo authored and ffesti committed Nov 29, 2015
1 parent 2e0e0a4 commit 29abb07fbf6b9ea255bd26e492c104eac8d2370f
Showing with 51 additions and 19 deletions.
  1. +51 −19 scripts/{pythoneggs.py → pythondistdeps.py}
@@ -7,7 +7,7 @@
# 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 (egg) dependency generator.
# RPM python dependency generator, using .egg-info/.egg-link/.dist-info data
#

from __future__ import print_function
@@ -18,14 +18,17 @@


opts, args = getopt(
argv[1:], 'hPRrCOE:',
['help', 'provides', 'requires', 'recommends', 'conflicts', 'extras'])
argv[1:], 'hPRrCOEMLl:',
['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'):
@@ -35,6 +38,9 @@
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
@@ -46,6 +52,12 @@
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
@@ -77,13 +89,15 @@
lower_dir = dirname(lower)
if lower_dir.endswith('.egg') or \
lower_dir.endswith('.egg-info') or \
lower_dir.endswith('.egg-link'):
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 metadata
# Determine provide, requires, conflicts & recommends based on egg/dist metadata
if lower.endswith('.egg') or \
lower.endswith('.egg-info') or \
lower.endswith('.egg-link'):
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)
@@ -94,25 +108,40 @@
path_item = f
metadata = FileMetadata(f)
dist = Distribution.from_location(path_item, dist_name, metadata)
# Get the Python major version
pyver_major = dist.py_version.split('.')[0]
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 metadata says package name is python, we provide python(abi)
# 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))
name = 'python{}egg({})'.format(pyver_major, dist.key)
if name not in py_deps:
py_deps[name] = []
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]:
py_deps[name].append(spec)
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 metadata says package name is python, we don't add dependency on 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:
@@ -131,9 +160,12 @@
if dep in deps:
depsextras.remove(dep)
deps = depsextras
# add requires/recommends based on egg metadata
# add requires/recommends based on egg/dist metadata
for dep in deps:
name = 'python{}egg({})'.format(pyver_major, dep.key)
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:
@@ -142,15 +174,15 @@
py_deps[name].append(spec)
if not dep.specs:
py_deps[name] = []
# Unused, for automatic sub-package generation based on 'extras' from egg metadata
# 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 egg'.format(extra, dist.key))
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):
@@ -164,7 +196,7 @@
else:
print('Requires:\t{} {} {}'.format(dep.key, spec[0], spec[1]))
print('%%description\t{}'.format(extra))
print('{} extra for {} python egg'.format(extra, dist.key))
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?

0 comments on commit 29abb07

Please sign in to comment.
You can’t perform that action at this time.