I think the different cli flags are not orthogonal enough. Here is the
latest version from the PR plus what I think should be done to get a
clean behavior.

Anyone missing anything?

Florian

-- 

Red Hat GmbH, http://www.de.redhat.com/ Registered seat: Grasbrunn,
Commercial register: Amtsgericht Muenchen, HRB 153243,
Managing Directors: Charles Cachera, Michael Cunningham, Michael
O'Neill, Charles Peters
>From 3c2c063694b5afe6f5333fda8db721747c952421 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?=
 <ngomp...@gmail.com>
Date: Sun, 29 Nov 2015 08:32:03 -0500
Subject: [PATCH 1/2] 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 and to give
them a path to transition from this usage over time.

This switch will also enable pythonXdist(M) Provides format
to allow for a transition, as the conditions for
using pythonXdist(M) are the same as pythonegg(X)(M).

Additionally, the switch '--majorver-prov-with-legacy'
uses new-style dependencies while additionally adding
old-style "pythonegg(X)(M)" Provides for compatibility.
---
 scripts/pythondistdeps.py | 223 ++++++++++++++++++++++++++++++++++++++++++++++
 scripts/pythoneggs.py     | 191 ---------------------------------------
 2 files changed, 223 insertions(+), 191 deletions(-)
 create mode 100755 scripts/pythondistdeps.py
 delete mode 100755 scripts/pythoneggs.py

diff --git a/scripts/pythondistdeps.py b/scripts/pythondistdeps.py
new file mode 100755
index 0000000..0b94dbd
--- /dev/null
+++ b/scripts/pythondistdeps.py
@@ -0,0 +1,223 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2010 Per Øyvind Karlsen <proyv...@moondrake.org>
+# Copyright 2015 Neal Gompa <ngomp...@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:], 'hPRrCOEMml:',
+    ['help', 'provides', 'requires', 'recommends', 'conflicts', 'extras', 'majorver-provides', 'majorver-prov-with-legacy' , '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('-m, --majorver-prov-with-legacy\tPrint extra Provides with Python major version only and extra legacy Provides')
+        print('-l, --legacy\tPrint extra legacy pythonegg Provides/Requires instead (also enables --majorver-provides)')
+        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 ('-m', '--majorver-prov-with-legacy'):
+        Provides_PyMajorVer_Variant = True
+        legacy_Provides = True
+    elif o in ('-l', '--legacy'):
+        legacy = True
+        Provides_PyMajorVer_Variant = 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 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))
+            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 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)
diff --git a/scripts/pythoneggs.py b/scripts/pythoneggs.py
deleted file mode 100755
index f0ec38d..0000000
--- a/scripts/pythoneggs.py
+++ /dev/null
@@ -1,191 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright 2010 Per Øyvind Karlsen <proyv...@moondrake.org>
-# Copyright 2015 Neal Gompa <ngomp...@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 (egg) dependency generator.
-#
-
-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:], 'hPRrCOE:',
-    ['help', 'provides', 'requires', 'recommends', 'conflicts', 'extras'])
-
-Provides = False
-Requires = False
-Recommends = False
-Conflicts = False
-Extras = 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 ')
-        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
-
-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'):
-        lower = lower_dir
-        f = dirname(f)
-    # Determine provide, requires, conflicts & recommends based on egg metadata
-    if lower.endswith('.egg') or \
-            lower.endswith('.egg-info') or \
-            lower.endswith('.egg-link'):
-        # 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)
-        # 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 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 dist.version:
-                spec = ('==', dist.version)
-                if spec not in py_deps[name]:
-                    py_deps[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 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 metadata
-            for dep in deps:
-                name = 'python{}egg({})'.format(pyver_major, 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 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('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 egg'.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)
-- 
2.1.0

>From 7e6d4d94f90d2ef0997f8da0f86398988837a4c3 Mon Sep 17 00:00:00 2001
From: Florian Festi <ffe...@redhat.com>
Date: Thu, 11 Feb 2016 17:25:54 +0100
Subject: [PATCH] Disentangle --majorver-provides from the legacy behaviour
 Make --legacy behave as before thet switch to the dist syntax Add -L,
 --legacy-provides to add old style Provides to the new dist deps

---
 scripts/pythondistdeps.py | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/scripts/pythondistdeps.py b/scripts/pythondistdeps.py
index 0b94dbd..10cbe9d 100755
--- a/scripts/pythondistdeps.py
+++ b/scripts/pythondistdeps.py
@@ -38,9 +38,9 @@ for o, a in opts:
         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('-m, --majorver-prov-with-legacy\tPrint extra Provides with Python major version only and extra legacy Provides')
-        print('-l, --legacy\tPrint extra legacy pythonegg Provides/Requires instead (also enables --majorver-provides)')
+        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
@@ -52,14 +52,12 @@ for o, a in opts:
         Conflicts = True
     elif o in ('-E', '--extras'):
         Extras = True
-    elif o in ('-M', '--majorver-provides'):
-        Provides_PyMajorVer_Variant = True
-    elif o in ('-m', '--majorver-prov-with-legacy'):
+    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
-        Provides_PyMajorVer_Variant = True
 
 if Requires:
     py_abi = True
@@ -120,9 +118,10 @@ for f in files:
                 if name not in py_deps:
                     py_deps[name] = []
                 py_deps[name].append(('==', dist.py_version))
-            name = 'python{}dist({})'.format(dist.py_version, 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:
@@ -134,7 +133,8 @@ for f in files:
             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:
-- 
2.1.0

_______________________________________________
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint

Reply via email to