Commit | Line | Data |
---|---|---|
c06db49a FT |
1 | import os, threading, types |
2 | import wsgiutil | |
3 | ||
14ef1e0e FT |
4 | class cachedmod: |
5 | def __init__(self, mod, mtime): | |
6 | self.lock = threading.Lock() | |
7 | self.mod = mod | |
8 | self.mtime = mtime | |
9 | ||
c06db49a FT |
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: | |
14ef1e0e FT |
28 | entry = modcache[path] |
29 | if sb.st_mtime <= entry.mtime: | |
30 | return entry | |
31 | ||
c06db49a FT |
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__ | |
14ef1e0e FT |
41 | entry = cachedmod(mod, sb.st_mtime) |
42 | modcache[path] = entry | |
43 | return entry | |
c06db49a FT |
44 | finally: |
45 | cachelock.release() | |
46 | ||
47 | def chain(path, env, startreq): | |
48 | mod = getmod(path) | |
14ef1e0e FT |
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"): | |
adb11d5f | 57 | entry = mod.mod.wmain() |
14ef1e0e FT |
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) | |
36ea06a6 | 65 | return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "Invalid WSGI handler.") |
c06db49a FT |
66 | exts["wsgi"] = chain |
67 | ||
48a91dd9 FT |
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 | ||
c06db49a FT |
75 | def application(env, startreq): |
76 | if not "SCRIPT_FILENAME" in env: | |
36ea06a6 | 77 | return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "The server is erroneously configured.") |
c06db49a FT |
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): | |
36ea06a6 | 82 | return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "The server is erroneously configured.") |
c06db49a FT |
83 | ext = base[p + 1:] |
84 | if not ext in exts: | |
36ea06a6 | 85 | return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "The server is erroneously configured.") |
c06db49a FT |
86 | return(exts[ext](path, env, startreq)) |
87 | ||
adb11d5f | 88 | def wmain(*argv): |
48a91dd9 FT |
89 | for arg in argv: |
90 | if arg[0] == '.': | |
91 | p = arg.index('=') | |
92 | addext(arg[1:p], arg[p + 1:]) | |
c06db49a | 93 | return application |