Patch for Python 3 Support
by Ralph Bean
Hello all,
I created a patch to update python-bugzilla to work on both python 2
and python 3. The unit tests all pass under both py2.7 and py3.2.
I have tested the login and query commands by hand on py2.6, py2.7,
and py3.2.
http://threebean.org/patches/python-bugzilla-Python3-support.patch
The patch is against the master branch (7ca8a60). If I should
recreate it against another branch, please let me know.
I'm also willing to update and maintain a spec file supporting both
versions if and when that time comes.
Cheers-
-Ralph
10 years, 9 months
[PATCH] Bug cloning
by Martin Cermak
Hi, I belive that cloning a bug is a useful feature. Below I'm
attaching a patch that should do the trick. I attempted to follow
the behaviour of Bugzilla's web UI:
----------------8<---------------------------------------------
diff --git a/bugzilla/base.py b/bugzilla/base.py
index 7748e2b..7e148c4 100644
--- a/bugzilla/base.py
+++ b/bugzilla/base.py
@@ -618,6 +618,17 @@ class BugzillaBase(object):
You may also add a "nomail":1 item, which will suppress email if set.'''
raise NotImplementedError
+ #---- Methods for cloning bugs.
+
+ def _clonebug(self,id,product=None,component=None,version=None):
+ '''IMPLEMENT ME: Clone the given bug. This is the raw call, and no data checking is
+ done here. That's up to the clonebug method.'''
+ raise NotImplementedError
+
+ def clonebug(self,product=None,component=None,version=None):
+ '''Clone the given bug.'''
+ return self.bugzilla._clonebug(self.bug_id,product,component,version)
+
#---- Methods for working with attachments
def _attachment_encode(self,fh):
@@ -1305,6 +1316,11 @@ class _Bug(object):
'''An alias for refresh()'''
self.refresh()
+ def clonebug(self,product=None,component=None,version=None):
+ '''Clone the given bug. This is the raw call, and no data checking is
+ done here. That's up to the clonebug method.'''
+ return self.bugzilla._clonebug(self.bug_id,product,component,version)
+
def setstatus(self,status,comment='',private=False,private_in_it=False,nomail=False):
'''Update the status for this bug report.
Valid values for status are listed in querydefaults['bug_status_list']
diff --git a/bugzilla/rhbugzilla.py b/bugzilla/rhbugzilla.py
index 4233d32..59fb418 100644
--- a/bugzilla/rhbugzilla.py
+++ b/bugzilla/rhbugzilla.py
@@ -130,6 +130,17 @@ class RHBugzilla(Bugzilla4):
requestee (as in: needinfo from smartguy(a)answers.com). Alas.'''
return self._proxy.bugzilla.updateFlags(id,flags)
+ #---- Methods for cloning bugs.
+
+ def _clonebug(self,id,product=None,component=None,version=None):
+ '''IMPLEMENT MEClone the given bug. This is the raw call, and no data checking is
+ done here. That's up to the clonebug method.'''
+ raise NotImplementedError
+
+ def clonebug(self,product=None,component=None,version=None):
+ '''Clone the given bug.'''
+ return self.bugzilla._clonebug(self.bug_id,product,component,version)
+
#---- Methods for working with attachments
# If your bugzilla wants attachments in something other than base64, you
@@ -281,6 +292,94 @@ class RHBugzilla(Bugzilla4):
return self._close_bug(id, update)
#return self._update_bug(id,update)
+ def _clonebug(self,id,product=None,component=None,version=None):
+ '''Clone this bug similarly as one can do it in the webui'''
+ origbug = self.getbug(id)
+ clone_message = '+++ This bug was initially created as a clone of Bug #%s +++\n\n' % (origbug.id)
+ isprivate = False
+ isadditional = False
+ for rec in origbug.longdescs:
+ if isadditional:
+ clone_message += '\n--- Additional comment from '
+ clone_message += rec['author']['realname']
+ clone_message += ' on '
+ clone_message += rec['time']
+ clone_message += ' EDT ---\n\n'
+ if 'extra_data' in rec.keys():
+ clone_message += '\n\n*** This bug has been marked as a duplicate of bug %s ***\n' % (rec['extra_data'])
+ else:
+ clone_message += rec['body'] + "\n"
+ isadditional = True
+ if rec['isprivate'] == 1:
+ isprivate = True
+ cc = origbug.cc
+ cc.append(origbug.reporter)
+ depends_on = str(origbug.bug_id) + ' '
+ depends_on += ' '.join([str(i) for i in origbug.dependson])
+ new_product = product
+ if new_product == None: new_product = origbug.product
+ new_component = component
+ if new_component == None: new_component = origbug.component
+ new_version = version
+ new_target_release = None
+ if new_version == None and new_product != origbug.product:
+ releases = self._proxy.Product.get({'names': new_product, 'include_fields': ['releases']})
+ prodinfo = releases['products'][0]['releases']
+ versions = [p['name'] for p in prodinfo]
+ new_version = versions[-1]
+ elif new_version == None:
+ new_target_release = origbug.target_release
+ new_version = origbug.version
+ kwargs = {
+ 'product': new_product,
+ 'component': new_component,
+ 'version': new_version,
+ 'op_sys': origbug.op_sys,
+ 'platform': origbug.platform,
+ 'summary': origbug.summary,
+ 'description': clone_message,
+ 'comment_is_private': isprivate,
+ 'priority': origbug.priority,
+ 'bug_severity': origbug.bug_severity,
+ 'depends_on': depends_on,
+ 'blocked': origbug.blocked,
+ 'whiteboard': origbug.whiteboard,
+ 'keywords': origbug.keywords,
+ 'cc': cc,
+ 'estimated_time': origbug.estimated_time,
+ 'remaining_time': origbug.remaining_time,
+ 'deadline': origbug.deadline,
+ 'url': origbug.bug_file_loc,
+ 'target_release': new_target_release
+ }
+ for key in kwargs.keys():
+ if kwargs[key] == None:
+ del kwargs[key]
+ newbug = self.createbug(**kwargs)
+ origgroups = [grp['name'] for grp in origbug.groups if grp['ison'] == 1]
+ update = dict(
+ cf_clone_of = str(origbug.id),
+ groups = dict(add = origgroups),
+ cf_qa_whiteboard = origbug.qa_whiteboard,
+ cf_cust_facing = origbug.cust_facing,
+ cf_devel_whiteboard = origbug.devel_whiteboard,
+ cf_internal_whiteboard = origbug.internal_whiteboard,
+ cf_build_id = origbug.build_id,
+ cf_partner = origbug.partner,
+ cf_verified = ['Any'],
+ cf_environment = origbug.cf_environment
+ )
+ changes = self._update_bug(newbug.id,update)
+ # external tracker references
+ extbugs = []
+ for eb in origbug.external_bugs:
+ neb = {}
+ neb['ext_bz_bug_id'] = eb['ext_bz_bug_id']
+ neb['ext_type_id'] = eb['type']['id']
+ extbugs.append(neb)
+ self._proxy.ExternalBugs.add_external_bug({'bug_ids': [newbug.id], 'external_bugs': extbugs})
+ return newbug
+
def _setassignee(self,id,**data):
'''Raw xmlrpc call to set one of the assignee fields on a bug.
changeAssignment($id, $data, $username, $password)
----------------8<---------------------------------------------
Martin
11 years, 1 month
ANNOUNCE: python-bugzilla 0.8.0 released
by Cole Robinson
I'm happy to announce a new release of python-bugzilla, version 0.8.0.
The releases can be downloaded from:
https://fedorahosted.org/released/python-bugzilla/python-bugzilla-0.8.0.t...
This release includes:
- Replace usage of non-upstream Red Hat bugzilla APIs with upstream replacements
- Test suite improvements, nearly complete code coverage
- Fix all open bug reports and RFEs
In particular, this release is necessary to support the next major update of
bugzilla.redhat.com. Most of the custom bugzilla.redhat.com XMLRPC API calls
are being removed, so python-bugzilla has been adjusted to transparently use
the upstream API replacements. There are some behavior changes though (that I
noticed):
- Format of Bug.longdescs/Bug.comments changed, though most of the info is
still available. Main change is that 'body' was renamed to 'text'
- ID field for Bug.attachments was renamed from attach_id -> id
- Bug.url (actual URL for the bug report) was been renamed to Bug.weburl.
Bug.url is now the URL field in the bug report.
- RHBZ parameter format back compatibility now must be explicitly enabled in
the API by setting RHBugzilla.rhbz_back_compat = True. Can also be set via
__init__. What this toggles:
-- Converts 'blocks'/'blockedby'/'blocked', 'keywords', and 'alias' fields
from a list to old style comma separated string
-- Converts current more verbose 'flags' field to old style comma separated string
-- Converts 'groups' value into more verbose setting per the old format.
However, usage of this back compat option is not recommended. I suggest
updating your scripts to use the new values returned by bugzilla.redhat.com,
since most fields are now stable and won't change in the future.
If you hit any regressions, please drop a mail to
python-bugzilla(a)lists.fedoraproject.org or file a bug in rhbz:
https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora&component=python...
Thanks,
Cole
11 years, 2 months
[PATCH] Fix version(s) typo
by Richard Marko
Signed-off-by: Richard Marko <rmarko(a)redhat.com>
---
bugzilla/rhbugzilla.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bugzilla/rhbugzilla.py b/bugzilla/rhbugzilla.py
index a7c14ff..dffcbdc 100644
--- a/bugzilla/rhbugzilla.py
+++ b/bugzilla/rhbugzilla.py
@@ -184,7 +184,7 @@ class RHBugzilla(Bugzilla42):
if 'version' in bug:
val = bug['version']
bug['versions'] = type(val) is list and val or [val]
- bug['version'] = bug['version'][0]
+ bug['version'] = bug['versions'][0]
if not self.rhbz_back_compat:
return
--
1.8.1
11 years, 2 months
[PATCH] Expose bug history
by Richard Marko
Signed-off-by: Richard Marko <rmarko(a)redhat.com>
---
bugzilla/base.py | 6 ++++++
bugzilla/bug.py | 10 ++++++++++
2 files changed, 16 insertions(+)
diff --git a/bugzilla/base.py b/bugzilla/base.py
index 57f5872..d43ce60 100644
--- a/bugzilla/base.py
+++ b/bugzilla/base.py
@@ -744,6 +744,12 @@ class BugzillaBase(object):
'''
pass
+ def bugs_history(self, bug_ids):
+ '''
+ Experimental. Gets the history of changes for
+ particular bugs in the database.
+ '''
+ return self._proxy.Bug.history({'ids': bug_ids})
#######################################
# Methods for modifying existing bugs #
diff --git a/bugzilla/bug.py b/bugzilla/bug.py
index 8c91b9b..feef51c 100644
--- a/bugzilla/bug.py
+++ b/bugzilla/bug.py
@@ -407,6 +407,16 @@ class _Bug(object):
return f[0]['status']
+ ########################
+ # Experimental methods #
+ ########################
+
+ def get_history(self):
+ '''
+ Experimental. Get the history of changes for this bug.
+ '''
+ return self.bugzilla.bugs_history([self.bug_id])
+
######################
# Deprecated methods #
######################
--
1.8.1
11 years, 2 months