handled, and the MODULE.HANDLER string is treated by splitting it
along its last constituent dot. The part left of the dot is the name
of a module which is imported, and the part right of the dot is the
-name of an object in that module, which should be a callable of three
-arguments. When files of the given extension are handled, that
-callable is called with the file's absolute path, the WSGI environment
-and the WSGI `start_response' function, in that order. For example,
-the argument `.fpy=my.module.foohandler' can be given to pass requests
-for `.fpy' files to the function `foohandler' in the module
-`my.module' (which must, of course, be importable). When writing such
-handler functions, you will probably want to use the getmod() function
-in this module.
+name of an object in that module, which should be a callable adhering
+to the WSGI specification. When called, this module will have made
+sure that the WSGI environment contains the SCRIPT_FILENAME parameter
+and that it is properly working. For example, the argument
+`.fpy=my.module.foohandler' can be given to pass requests for `.fpy'
+files to the function `foohandler' in the module `my.module' (which
+must, of course, be importable). When writing such handler functions,
+you will probably want to use the getmod() function in this module.
"""
import os, threading, types
Additional data attributes can be arbitrarily added for recording
any meta-data about the module.
"""
- def __init__(self, mod, mtime):
+ def __init__(self, mod = None, mtime = -1):
self.lock = threading.Lock()
self.mod = mod
self.mtime = mtime
try:
if path in modcache:
entry = modcache[path]
- if sb.st_mtime <= entry.mtime:
- return entry
-
- f = open(path)
- try:
- text = f.read()
- finally:
- f.close()
- code = compile(text, path, "exec")
- mod = types.ModuleType(mangle(path))
- mod.__file__ = path
- exec code in mod.__dict__
- entry = cachedmod(mod, sb.st_mtime)
- modcache[path] = entry
- return entry
+ else:
+ entry = cachedmod()
+ modcache[path] = entry
finally:
cachelock.release()
+ entry.lock.acquire()
+ try:
+ if entry.mod is None or sb.st_mtime > entry.mtime:
+ f = open(path, "r")
+ try:
+ text = f.read()
+ finally:
+ f.close()
+ code = compile(text, path, "exec")
+ mod = types.ModuleType(mangle(path))
+ mod.__file__ = path
+ exec code in mod.__dict__
+ entry.mod = mod
+ entry.mtime = sb.st_mtime
+ return entry
+ finally:
+ entry.lock.release()
-def chain(path, env, startreq):
+def chain(env, startreq):
+ path = env["SCRIPT_FILENAME"]
mod = getmod(path)
entry = None
if mod is not None:
ext = base[p + 1:]
if not ext in exts:
return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "The server is erroneously configured.")
- return(exts[ext](path, env, startreq))
+ return(exts[ext](env, startreq))
def wmain(*argv):
"""Main function for ashd(7)-compatible WSGI handlers