Skip to content

Commit

Permalink
Rename to pythonX.Ydist, read .dist-info, support legacy pythoneggs()()
Browse files Browse the repository at this point in the history
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 Feb 11, 2016
1 parent 2e0e0a4 commit 29abb07
Showing 1 changed file with 51 additions and 19 deletions.
70 changes: 51 additions & 19 deletions scripts/pythoneggs.py → scripts/pythondistdeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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'):
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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):
Expand All @@ -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?
Expand Down

0 comments on commit 29abb07

Please sign in to comment.