Author: kskuhlman
Date: Tue Sep 29 22:59:00 2009
New Revision: 6745
URL: http://trac.turbogears.org/changeset/6745

Log:
Port r6651 to 1.5, plus add module setup & teardown to test_visit, since CP3 is 
pedantic about clean exits.

Modified:
   branches/1.1/turbogears/identity/tests/test_visit.py
   branches/1.5/turbogears/identity/tests/test_visit.py
   branches/1.5/turbogears/qstemplates/quickstart/+package+/config/app.cfg_tmpl
   branches/1.5/turbogears/visit/api.py

Modified: branches/1.1/turbogears/identity/tests/test_visit.py
==============================================================================
--- branches/1.1/turbogears/identity/tests/test_visit.py        (original)
+++ branches/1.1/turbogears/identity/tests/test_visit.py        Tue Sep 29 
22:59:00 2009
@@ -13,6 +13,12 @@
     """Returns a dict containing cookie information to pass to a server."""
     return dict(Cookie=response.headers['Set-Cookie'])
 
+def setup_module():
+    testutil.start_server()
+
+def teardown_module():
+    testutil.stop_server()
+
 
 class SimpleVisitPlugin(object):
 

Modified: branches/1.5/turbogears/identity/tests/test_visit.py
==============================================================================
--- branches/1.5/turbogears/identity/tests/test_visit.py        (original)
+++ branches/1.5/turbogears/identity/tests/test_visit.py        Tue Sep 29 
22:59:00 2009
@@ -5,19 +5,36 @@
 
 import cherrypy
 
+import turbogears.visit.api
 from turbogears import config, controllers, expose, startup, testutil, visit
-
+from turbogears.visit.savisit import SqlAlchemyVisitManager
 
 def cookie_header(response):
     """Returns a dict containing cookie information to pass to a server."""
     return dict(Cookie=response.headers['Set-Cookie'])
 
 
+def setup_module():
+    testutil.start_server()
+
+def teardown_module():
+    testutil.stop_server()
+
+
+class SimpleVisitPlugin(object):
+
+    def record_request(self, visit):
+        cherrypy.request.simple_visit_plugin = visit
+
+    def register(self):
+        visit.enable_visit_plugin(self)
+
+
 class VisitRoot(controllers.RootController):
 
     @expose()
     def index(self):
-        new = visit_key = None
+        new = key = None
         cur_visit = visit.current()
         if cur_visit:
             new = cur_visit.is_new
@@ -25,20 +42,25 @@
         visit_on = config.get('tools.visit.on')
         return dict(new=new, key=key, visit_on=visit_on)
 
+    @expose()
+    def visit_plugin(self):
+        vi = cherrypy.request.simple_visit_plugin
+        return dict(key=vi.key, is_new=vi.is_new)
+
 
 class TestVisit(TestCase):
 
     def setUp(self):
         testutil.stop_server(tg_only = True)
         self._visit_manager = config.get('tools.visit.source', 'sqlalchemy')
-        config.update({'tools.visit.manager': 'sqlobject'})
+        config.update({'tools.visit.manager': 'sqlalchemy'})
         self._visit_on = config.get('tools.visit.on', False)
-        self._visit_source = config.get('tools.visit.source', 'cookie')
         config.update({'tools.visit.on': True})
         self._visit_timeout = config.get('tools.visit.timeout', 20)
         config.update({'tools.visit.timeout': 50})
-        self.cookie_name = config.get("tools.visit.cookie.name", 'tg-visit')
+        self._visit_source = config.get('tools.visit.source', 'cookie')
         self._visit_key_param = config.get("tools.visit.form.name", 'tg_visit')
+        self.cookie_name = config.get("tools.visit.cookie.name", 'tg-visit')
         self.app = testutil.make_app(VisitRoot)
         testutil.start_server()
 
@@ -153,3 +175,49 @@
             '%a, %d-%b-%Y %H:%M:%S GMT')[:8] + (0,))
         should_expire = time.mktime(time.gmtime()) + int(morsel['max-age'])
         assert abs(should_expire - expires) < 3, (should_expire, expires, 
should_expire - expires)
+
+    def test_visit_plugin(self):
+        """Visit plugins are registered correctly and called for each 
request."""
+        plug = SimpleVisitPlugin()
+        plug.register()
+        response1 = self.app.get('/visit_plugin')
+        key = response1.raw['key']
+        response2 = self.app.get('/visit_plugin')
+        assert key == response2.raw['key']
+        assert not response2.raw['is_new']
+
+class MyVisitManager(SqlAlchemyVisitManager):
+    pass
+
+class TestSetVisitManager(TestCase):
+
+    def setUp(self):
+        testutil.stop_server(tg_only = True)
+        self._visit_manager = config.get('tools.visit.manager', 'sqlalchemy')
+        self._visit_on = config.get('tools.visit.on', False)
+        config.update({'tools.visit.on': True})
+        self._visit_timeout = config.get('tools.visit.timeout', 20)
+        config.update({'tools.visit.timeout': 50})
+
+    def tearDown(self):
+        testutil.stop_server(tg_only = True)
+        config.update({'tools.visit.timeout': self._visit_timeout})
+        config.update({'tools.visit.on': self._visit_on})
+        config.update({'tools.visit.manager': self._visit_manager})
+
+    def test_visit_manager_from_class(self):
+        """Visit manager class is loaded correctly from dotted-path 
notation."""
+        config.update({'tools.visit.manager': 
'turbogears.identity.tests.test_visit.MyVisitManager'})
+        testutil.start_server()
+        assert isinstance(turbogears.visit.api._manager, MyVisitManager)
+
+    def test_visit_manager_from_plugin(self):
+        """Visit manager class is loaded correctly from entry point plugin."""
+        config.update({'tools.visit.manager': 'sqlalchemy'})
+        testutil.start_server()
+        assert isinstance(turbogears.visit.api._manager, 
SqlAlchemyVisitManager)
+
+    def test_visit_manager_faiL_missing(self):
+        """Runtime Exception is raised when no visit manager class is found."""
+        config.update({'tools.visit.manager': 'bogus'})
+        self.assertRaises(RuntimeError, visit.start_extension)

Modified: 
branches/1.5/turbogears/qstemplates/quickstart/+package+/config/app.cfg_tmpl
==============================================================================
--- 
branches/1.5/turbogears/qstemplates/quickstart/+package+/config/app.cfg_tmpl    
    (original)
+++ 
branches/1.5/turbogears/qstemplates/quickstart/+package+/config/app.cfg_tmpl    
    Tue Sep 29 22:59:00 2009
@@ -142,7 +142,7 @@
 # Specific path for the cookie
 # tools.visit.cookie.path = "/"
 
-# The name of the VisitManager plugin to use for visitor tracking.
+# The name of the VisitManager class or plugin used for visitor tracking.
 tools.visit.manager = "${identity}"
 
 #if $identity == "sqlobject"

Modified: branches/1.5/turbogears/visit/api.py
==============================================================================
--- branches/1.5/turbogears/visit/api.py        (original)
+++ branches/1.5/turbogears/visit/api.py        Tue Sep 29 22:59:00 2009
@@ -10,6 +10,7 @@
 import pkg_resources
 
 from turbogears import config
+from turbogears.util import load_class
 
 log = logging.getLogger("turbogears.visit")
 
@@ -34,13 +35,22 @@
     plugins = pkg_resources.iter_entry_points(
         "turbogears.visit.manager", plugin_name)
     log.debug("Loading visit manager from plugin: %s", plugin_name)
+    provider_class = None
     for entrypoint in plugins:
         try:
-            plugin = entrypoint.load()
-            return plugin(timeout)
-        except Exception, e:
+            provider_class = entrypoint.load()
+            break
+        except ImportError, e:
             log.error("Error loading visit plugin '%s': %s", entrypoint, e)
-    raise RuntimeError("VisitManager plugin missing: %s" % plugin_name)
+
+    if not provider_class and '.' in plugin_name:
+        try:
+            provider_class = load_class(plugin_name)
+        except ImportError, e:
+            log.error("Error loading visit class '%s': %s", plugin_name, e)
+    if not provider_class:
+        raise RuntimeError("VisitManager plugin missing: %s" % plugin_name)
+    return provider_class(timeout)
 
 
 # Interface for the TurboGears extension

Reply via email to