changeset 11:29efa19d959a

Added bzgetpatch.py and bugzilla.User class
author Atul Varma <avarma@mozilla.com>
date Tue, 13 Apr 2010 17:27:23 -0700
parents b85bd0fc50e4
children d8db9b733a12
files bugzilla.py bzgetpatch.py test_bugzilla.py
diffstat 3 files changed, 140 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/bugzilla.py	Tue Apr 13 16:07:39 2010 -0700
+++ b/bugzilla.py	Tue Apr 13 17:27:23 2010 -0700
@@ -122,7 +122,7 @@
     def __init__(self, config=None, jsonreq=None,
                  getpass=getpass_or_die):
         if config is None:
-            config = load_config()
+            config = load_config(getpass=getpass)
 
         if jsonreq is None:
             if 'cache_dir' in config:
@@ -243,6 +243,62 @@
                 raise ValueError("bad proptype for '%s': %s" %
                                  name, repr(proptype))
 
+class User(BugzillaObject):
+    """
+    >>> u = User(TEST_USER)
+    >>> u.name
+    u'avarma@mozilla.com'
+    >>> u.real_name
+    u'Atul Varma [:atul]'
+    >>> u.email
+    u'avarma@mozilla.com'
+
+    >>> bzapi = Mock('bzapi')
+    >>> bzapi.request.mock_returns = TEST_USER_SEARCH_RESULT
+    >>> u = User({'name': 'avarma@mozilla.com'}, bzapi)
+    >>> u.real_name
+    Called bzapi.request(
+        'GET',
+        '/user',
+        query_args={'match': u'avarma@mozilla.com'})
+    u'Atul Varma [:atul]'
+    """
+
+    __bzprops__ = {
+        'name': unicode
+        }
+
+    def __init__(self, jsonobj, bzapi=None):
+        self.bzapi = bzapi
+        self.__email = jsonobj.get('email')
+        self.__real_name = jsonobj.get('real_name')
+        self._set_bzprops(jsonobj)
+
+    def __fulfill(self):
+        response = self.bzapi.request('GET', '/user',
+                                      query_args={'match': self.name})
+        users = response['users']
+        if len(users) > 1:
+            raise BugzillaApiError("more than one user found for "
+                                   "name '%s'" % self.name)
+        elif not users:
+            raise BugzillaApiError("no users found for "
+                                   "name '%s'" % self.name)
+        self.__email = users[0]['email']
+        self.__real_name = users[0]['real_name']
+
+    @property
+    def email(self):
+        if self.__email is None:
+            self.__fulfill()
+        return self.__email
+
+    @property
+    def real_name(self):
+        if self.__real_name is None:
+            self.__fulfill()
+        return self.__real_name
+
 class Attachment(BugzillaObject):
     """
     >>> bzapi = Mock('bzapi')
@@ -258,23 +314,42 @@
 
     __bzprops__ = {
         'id': int,
+        'bug_id': int,
         'last_change_time': datetime.datetime,
         'creation_time': datetime.datetime,
         'description': unicode,
-        'content_type': str
+        'content_type': str,
+        'is_patch': bool,
+        'is_obsolete': bool
         }
 
-    def __init__(self, jsonobj, bzapi=None):
+    def __init__(self, jsonobj, bzapi=None, bug=None):
         self._set_bzprops(jsonobj)
         self.bzapi = bzapi
         if 'data' in jsonobj:
             self.__data = self.__decode_data(jsonobj)
         else:
             self.__data = None
+        self.__bug = bug
+        self.attacher = User(jsonobj['attacher'], bzapi)
+
+    @property
+    def bug(self):
+        if self.__bug is None:
+            if not self.bzapi:
+                raise AttributeError('cannot fetch bug %d for '
+                                     'attachment %d; no bzapi' %
+                                     (self.bug_id, self.id))
+            self.__bug = Bug.fetch(self.bzapi, self.bug_id)
+        return self.__bug
 
     @property
     def data(self):
-        if self.__data is None and self.bzapi:
+        if self.__data is None:
+            if not self.bzapi:
+                raise AttributeError('cannot fetch data for '
+                                     'attachment %d; no bzapi' %
+                                     self.id)
             jsonobj = self.__get_full_attachment(self.bzapi, self.id)
             self.__data = self.__decode_data(jsonobj)
         return self.__data
@@ -306,7 +381,8 @@
         <Attachment 438797 - u'test upload'>
         """
 
-        return klass(klass.__get_full_attachment(bzapi, attach_id))
+        return klass(klass.__get_full_attachment(bzapi, attach_id),
+                     bzapi)
 
 class Bug(BugzillaObject):
     """
@@ -319,9 +395,9 @@
         'summary': unicode
         }
 
-    def __init__(self, jsonobj):
+    def __init__(self, jsonobj, bzapi=None):
         self._set_bzprops(jsonobj)
-        self.attachments = [Attachment(attach)
+        self.attachments = [Attachment(attach, bzapi, self)
                             for attach in jsonobj['attachments']]
 
     def __repr__(self):
@@ -337,13 +413,4 @@
         <Bug 558680 - u'Here is a summary'>
         """
 
-        return klass(bzapi.request('GET', '/bug/%d' % bug_id))
-
-if __name__ == '__main__':
-    bzapi = BugzillaApi()
-    print bzapi.request('GET', '/attachment/436897',
-                        query_args={'attachmentdata': 1})
-    #bzapi.post_attachment(bug_id=536619,
-    #                      contents="testing!",
-    #                      filename="contents.txt",
-    #                      description="test upload")
+        return klass(bzapi.request('GET', '/bug/%d' % bug_id), bzapi)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bzgetpatch.py	Tue Apr 13 17:27:23 2010 -0700
@@ -0,0 +1,46 @@
+import sys
+import datetime
+import base64
+
+import bugzilla
+
+def strip_patch_header(patch):
+    """
+    >>> strip_patch_header('#HG blarg\\n\\ndiff --git\\n')
+    'diff --git\\n'
+
+    >>> strip_patch_header('sup')
+    'sup'
+    """
+    
+    index = patch.find('\ndiff')
+    if index == -1:
+        return patch
+    return patch[index+1:]
+
+def get_patch_with_header(attachment):
+    patch = strip_patch_header(attachment.data)
+    lines = ['# HG changeset patch',
+             '# User %s <%s>' % (attachment.attacher.real_name,
+                                 attachment.attacher.email),
+             'Bug %d - %s' % (attachment.bug.id,
+                              attachment.bug.summary),
+             '',
+             patch]
+    return '\n'.join(lines)
+
+if __name__ == '__main__':
+    bug_id = int(sys.argv[1])
+    bzapi = bugzilla.BugzillaApi()
+    bug = bugzilla.Bug.fetch(bzapi, bug_id)
+
+    def cmp_lastcreated(a, b):
+        return cmp(a.creation_time, b.creation_time)
+
+    patches = [patch for patch in bug.attachments
+               if patch.is_patch and not patch.is_obsolete]
+    patches.sort(cmp_lastcreated)
+
+    most_recent_patch = patches[-1]
+
+    print get_patch_with_header(most_recent_patch)
--- a/test_bugzilla.py	Tue Apr 13 16:07:39 2010 -0700
+++ b/test_bugzilla.py	Tue Apr 13 17:27:23 2010 -0700
@@ -9,6 +9,16 @@
                        'username': 'bar',
                        'password': 'baz'}
 
+TEST_USER = {
+    u'email': u'avarma@mozilla.com', u'real_name': u'Atul Varma [:atul]',
+    u'can_login': u'1', u'name': u'avarma@mozilla.com',
+    u'id': u'298253'
+    }
+
+TEST_USER_SEARCH_RESULT = {
+    u'users': [TEST_USER]
+}
+
 TEST_ATTACHMENT_WITHOUT_DATA = {
     u'is_obsolete': u'0',
     u'description': u'test upload', u'encoding': u'base64',