Package turbogears :: Package visit :: Module savisit

Source Code for Module turbogears.visit.savisit

  1  from datetime import datetime 
  2   
  3  from sqlalchemy import Table, Column, String, DateTime 
  4  from sqlalchemy.orm import class_mapper, mapper 
  5  try: 
  6      from sqlalchemy.orm.exc import UnmappedClassError 
  7  except ImportError: # SQLAlchemy < 0.5 
  8      from sqlalchemy.exceptions import InvalidRequestError as UnmappedClassError 
  9   
 10  from turbogears import config 
 11  from turbogears.database import bind_metadata, metadata, session 
 12  from turbogears.util import load_class 
 13  from turbogears.visit.api import BaseVisitManager, Visit 
 14   
 15  import logging 
 16  log = logging.getLogger('turbogears.identity.savisit') 
 17   
 18  visit_class = None 
19 20 21 -class SqlAlchemyVisitManager(BaseVisitManager):
22
23 - def __init__(self, timeout):
24 global visit_class 25 visit_class_path = config.get('visit.saprovider.model', 26 'turbogears.visit.savisit.TG_Visit') 27 visit_class = load_class(visit_class_path) 28 if visit_class is None: 29 msg = 'No visit class found for %s' % visit_class_path 30 msg += ', did you run setup.py develop?' 31 log.error(msg) 32 else: 33 log.info("Successfully loaded '%s'", visit_class_path) 34 if visit_class is TG_Visit: 35 try: 36 class_mapper(visit_class) 37 except UnmappedClassError: 38 visit_class._map() 39 # base-class' __init__ triggers self.create_model, 40 # so mappers need to be initialized before. 41 super(SqlAlchemyVisitManager, self).__init__(timeout)
42
43 - def create_model(self):
44 """Create the Visit table if it doesn't already exist.""" 45 bind_metadata() 46 class_mapper(visit_class).local_table.create(checkfirst=True) 47 log.debug("Visit model database table(s) created.")
48
49 - def new_visit_with_key(self, visit_key):
50 """Return a new Visit object with the given key.""" 51 created = datetime.now() 52 visit = visit_class() 53 visit.visit_key = visit_key 54 visit.created = created 55 visit.expiry = created + self.timeout 56 session.add(visit) 57 session.flush() 58 return Visit(visit_key, True)
59
60 - def visit_for_key(self, visit_key):
61 """Return the visit (tg api Visit) for this key. 62 63 Returns None if the visit doesn't exist or has expired. 64 65 """ 66 try: 67 expiry = self.queue[visit_key] 68 except KeyError: 69 visit = visit_class.lookup_visit(visit_key) 70 if not visit: 71 return None 72 expiry = visit.expiry 73 now = datetime.now(expiry.tzinfo) 74 if expiry < now: 75 return None 76 # Visit hasn't expired, extend it 77 self.update_visit(visit_key, now + self.timeout) 78 return Visit(visit_key, False)
79
80 - def update_queued_visits(self, queue):
81 if not visit_class: 82 return # if VisitManager extension wasn't shutted down cleanly 83 # TODO this should be made transactional 84 table = class_mapper(visit_class).mapped_table 85 engine = table.bind 86 # Now update each of the visits with the most recent expiry 87 for visit_key, expiry in queue.items(): 88 log.info("updating visit (%s) to expire at %s", visit_key, expiry) 89 engine.execute(table.update(table.c.visit_key == visit_key, 90 values=dict(expiry=expiry)))
91
92 93 # The default Visit model class 94 95 -class TG_Visit(object):
96 97 @classmethod
98 - def lookup_visit(cls, visit_key):
99 return session.query(cls).get(visit_key)
100 101 @classmethod
102 - def _map(cls):
103 cls._table = Table('visit', metadata, 104 Column('visit_key', String(40), primary_key=True), 105 Column('created', DateTime, nullable=False, default=datetime.now), 106 Column('expiry', DateTime)) 107 cls._mapper = mapper(cls, cls._table)
108