5ce7638f11b3e029839f7ebcb80c6cd081c87c9c
[ashd.git] / python / ashd / wsgidir.py
1 import os, threading, types
2 import wsgiutil
3
4 class cachedmod:
5     def __init__(self, mod, mtime):
6         self.lock = threading.Lock()
7         self.mod = mod
8         self.mtime = mtime
9
10 exts = {}
11 modcache = {}
12 cachelock = threading.Lock()
13
14 def mangle(path):
15     ret = ""
16     for c in path:
17         if c.isalnum():
18             ret += c
19         else:
20             ret += "_"
21     return ret
22
23 def getmod(path):
24     sb = os.stat(path)
25     cachelock.acquire()
26     try:
27         if path in modcache:
28             entry = modcache[path]
29             if sb.st_mtime <= entry.mtime:
30                 return entry
31         
32         f = open(path)
33         try:
34             text = f.read()
35         finally:
36             f.close()
37         code = compile(text, path, "exec")
38         mod = types.ModuleType(mangle(path))
39         mod.__file__ = path
40         exec code in mod.__dict__
41         entry = cachedmod(mod, sb.st_mtime)
42         modcache[path] = entry
43         return entry
44     finally:
45         cachelock.release()
46
47 def chain(path, env, startreq):
48     mod = getmod(path)
49     entry = None
50     if mod is not None:
51         mod.lock.acquire()
52         try:
53             if hasattr(mod, "entry"):
54                 entry = mod.entry
55             else:
56                 if hasattr(mod.mod, "wmain"):
57                     entry = mod.mod.wmain()
58                 elif hasattr(mod.mod, "application"):
59                     entry = mod.mod.application
60                 mod.entry = entry
61         finally:
62             mod.lock.release()
63     if entry is not None:
64         return entry(env, startreq)
65     return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "Invalid WSGI handler.")
66 exts["wsgi"] = chain
67
68 def addext(ext, handler):
69     p = handler.rindex('.')
70     mname = handler[:p]
71     hname = handler[p + 1:]
72     mod = __import__(mname, fromlist = ["dummy"])
73     exts[ext] = getattr(mod, hname)
74
75 def application(env, startreq):
76     if not "SCRIPT_FILENAME" in env:
77         return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "The server is erroneously configured.")
78     path = env["SCRIPT_FILENAME"]
79     base = os.path.basename(path)
80     p = base.rfind('.')
81     if p < 0 or not os.access(path, os.R_OK):
82         return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "The server is erroneously configured.")
83     ext = base[p + 1:]
84     if not ext in exts:
85         return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "The server is erroneously configured.")
86     return(exts[ext](path, env, startreq))
87
88 def wmain(*argv):
89     for arg in argv:
90         if arg[0] == '.':
91             p = arg.index('=')
92             addext(arg[1:p], arg[p + 1:])
93     return application