You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mod_python-commits@quetz.apache.org by nl...@apache.org on 2005/05/20 18:28:32 UTC

svn commit: r171133 - in /httpd/mod_python/trunk/lib/python/mod_python: cache.py publisher.py

Author: nlehuen
Date: Fri May 20 09:28:31 2005
New Revision: 171133

URL: http://svn.apache.org/viewcvs?rev=171133&view=rev
Log:
Dropped the import_page function as I don't want to get into the business of recursively managing module dependencies yet. Everything can be done with get_page in a much safer (yet less elegant) way.

Modified:
    httpd/mod_python/trunk/lib/python/mod_python/cache.py
    httpd/mod_python/trunk/lib/python/mod_python/publisher.py

Modified: httpd/mod_python/trunk/lib/python/mod_python/cache.py
URL: http://svn.apache.org/viewcvs/httpd/mod_python/trunk/lib/python/mod_python/cache.py?rev=171133&r1=171132&r2=171133&view=diff
==============================================================================
--- httpd/mod_python/trunk/lib/python/mod_python/cache.py (original)
+++ httpd/mod_python/trunk/lib/python/mod_python/cache.py Fri May 20 09:28:31 2005
@@ -61,37 +61,33 @@
 
     def __setitem__(self, name, value):
         """ Populates the cache with a given name and value. """
-        self._lock.acquire()
+        key = self.key(name)
+        
+        entry = self._get_entry(key)
+        
+        entry._lock.acquire()
         try:
-            key = self.key(name)
-            entry = self._dict.get(key)
-            if not entry:
-                entry = Entry(key)
-                self._pack(entry, value)
-                self._dict[key]=entry
-                if self._maxsize:
-                    entry._next = entry._previous = None
-                    self._access(entry)
-                    self._checklru()
-            else:
-                self._pack(entry, value)
-                if self._maxsize:
-                    self._access(entry)
+            self._pack(entry,value)
             self.commit()
         finally:
-            self._lock.release()
+            entry._lock.release()
 
     def __getitem__(self, name):
-        return self.checkitem(name)[1]
-
-    def checkitem(self, name):
         """ Gets a value from the cache, builds it if required.
-            Returns a tuple is_new, value. If is_new is True, the dependency had
-            to be rebuilt.
         """
+        return self._checkitem(name)[2]
+
+    def __delitem__(self, name):
         self._lock.acquire()
         try:
             key = self.key(name)
+            del self._dict[key]
+        finally:
+            self._lock.release()
+
+    def _get_entry(self,key):
+        self._lock.acquire()
+        try:
             entry = self._dict.get(key)
             if not entry:
                 entry = Entry(key)
@@ -102,9 +98,19 @@
                     self._checklru()
             elif self._maxsize:
                 self._access(entry)
+            return entry
         finally:
             self._lock.release()
 
+    def _checkitem(self, name):
+        """ Gets a value from the cache, builds it if required.
+            Returns a tuple is_new, key, value, entry.
+            If is_new is True, the result had to be rebuilt.
+        """
+        key = self.key(name)
+        
+        entry = self._get_entry(key)
+
         entry._lock.acquire()
         try:
             value = self._unpack(entry)
@@ -122,18 +128,10 @@
                     is_new = True
                     self._pack(entry, value)
                     self.commit()
-            return is_new, value
+            return is_new, key, value, entry
         finally:
             entry._lock.release()
 
-    def __delitem__(self, key):
-        self._lock.acquire()
-        try:
-            key = self.key(key)
-            del self._dict[key]
-        finally:
-            self._lock.release()
-
     def mru(self):
         """ Returns the Most Recently Used key """
         if self._maxsize:
@@ -249,21 +247,20 @@
         self.mode=mode
     
     def check(self, key, name, entry):
-        """ Checks the modification time to determine whether a file has changed or not. """
-        f = file(key, self.mode)
-        fs = fstat(f.fileno())
-        ts1 = fs[-2]
-        try:
-            ts2 = entry._timestamp
-        except AttributeError:
-            ts2 = ts1-1
-                        
-        if ts2!=ts1:
-            entry._timestamp=ts1
-            return f
+        opened = file(key, self.mode)
+
+        timestamp = fstat(opened.fileno())[-2]
+
+        if entry._value is NOT_INITIALIZED:
+            entry._timestamp = timestamp
+            return opened
         else:
-            f.close()
-            return None
+            if entry._timestamp != timestamp:
+                entry._timestamp = timestamp
+                return opened
+            else:
+                opened.close()
+                return None
 
     def build(self, key, name, opened, entry):
         """ Return the content of the file as a string. Override this for better behaviour. """
@@ -357,8 +354,9 @@
             opened.close()
 
 class ModuleCache(FileCache):
-    """ A module cache. Give it a file name, it returns a module-like object
+    """ A module cache. Give it a file name, it returns a module
         which results from the execution of the Python script it contains.
+        This module is not inserted into sys.modules.
     """
     def __init__(self, max_size=0):
         FileCache.__init__(self, max_size, 'r')
@@ -373,8 +371,9 @@
             opened.close()
 
 class HttpModuleCache(HTTPCache):
-    """ A module cache. Give it a file name, it returns a module-like object
+    """ A module cache. Give it a file name, it returns a module
         which results from the execution of the Python script it contains.
+        This module is not inserted into sys.modules.
     """
     def __init__(self, max_size=0):
         HTTPCache.__init__(self, max_size)

Modified: httpd/mod_python/trunk/lib/python/mod_python/publisher.py
URL: http://svn.apache.org/viewcvs/httpd/mod_python/trunk/lib/python/mod_python/publisher.py?rev=171133&r1=171132&r2=171133&view=diff
==============================================================================
--- httpd/mod_python/trunk/lib/python/mod_python/publisher.py (original)
+++ httpd/mod_python/trunk/lib/python/mod_python/publisher.py Fri May 20 09:28:31 2005
@@ -18,7 +18,7 @@
  # $Id$
 
 """
-  This handler is conceputally similar to Zope's ZPublisher, except
+  This handler is conceptually similar to Zope's ZPublisher, except
   that it:
 
   1. Is written specifically for mod_python and is therefore much faster
@@ -33,7 +33,7 @@
 
 import sys
 import os
-from os.path import normpath, split, isfile, join, dirname
+from os.path import isabs, normpath, split, isfile, join, dirname
 import imp
 import re
 import base64
@@ -78,66 +78,14 @@
 
 page_cache = PageCache()
 
-class DummyModule(object):
-    """
-        This class is used to simulate a request object to be able to import
-        an arbitrary module from the page cache.
-    """
-    def __init__(self, filename):
-        self.filename = filename
-        
-    def get_config(self):
-        return {}
-        
-    def log_error(self, message, level):
-        apache.log_error(message, level)
-    
-    def __str__(self):
-        return "<mod_python.publisher.DummyModule at 0x%08x for %s>"%(id(self), self.filename)
-
-    def __getattr__(self, name):
-        return getattr(page_cache[self], name)
-
 ####################### Interface to the published page cache ##################    
 
-def import_page(relative_path, auto_reload=True):
-    """
-        This imports a published page. The relative_path argument is a path
-        relative to the directory of the page where import_page() is called.
-        Hence, if we have index.py and foobar.py in the same directory, index.py
-        can simply do something like :
-        
-        import mod_python.publisher
-        foobar = mod_python.publisher.import_page('foobar.py')
-        
-        If auto_reload is True (the default), the returned object is not really
-        the module itself, but a placeholder object which allows the real module
-        to be automatically reloaded whenever its source file changes.
-    """
-
-    # this is quite a hack but this is handy.
-    try:
-        raise ZeroDivisionError
-    except ZeroDivisionError:
-        calling_frame = sys.exc_info()[2].tb_frame.f_back
-    
-    calling_page = calling_frame.f_code.co_filename
-    
-    # we look for the given page in the same directory as the calling page
-    page = normpath(join(dirname(calling_page), relative_path))
-    
-    if auto_reload:
-        return DummyModule(page)
-    else:
-        # the DummyModule instance can masquerade itself as a request object
-        # so the PageCache will be happy.
-        return page_cache[DummyModule(page)]
-
-def get_page(req, relative_path):
+def get_page(req, path):
     """
-        This imports a published page. The relative_path argument is a path 
-        relative to the published page where the request is really handled (not
-        relative to the path given in the URL).
+        This imports a published page. If the path is absolute it is used as is.
+        If it is a relative path it is relative to the published page
+        where the request is really handled (not relative to the path
+        given in the URL).
         
         Warning : in order to maintain consistency in case of module reloading,
         do not store the resulting module in a place that outlives the request
@@ -145,9 +93,15 @@
     """
     
     real_filename = req.filename
-    req.filename = normpath(join(dirname(req.filename), relative_path))
+    
     try:
+        if isabs(path):
+            req.filename = path
+        else:
+            req.filename = normpath(join(dirname(req.filename), path))
+        
         return page_cache[req]
+    
     finally:
         req.filename = real_filename
 
@@ -408,7 +362,7 @@
 })
 
 # types which are not referenced in the tp_rules dictionary will be traversable
-# AND publishables 
+# AND publishable 
 default_tp_rule = (True, True)
 
 def resolve_object(req, obj, object_str, realm=None, user=None, passwd=None):