-import Cookie, time
-import proto
+import http.cookies, time
+from . import proto
__all__ = ["cookies", "get", "add"]
class cookiedict(object):
def __init__(self, req):
try:
- self.bk = Cookie.SimpleCookie(req.ihead.get("Cookie"))
- except Cookie.CookieError:
- self.bk = Cookie.SimpleCookie()
- self.codec = Cookie.SimpleCookie()
+ self.bk = http.cookies.SimpleCookie(req.ihead.get("Cookie"))
+ except http.cookies.CookieError:
+ self.bk = http.cookies.SimpleCookie()
+ self.codec = http.cookies.SimpleCookie()
req.oncommit(addcookies)
def __getitem__(self, name):
def __contains__(self, name):
return name in self.bk
- def get(self, name, default = None):
+ def get(self, name, default=None):
if name not in self.bk:
return default
return self.bk[name].value
def add(self, name, value, **kw):
self.codec[name] = value
- for key, value in kw.iteritems():
+ for key, value in kw.items():
self.codec[name][key] = value
def __setitem__(self, name, value):
def cookies(req):
return req.item(cookiedict)
- def get(req, name, default = None):
+ def get(req, name, default=None):
return cookies(req).get(name, default)
def add(req, name, value, **kw):
import cgi
-import proto
+from . import proto
__all__ = ["formdata"]
def __getitem__(self, key):
return self.cf[key][0]
- def get(self, key, default = ""):
+ def get(self, key, default=""):
if key in self:
return self.cf[key][0]
return default
return list(iter())
def keys(self):
- return self.cf.keys()
+ return list(self.cf.keys())
def values(self):
return [val for key, val in self.items()]
class formpart(object):
def __init__(self, form):
self.form = form
- self.buf = ""
+ self.buf = b""
self.eof = False
self.head = {}
def fillbuf(self, sz):
req = self.form.req
- mboundary = "\r\n--" + self.form.boundary + "\r\n"
- lboundary = "\r\n--" + self.form.boundary + "--\r\n"
+ mboundary = b"\r\n--" + self.form.boundary + b"\r\n"
+ lboundary = b"\r\n--" + self.form.boundary + b"--\r\n"
while not self.eof:
p = self.form.buf.find(mboundary)
if p >= 0:
raise badmultipart("Missing last multipart boundary")
self.form.buf += ret
- def read(self, limit = -1):
+ def read(self, limit=-1):
self.fillbuf(limit)
if limit >= 0:
ret = self.buf[:limit]
self.buf = ""
return ret
- def readline(self, limit = -1):
+ def readline(self, limit=-1):
last = 0
while True:
- p = self.buf.find('\n', last)
+ p = self.buf.find(b'\n', last)
if p < 0:
if self.eof:
ret = self.buf
self.close()
return False
- def parsehead(self):
+ def parsehead(self, charset):
def headline():
ln = self.readline(256)
- if ln[-1] != '\n':
+ if ln[-1] != ord(b'\n'):
raise badmultipart("Too long header line in part")
- return ln.rstrip()
+ try:
+ return ln.decode(charset).rstrip()
+ except UnicodeError:
+ raise badmultipart("Form part header is not in assumed charset")
ln = headline()
while True:
raise badmultipart("Form part uses unexpected transfer encoding: %r" % encoding)
class multipart(object):
- def __init__(self, req):
+ def __init__(self, req, charset):
val, par = proto.pmimehead(req.ihead.get("Content-Type", ""))
if req.method != "POST" or val != "multipart/form-data":
raise badmultipart("Request is not a multipart form")
if "boundary" not in par:
raise badmultipart("Multipart form lacks boundary")
- self.boundary = par["boundary"]
+ try:
+ self.boundary = par["boundary"].encode("us-ascii")
+ except UnicodeError:
+ raise badmultipart("Multipart boundary must be ASCII string")
self.req = req
- self.buf = "\r\n"
+ self.buf = b"\r\n"
self.eof = False
+ self.headcs = charset
self.lastpart = formpart(self)
self.lastpart.close()
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
if not self.lastpart.eof:
raise RuntimeError("All form parts must be read entirely")
if self.eof:
raise StopIteration()
self.lastpart = formpart(self)
- self.lastpart.parsehead()
+ self.lastpart.parsehead(self.headcs)
return self.lastpart
def formdata(req):
</body>
</html>
""" % (title, title, htmlq(msg))
+ buf = buf.encode("us-ascii")
startreq("%i %s" % (code, title), [("Content-Type", "text/html"), ("Content-Length", str(len(buf)))])
return [buf]
def urlq(url):
ret = ""
+ invalid = "&=#?/\"'"
for c in url:
- if c == "&" or c == "=" or c == "#" or c == "?" or c == "/" or (ord(c) <= 32):
+ if c in invalid or (ord(c) <= 32):
ret += "%%%02X" % ord(c)
else:
ret += c
del self.dict[key.lower()]
def __iter__(self):
- return iter((list[0] for list in self.dict.itervalues()))
+ return iter((list[0] for list in self.dict.values()))
- def get(self, key, default = ""):
+ def get(self, key, default=""):
if key.lower() in self.dict:
return self.dict[key.lower()][1]
return default
ra = min(ra, size)
while len(self.buf) < ra:
ret = self.bk.read(ra - len(self.buf))
- if ret == "":
+ if ret == b"":
raise IOError("Unexpected EOF")
self.buf.extend(ret)
self.rb += len(ret)
- ret = str(self.buf[:ra])
+ ret = bytes(self.buf[:ra])
self.buf = self.buf[ra:]
return ret
def readline(self, size=-1):
off = 0
while True:
- p = self.buf.find('\n', off)
+ p = self.buf.find(b'\n', off)
if p >= 0:
- ret = str(self.buf[:p + 1])
+ ret = bytes(self.buf[:p + 1])
self.buf = self.buf[p + 1:]
return ret
off = len(self.buf)
if size >= 0 and len(self.buf) >= size:
- ret = str(self.buf[:size])
+ ret = bytes(self.buf[:size])
self.buf = self.buf[size:]
return ret
if self.rb == self.limit:
- ret = str(self.buf)
+ ret = bytes(self.buf)
self.buf = bytearray()
return ret
ra = self.limit - self.rb
ra = min(ra, size)
ra = min(ra, 1024)
ret = self.bk.read(ra)
- if ret == "":
+ if ret == b"":
raise IOError("Unpexpected EOF")
self.buf.extend(ret)
self.rb += len(ret)
class lineiter(object):
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
ret = rd.readline()
- if ret == "":
+ if ret == b"":
raise StopIteration()
return ret
return lineiter()
self.input = limitreader(env["wsgi.input"], int(clen))
else:
# XXX: What to do?
- self.input = io.BytesIO("")
+ self.input = io.BytesIO(b"")
else:
# Assume input is chunked and read until ordinary EOF.
self.input = env["wsgi.input"]
-import dispatch, proto, env
-from sp import xhtml
+from . import dispatch, proto, env
+from .sp import xhtml
h = xhtml.cons()
__all__ = ["skeleton", "skelfor", "setskel", "usererror"]
class usererror(dispatch.restart):
def __init__(self, message, *detail):
- super(usererror, self).__init__()
+ super().__init__()
self.message = message
self.detail = detail
return skelfor(req).error(req, self.message, *self.detail)
class message(dispatch.restart):
- def __init__(self, msg, *detail):
- super(message, self).__init__()
- self.message = msg
+ def __init__(self, message, *detail):
+ super().__init__()
+ self.message = message
self.detail = detail
def handle(self, req):
- return skelfor(req).error(req, self.message, *self.detail)
+ return skelfor(req).message(req, self.message, *self.detail)
class httperror(usererror):
- def __init__(self, status, message = None, detail = None):
+ def __init__(self, status, message=None, detail=None):
if message is None:
message = proto.statusinfo[status][0]
if detail is None:
detail = (proto.statusinfo[status][1],)
- super(httperror, self).__init__(message, *detail)
+ super().__init__(message, *detail)
self.status = status
def handle(self, req):
req.status(self.status, self.message)
- return super(httperror, self).handle(req)
+ return super().handle(req)
class notfound(httperror):
def __init__(self):
- return super(notfound, self).__init__(404)
+ return super().__init__(404)
class redirect(dispatch.restart):
- def __init__(self, url, status = 303):
+ bases = {"url": proto.requrl,
+ "script": proto.scripturl,
+ "site": proto.siteurl}
+
+ def __init__(self, url, status=303, base="url"):
- super(redirect, self).__init__()
+ super().__init__()
self.url = url
self.status = status
+ self.bases[base]
+ self.base = base
def handle(self, req):
req.status(self.status, "Redirect")
- req.ohead["Location"] = proto.appendurl(proto.requrl(req), self.url)
+ req.ohead["Location"] = proto.appendurl(self.bases[self.base](req), self.url)
req.ohead["Content-Length"] = 0
return []
import threading, time, pickle, random, os
-import cookie, env
+from . import cookie, env
__all__ = ["db", "get"]
def gennonce(length):
nonce = ""
- for i in xrange(length):
+ for i in range(length):
nonce += chr(random.randint(0, 255))
return nonce
class session(object):
- def __init__(self, lock, expire = 86400 * 7):
+ def __init__(self, lock, expire=86400 * 7):
self.id = hexencode(gennonce(16))
self.dict = {}
self.lock = lock
def __getitem__(self, key):
return self.dict[key]
- def get(self, key, default = None):
+ def get(self, key, default=None):
return self.dict.get(key, default)
def __setitem__(self, key, value):
return "<session %s>" % self.id
class db(object):
- def __init__(self, backdb = None, cookiename = "wrwsess", path = "/"):
+ def __init__(self, backdb=None, cookiename="wrwsess", path="/"):
self.live = {}
self.cookiename = cookiename
self.path = path
def clean(self):
now = int(time.time())
with self.lock:
- clist = self.live.keys()
+ clist = list(self.live.keys())
for sessid in clist:
with self.lock:
try:
data = self.backdb[sessid]
try:
return pickle.loads(data)
- except Exception, e:
+ except:
raise KeyError()
def freeze(self, sess):
with open(os.path.join(self.path, key), "w") as out:
out.write(value)
- default = env.var(db(backdb = dirback(os.path.join("/tmp", "wrwsess-" + str(os.getuid())))))
+ default = env.var(db(backdb=dirback(os.path.join("/tmp", "wrwsess-" + str(os.getuid())))))
def get(req):
return default.val.get(req)
class node(object):
pass
-class text(node, unicode):
+class text(node, str):
def __todom__(self, doc):
return doc.createTextNode(self)
-class raw(node, unicode):
+class raw(node, str):
def __todom__(self, doc):
raise Exception("Cannot convert raw code to DOM objects")
class element(node):
def __init__(self, ns, name, ctx):
self.ns = ns
- self.name = unicode(name)
+ self.name = str(name)
self.ctx = ctx
self.attrs = {}
self.children = []
def __call__(self, *children, **attrs):
for child in children:
self.ctx.addchild(self, child)
- for k, v in attrs.iteritems():
+ for k, v in attrs.items():
self.ctx.addattr(self, k, v)
return self
def __todom__(self, doc):
el = doc.createElementNS(self.ns, self.name)
- for k, v in self.attrs.iteritems():
+ for k, v in self.attrs.items():
el.setAttribute(k, v)
for child in self.children:
el.appendChild(child.__todom__(doc))
class context(object):
def __init__(self):
self.nodeconv = {}
- self.nodeconv[str] = lambda ob: text(ob, "utf-8")
- self.nodeconv[unicode] = text
+ self.nodeconv[bytes] = lambda ob: text(ob, "utf-8")
+ self.nodeconv[str] = text
self.nodeconv[int] = text
- self.nodeconv[long] = text
self.nodeconv[float] = text
def nodefrom(self, ob):
node.children.append(self.nodefrom(child))
def addattr(self, node, k, v):
- node.attrs[unicode(k)] = unicode(v)
+ node.attrs[str(k)] = str(v)
class constructor(object):
- def __init__(self, ns, elcls = element, ctx=None):
+ def __init__(self, ns, elcls=element, ctx=None):
self._ns = ns
self._elcls = elcls
if ctx is None: ctx = context()
import inspect, math
-import req, dispatch, session, form, resp, proto
+from . import req, dispatch, session, form, resp, proto
def wsgiwrap(callable):
def wrapper(env, startreq):
wrapper.__wrapped__ = callable
return wrapper
+def stringwrap(charset):
+ def dec(callable):
+ def wrapper(*args, **kwargs):
+ bk = callable(*args, **kwargs)
+ for string in bk:
+ yield string.encode(charset)
+ return wrapper
+ return dec
+
def formparams(callable):
+ spec = inspect.getargspec(callable)
def wrapper(req):
data = form.formdata(req)
- spec = inspect.getargspec(callable)
args = dict(data.items())
args["req"] = req
if not spec.keywords:
for arg in list(args):
if arg not in spec.args:
del args[arg]
- for i in range(len(spec.args) - len(spec.defaults)):
- for i in xrange(len(spec.args) - (len(spec.defaults) if spec.defaults else 0)):
++ for i in range(len(spec.args) - (len(spec.defaults) if spec.defaults else 0)):
if spec.args[i] not in args:
raise resp.httperror(400, "Missing parameter", ("The query parameter `", resp.h.code(spec.args[i]), "' is required but not supplied."))
return callable(**args)
return fun
return dec
- def persession(data = None):
+ def persession(data=None):
def dec(callable):
def wrapper(req):
sess = session.get(req)
self.bk = real
self.bki = iter(real)
self._next = None
- self.next()
+ self.__next__()
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
if self._next is self.end:
raise StopIteration()
ret = self._next
class sessiondata(object):
@classmethod
- def get(cls, req, create = True):
+ def get(cls, req, create=True):
sess = cls.sessdb().get(req)
with sess.lock:
try:
class autodirty(sessiondata):
@classmethod
def get(cls, req):
- ret = super(autodirty, cls).get(req)
+ ret = super().get(req)
if "_is_dirty" not in ret.__dict__:
ret.__dict__["_is_dirty"] = False
return ret
return self._is_dirty
def __setattr__(self, name, value):
- super(autodirty, self).__setattr__(name, value)
+ super().__setattr__(name, value)
if "_is_dirty" in self.__dict__:
self.__dict__["_is_dirty"] = True
def __delattr__(self, name):
- super(autodirty, self).__delattr__(name, value)
+ super().__delattr__(name, value)
if "_is_dirty" in self.__dict__:
self.__dict__["_is_dirty"] = True
class manudirty(object):
def __init__(self, *args, **kwargs):
- super(manudirty, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.__dirty = False
def sessfrozen(self):
class specclass(type):
def __init__(self, name, bases, tdict):
- super(specclass, self).__init__(name, bases, tdict)
+ super().__init__(name, bases, tdict)
sslots = set()
dslots = set()
for cls in self.__mro__:
for i, slot in enumerate(self.__sslots_a__):
setattr(self, slot, specslot(slot, i, slot in dslots))
-class specdirty(sessiondata):
- __metaclass__ = specclass
+class specdirty(sessiondata, metaclass=specclass):
__slots__ = ["session", "__sslots__", "_is_dirty"]
def __specinit__(self):
@staticmethod
def __new__(cls, req, sess):
- self = super(specdirty, cls).__new__(cls)
+ self = super().__new__(cls)
self.session = sess
self.__sslots__ = [specslot.unbound] * len(cls.__sslots_a__)
self.__specinit__()