|
Packit Service |
4b33e2 |
# base.py - the base classes etc. for a Python interface to bugzilla
|
|
Packit Service |
4b33e2 |
#
|
|
Packit Service |
4b33e2 |
# Copyright (C) 2007, 2008, 2009, 2010 Red Hat Inc.
|
|
Packit Service |
4b33e2 |
# Author: Will Woods <wwoods@redhat.com>
|
|
Packit Service |
4b33e2 |
#
|
|
Packit Service |
4b33e2 |
# This program is free software; you can redistribute it and/or modify it
|
|
Packit Service |
4b33e2 |
# under the terms of the GNU General Public License as published by the
|
|
Packit Service |
4b33e2 |
# Free Software Foundation; either version 2 of the License, or (at your
|
|
Packit Service |
4b33e2 |
# option) any later version. See http://www.gnu.org/copyleft/gpl.html for
|
|
Packit Service |
4b33e2 |
# the full text of the license.
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
from __future__ import unicode_literals
|
|
Packit Service |
4b33e2 |
import locale
|
|
Packit Service |
4b33e2 |
from logging import getLogger
|
|
Packit Service |
4b33e2 |
import sys
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
log = getLogger(__name__)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
class Bug(object):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
A container object for a bug report. Requires a Bugzilla instance -
|
|
Packit Service |
4b33e2 |
every Bug is on a Bugzilla, obviously.
|
|
Packit Service |
4b33e2 |
Optional keyword args:
|
|
Packit Service |
4b33e2 |
dict=DICT - populate attributes with the result of a getBug() call
|
|
Packit Service |
4b33e2 |
bug_id=ID - if dict does not contain bug_id, this is required before
|
|
Packit Service |
4b33e2 |
you can read any attributes or make modifications to this
|
|
Packit Service |
4b33e2 |
bug.
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
def __init__(self, bugzilla, bug_id=None, dict=None, autorefresh=False):
|
|
Packit Service |
4b33e2 |
# pylint: disable=redefined-builtin
|
|
Packit Service |
4b33e2 |
# API had pre-existing issue that we can't change ('dict' usage)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
self.bugzilla = bugzilla
|
|
Packit Service |
4b33e2 |
self._bug_fields = []
|
|
Packit Service |
4b33e2 |
self.autorefresh = autorefresh
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
if not dict:
|
|
Packit Service |
4b33e2 |
dict = {}
|
|
Packit Service |
4b33e2 |
if bug_id:
|
|
Packit Service |
4b33e2 |
dict["id"] = bug_id
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
log.debug("Bug(%s)", sorted(dict.keys()))
|
|
Packit Service |
4b33e2 |
self._update_dict(dict)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
self.weburl = bugzilla.url.replace('xmlrpc.cgi',
|
|
Packit Service |
4b33e2 |
'show_bug.cgi?id=%i' % self.bug_id)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def __str__(self):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Return a simple string representation of this bug
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
This is available only for compatibility. Using 'str(bug)' and
|
|
Packit Service |
4b33e2 |
'print(bug)' is not recommended because of potential encoding issues.
|
|
Packit Service |
4b33e2 |
Please use unicode(bug) where possible.
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
if sys.version_info[0] >= 3:
|
|
Packit Service |
4b33e2 |
return self.__unicode__()
|
|
Packit Service |
4b33e2 |
else:
|
|
Packit Service |
4b33e2 |
return self.__unicode__().encode(
|
|
Packit Service |
4b33e2 |
locale.getpreferredencoding(), 'replace')
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def __unicode__(self):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Return a simple unicode string representation of this bug
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
return "#%-6s %-10s - %s - %s" % (self.bug_id, self.bug_status,
|
|
Packit Service |
4b33e2 |
self.assigned_to, self.summary)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def __repr__(self):
|
|
Packit Service |
4b33e2 |
return '<Bug #%i on %s at %#x>' % (self.bug_id, self.bugzilla.url,
|
|
Packit Service |
4b33e2 |
id(self))
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def __getattr__(self, name):
|
|
Packit Service |
4b33e2 |
refreshed = False
|
|
Packit Service |
4b33e2 |
while True:
|
|
Packit Service |
4b33e2 |
if refreshed and name in self.__dict__:
|
|
Packit Service |
4b33e2 |
# If name was in __dict__ to begin with, __getattr__ would
|
|
Packit Service |
4b33e2 |
# have never been called.
|
|
Packit Service |
4b33e2 |
return self.__dict__[name]
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
# pylint: disable=protected-access
|
|
Packit Service |
4b33e2 |
aliases = self.bugzilla._get_bug_aliases()
|
|
Packit Service |
4b33e2 |
# pylint: enable=protected-access
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
for newname, oldname in aliases:
|
|
Packit Service |
4b33e2 |
if name == oldname and newname in self.__dict__:
|
|
Packit Service |
4b33e2 |
return self.__dict__[newname]
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
# Doing dir(bugobj) does getattr __members__/__methods__,
|
|
Packit Service |
4b33e2 |
# don't refresh for those
|
|
Packit Service |
4b33e2 |
if name.startswith("__") and name.endswith("__"):
|
|
Packit Service |
4b33e2 |
break
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
if refreshed or not self.autorefresh:
|
|
Packit Service |
4b33e2 |
break
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
log.info("Bug %i missing attribute '%s' - doing implicit "
|
|
Packit Service |
4b33e2 |
"refresh(). This will be slow, if you want to avoid "
|
|
Packit Service |
4b33e2 |
"this, properly use query/getbug include_fields, and "
|
|
Packit Service |
4b33e2 |
"set bugzilla.bug_autorefresh = False to force failure.",
|
|
Packit Service |
4b33e2 |
self.bug_id, name)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
# We pass the attribute name to getbug, since for something like
|
|
Packit Service |
4b33e2 |
# 'attachments' which downloads lots of data we really want the
|
|
Packit Service |
4b33e2 |
# user to opt in.
|
|
Packit Service |
4b33e2 |
self.refresh(extra_fields=[name])
|
|
Packit Service |
4b33e2 |
refreshed = True
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
msg = ("Bug object has no attribute '%s'." % name)
|
|
Packit Service |
4b33e2 |
if not self.autorefresh:
|
|
Packit Service |
4b33e2 |
msg += ("\nIf '%s' is a bugzilla attribute, it may not have "
|
|
Packit Service |
4b33e2 |
"been cached when the bug was fetched. You may want "
|
|
Packit Service |
4b33e2 |
"to adjust your include_fields for getbug/query." % name)
|
|
Packit Service |
4b33e2 |
raise AttributeError(msg)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def refresh(self, include_fields=None, exclude_fields=None,
|
|
Packit Service |
4b33e2 |
extra_fields=None):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Refresh the bug with the latest data from bugzilla
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
# pylint: disable=protected-access
|
|
Packit Service |
4b33e2 |
r = self.bugzilla._getbug(self.bug_id,
|
|
Packit Service |
4b33e2 |
include_fields=include_fields, exclude_fields=exclude_fields,
|
|
Packit Service |
4b33e2 |
extra_fields=self._bug_fields + (extra_fields or []))
|
|
Packit Service |
4b33e2 |
# pylint: enable=protected-access
|
|
Packit Service |
4b33e2 |
self._update_dict(r)
|
|
Packit Service |
4b33e2 |
reload = refresh
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def _update_dict(self, newdict):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Update internal dictionary, in a way that ensures no duplicate
|
|
Packit Service |
4b33e2 |
entries are stored WRT field aliases
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
if self.bugzilla:
|
|
Packit Service |
4b33e2 |
self.bugzilla.post_translation({}, newdict)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
# pylint: disable=protected-access
|
|
Packit Service |
4b33e2 |
aliases = self.bugzilla._get_bug_aliases()
|
|
Packit Service |
4b33e2 |
# pylint: enable=protected-access
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
for newname, oldname in aliases:
|
|
Packit Service |
4b33e2 |
if oldname not in newdict:
|
|
Packit Service |
4b33e2 |
continue
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
if newname not in newdict:
|
|
Packit Service |
4b33e2 |
newdict[newname] = newdict[oldname]
|
|
Packit Service |
4b33e2 |
elif newdict[newname] != newdict[oldname]:
|
|
Packit Service |
4b33e2 |
log.debug("Update dict contained differing alias values "
|
|
Packit Service |
4b33e2 |
"d[%s]=%s and d[%s]=%s , dropping the value "
|
|
Packit Service |
4b33e2 |
"d[%s]", newname, newdict[newname], oldname,
|
|
Packit Service |
4b33e2 |
newdict[oldname], oldname)
|
|
Packit Service |
4b33e2 |
del(newdict[oldname])
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
for key in newdict.keys():
|
|
Packit Service |
4b33e2 |
if key not in self._bug_fields:
|
|
Packit Service |
4b33e2 |
self._bug_fields.append(key)
|
|
Packit Service |
4b33e2 |
self.__dict__.update(newdict)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
if 'id' not in self.__dict__ and 'bug_id' not in self.__dict__:
|
|
Packit Service |
4b33e2 |
raise TypeError("Bug object needs a bug_id")
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
##################
|
|
Packit Service |
4b33e2 |
# pickle helpers #
|
|
Packit Service |
4b33e2 |
##################
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def __getstate__(self):
|
|
Packit Service |
4b33e2 |
ret = {}
|
|
Packit Service |
4b33e2 |
for key in self._bug_fields:
|
|
Packit Service |
4b33e2 |
ret[key] = self.__dict__[key]
|
|
Packit Service |
4b33e2 |
return ret
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def __setstate__(self, vals):
|
|
Packit Service |
4b33e2 |
self._bug_fields = []
|
|
Packit Service |
4b33e2 |
self.bugzilla = None
|
|
Packit Service |
4b33e2 |
self._update_dict(vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
#####################
|
|
Packit Service |
4b33e2 |
# Modify bug status #
|
|
Packit Service |
4b33e2 |
#####################
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def setstatus(self, status, comment=None, private=False):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Update the status for this bug report.
|
|
Packit Service |
4b33e2 |
Commonly-used values are ASSIGNED, MODIFIED, and NEEDINFO.
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
To change bugs to CLOSED, use .close() instead.
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
# Note: fedora bodhi uses this function
|
|
Packit Service |
4b33e2 |
vals = self.bugzilla.build_update(status=status,
|
|
Packit Service |
4b33e2 |
comment=comment,
|
|
Packit Service |
4b33e2 |
comment_private=private)
|
|
Packit Service |
4b33e2 |
log.debug("setstatus: update=%s", vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
return self.bugzilla.update_bugs(self.bug_id, vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def close(self, resolution, dupeid=None, fixedin=None,
|
|
Packit Service |
4b33e2 |
comment=None, isprivate=False):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Close this bug.
|
|
Packit Service |
4b33e2 |
Valid values for resolution are in bz.querydefaults['resolution_list']
|
|
Packit Service |
4b33e2 |
For bugzilla.redhat.com that's:
|
|
Packit Service |
4b33e2 |
['NOTABUG', 'WONTFIX', 'DEFERRED', 'WORKSFORME', 'CURRENTRELEASE',
|
|
Packit Service |
4b33e2 |
'RAWHIDE', 'ERRATA', 'DUPLICATE', 'UPSTREAM', 'NEXTRELEASE',
|
|
Packit Service |
4b33e2 |
'CANTFIX', 'INSUFFICIENT_DATA']
|
|
Packit Service |
4b33e2 |
If using DUPLICATE, you need to set dupeid to the ID of the other bug.
|
|
Packit Service |
4b33e2 |
If using WORKSFORME/CURRENTRELEASE/RAWHIDE/ERRATA/UPSTREAM/NEXTRELEASE
|
|
Packit Service |
4b33e2 |
you can (and should) set 'new_fixed_in' to a string representing the
|
|
Packit Service |
4b33e2 |
version that fixes the bug.
|
|
Packit Service |
4b33e2 |
You can optionally add a comment while closing the bug. Set 'isprivate'
|
|
Packit Service |
4b33e2 |
to True if you want that comment to be private.
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
# Note: fedora bodhi uses this function
|
|
Packit Service |
4b33e2 |
vals = self.bugzilla.build_update(comment=comment,
|
|
Packit Service |
4b33e2 |
comment_private=isprivate,
|
|
Packit Service |
4b33e2 |
resolution=resolution,
|
|
Packit Service |
4b33e2 |
dupe_of=dupeid,
|
|
Packit Service |
4b33e2 |
fixed_in=fixedin,
|
|
Packit Service |
4b33e2 |
status="CLOSED")
|
|
Packit Service |
4b33e2 |
log.debug("close: update=%s", vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
return self.bugzilla.update_bugs(self.bug_id, vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
#####################
|
|
Packit Service |
4b33e2 |
# Modify bug emails #
|
|
Packit Service |
4b33e2 |
#####################
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def setassignee(self, assigned_to=None,
|
|
Packit Service |
4b33e2 |
qa_contact=None, comment=None):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Set any of the assigned_to or qa_contact fields to a new
|
|
Packit Service |
4b33e2 |
bugzilla account, with an optional comment, e.g.
|
|
Packit Service |
4b33e2 |
setassignee(assigned_to='wwoods@redhat.com')
|
|
Packit Service |
4b33e2 |
setassignee(qa_contact='wwoods@redhat.com', comment='wwoods QA ftw')
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
You must set at least one of the two assignee fields, or this method
|
|
Packit Service |
4b33e2 |
will throw a ValueError.
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
Returns [bug_id, mailresults].
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
if not (assigned_to or qa_contact):
|
|
Packit Service |
4b33e2 |
raise ValueError("You must set one of assigned_to "
|
|
Packit Service |
4b33e2 |
" or qa_contact")
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
vals = self.bugzilla.build_update(assigned_to=assigned_to,
|
|
Packit Service |
4b33e2 |
qa_contact=qa_contact,
|
|
Packit Service |
4b33e2 |
comment=comment)
|
|
Packit Service |
4b33e2 |
log.debug("setassignee: update=%s", vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
return self.bugzilla.update_bugs(self.bug_id, vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def addcc(self, cclist, comment=None):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Adds the given email addresses to the CC list for this bug.
|
|
Packit Service |
4b33e2 |
cclist: list of email addresses (strings)
|
|
Packit Service |
4b33e2 |
comment: optional comment to add to the bug
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
vals = self.bugzilla.build_update(comment=comment,
|
|
Packit Service |
4b33e2 |
cc_add=cclist)
|
|
Packit Service |
4b33e2 |
log.debug("addcc: update=%s", vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
return self.bugzilla.update_bugs(self.bug_id, vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def deletecc(self, cclist, comment=None):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Removes the given email addresses from the CC list for this bug.
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
vals = self.bugzilla.build_update(comment=comment,
|
|
Packit Service |
4b33e2 |
cc_remove=cclist)
|
|
Packit Service |
4b33e2 |
log.debug("deletecc: update=%s", vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
return self.bugzilla.update_bugs(self.bug_id, vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
####################
|
|
Packit Service |
4b33e2 |
# comment handling #
|
|
Packit Service |
4b33e2 |
####################
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def addcomment(self, comment, private=False):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Add the given comment to this bug. Set private to True to mark this
|
|
Packit Service |
4b33e2 |
comment as private.
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
# Note: fedora bodhi uses this function
|
|
Packit Service |
4b33e2 |
vals = self.bugzilla.build_update(comment=comment,
|
|
Packit Service |
4b33e2 |
comment_private=private)
|
|
Packit Service |
4b33e2 |
log.debug("addcomment: update=%s", vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
return self.bugzilla.update_bugs(self.bug_id, vals)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def getcomments(self):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Returns an array of comment dictionaries for this bug
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
comment_list = self.bugzilla.get_comments([self.bug_id])
|
|
Packit Service |
4b33e2 |
return comment_list['bugs'][str(self.bug_id)]['comments']
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
#####################
|
|
Packit Service |
4b33e2 |
# Get/Set bug flags #
|
|
Packit Service |
4b33e2 |
#####################
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def get_flag_type(self, name):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Return flag_type information for a specific flag
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
Older RHBugzilla returned a lot more info here, but it was
|
|
Packit Service |
4b33e2 |
non-upstream and is now gone.
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
for t in self.flags:
|
|
Packit Service |
4b33e2 |
if t['name'] == name:
|
|
Packit Service |
4b33e2 |
return t
|
|
Packit Service |
4b33e2 |
return None
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def get_flags(self, name):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Return flag value information for a specific flag
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
ft = self.get_flag_type(name)
|
|
Packit Service |
4b33e2 |
if not ft:
|
|
Packit Service |
4b33e2 |
return None
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
return [ft]
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def get_flag_status(self, name):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Return a flag 'status' field
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
This method works only for simple flags that have only a 'status' field
|
|
Packit Service |
4b33e2 |
with no "requestee" info, and no multiple values. For more complex
|
|
Packit Service |
4b33e2 |
flags, use get_flags() to get extended flag value information.
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
f = self.get_flags(name)
|
|
Packit Service |
4b33e2 |
if not f:
|
|
Packit Service |
4b33e2 |
return None
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
# This method works only for simple flags that have only one
|
|
Packit Service |
4b33e2 |
# value set.
|
|
Packit Service |
4b33e2 |
assert len(f) <= 1
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
return f[0]['status']
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def updateflags(self, flags):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Thin wrapper around build_update(flags=X). This only handles simple
|
|
Packit Service |
4b33e2 |
status changes, anything like needinfo requestee needs to call
|
|
Packit Service |
4b33e2 |
build_update + update_bugs directly
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
:param flags: Dictionary of the form {"flagname": "status"}, example
|
|
Packit Service |
4b33e2 |
{"needinfo": "?", "devel_ack": "+"}
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
flaglist = []
|
|
Packit Service |
4b33e2 |
for key, value in flags.items():
|
|
Packit Service |
4b33e2 |
flaglist.append({"name": key, "status": value})
|
|
Packit Service |
4b33e2 |
return self.bugzilla.update_bugs([self.bug_id],
|
|
Packit Service |
4b33e2 |
self.bugzilla.build_update(flags=flaglist))
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
########################
|
|
Packit Service |
4b33e2 |
# Experimental methods #
|
|
Packit Service |
4b33e2 |
########################
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def get_attachments(self, include_fields=None, exclude_fields=None):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Helper call to Bugzilla.get_attachments. If you want to fetch
|
|
Packit Service |
4b33e2 |
specific attachment IDs, use that function instead
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
if "attachments" in self.__dict__:
|
|
Packit Service |
4b33e2 |
return self.attachments
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
data = self.bugzilla.get_attachments([self.bug_id], None,
|
|
Packit Service |
4b33e2 |
include_fields, exclude_fields)
|
|
Packit Service |
4b33e2 |
return data["bugs"][str(self.bug_id)]
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def get_attachment_ids(self):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Helper function to return only the attachment IDs for this bug
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
return [a["id"] for a in self.get_attachments(exclude_fields=["data"])]
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def get_history_raw(self):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Experimental. Get the history of changes for this bug.
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
return self.bugzilla.bugs_history_raw([self.bug_id])
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
class User(object):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Container object for a bugzilla User.
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
:arg bugzilla: Bugzilla instance that this User belongs to.
|
|
Packit Service |
4b33e2 |
Rest of the params come straight from User.get()
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
def __init__(self, bugzilla, **kwargs):
|
|
Packit Service |
4b33e2 |
self.bugzilla = bugzilla
|
|
Packit Service |
4b33e2 |
self.__userid = kwargs.get('id')
|
|
Packit Service |
4b33e2 |
self.__name = kwargs.get('name')
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
self.__email = kwargs.get('email', self.__name)
|
|
Packit Service |
4b33e2 |
self.__can_login = kwargs.get('can_login', False)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
self.real_name = kwargs.get('real_name', None)
|
|
Packit Service |
4b33e2 |
self.password = None
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
self.groups = kwargs.get('groups', {})
|
|
Packit Service |
4b33e2 |
self.groupnames = []
|
|
Packit Service |
4b33e2 |
for g in self.groups:
|
|
Packit Service |
4b33e2 |
if "name" in g:
|
|
Packit Service |
4b33e2 |
self.groupnames.append(g["name"])
|
|
Packit Service |
4b33e2 |
self.groupnames.sort()
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
########################
|
|
Packit Service |
4b33e2 |
# Read-only attributes #
|
|
Packit Service |
4b33e2 |
########################
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
# We make these properties so that the user cannot set them. They are
|
|
Packit Service |
4b33e2 |
# unaffected by the update() method so it would be misleading to let them
|
|
Packit Service |
4b33e2 |
# be changed.
|
|
Packit Service |
4b33e2 |
@property
|
|
Packit Service |
4b33e2 |
def userid(self):
|
|
Packit Service |
4b33e2 |
return self.__userid
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
@property
|
|
Packit Service |
4b33e2 |
def email(self):
|
|
Packit Service |
4b33e2 |
return self.__email
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
@property
|
|
Packit Service |
4b33e2 |
def can_login(self):
|
|
Packit Service |
4b33e2 |
return self.__can_login
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
# name is a key in some methods. Mark it dirty when we change it #
|
|
Packit Service |
4b33e2 |
@property
|
|
Packit Service |
4b33e2 |
def name(self):
|
|
Packit Service |
4b33e2 |
return self.__name
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def refresh(self):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
Update User object with latest info from bugzilla
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
newuser = self.bugzilla.getuser(self.email)
|
|
Packit Service |
4b33e2 |
self.__dict__.update(newuser.__dict__)
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
def updateperms(self, action, groups):
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
A method to update the permissions (group membership) of a bugzilla
|
|
Packit Service |
4b33e2 |
user.
|
|
Packit Service |
4b33e2 |
|
|
Packit Service |
4b33e2 |
:arg action: add, remove, or set
|
|
Packit Service |
4b33e2 |
:arg groups: list of groups to be added to (i.e. ['fedora_contrib'])
|
|
Packit Service |
4b33e2 |
"""
|
|
Packit Service |
4b33e2 |
self.bugzilla.updateperms(self.name, action, groups)
|