changeset 0:78e4757601ec

origination
author Atul Varma <varmaa@toolness.com>
date Tue, 22 Dec 2009 21:40:25 -0800
parents
children f2147b34d6af
files .hgignore bzapi.py example.py
diffstat 3 files changed, 138 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Tue Dec 22 21:40:25 2009 -0800
@@ -0,0 +1,2 @@
+syntax: glob
+*.pickle
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bzapi.py	Tue Dec 22 21:40:25 2009 -0800
@@ -0,0 +1,76 @@
+import urllib2
+import urllib
+from datetime import datetime
+
+import simplejson as json
+
+def datetime_from_iso(timestamp):
+    return datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%SZ')
+
+class CachedSearch(object):
+    def __init__(self, api, **kwargs):
+        self.options = kwargs
+        self.last_update = None
+        self.bugs = {}
+        self.update(api)
+
+    def update(self, api):
+        params = {}
+        params.update(self.options)
+        if self.last_update:
+            params['changed_after'] = self.last_update
+        bugs = api.get('/bug', **params)['bugs']
+        latest_time = None
+        for bug in bugs:
+            last_change_time = datetime_from_iso(bug['last_change_time'])
+            if not latest_time or last_change_time > latest_time:
+                latest_time = last_change_time
+            self.bugs[bug['id']] = bug
+        self.last_update = last_change_time
+
+class BugzillaApi(object):
+    def __init__(self, base_url, username=None, password=None):
+        self.base_url = base_url
+        self.username = username
+        self.password = password
+        self.config = self.get('/configuration')
+
+    def _validate_component(self, product, component=None):
+        products = self.config['product']
+        if product not in products:
+            msg = 'product %s not in configuration' % repr(product)
+            raise ValueError(msg)
+        if component and component not in products[product]['component']:
+            msg = 'component %s of product %s not in configuration' % (
+                repr(component),
+                repr(product)
+                )
+            raise ValueError(msg)
+
+    def get(self, url, **kwargs):
+        for name, value in kwargs.items():
+            if isinstance(value, datetime):
+                kwargs[name] = "%sZ" % (
+                    value.replace(microsecond=0).isoformat('T')
+                    )
+
+        if self.username and self.password:
+            params = dict(username = self.username,
+                          password = self.password)
+        params.update(kwargs)
+
+        if 'product' in params:
+            self._validate_component(params['product'],
+                                     params.get('component'))
+
+        full_url = "%s%s?%s" % (self.base_url,
+                                url,
+                                urllib.urlencode(params))
+
+        request = urllib2.Request(full_url)
+        request.add_header('Accept', 'application/json')
+        request.add_header('Content-Type', 'application/json')
+
+        response = urllib2.urlopen(request)
+
+        return json.loads(response.read())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example.py	Tue Dec 22 21:40:25 2009 -0800
@@ -0,0 +1,60 @@
+import os
+from datetime import datetime, timedelta
+import cPickle as pickle
+
+import bzapi
+
+class Picklable(object):
+    def __init__(self, filename, constructor, **kwargs):
+        self.__filename = filename
+
+        if not os.path.exists(filename):
+            self.__obj = constructor(**kwargs)
+            self.save()
+        else:
+            obj_file = open(filename, 'r')
+            self.__obj = pickle.load(obj_file)
+            obj_file.close()
+
+    def save(self):
+        obj_file = open(self.__filename, 'w')
+        pickle.dump(self.__obj, obj_file)
+        obj_file.close()
+
+    def __getattr__(self, attr):
+        if not attr.startswith('_Picklable_'):
+            return getattr(self.__obj, attr)
+        else:
+            return self.__dict__[attr]
+
+    def __setattr__(self, attr, value):
+        if not attr.startswith('_Picklable_'):
+            setattr(self.__obj, attr, value)
+        else:
+            self.__dict__[attr] = value
+
+api = Picklable(
+    'example.api.pickle',
+    bzapi.BugzillaApi,
+    base_url = 'https://api-dev.bugzilla.mozilla.org/latest'
+    )
+
+search = Picklable(
+    'example.cached-search.pickle',
+    bzapi.CachedSearch,
+    api = api,
+    product='Mozilla Labs',
+    component='Jetpack'
+    )
+
+#search.update(api)
+
+#print len([bug for bug in search.bugs.itervalues()])
+
+#print search.bugs.values()[12]['summary']
+
+#print api.get('/bug/510339/history')
+
+#print api.get('/bug',
+#              product='Mozilla Labs', component='Jetpack',
+#              changed_after=now-timedelta(minutes=60))