Commits

Anonymous committed fca319f

implement pluggable picture-provider component, and two examples: gravatar and usermanager (as well as a default)

  • Participants
  • Parent commits 06d229a

Comments (0)

Files changed (6)

File TODO

- 
-2. Replace hardcoded gravatar with an OrderedExtensionPoint implementing IUserPicturesProvider
-
-3. Implement Gravatar IUserPicturesProvider
-
-4. Implement UserManager IUserPicturesProvider
-
-5. Implement preferences screens for both IUserPicturesProviders
-
-6. Contact mike bayer
-
-7. Release! Announce!
-

File userpictures/__init__.py

 from genshi.filters.transform import Transformer
 from genshi.builder import tag
-import hashlib
 import itertools
 from pkg_resources import resource_filename
-import re
 
 from trac.config import *
 from trac.core import *
+from trac.web.api import ITemplateStreamFilter
 from trac.web.chrome import ITemplateProvider, add_stylesheet
-from trac.web.api import ITemplateStreamFilter
+
+class IUserPicturesProvider(Interface):
+    def get_src(req, username, size):
+        """
+        Return the path to an image for this user, either locally or on the web
+        """
+
+class DefaultUserPicturesProvider(Component):
+    implements(IUserPicturesProvider)
+
+    def get_src(self, req, username, size):
+        return req.href.chrome('userpictures/default-portrait.gif')
+
+from userpictures.providers import *
 
 class _render_event(object):
     def __init__(self, event, base_render, generate_avatar):
 class UserPicturesModule(Component):
     implements(ITemplateStreamFilter, ITemplateProvider)
 
+    pictures_provider = ExtensionOption('userpictures', 'pictures_provider',
+                                        IUserPicturesProvider,
+                                        'DefaultUserPicturesProvider')
+
     ticket_comment_diff_size = Option("userpictures", "ticket_comment_diff_size", default="30")
     ticket_reporter_size = Option("userpictures", "ticket_reporter_size", default="60")
     ticket_owner_size = Option("userpictures", "ticket_owner_size", default="30")
         return stream
 
     def _generate_avatar(self, req, author, class_, size):
-        email_hash = hashlib.md5("ethan.jucovy@gmail.com").hexdigest()
-        if req.base_url.startswith("https://"):
-            href = "https://gravatar.com/avatar/" + email_hash
-        else:
-            href = "http://www.gravatar.com/avatar/" + email_hash
-        href += "?size=%s" % size
+        href = self.pictures_provider.get_src(req, author, size)
         return tag.img(src=href, class_='userpictures_avatar %s' % class_,
                        width=size, height=size).generate()
 
         if not data.get('attachment'):
             return []
         author = data['attachment'].author
+        if not author:
+            return []
         return [Transformer('//table[@id="info"]//th'
                             ).prepend(
                 self._generate_avatar(

File userpictures/htdocs/default-portrait.gif

Added
New image

File userpictures/providers/__init__.py

+from userpictures.providers.gravatar import UserPicturesGravatarProvider
+from userpictures.providers.usermanager import UserPicturesUserManagerProvider
+    

File userpictures/providers/gravatar.py

+import hashlib
+import re
+
+from trac.config import *
+from trac.core import *
+
+from userpictures import IUserPicturesProvider
+
+class UserPicturesGravatarProvider(Component):
+    implements(IUserPicturesProvider)
+
+    # from trac source
+    _long_author_re = re.compile(r'.*<([^@]+)@([^@]+)>\s*|([^@]+)@([^@]+)')
+
+    @property
+    def email_map(self):
+        if hasattr(self, '_email_map'):
+            return self._email_map
+        _email_map = {}
+        for username, name, email in self.env.get_known_users():
+            _email_map[username] = email
+        setattr(self, '_email_map', _email_map)
+        return self._email_map
+
+    def get_src(self, req, username, size):
+        email = ''
+        if '@' not in username:
+            if username != 'anonymous':
+                email = self.email_map.get(username, '')
+        else:
+            author_info = self._long_author_re.match(username)
+            if author_info:
+                if author_info.group(1):
+                    email = '%s@%s' % author_info.group(1, 2)
+                elif author_info.group(3):
+                    email = '%s@%s' % author_info.group(3, 4)
+
+        email_hash = hashlib.md5(email).hexdigest()
+        if req.base_url.startswith("https://"):
+            href = "https://gravatar.com/avatar/" + email_hash
+        else:
+            href = "http://www.gravatar.com/avatar/" + email_hash
+        href += "?size=%s" % size
+        return href
+

File userpictures/providers/usermanager.py

+from trac.config import *
+from trac.core import *
+
+try:
+    from tracusermanager.api import UserManager
+except ImportError:
+    class UserManager(object):
+        def __init__(self, env):
+            self.env = env
+        def get_user(self, username):
+            self.env.log.warning("Trying to use UserPicturesUserManagerProvider, but UserManager plugin is not installed!")
+            return None
+
+from userpictures import IUserPicturesProvider
+
+class UserPicturesUserManagerProvider(Component):
+    implements(IUserPicturesProvider)
+
+    def get_src(self, req, username, size):
+        user_manager = UserManager(self.env)
+        user = user_manager.get_user(username)
+        if not user or not user['picture_href']:
+            return req.href.chrome('userpictures/default-portrait.gif')
+        return user['picture_href']
+
+