Commits

Brad Montgomery committed 2dd678f Draft

new style string formatting; Issue.followers now returns number of followers

Comments (0)

Files changed (2)

 
 from stripperparser import strip_tags
 
+
 try:
     import json
 except ImportError:
     import simplejson as json
 
+
 __all__ = ['AuthenticationRequired', 'to_datetime', 'BitBucket']
 
 api_base = 'https://api.bitbucket.org/1.0/'
 api_toplevel = 'https://api.bitbucket.org/'
 
+
 class AuthenticationRequired(Exception):
     pass
 
+
 def requires_authentication(method):
     @wraps(method)
     def wrapper(self, *args, **kwargs):
         username = self.bb.username if hasattr(self, 'bb') else self.username
         password = self.bb.password if hasattr(self, 'bb') else self.password
         if not all((username, password)):
-            raise AuthenticationRequired("%s requires authentication" % method.__name__)
+            msg = "{0} requires authentication".format(method.__name__)
+            raise AuthenticationRequired(msg)
         return method(self, *args, **kwargs)
     return wrapper
 
+
 def smart_encode(**kwargs):
     """Urlencode's provided keyword arguments.  If any kwargs are None, it does
     not include those."""
         return ''
     return urlencode(args)
 
+
 def to_datetime(timestring):
     """Convert one of the bitbucket API's timestamps to a datetime object."""
     format = '%Y-%m-%d %H:%M:%S'
     timestring = timestring.split('+')[0].strip()
     return datetime.datetime(*time.strptime(timestring, format)[:7])
 
+
 class BitBucket(object):
     """Main bitbucket class.  Use an instantiated version of this class
     to make calls against the REST API."""
         try:
             return json.loads(self.load_url(url))
         except ValueError:
-            raise URLError, "Could not parse JSON result from %s" % url
+            msg = "Could not parse JSON result from {0}".format(url)
+            raise URLError(msg)
 
     def build_request(self, url, data=None):
         if not all((self.username, self.password)):
             return Request(url,data)
-        auth = '%s:%s' % (self.username, self.password)
-        auth = {'Authorization': 'Basic %s' % (auth.encode('base64').strip())}
+        auth = '{0}:{1}'.format(self.username, self.password)
+        auth = auth.encode("base64").strip()
+        auth = {'Authorization': 'Basic {0}'.format(auth)}
         if data:
             data = urlencode(data)
         return Request(url, data, auth)
 
     def load_url(self, url, quiet=False, method=None, data=None):
-        """ NOTE: This raises urllib2.HTTPError in the event of a 404, 500, etc. """
+        """NOTE: Raises urllib2.HTTPError if something goes wrong (eg 404)"""
         request = self.build_request(url,data)
         if method:
             request.get_method = lambda : method
     
     @requires_authentication
     def new_repository(self,name,**data):
-        """Create a new repository with the given name
-           for the authenticated user.
-           Return a Repository object
+        """Create a new repository with the given name for the authenticated
+        user. Returns a Repository object
         """
         url = api_base + 'repositories/'
         data['name'] = name
         
     @requires_authentication
     def remove_repository(self,slug):
-        """Given a slug, remove a repository from the 
-           authenticated user"""
-        url = api_base + 'repositories/%s/%s' % (self.username,slug)
+        """Given a slug, remove a repository from the authenticated user"""
+        url = api_base + 'repositories/{0}/{1}'.format(self.username, slug)
         method = 'DELETE'
         self.load_url(url,method=method)
         return True
         
     @requires_authentication
     def emails(self):
-        """Returns a list of configured email addresses for the authenticated user."""
+        """Returns a list of configured email addresses for the authenticated
+        user."""
         url = api_base + 'emails/'
         try:
             return json.loads(self.load_url(url))
     def __repr__(self):
         extra = ''
         if all((self.username, self.password)):
-            extra = ' (auth: %s)' % self.username
-        return '<BitBucket API%s>' % extra
+            extra = ' (auth: {0})'.format(self.username)
+        return '<BitBucket API{0}>'.format(extra)
+
 
 class User(object):
     """API encapsulation for user related bitbucket queries."""
         self.username = username
 
     def followers(self):
-        url = api_base + 'users/%s/followers/' % self.username
+        url = api_base + 'users/{0}/followers/'.format(self.username)
         return self.bb._loads(url)
 
     def repository(self, slug):
 
     def events(self, start=None, limit=None):
         query = smart_encode(start=start, limit=limit)
-        url = api_base + 'users/%s/events/' % self.username
+        url = api_base + 'users/{0}/events/'.format(self.username)
         if query:
-            url += '?%s' % query
+            url += '?{0}'.format(query)
         return self.bb._loads(url)
 
     def get(self):
-        url = api_base + 'users/%s/' % self.username
+        url = api_base + 'users/{0}/'.format(self.username)
         return self.bb._loads(url)
 
     def __repr__(self):
-        return '<User: %s>' % self.username
+        return '<User: {0}>'.format(self.username)
+
 
 class Repository(object):
     def __init__(self, bb, username, slug):
 
     def changeset(self, revision):
         """Get one changeset from a repos."""
-        url = self.base_url + 'changesets/%s/' % (revision)
+        url = self.base_url + 'changesets/{0}/'.format(revision)
         return self.bb._loads(url)
 
     def changesets(self, limit=None, start=None):
         """Get information about changesets on a repository."""
         url = self.base_url + 'changesets/'
         query = smart_encode(limit=limit, start=start)
-        if query: url += '?%s' % query
+        if query: url += '?{0}'.format(query)
         return self.bb._loads(url)
 
     def parse_changeset_for_author(self, cset):
     def issues(self, start=None, limit=None):
         url = self.base_url + 'issues/'
         query = smart_encode(start=start, limit=limit)
-        if query: url += '?%s' % query
+        if query: url += '?{0}'.format(query)
         return self.bb._loads(url)
 
     def events(self, start=None, limit=None):
         url = self.base_url + 'events/'
         query = smart_encode(start=start, limit=limit)
-        if query: url += '?%s' % query
+        if query: url += '?{0}'.format(query)
         return self.bb._loads(url)
 
     def followers(self):
         return {'contributors': contributors.values()}
 
     def __repr__(self):
-        return '<Repository: %s\'s %s>' % (self.username, self.slug)
+        return '<Repository: {0}\'s {1}>'.format(self.username, self.slug)
+
 
 class Issue(object):
     def __init__(self, bb, username, slug, number):
         self.username = username
         self.slug = slug
         self.number = number
-        self.base_url = api_base + 'repositories/%s/%s/issues/%s/' % (username, slug, number)
+        path = 'repositories/{0}/{1}/issues/{2}'.format(username, slug, number)
+        self.base_url = api_base + path
+        self._data = None
     
     def get(self):
-        return self.bb._loads(self.base_url)
+        if self._data is None:
+            self._data = self.bb._loads(self.base_url)
+        return self._data
 
     def followers(self):
-        url = self.base_url + 'followers/'
-        return self.bb._loads(url)
+        """Number of people following this Issue."""
+        d = self.get()
+        return d.get("follower_count", 0)
 
     def __repr__(self):
-        return '<Issue #%s on %s\'s %s>' % (self.number, self.username, self.slug)
-
+        return '<Issue #{0} on {1}\'s {2}>'.format(
+            self.number,
+            self.username,
+            self.slug
+        )

bitbucket/tests/test_bitbucket.py

     eq_(data['content'], u"there aren't any tests!")
 
     # followers
-    followers = issue.followers()
-    eq_(followers.keys(), [u'count', u'followers'])
-    ok_(len(followers['followers']) > 0)
+    ok_(issue.followers() > 0)