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 35 if visit_class is TG_Visit: 36 # Handle it gracefully when TG_Visit is already mapped. 37 # May happen, when the visit manager is shutdown and started again 38 try: 39 class_mapper(visit_class) 40 except UnmappedClassError: 41 mapper(visit_class, visits_table) 42 # base-class' __init__ triggers self.create_model, so mappers need to 43 # be initialized before. 44 super(SqlAlchemyVisitManager, self).__init__(timeout)
45
46 - def create_model(self):
47 """Create the Visit table if it doesn't already exist.""" 48 bind_metadata() 49 class_mapper(visit_class).local_table.create(checkfirst=True) 50 log.debug("Visit model database table(s) created.")
51
52 - def new_visit_with_key(self, visit_key):
53 """Return a new Visit object with the given key.""" 54 created = datetime.now() 55 visit = visit_class() 56 visit.visit_key = visit_key 57 visit.created = created 58 visit.expiry = created + self.timeout 59 session.add(visit) 60 session.flush() 61 return Visit(visit_key, True)
62
63 - def visit_for_key(self, visit_key):
64 """Return the visit (tg api Visit) for this key. 65 66 Returns None if the visit doesn't exist or has expired. 67 68 """ 69 try: 70 expiry = self.queue[visit_key] 71 except KeyError: 72 visit = visit_class.lookup_visit(visit_key) 73 if not visit: 74 return None 75 expiry = visit.expiry 76 now = datetime.now(expiry.tzinfo) 77 if expiry < now: 78 return None 79 # Visit hasn't expired, extend it 80 self.update_visit(visit_key, now + self.timeout) 81 return Visit(visit_key, False)
82
83 - def update_queued_visits(self, queue):
84 # TODO this should be made transactional 85 table = class_mapper(visit_class).mapped_table 86 engine = table.bind 87 # Now update each of the visits with the most recent expiry 88 for visit_key, expiry in queue.items(): 89 log.info("updating visit (%s) to expire at %s", visit_key, expiry) 90 engine.execute(table.update(table.c.visit_key == visit_key, 91 values=dict(expiry=expiry)))
92 93 94 # The Visit table 95 96 visits_table = Table('tg_visit', metadata, 97 Column('visit_key', String(40), primary_key=True), 98 Column('created', DateTime, nullable=False, default=datetime.now), 99 Column('expiry', DateTime) 100 )
101 102 103 -class TG_Visit(object):
104 105 @classmethod
106 - def lookup_visit(cls, visit_key):
107 return session.query(cls).get(visit_key)
108