From 4b8e47eabf4d4eb79d0a660ba3592c212daa4578 Mon Sep 17 00:00:00 2001 From: Iryna Shcherbina Date: Dec 18 2017 18:32:40 +0000 Subject: Rely on dnf when guessing the replqcement for the requirement It is not possible to maintain the list of requirements like tkinter -> python2-tkinter, so guessing the replacement is not the way to go. Check all provides of the the required package, and pick the one that suits most. --- diff --git a/fixrequires/dnf_info.py b/fixrequires/dnf_info.py index db9ce25..ae0d82a 100644 --- a/fixrequires/dnf_info.py +++ b/fixrequires/dnf_info.py @@ -4,6 +4,7 @@ that the modified dependencies are there. """ import dnf +import re PYTHON2_SEED = [ @@ -43,6 +44,34 @@ class DNFInfo(object): return [pkg.name for pkg in self.rawhide_query.filter(requires=PYTHON2_SEED).run()] + def get_correct_require(self, require_name): + pkgs = self.rawhide_query.filter(provides=require_name).run() + if pkgs: + pkg = pkgs[0] + provides = [str(x).split()[0] for x in pkg.provides] + provides = [x for x in provides if bool(re.match('^[a-zA-Z0-9\.\_\-\+]+$', x))] + possible_replacements = [] + for provide in provides: + if (provide == 'python2' or + '-python2-' in provide or + provide.startswith('python2-') or + provide.endswith('-python2')): + possible_replacements.append(provide) + + if not possible_replacements: + # Can't find a replacement. + return + + # There are multiple valiants of python2- names. + # E.g. python2-Sphinx and python2-sphinx. + # Prefer the lovercase one. + for correct_require in possible_replacements: + if correct_require.islower(): + return correct_require + else: + # No other preference, just take the first one. + return possible_replacements[0] + def requires_py2(self, require_name): pkg = self.rawhide_query.filter(provides=require_name) if pkg.count(): diff --git a/fixrequires/modifier.py b/fixrequires/modifier.py index e0fecc0..7228e65 100644 --- a/fixrequires/modifier.py +++ b/fixrequires/modifier.py @@ -6,7 +6,7 @@ from .dnf_info import DNFInfo EL_MARKERS = ('{?rhel}', '{?el6}', '{?epel7}') -R_IGNORE_IN_CLAUSES = ('%if {?rhel}', '%if {?el6}', '%if {?epel7}') +R_IGNORE_IN_CLAUSES = ('%if {?rhel}', '%if {?el6}', '%if {?epel7}', '%if 0%{?rhel} && 0%{?rhel} <= 7') R_ELSE_CLAUSES = [elem + '%else' for elem in R_IGNORE_IN_CLAUSES] F_IGNORE_IN_CLAUSES = ('%if %{fedora} < 27',) @@ -16,31 +16,6 @@ REQUIRES_PATTERN = '#?\s*(Build)?(Requires|Recommends|Suggests|Supplements|Enhan # pattern: (what to replace, how to replace, what to prepend) REPLACE_PATTERNS = { - # Special cases are sometimes special enough. - '^PyYAML$': ('^PyYAML$', 'python2-pyyaml', ''), - '^wxPython$': ('^wxPython$', 'python2-wxpython', ''), - '^PyOpenGL$': ('^PyOpenGL$', 'python2-pyopengl', ''), - '^pyserial$': ('^pyserial$', 'python2-pyserial', ''), - '^numpy$': ('^numpy$', 'python2-numpy', ''), - '^pycairo$': ('^pycairo$', 'python2-cairo', ''), - '^scipy$': ('^scipy$', 'python2-scipy', ''), - '^xapian-bindings-python$': ('^xapian-bindings-python$', 'python2-xapian', ''), - '^gpaw$': ('^gpaw$', 'python2-gpaw', ''), - '^ATpy$': ('^ATpy$', 'python2-atpy', ''), - '^PyPAM$': ('^PyPAM$', 'python2-pypam', ''), - '^pysvn$': ('^pysvn$', 'python2-pysvn', ''), - '^python-4Suite-XML$': ('^python-4Suite-XML$', 'python2-suite-xml', ''), - '^python-BeautifulSoup$': ('^python-BeautifulSoup$', 'python2-beautifulsoup', ''), - '^python-Scriptaculous$': ('^python-Scriptaculous$', 'python2-scriptaculous', ''), - '^python-krbV$': ('^python-krbV$', 'python2-krbv', ''), - '^dogtail$': ('^dogtail$', 'python2-dogtail', ''), - '^pyatspi$': ('^pyatspi$', 'python2-pyatspi', ''), - '^pyparted$': ('^pyparted$', 'python2-pyparted', ''), - '^rhnlib$': ('^rhnlib$', 'python2-rhnlib', ''), - '^sympy$': ('^sympy$', 'python2-sympy', ''), - '^pywbem$': ('^pywbem$', 'python2-pywbem', ''), - '^rb_libtorrent-python$': ('^rb_libtorrent-python$', 'rb_libtorrent-python2', ''), - '^tkinter$': ('^tkinter$', 'python2-tkinter', ''), # Common cases. '^python-\w*': ('^python-', 'python2-', ''), '[^/]*-python-\w*': ('-python-', '-python2-', ''), @@ -101,24 +76,29 @@ class RequiresModifier(object): modified_requires = [] for require in requires: - for pattern, (replace_what, replace_with, prepend) in REPLACE_PATTERNS.items(): - if re.match(pattern, require): - - # If the package is named python-smth but does not depend on - # python2, then we do not care about it (e.g. python-rpm-macros) - if not self.dnf_info.requires_py2(require): - continue - - new_require = re.sub(replace_what, replace_with, require) - new_require = prepend + new_require.lower() - - if self.dnf_info.is_in_rawhide(new_require): - require = new_require - self.modified_requires.add(new_require) - else: - raise ModifierException( - f'{require} should be changed to {new_require}, ' - 'but seems like it was converted wrong!') + # If the package does not depend on + # python2, then we do not care about it (e.g. python-rpm-macros) + if self.dnf_info.requires_py2(require): + new_require = self.dnf_info.get_correct_require(require) + if new_require: + require = new_require + self.modified_requires.add(new_require) + else: + # Could not find the replacement for the requirement, + # check common patterns if it should be converted. + for pattern, (replace_what, replace_with, + prepend) in REPLACE_PATTERNS.items(): + if re.match(pattern, require): + new_require = re.sub(replace_what, replace_with, require) + new_require = prepend + new_require.lower() + + if self.dnf_info.is_in_rawhide(new_require): + require = new_require + self.modified_requires.add(new_require) + else: + raise ModifierException( + f'{require} should be changed to {new_require}, ' + 'but seems like it was converted wrong!') modified_requires.append(require)