Skip to content

Commit 1bc70c4

Browse files
committed
rhbugzilla: Turn converter functions into a static class
This decouples the class inheritance magic and makes it more clear in Bugzilla() when exactly behavior is changing for rhbz handling Signed-off-by: Cole Robinson <[email protected]>
1 parent e28881e commit 1bc70c4

4 files changed

Lines changed: 102 additions & 92 deletions

File tree

bugzilla/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
from .apiversion import version, __version__
1010
from .base import Bugzilla
1111
from .exceptions import BugzillaError
12-
from .rhbugzilla import RHBugzilla
1312
from .oldclasses import (Bugzilla3, Bugzilla32, Bugzilla34, Bugzilla36,
1413
Bugzilla4, Bugzilla42, Bugzilla44,
15-
NovellBugzilla, RHBugzilla3, RHBugzilla4)
14+
NovellBugzilla, RHBugzilla, RHBugzilla3, RHBugzilla4)
1615

1716

1817
# This is the public API. If you are explicitly instantiating any other

bugzilla/base.py

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from ._compatimports import Mapping, urlparse, urlunparse, parse_qsl
2424
from .bug import Bug, User
2525
from .exceptions import BugzillaError
26+
from .rhbugzilla import _RHBugzillaConverters
2627
from ._session import _BugzillaSession
2728
from ._util import listify
2829

@@ -233,33 +234,34 @@ def __init__(self, url=-1, user=None, password=None, cookiefile=-1,
233234
if url:
234235
self.connect(url)
235236

237+
def _detect_is_redhat_bugzilla(self):
238+
if self._is_redhat_bugzilla:
239+
return True
240+
241+
if "bugzilla.redhat.com" in self.url:
242+
log.info("Using RHBugzilla for URL containing bugzilla.redhat.com")
243+
return True
244+
245+
try:
246+
extensions = self._backend.bugzilla_extensions()
247+
if "RedHat" in extensions.get('extensions', {}):
248+
log.info("Found RedHat bugzilla extension, "
249+
"using RHBugzilla")
250+
return True
251+
except Exception:
252+
log.debug("Failed to fetch bugzilla extensions", exc_info=True)
253+
254+
return False
255+
236256
def _init_class_from_url(self):
237257
"""
238258
Detect if we should use RHBugzilla class, and if so, set it
239259
"""
240-
from .rhbugzilla import RHBugzilla # pylint: disable=cyclic-import
241-
if isinstance(self, RHBugzilla):
242-
return
243-
244-
c = None
245-
if "bugzilla.redhat.com" in self.url:
246-
log.info("Using RHBugzilla for URL containing bugzilla.redhat.com")
247-
c = RHBugzilla
248-
else:
249-
try:
250-
extensions = self._backend.bugzilla_extensions()
251-
if "RedHat" in extensions.get('extensions', {}):
252-
log.info("Found RedHat bugzilla extension, "
253-
"using RHBugzilla")
254-
c = RHBugzilla
255-
except Exception:
256-
log.debug("Failed to fetch bugzilla extensions", exc_info=True)
257-
258-
if not c:
259-
return
260+
from .oldclasses import RHBugzilla # pylint: disable=cyclic-import
260261

261-
self.__class__ = c
262-
self._is_redhat_bugzilla = True
262+
if self._detect_is_redhat_bugzilla():
263+
self.__class__ = RHBugzilla
264+
self._is_redhat_bugzilla = True
263265

264266
def _get_field_aliases(self):
265267
# List of field aliases. Maps old style RHBZ parameter
@@ -1279,12 +1281,18 @@ def pre_translation(self, query):
12791281
In order to keep the API the same, Bugzilla4 needs to process the
12801282
query and the result. This also applies to the refresh() function
12811283
"""
1284+
if self._is_redhat_bugzilla:
1285+
_RHBugzillaConverters.pre_translation(query)
1286+
query.update(self._process_include_fields(
1287+
query["include_fields"], None, None))
12821288

12831289
def post_translation(self, query, bug):
12841290
"""
12851291
In order to keep the API the same, Bugzilla4 needs to process the
12861292
query and the result. This also applies to the refresh() function
12871293
"""
1294+
if self._is_redhat_bugzilla:
1295+
_RHBugzillaConverters.post_translation(query, bug)
12881296

12891297
def bugs_history_raw(self, bug_ids):
12901298
"""
@@ -1396,18 +1404,28 @@ def build_update(self,
13961404
https://bugzilla.readthedocs.io/en/latest/api/core/v1/bug.html#create-bug
13971405
"""
13981406
ret = {}
1407+
rhbzret = {}
13991408

14001409
# These are only supported for rhbugzilla
1401-
for key, val in [
1402-
("fixed_in", fixed_in),
1403-
("devel_whiteboard", devel_whiteboard),
1404-
("qa_whiteboard", qa_whiteboard),
1405-
("internal_whiteboard", internal_whiteboard),
1406-
("sub_component", sub_component),
1407-
]:
1408-
if val is not None:
1409-
raise ValueError("bugzilla instance does not support "
1410-
"updating '%s'" % key)
1410+
#
1411+
# This should not be extended any more.
1412+
# If people want to handle custom fields, manually extend the
1413+
# returned dictionary.
1414+
rhbzargs = {
1415+
"fixed_in": fixed_in,
1416+
"devel_whiteboard": devel_whiteboard,
1417+
"qa_whiteboard": qa_whiteboard,
1418+
"internal_whiteboard": internal_whiteboard,
1419+
"sub_component": sub_component,
1420+
}
1421+
if self._is_redhat_bugzilla:
1422+
rhbzret = _RHBugzillaConverters.convert_build_update(
1423+
component=component, **rhbzargs)
1424+
else:
1425+
for key, val in rhbzargs.items():
1426+
if val is not None:
1427+
raise ValueError("bugzilla instance does not support "
1428+
"updating '%s'" % key)
14111429

14121430
def s(key, val, convert=None):
14131431
if val is None:
@@ -1479,6 +1497,7 @@ def c(val):
14791497
if comment_private:
14801498
ret["comment"]["is_private"] = comment_private
14811499

1500+
ret.update(rhbzret)
14821501
return ret
14831502

14841503

bugzilla/oldclasses.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# See the COPYING file in the top-level directory.
33

44
from .base import Bugzilla
5-
from .rhbugzilla import RHBugzilla
65

76
# These are old compat classes. Nothing new should be added here,
87
# and these should not be altered
@@ -40,6 +39,23 @@ class NovellBugzilla(Bugzilla):
4039
pass
4140

4241

42+
class RHBugzilla(Bugzilla):
43+
"""
44+
Helper class for historical bugzilla.redhat.com back compat
45+
46+
Historically this class used many more non-upstream methods, but
47+
in 2012 RH started dropping most of its custom bits. By that time,
48+
upstream BZ had most of the important functionality.
49+
50+
Much of the remaining code here is just trying to keep things operating
51+
in python-bugzilla back compatible manner.
52+
53+
This class was written using bugzilla.redhat.com's API docs:
54+
https://bugzilla.redhat.com/docs/en/html/api/
55+
"""
56+
_is_redhat_bugzilla = True
57+
58+
4359
class RHBugzilla3(RHBugzilla):
4460
pass
4561

bugzilla/rhbugzilla.py

Lines changed: 33 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -8,56 +8,26 @@
88

99
from logging import getLogger
1010

11-
from .base import Bugzilla
1211
from ._util import listify
1312

1413
log = getLogger(__name__)
1514

1615

17-
class RHBugzilla(Bugzilla):
16+
class _RHBugzillaConverters(object):
1817
"""
19-
Bugzilla class for connecting Red Hat's forked bugzilla instance,
20-
bugzilla.redhat.com
21-
22-
Historically this class used many more non-upstream methods, but
23-
in 2012 RH started dropping most of its custom bits. By that time,
24-
upstream BZ had most of the important functionality.
25-
26-
Much of the remaining code here is just trying to keep things operating
27-
in python-bugzilla back compatible manner.
28-
29-
This class was written using bugzilla.redhat.com's API docs:
30-
https://bugzilla.redhat.com/docs/en/html/api/
18+
Static class that holds functional Red Hat back compat converters.
19+
Called inline in Bugzilla
3120
"""
32-
_is_redhat_bugzilla = True
33-
34-
######################
35-
# Bug update methods #
36-
######################
37-
38-
def build_update(self, **kwargs):
39-
# pylint: disable=arguments-differ
21+
@staticmethod
22+
def convert_build_update(
23+
component=None,
24+
fixed_in=None,
25+
qa_whiteboard=None,
26+
devel_whiteboard=None,
27+
internal_whiteboard=None,
28+
sub_component=None):
4029
adddict = {}
4130

42-
def pop(key, destkey):
43-
val = kwargs.pop(key, None)
44-
if val is None:
45-
return
46-
adddict[destkey] = val
47-
48-
def get_sub_component():
49-
val = kwargs.pop("sub_component", None)
50-
if val is None:
51-
return
52-
53-
if not isinstance(val, dict):
54-
component = listify(kwargs.get("component"))
55-
if not component:
56-
raise ValueError("component must be specified if "
57-
"specifying sub_component")
58-
val = {component[0]: val}
59-
adddict["sub_components"] = val
60-
6131
def get_alias():
6232
# RHBZ has a custom extension to allow a bug to have multiple
6333
# aliases, so the format of aliases is
@@ -74,25 +44,35 @@ def get_alias():
7444
# Implementation will go here when it's available
7545
pass
7646

77-
pop("fixed_in", "cf_fixed_in")
78-
pop("qa_whiteboard", "cf_qa_whiteboard")
79-
pop("devel_whiteboard", "cf_devel_whiteboard")
80-
pop("internal_whiteboard", "cf_internal_whiteboard")
47+
if fixed_in is not None:
48+
adddict["cf_fixed_in"] = fixed_in
49+
if qa_whiteboard is not None:
50+
adddict["cf_qa_whiteboard"] = qa_whiteboard
51+
if devel_whiteboard is not None:
52+
adddict["cf_devel_whiteboard"] = devel_whiteboard
53+
if internal_whiteboard is not None:
54+
adddict["cf_internal_whiteboard"] = internal_whiteboard
55+
56+
if sub_component:
57+
if not isinstance(sub_component, dict):
58+
component = listify(component)
59+
if not component:
60+
raise ValueError("component must be specified if "
61+
"specifying sub_component")
62+
sub_component = {component[0]: sub_component}
63+
adddict["sub_components"] = sub_component
8164

82-
get_sub_component()
8365
get_alias()
8466

85-
vals = Bugzilla.build_update(self, **kwargs)
86-
vals.update(adddict)
87-
88-
return vals
67+
return adddict
8968

9069

9170
#################
9271
# Query methods #
9372
#################
9473

95-
def pre_translation(self, query):
74+
@staticmethod
75+
def pre_translation(query):
9676
"""
9777
Translates the query for possible aliases
9878
"""
@@ -118,15 +98,11 @@ def pre_translation(self, query):
11898
query['include_fields'] = query['column_list']
11999
del query['column_list']
120100

121-
# We need to do this for users here for users that
122-
# don't call build_query
123-
query.update(self._process_include_fields(query["include_fields"],
124-
None, None))
125-
126101
if old != query:
127102
log.debug("RHBugzilla pretranslated query to: %s", query)
128103

129-
def post_translation(self, query, bug):
104+
@staticmethod
105+
def post_translation(query, bug):
130106
"""
131107
Convert the results of getbug back to the ancient RHBZ value
132108
formats

0 commit comments

Comments
 (0)