root/hackergotchiplugin/0.11/hackergotchi/web_ui.py

Revision 11248, 4.2 kB (checked in by rjollos, 4 months ago)

Fixes #6765: Attempt to fix "Cannot operate on a closed cursor." error by passing the db object rather than the cursor object to the subfunction. The assumption here is that the db object is going out of scope.

I wasn't able to reproduce the issue with Trac 0.11 in a development environment. Please report back if this fixes the issue for you.

Line 
1 # Created by Noah Kantrowitz on 2008-05-16.
2 # Copyright (c) 2008 Noah Kantrowitz. All rights reserved.
3 import itertools
4 import re
5
6
7 from trac.core import *
8 from trac.web.api import ITemplateStreamFilter
9 from trac.web.chrome import ITemplateProvider, add_stylesheet
10 from trac.config import Option, OrderedExtensionsOption
11 from genshi.builder import tag
12 from genshi.filters.transform import Transformer
13 from pkg_resources import resource_filename
14
15 from hackergotchi.api import IHackergotchiProvider
16
17 class HackergotchiModule(Component):
18     """A stream filter to add hackergotchi emblems to the timeline."""
19
20     providers = OrderedExtensionsOption('hackergotchi', 'providers',
21                                         IHackergotchiProvider,
22                                         default='GravatarHackergotchiProvider, IdenticonHackergotchiProvider')
23
24     implements(ITemplateStreamFilter, ITemplateProvider)
25    
26     anon_re = re.compile('([^<]+?)\s+<([^>]+)>', re.U)
27    
28     # ITemplateStreamFilter methods
29     def filter_stream(self, req, method, filename, stream, data):
30         if req.path_info.startswith('/timeline'):
31             closure_state = [0]           
32             cache = {}
33             def f(stream):
34                 # Update the closed value
35                 n = closure_state[0]
36                 closure_state[0] += 1
37                
38                 # Extract the user information
39                 author = data['events'][n]['author'].strip()
40                 user_info = cache.get(author)
41                 if user_info is not None:
42                     author, name, email = user_info
43                 else:
44                     db = self.env.get_db_cnx()
45                     user_info = self._get_info(author, db)
46                     cache[author] = user_info
47                     author, name, email = user_info
48                
49                 # Try to find a provider
50                 for provider in self.providers:
51                     href = provider.get_hackergotchi(req.href, author, name, email)
52                     if href is not None:
53                         break
54                 else:
55                     href = req.href.chrome('hackergotchi', 'default.png')
56                
57                 # Build our element
58                 elm = tag.img(src=href, alt='Hackergotchi for %s'%author,
59                               class_='hackergotchi')
60                
61                 # Output the combined stream
62                 return itertools.chain(elm.generate(), stream)
63            
64             stream |= Transformer('//div[@id="content"]/dl/dt/a/span[@class="time"]').filter(f)
65             add_stylesheet(req, 'hackergotchi/hackergotchi.css')
66         return stream
67    
68     # ITemplateProvider methods
69     def get_htdocs_dirs(self):
70         yield 'hackergotchi', resource_filename(__name__, 'htdocs')
71            
72     def get_templates_dirs(self):
73         #return [resource_filename(__name__, 'templates')]
74         return []
75    
76     # Internal methods
77     def _get_info(self, author, db):
78         if author == 'anonymous':
79             # Don't even bother trying for "anonymous"
80             return author, None, None
81        
82         md = self.anon_re.match(author)
83         if md:
84             # name <email>
85             return 'anonymous', md.group(1), md.group(2)
86        
87         cursor = db.cursor()       
88         cursor.execute('SELECT name, value FROM session_attribute WHERE sid=%s AND authenticated=%s',
89                        (author, 1))
90         rows = cursor.fetchall()
91         if rows:
92             # Authenticated user, with session
93             name = email = None
94             for key, value in rows:
95                 if key == 'name':
96                     name = value
97                 elif key == 'email':
98                     email = value
99             if name or email:
100                 return author, name, email
101             else:
102                 return author, None, None
103        
104         # Assume anonymous user from this point on
105         if '@' in author:
106             # Likely an email address
107             return 'anonymous', None, author
108        
109         # See if there is a default domain
110         domain = self.config.get('notification', 'smtp_default_domain')
111         if domain and ' ' not in author:
112             return author, None, author+'@'+domain
113        
114         return 'anonymous', author, None
Note: See TracBrowser for help on using the browser.