Bug 2290349

Summary: python-specfile: FTBFS in Fedora Rawhide (caused by RPM 4.20alpha): specfile.exceptions.RPMException: %patchN is obsolete, use %patch N (or %patch -P N): %patch0 -p1
Product: [Fedora] Fedora Reporter: Karolina Surma <ksurma>
Component: python-specfileAssignee: Nikola Forró <nforro>
Status: CLOSED WORKSFORME QA Contact:
Severity: medium Docs Contact:
Priority: unspecified    
Version: rawhideCC: flachman, fti-bugs, jkyjovsk, lbarczio, mfocko, mmassari, nforro, ttomecek
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Linux   
URL: https://koschei.fedoraproject.org/package/python-specfile
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2024-06-17 18:10:31 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 2260875, 2260877, 2244836, 2292002    

Description Karolina Surma 2024-06-04 09:44:05 UTC
Description of problem:
Package python-specfile fails to build from source in Fedora Rawhide.

Version-Release number of selected component (if applicable):
0.28.3-1.fc41

Steps to Reproduce:
koji build --scratch f41 python-specfile-0.28.3-1.fc41.src.rpm

Additional info:
This package is tracked by Koschei. See:
https://koschei.fedoraproject.org/package/python-specfile

Reproducible: Always

Actual Results:  
=================================== FAILURES ===================================
____________________________ test_prep_traditional _____________________________
content = 'Name:           test\nVersion:        0.1\nRelease:        1%{?dist}\nSummary:        Test package\n\nLicense:       ...patch1 -p1\n%patch2 -p1\n\n\n%changelog\n* Thu Jun 07 2018 Nikola Forró <nforro> - 0.1-1\n- first version\n'
flags = 3
    def get_rpm_spec(content, flags):
        Macros.reinit()
        for name, value in self.macros + (extra_macros or []):
            if value is None:
                Macros.remove(name)
            else:
                Macros.define(name, value)
        Macros.define("_sourcedir", str(self.sourcedir))
        with tempfile.NamedTemporaryFile() as tmp:
            tmp.write(content.encode())
            tmp.flush()
            try:
                with self._sanitize_environment():
                    with capture_stderr() as stderr:
>                       return rpm.spec(tmp.name, flags)
E                       ValueError: can't parse specfile
specfile/spec_parser.py:226: ValueError
The above exception was the direct cause of the following exception:
spec_traditional = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_prep_traditional0/spec_traditional/test.spec')
    def test_prep_traditional(spec_traditional):
>       spec = Specfile(spec_traditional)
tests/integration/test_specfile.py:30: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
specfile/specfile.py:72: in __init__
    self._parser.parse(str(self))
specfile/spec_parser.py:380: in parse
    self.spec, self.tainted = self._do_parse(content, extra_macros)
specfile/spec_parser.py:294: in _do_parse
    spec = get_rpm_spec(content, rpm.RPMSPEC_ANYARCH | rpm.RPMSPEC_FORCE)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
content = 'Name:           test\nVersion:        0.1\nRelease:        1%{?dist}\nSummary:        Test package\n\nLicense:       ...patch1 -p1\n%patch2 -p1\n\n\n%changelog\n* Thu Jun 07 2018 Nikola Forró <nforro> - 0.1-1\n- first version\n'
flags = 3
    def get_rpm_spec(content, flags):
        Macros.reinit()
        for name, value in self.macros + (extra_macros or []):
            if value is None:
                Macros.remove(name)
            else:
                Macros.define(name, value)
        Macros.define("_sourcedir", str(self.sourcedir))
        with tempfile.NamedTemporaryFile() as tmp:
            tmp.write(content.encode())
            tmp.flush()
            try:
                with self._sanitize_environment():
                    with capture_stderr() as stderr:
                        return rpm.spec(tmp.name, flags)
            except ValueError as e:
>               raise RPMException(stderr=stderr) from e
E               specfile.exceptions.RPMException: %patchN is obsolete, use %patch N (or %patch -P N): %patch0 -p1
specfile/spec_parser.py:228: RPMException
_______________________________ test_update_tag ________________________________
content = '%global majorver 0\n%global minorver 1\n%global patchver 2\n%global mainver %{majorver}.%{minorver}.%{patchver}\n\n%g... -p1\n%patch2 -p1\n\n\n%changelog\n* Thu Jun 07 2018 Nikola Forró <nforro> - 0.1.2~rc2-1\n- first version\n'
flags = 3
    def get_rpm_spec(content, flags):
        Macros.reinit()
        for name, value in self.macros + (extra_macros or []):
            if value is None:
                Macros.remove(name)
            else:
                Macros.define(name, value)
        Macros.define("_sourcedir", str(self.sourcedir))
        with tempfile.NamedTemporaryFile() as tmp:
            tmp.write(content.encode())
            tmp.flush()
            try:
                with self._sanitize_environment():
                    with capture_stderr() as stderr:
>                       return rpm.spec(tmp.name, flags)
E                       ValueError: can't parse specfile
specfile/spec_parser.py:226: ValueError
The above exception was the direct cause of the following exception:
spec_macros = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_update_tag0/spec_macros/test.spec')
    @pytest.mark.skipif(
        rpm.__version__ < "4.16",
        reason="condition expression evaluation requires rpm 4.16 or higher",
    )
    def test_update_tag(spec_macros):
>       spec = Specfile(spec_macros)
tests/integration/test_specfile.py:359: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
specfile/specfile.py:72: in __init__
    self._parser.parse(str(self))
specfile/spec_parser.py:380: in parse
    self.spec, self.tainted = self._do_parse(content, extra_macros)
specfile/spec_parser.py:294: in _do_parse
    spec = get_rpm_spec(content, rpm.RPMSPEC_ANYARCH | rpm.RPMSPEC_FORCE)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
content = '%global majorver 0\n%global minorver 1\n%global patchver 2\n%global mainver %{majorver}.%{minorver}.%{patchver}\n\n%g... -p1\n%patch2 -p1\n\n\n%changelog\n* Thu Jun 07 2018 Nikola Forró <nforro> - 0.1.2~rc2-1\n- first version\n'
flags = 3
    def get_rpm_spec(content, flags):
        Macros.reinit()
        for name, value in self.macros + (extra_macros or []):
            if value is None:
                Macros.remove(name)
            else:
                Macros.define(name, value)
        Macros.define("_sourcedir", str(self.sourcedir))
        with tempfile.NamedTemporaryFile() as tmp:
            tmp.write(content.encode())
            tmp.flush()
            try:
                with self._sanitize_environment():
                    with capture_stderr() as stderr:
                        return rpm.spec(tmp.name, flags)
            except ValueError as e:
>               raise RPMException(stderr=stderr) from e
E               specfile.exceptions.RPMException: %patchN is obsolete, use %patch N (or %patch -P N): %patch0 -p1
specfile/spec_parser.py:228: RPMException
___________________________ test_context_management ____________________________
content = 'Name:           test\nVersion:        0.1\nRelease:        1%{?dist}\nSummary:        Test package\n\nLicense:       ...patch1 -p1\n%patch2 -p1\n\n\n%changelog\n* Thu Jun 07 2018 Nikola Forró <nforro> - 0.1-1\n- first version\n'
flags = 3
    def get_rpm_spec(content, flags):
        Macros.reinit()
        for name, value in self.macros + (extra_macros or []):
            if value is None:
                Macros.remove(name)
            else:
                Macros.define(name, value)
        Macros.define("_sourcedir", str(self.sourcedir))
        with tempfile.NamedTemporaryFile() as tmp:
            tmp.write(content.encode())
            tmp.flush()
            try:
                with self._sanitize_environment():
                    with capture_stderr() as stderr:
>                       return rpm.spec(tmp.name, flags)
E                       ValueError: can't parse specfile
specfile/spec_parser.py:226: ValueError
The above exception was the direct cause of the following exception:
spec_autosetup = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_context_management0/spec_autosetup/test.spec')
spec_traditional = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_context_management0/spec_traditional/test.spec')
    def test_context_management(spec_autosetup, spec_traditional):
        spec = Specfile(spec_autosetup)
        with spec.tags() as tags:
            tags.license.value = "BSD"
            assert spec.license == "BSD"
            spec.license = "BSD-3-Clause"
            tags.patch0.value = "first_patch.patch"
            with spec.patches() as patches:
                assert patches[0].location == "first_patch.patch"
                patches[0].location = "patch_0.patch"
        assert spec.license == "BSD-3-Clause"
        with spec.patches() as patches:
            assert patches[0].location == "patch_0.patch"
        spec1 = Specfile(spec_autosetup)
>       spec2 = Specfile(spec_traditional)
tests/integration/test_specfile.py:534: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
specfile/specfile.py:72: in __init__
    self._parser.parse(str(self))
specfile/spec_parser.py:380: in parse
    self.spec, self.tainted = self._do_parse(content, extra_macros)
specfile/spec_parser.py:294: in _do_parse
    spec = get_rpm_spec(content, rpm.RPMSPEC_ANYARCH | rpm.RPMSPEC_FORCE)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
content = 'Name:           test\nVersion:        0.1\nRelease:        1%{?dist}\nSummary:        Test package\n\nLicense:       ...patch1 -p1\n%patch2 -p1\n\n\n%changelog\n* Thu Jun 07 2018 Nikola Forró <nforro> - 0.1-1\n- first version\n'
flags = 3
    def get_rpm_spec(content, flags):
        Macros.reinit()
        for name, value in self.macros + (extra_macros or []):
            if value is None:
                Macros.remove(name)
            else:
                Macros.define(name, value)
        Macros.define("_sourcedir", str(self.sourcedir))
        with tempfile.NamedTemporaryFile() as tmp:
            tmp.write(content.encode())
            tmp.flush()
            try:
                with self._sanitize_environment():
                    with capture_stderr() as stderr:
                        return rpm.spec(tmp.name, flags)
            except ValueError as e:
>               raise RPMException(stderr=stderr) from e
E               specfile.exceptions.RPMException: %patchN is obsolete, use %patch N (or %patch -P N): %patch0 -p1
specfile/spec_parser.py:228: RPMException
___________________________ test_parse_if_necessary ____________________________
content = '%global majorver 0\n%global minorver 1\n%global patchver 2\n%global mainver %{majorver}.%{minorver}.%{patchver}\n\n%g... -p1\n%patch2 -p1\n\n\n%changelog\n* Thu Jun 07 2018 Nikola Forró <nforro> - 0.1.2~rc2-1\n- first version\n'
flags = 3
    def get_rpm_spec(content, flags):
        Macros.reinit()
        for name, value in self.macros + (extra_macros or []):
            if value is None:
                Macros.remove(name)
            else:
                Macros.define(name, value)
        Macros.define("_sourcedir", str(self.sourcedir))
        with tempfile.NamedTemporaryFile() as tmp:
            tmp.write(content.encode())
            tmp.flush()
            try:
                with self._sanitize_environment():
                    with capture_stderr() as stderr:
>                       return rpm.spec(tmp.name, flags)
E                       ValueError: can't parse specfile
specfile/spec_parser.py:226: ValueError
The above exception was the direct cause of the following exception:
spec_macros = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_parse_if_necessary0/spec_macros/test.spec')
    def test_parse_if_necessary(spec_macros):
        flexmock(SpecParser).should_call("_do_parse").once()
>       spec1 = Specfile(spec_macros)
tests/integration/test_specfile.py:558: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
specfile/specfile.py:72: in __init__
    self._parser.parse(str(self))
specfile/spec_parser.py:380: in parse
    self.spec, self.tainted = self._do_parse(content, extra_macros)
/usr/lib/python3.12/site-packages/flexmock/_api.py:510: in mock_method
    return _handle_matched_expectation(expectation, runtime_self, *kargs, **kwargs)
/usr/lib/python3.12/site-packages/flexmock/_api.py:488: in _handle_matched_expectation
    return pass_thru(expectation, runtime_self, *kargs, **kwargs)
/usr/lib/python3.12/site-packages/flexmock/_api.py:458: in pass_thru
    return _handle_exception_matching(expectation)
/usr/lib/python3.12/site-packages/flexmock/_api.py:454: in pass_thru
    return_values = original(runtime_self, *kargs, **kwargs)
specfile/spec_parser.py:294: in _do_parse
    spec = get_rpm_spec(content, rpm.RPMSPEC_ANYARCH | rpm.RPMSPEC_FORCE)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
content = '%global majorver 0\n%global minorver 1\n%global patchver 2\n%global mainver %{majorver}.%{minorver}.%{patchver}\n\n%g... -p1\n%patch2 -p1\n\n\n%changelog\n* Thu Jun 07 2018 Nikola Forró <nforro> - 0.1.2~rc2-1\n- first version\n'
flags = 3
    def get_rpm_spec(content, flags):
        Macros.reinit()
        for name, value in self.macros + (extra_macros or []):
            if value is None:
                Macros.remove(name)
            else:
                Macros.define(name, value)
        Macros.define("_sourcedir", str(self.sourcedir))
        with tempfile.NamedTemporaryFile() as tmp:
            tmp.write(content.encode())
            tmp.flush()
            try:
                with self._sanitize_environment():
                    with capture_stderr() as stderr:
                        return rpm.spec(tmp.name, flags)
            except ValueError as e:
>               raise RPMException(stderr=stderr) from e
E               specfile.exceptions.RPMException: %patchN is obsolete, use %patch N (or %patch -P N): %patch0 -p1
specfile/spec_parser.py:228: RPMException
=========================== short test summary info ============================
FAILED tests/integration/test_specfile.py::test_prep_traditional - specfile.e...
FAILED tests/integration/test_specfile.py::test_update_tag - specfile.excepti...
FAILED tests/integration/test_specfile.py::test_context_management - specfile...
FAILED tests/integration/test_specfile.py::test_parse_if_necessary - specfile...
================== 4 failed, 278 passed, 84 warnings in 6.00s ==================

Comment 1 Karolina Surma 2024-06-12 15:07:35 UTC
*** Bug 2291922 has been marked as a duplicate of this bug. ***

Comment 2 Fedora Fails To Install 2024-06-17 18:10:31 UTC
Hello,

Please note that this comment was generated automatically by https://pagure.io/releng/blob/main/f/scripts/ftbfs-fti/follow-policy.py
If you feel that this output has mistakes, please open an issue at https://pagure.io/releng/

All subpackages of a package against which this bug was filled are now installable or removed from Fedora 41.

Thanks for taking care of it!