2 import req, dispatch, session, form, resp, proto
4 def wsgiwrap(callable):
5 def wrapper(env, startreq):
6 return dispatch.handleenv(env, startreq, callable)
7 wrapper.__wrapped__ = callable
10 def formparams(callable):
11 spec = inspect.getargspec(callable)
13 data = form.formdata(req)
14 args = dict(data.items())
17 for arg in list(args):
18 if arg not in spec.args:
20 for i in xrange(len(spec.args) - (len(spec.defaults) if spec.defaults else 0)):
21 if spec.args[i] not in args:
22 raise resp.httperror(400, "Missing parameter", ("The query parameter `", resp.h.code(spec.args[i]), "' is required but not supplied."))
23 return callable(**args)
24 wrapper.__wrapped__ = callable
27 class funplex(object):
28 def __init__(self, *funs, **nfuns):
30 self.dir.update(((self.unwrap(fun).__name__, fun) for fun in funs))
31 self.dir.update(nfuns)
35 while hasattr(fun, "__wrapped__"):
39 def __call__(self, req):
40 if req.pathinfo == "":
41 raise resp.redirect(req.uriname + "/")
42 if req.pathinfo[:1] != "/":
49 p = p.partition("/")[0]
53 sreq.selfpath = req.pathinfo[1:]
54 return self.dir[p](sreq)
58 self.dir[self.unwrap(fun).__name__] = fun
67 def persession(data=None):
70 sess = session.get(req)
71 if callable not in sess:
73 sess[callable] = callable()
77 sess[callable] = callable(data)
78 return sess[callable].handle(req)
79 wrapper.__wrapped__ = callable
83 class preiter(object):
84 __slots__ = ["bk", "bki", "_next"]
86 def __init__(self, real):
96 if self._next is self.end:
100 self._next = next(self.bki)
101 except StopIteration:
102 self._next = self.end
106 if hasattr(self.bk, "close"):
109 def pregen(callable):
110 def wrapper(*args, **kwargs):
111 return preiter(callable(*args, **kwargs))
112 wrapper.__wrapped__ = callable
115 class sessiondata(object):
117 def get(cls, req, create=True):
118 sess = cls.sessdb().get(req)
131 return session.default.val
133 class autodirty(sessiondata):
136 ret = super(autodirty, cls).get(req)
137 if "_is_dirty" not in ret.__dict__:
138 ret.__dict__["_is_dirty"] = False
141 def sessfrozen(self):
142 self.__dict__["_is_dirty"] = False
145 return self._is_dirty
147 def __setattr__(self, name, value):
148 super(autodirty, self).__setattr__(name, value)
149 if "_is_dirty" in self.__dict__:
150 self.__dict__["_is_dirty"] = True
152 def __delattr__(self, name):
153 super(autodirty, self).__delattr__(name, value)
154 if "_is_dirty" in self.__dict__:
155 self.__dict__["_is_dirty"] = True
157 class manudirty(object):
158 def __init__(self, *args, **kwargs):
159 super(manudirty, self).__init__(*args, **kwargs)
162 def sessfrozen(self):
171 class specslot(object):
172 __slots__ = ["nm", "idx", "dirty"]
175 def __init__(self, nm, idx, dirty):
182 # Avoid calling __getattribute__
183 return specdirty.__sslots__.__get__(ins, type(ins))
185 def __get__(self, ins, cls):
186 val = self.slist(ins)[self.idx]
187 if val is specslot.unbound:
188 raise AttributeError("specslot %r is unbound" % self.nm)
191 def __set__(self, ins, val):
192 self.slist(ins)[self.idx] = val
196 def __delete__(self, ins):
197 self.slist(ins)[self.idx] = specslot.unbound
200 class specclass(type):
201 def __init__(self, name, bases, tdict):
202 super(specclass, self).__init__(name, bases, tdict)
205 for cls in self.__mro__:
206 css = cls.__dict__.get("__saveslots__", ())
208 dslots.update(cls.__dict__.get("__dirtyslots__", css))
209 self.__sslots_l__ = list(sslots)
210 self.__sslots_a__ = list(sslots | dslots)
211 for i, slot in enumerate(self.__sslots_a__):
212 setattr(self, slot, specslot(slot, i, slot in dslots))
214 class specdirty(sessiondata):
215 __metaclass__ = specclass
216 __slots__ = ["session", "__sslots__", "_is_dirty"]
218 def __specinit__(self):
222 def __new__(cls, req, sess):
223 self = super(specdirty, cls).__new__(cls)
225 self.__sslots__ = [specslot.unbound] * len(cls.__sslots_a__)
227 self._is_dirty = False
230 def __getnewargs__(self):
231 return (None, self.session)
234 self._is_dirty = True
236 def sessfrozen(self):
237 self._is_dirty = False
240 return self._is_dirty
242 def __getstate__(self):
244 for nm, val in zip(type(self).__sslots_a__, specslot.slist(self)):
245 if val is specslot.unbound:
246 ret[nm] = False, None
251 def __setstate__(self, st):
252 ss = specslot.slist(self)
253 for i, nm in enumerate(type(self).__sslots_a__):
254 bound, val = st.pop(nm, (False, None))
256 ss[i] = specslot.unbound
260 def datecheck(req, mtime):
261 if "If-Modified-Since" in req.ihead:
262 rtime = proto.phttpdate(req.ihead["If-Modified-Since"])
263 if rtime is not None and rtime >= math.floor(mtime):
264 raise resp.unmodified()
265 req.ohead["Last-Modified"] = proto.httpdate(mtime)