From 068ba5f211833cc1232acfe15b673d26436719cd Mon Sep 17 00:00:00 2001
From: Aurélien Bompard <aurelien@bompard.org>
Date: Apr 20 2022 13:40:37 +0000
Subject: Add compatibility for Bodhi >= 6.0.0


Compatibility with Bodhi 5.X is retained.

Signed-off-by: Aurélien Bompard <aurelien@bompard.org>

---

diff --git a/fedpkg/__init__.py b/fedpkg/__init__.py
index 60a8193..f041b97 100644
--- a/fedpkg/__init__.py
+++ b/fedpkg/__init__.py
@@ -21,11 +21,7 @@ from datetime import datetime, timedelta
 from . import cli  # noqa
 from .lookaside import FedoraLookasideCache
 from pyrpkg.utils import cached_property
-
-try:
-    from bodhi.client.bindings import BodhiClient as _BodhiClient
-except ImportError:
-    _BodhiClient = None
+from pkg_resources import get_distribution, parse_version
 
 try:
     from distro import linux_distribution  # noqa
@@ -33,56 +29,11 @@ except ImportError:
     from platform import linux_distribution  # noqa
 
 
-if _BodhiClient is not None:
-    from fedora.client import AuthError
-
-    def clear_csrf_and_retry(func):
-        """Clear csrf token and retry
-
-        fedpkg uses Bodhi Python binding API list_overrides first before other
-        save and extend APIs. That causes a readonly csrf token is received,
-        which will be got again when next time to construct request data to
-        modify updates. That is not expected and AuthError will be raised.
-
-        So, the solution is to capture the AuthError error, clear the token and
-        try to modify update again by requesting another token with user's
-        credential.
-        """
-        def _decorator(self, *args, **kwargs):
-            try:
-                return func(self, *args, **kwargs)
-            except AuthError:
-                self._session.cookies.clear()
-                self.csrf_token = None
-                return func(self, *args, **kwargs)
-        return _decorator
-
-    class BodhiClient(_BodhiClient):
-        """Customized BodhiClient for fedpkg"""
-
-        UPDATE_TYPES = ['bugfix', 'security', 'enhancement', 'newpackage']
-        REQUEST_TYPES = ['testing', 'stable']
-        SUGGEST_TYPES = ['unspecified', 'reboot', 'logout']
-
-        @clear_csrf_and_retry
-        def save(self, *args, **kwargs):
-            return super(BodhiClient, self).save(*args, **kwargs)
-
-        @clear_csrf_and_retry
-        def save_override(self, *args, **kwargs):
-            return super(BodhiClient, self).save_override(*args, **kwargs)
-
-        @clear_csrf_and_retry
-        def extend_override(self, override, expiration_date):
-            data = dict(
-                nvr=override['nvr'],
-                notes=override['notes'],
-                expiration_date=expiration_date,
-                edited=override['nvr'],
-                csrf_token=self.csrf(),
-            )
-            return self.send_request(
-                'overrides/', verb='POST', auth=True, data=data)
+bodhi_version = get_distribution('bodhi-client').version
+if parse_version(bodhi_version) < parse_version("6.0.0"):
+    from .bodhi_5 import BodhiClient, UPDATE_TYPES, REQUEST_TYPES, SUGGEST_TYPES
+else:
+    from .bodhi_6 import BodhiClient, UPDATE_TYPES, REQUEST_TYPES, SUGGEST_TYPES
 
 
 class Commands(pyrpkg.Commands):
@@ -354,13 +305,13 @@ class Commands(pyrpkg.Commands):
             if not detail['type']:
                 raise ValueError(
                     'Missing update type, which is required to create update.')
-            if detail['type'] not in BodhiClient.UPDATE_TYPES:
+            if detail['type'] not in UPDATE_TYPES:
                 raise ValueError(
                     'Incorrect update type {0}'.format(detail['type']))
-            if detail['request'] not in BodhiClient.REQUEST_TYPES:
+            if detail['request'] not in REQUEST_TYPES:
                 raise ValueError(
                     'Incorrect request type {0}'.format(detail['request']))
-            if detail['suggest'] not in BodhiClient.SUGGEST_TYPES:
+            if detail['suggest'] not in SUGGEST_TYPES:
                 raise ValueError(
                     'Incorrect suggest type {0}'.format(detail['suggest']))
 
diff --git a/fedpkg/bodhi_5.py b/fedpkg/bodhi_5.py
new file mode 100644
index 0000000..9ffa1df
--- /dev/null
+++ b/fedpkg/bodhi_5.py
@@ -0,0 +1,63 @@
+# fedpkg - a Python library for RPM Packagers
+#
+# Copyright (C) 2011 Red Hat Inc.
+# Author(s): Jesse Keating <jkeating@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.  See http://www.gnu.org/copyleft/gpl.html for
+# the full text of the license.
+
+from bodhi.client.bindings import BodhiClient as _BodhiClient
+from fedora.client import AuthError
+
+
+UPDATE_TYPES = ['bugfix', 'security', 'enhancement', 'newpackage']
+REQUEST_TYPES = ['testing', 'stable']
+SUGGEST_TYPES = ['unspecified', 'reboot', 'logout']
+
+
+def clear_csrf_and_retry(func):
+    """Clear csrf token and retry
+
+    fedpkg uses Bodhi Python binding API list_overrides first before other
+    save and extend APIs. That causes a readonly csrf token is received,
+    which will be got again when next time to construct request data to
+    modify updates. That is not expected and AuthError will be raised.
+
+    So, the solution is to capture the AuthError error, clear the token and
+    try to modify update again by requesting another token with user's
+    credential.
+    """
+    def _decorator(self, *args, **kwargs):
+        try:
+            return func(self, *args, **kwargs)
+        except AuthError:
+            self._session.cookies.clear()
+            self.csrf_token = None
+            return func(self, *args, **kwargs)
+    return _decorator
+
+
+class BodhiClient(_BodhiClient):
+    """Customized BodhiClient for fedpkg"""
+
+    @clear_csrf_and_retry
+    def save(self, *args, **kwargs):
+        return super(BodhiClient, self).save(*args, **kwargs)
+
+    @clear_csrf_and_retry
+    def save_override(self, *args, **kwargs):
+        return super(BodhiClient, self).save_override(*args, **kwargs)
+
+    @clear_csrf_and_retry
+    def extend_override(self, override, expiration_date):
+        data = dict(
+            nvr=override['nvr'],
+            notes=override['notes'],
+            expiration_date=expiration_date,
+            csrf_token=self.csrf(),
+        )
+        return self.send_request(
+            'overrides/', verb='POST', auth=True, data=data)
diff --git a/fedpkg/bodhi_6.py b/fedpkg/bodhi_6.py
new file mode 100644
index 0000000..3b72cb0
--- /dev/null
+++ b/fedpkg/bodhi_6.py
@@ -0,0 +1,26 @@
+# fedpkg - a Python library for RPM Packagers
+#
+# Copyright (C) 2011 Red Hat Inc.
+# Author(s): Jesse Keating <jkeating@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.  See http://www.gnu.org/copyleft/gpl.html for
+# the full text of the license.
+
+from bodhi.client.bindings import BodhiClient as BodhiClient_
+from bodhi.client.constants import UPDATE_TYPES, REQUEST_TYPES, SUGGEST_TYPES  # noqa
+
+
+class BodhiClient(BodhiClient_):
+
+    def __init__(self, username, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+    def extend_override(self, override, new_expiration_date):
+        return self.save_override(
+            nvr=override["nvr"],
+            notes=override["notes"],
+            expiration_date=new_expiration_date
+        )
diff --git a/requirements.txt b/requirements.txt
index 7e52a2c..f880e99 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,3 +4,4 @@ openidc-client
 python-bugzilla
 rpkg
 six
+python-fedora
diff --git a/test/test_cli.py b/test/test_cli.py
index 6a9864d..03c9403 100644
--- a/test/test_cli.py
+++ b/test/test_cli.py
@@ -26,6 +26,7 @@ from six.moves import StringIO
 from six.moves.configparser import NoOptionError, NoSectionError
 
 import fedpkg.cli
+from fedpkg import parse_version, bodhi_version
 from fedpkg.bugzilla import BugzillaClient
 from fedpkg.cli import check_bodhi_version
 from freezegun import freeze_time
@@ -1712,6 +1713,10 @@ class TestBodhiOverride(CliTestCase):
                     'Buildroot override for %s already exists and not '
                     'expired.', 'rpkg-1.54-2.fc28')
 
+    @unittest.skipIf(
+        parse_version(bodhi_version) >= parse_version("6.0.0"),
+        "Retrying is built in Bodhi 6"
+    )
     @patch('fedora.client.OpenIdBaseClient._load_cookies')
     @patch('bodhi.client.bindings.BodhiClient.list_overrides')
     @patch('bodhi.client.bindings.BodhiClient.save_override')
@@ -1888,7 +1893,6 @@ class TestBodhiOverrideExtend(CliTestCase):
             'expiration_date': expected_expiration_date,
             'nvr': build_nvr,
             'notes': build_override['notes'],
-            'edited': build_nvr,
             'csrf_token': csrf.return_value,
         }
         send_request.assert_called_once_with(
@@ -1945,7 +1949,6 @@ class TestBodhiOverrideExtend(CliTestCase):
             'expiration_date': expected_expiration_date,
             'nvr': build_nvr,
             'notes': build_override['notes'],
-            'edited': build_nvr,
             'csrf_token': csrf.return_value,
         }
         send_request.assert_called_once_with(
@@ -2003,7 +2006,6 @@ class TestBodhiOverrideExtend(CliTestCase):
             'expiration_date': expected_expiration_date,
             'nvr': build_nvr,
             'notes': build_override['notes'],
-            'edited': build_nvr,
             'csrf_token': csrf.return_value,
         }
         send_request.assert_called_once_with(
@@ -2042,6 +2044,10 @@ class TestBodhiOverrideExtend(CliTestCase):
             six.assertRaisesRegex(self, rpkgError, '',
                                   cli.extend_buildroot_override)
 
+    @unittest.skipIf(
+        parse_version(bodhi_version) >= parse_version("6.0.0"),
+        "Retrying is built in Bodhi 6"
+    )
     @patch('fedpkg.BodhiClient.list_overrides')
     @patch('fedpkg.BodhiClient.csrf')
     @patch('fedpkg.BodhiClient.send_request')
@@ -2102,7 +2108,6 @@ class TestBodhiOverrideExtend(CliTestCase):
                 'expiration_date': expected_expiration_date,
                 'nvr': build_nvr,
                 'notes': build_override['notes'],
-                'edited': build_nvr,
                 'csrf_token': token,
             })
             for token in csrf.side_effect
diff --git a/tox.ini b/tox.ini
index 009f3ae..1be6026 100644
--- a/tox.ini
+++ b/tox.ini
@@ -18,6 +18,7 @@ commands =
     python -m pytest {posargs}
 setenv=
     PYCURL_SSL_LIBRARY=openssl
+    HOME={envtmpdir}/home
 
 [testenv:py27]
 deps =

