Merge branch 'master' into python2
authorFredrik Tolf <fredrik@dolda2000.com>
Wed, 22 Mar 2017 04:40:43 +0000 (05:40 +0100)
committerFredrik Tolf <fredrik@dolda2000.com>
Wed, 22 Mar 2017 04:40:43 +0000 (05:40 +0100)
16 files changed:
setup.py
wrw/__init__.py
wrw/auth.py
wrw/cookie.py
wrw/dispatch.py
wrw/filesys.py
wrw/form.py
wrw/proto.py
wrw/req.py
wrw/resp.py
wrw/session.py
wrw/sp/cons.py
wrw/sp/util.py
wrw/sp/xhtml.py
wrw/util.py
wrw/wmako.py

index d8eb073..3775c63 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/python
 
 from distutils.core import setup, Extension
 
index eb4a0a0..95ff4cd 100644 (file)
@@ -1,7 +1,7 @@
 __all__ = ["wsgiwrap", "restart", "cookie", "formdata"]
 
-from . import proto
-from .util import wsgiwrap, stringwrap, formparams, funplex, persession, sessiondata, autodirty, manudirty, specdirty
-from .dispatch import restart
-from . import cookie
-from .form import formdata
+import proto
+from util import wsgiwrap, formparams, funplex, persession, sessiondata, autodirty, manudirty, specdirty
+from dispatch import restart
+import cookie
+from form import formdata
index 27e2a98..bb0e0cd 100644 (file)
@@ -1,9 +1,9 @@
 import binascii, hashlib, threading, time
-from . import resp, proto
+import resp, proto
 
 class unauthorized(resp.httperror):
     def __init__(self, challenge, message=None, detail=None):
-        super().__init__(401, message, detail)
+        super(unauthorized, self).__init__(401, message, detail)
         if isinstance(challenge, str):
             challenge = [challenge]
         self.challenge = challenge
@@ -11,11 +11,11 @@ class unauthorized(resp.httperror):
     def handle(self, req):
         for challenge in self.challenge:
             req.ohead.add("WWW-Authenticate", challenge)
-        return super().handle(req)
+        return super(unauthorized, self).handle(req)
 
 class forbidden(resp.httperror):
     def __init__(self, message=None, detail=None):
-        super().__init__(403, message, detail)
+        super(forbidden, self).__init__(403, message, detail)
 
 def parsemech(req):
     h = req.ihead.get("Authorization", None)
@@ -34,10 +34,6 @@ def parsebasic(req):
         raw = proto.unb64(data)
     except binascii.Error:
         return None, None
-    try:
-        raw = raw.decode("utf-8")
-    except UnicodeError:
-        raw = raw.decode("latin1")
     p = raw.find(":")
     if p < 0:
         return None, None
@@ -55,9 +51,9 @@ class basiccache(object):
 
     def _obscure(self, nm, pw):
         dig = hashlib.sha256()
-        dig.update(self.realm.encode("utf-8"))
-        dig.update(nm.encode("utf-8"))
-        dig.update(pw.encode("utf-8"))
+        dig.update(self.realm)
+        dig.update(nm)
+        dig.update(pw)
         return dig.digest()
 
     def check(self, req):
@@ -80,7 +76,7 @@ class basiccache(object):
         with lock:
             try:
                 ret = self.auth(req, nm, pw)
-            except forbidden as exc:
+            except forbidden, exc:
                 with self._lock:
                     self._cache[nm, pwh] = (lock, now, "f", exc)
                 raise
index c6e848f..140ba8f 100644 (file)
@@ -1,5 +1,5 @@
-import http.cookies, time
-from . import proto
+import Cookie, time
+import proto
 
 __all__ = ["cookies", "get", "add"]
 
@@ -11,10 +11,10 @@ def addcookies(req):
 class cookiedict(object):
     def __init__(self, req):
         try:
-            self.bk = http.cookies.SimpleCookie(req.ihead.get("Cookie"))
-        except http.cookies.CookieError:
-            self.bk = http.cookies.SimpleCookie()
-        self.codec = http.cookies.SimpleCookie()
+            self.bk = Cookie.SimpleCookie(req.ihead.get("Cookie"))
+        except Cookie.CookieError:
+            self.bk = Cookie.SimpleCookie()
+        self.codec = Cookie.SimpleCookie()
         req.oncommit(addcookies)
 
     def __getitem__(self, name):
@@ -30,7 +30,7 @@ class cookiedict(object):
 
     def add(self, name, value, **kw):
         self.codec[name] = value
-        for key, value in kw.items():
+        for key, value in kw.iteritems():
             self.codec[name][key] = value
 
     def __setitem__(self, name, value):
index 2c97b9f..666d7a7 100644 (file)
@@ -1,5 +1,5 @@
 import sys, traceback
-from . import env, req, proto
+import env, req, proto
 
 __all__ = ["restart"]
 
@@ -17,7 +17,7 @@ def mangle(result):
     return [str(result)]
 
 def defaulterror(req, excinfo):
-    from . import resp
+    import resp
     traceback.print_exception(*excinfo)
     sys.stderr.flush()
     raise resp.httperror(500)
@@ -38,9 +38,9 @@ def handle(req, startreq, handler):
             try:
                 resp = handler(req)
                 break
-            except restart as i:
+            except restart, i:
                 handler = i.handle
-            except Exception as i:
+            except Exception, i:
                 if eh is None:
                     raise
                 handler = wraphandler(eh, sys.exc_info())
@@ -58,7 +58,7 @@ def handleenv(env, startreq, handler):
 
 def exterror(env, startreq):
     def handler(req):
-        from . import resp
+        import resp
         code = 404
         if "Response-Code" in req.ihead:
             try:
index 56d58aa..dcdc802 100644 (file)
@@ -1,5 +1,5 @@
 import os
-from . import resp
+import resp
 pj = os.path.join
 
 __all__ = ["filehandler"]
@@ -29,7 +29,7 @@ class filehandler(object):
             elif ext == "html":
                 ctype = "text/html"
         req.ohead["Content-Type"] = ctype
-        return open(path, "rb")
+        return open(path, "r")
 
     def resolvefile(self, req, curpath, el):
         if os.path.isfile(pj(curpath, el)):
index 7905dc6..76abab6 100644 (file)
@@ -1,11 +1,11 @@
-import urllib.parse
-from . import proto
+import urlparse
+import proto
 
 __all__ = ["formdata"]
 
 def formparse(req):
     buf = {}
-    buf.update(urllib.parse.parse_qsl(req.query))
+    buf.update(urlparse.parse_qsl(req.query))
     if req.ihead.get("Content-Type") == "application/x-www-form-urlencoded":
         try:
             rbody = req.input.read(2 ** 20)
@@ -13,7 +13,7 @@ def formparse(req):
             return exc
         if len(rbody) >= 2 ** 20:
             return ValueError("x-www-form-urlencoded data is absurdly long")
-        buf.update(urllib.parse.parse_qsl(rbody.decode("latin1")))
+        buf.update(urlparse.parse_qsl(rbody))
     return buf
 
 class badmultipart(Exception):
@@ -22,7 +22,7 @@ class badmultipart(Exception):
 class formpart(object):
     def __init__(self, form):
         self.form = form
-        self.buf = b""
+        self.buf = ""
         self.eof = False
         self.head = {}
 
@@ -31,8 +31,8 @@ class formpart(object):
 
     def fillbuf(self, sz):
         req = self.form.req
-        mboundary = b"\r\n--" + self.form.boundary + b"\r\n"
-        lboundary = b"\r\n--" + self.form.boundary + b"--\r\n"
+        mboundary = "\r\n--" + self.form.boundary + "\r\n"
+        lboundary = "\r\n--" + self.form.boundary + "--\r\n"
         while not self.eof:
             p = self.form.buf.find(mboundary)
             if p >= 0:
@@ -53,7 +53,7 @@ class formpart(object):
                 break
             while len(self.form.buf) <= len(lboundary):
                 ret = req.input.read(8192)
-                if ret == b"":
+                if ret == "":
                     raise badmultipart("Missing last multipart boundary")
                 self.form.buf += ret
 
@@ -64,17 +64,17 @@ class formpart(object):
             self.buf = self.buf[limit:]
         else:
             ret = self.buf
-            self.buf = b""
+            self.buf = ""
         return ret
 
     def readline(self, limit=-1):
         last = 0
         while True:
-            p = self.buf.find(b'\n', last)
+            p = self.buf.find('\n', last)
             if p < 0:
                 if self.eof:
                     ret = self.buf
-                    self.buf = b""
+                    self.buf = ""
                     return ret
                 last = len(self.buf)
                 self.fillbuf(last + 128)
@@ -85,7 +85,7 @@ class formpart(object):
 
     def close(self):
         while True:
-            if self.read(8192) == b"":
+            if self.read(8192) == "":
                 break
 
     def __enter__(self):
@@ -95,15 +95,12 @@ class formpart(object):
         self.close()
         return False
 
-    def parsehead(self, charset):
+    def parsehead(self):
         def headline():
             ln = self.readline(256)
-            if ln[-1] != ord(b'\n'):
+            if ln[-1] != '\n':
                 raise badmultipart("Too long header line in part")
-            try:
-                return ln.decode(charset).rstrip()
-            except UnicodeError:
-                raise badmultipart("Form part header is not in assumed charset")
+            return ln.rstrip()
 
         ln = headline()
         while True:
@@ -135,33 +132,29 @@ class formpart(object):
             raise badmultipart("Form part uses unexpected transfer encoding: %r" % encoding)
 
 class multipart(object):
-    def __init__(self, req, charset):
+    def __init__(self, req):
         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")
-        try:
-            self.boundary = par["boundary"].encode("us-ascii")
-        except UnicodeError:
-            raise badmultipart("Multipart boundary must be ASCII string")
+        self.boundary = par["boundary"]
         self.req = req
-        self.buf = b"\r\n"
+        self.buf = "\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.headcs)
+        self.lastpart.parsehead()
         return self.lastpart
 
 def formdata(req, onerror=Exception):
index 628bfc9..7cb6d31 100644 (file)
@@ -98,20 +98,19 @@ def simpleerror(env, startreq, code, title, msg):
 </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):
-    if isinstance(url, str):
+    if isinstance(url, unicode):
         url = url.encode("utf-8")
     ret = ""
-    invalid = b"%;&=#?/\"'"
+    invalid = "%;&=#?/\"'"
     for c in url:
-        if c in invalid or (c <= 32) or (c >= 128):
-            ret += "%%%02X" % c
+        if c in invalid or (ord(c) <= 32) or (ord(c) >= 128):
+            ret += "%%%02X" % ord(c)
         else:
-            ret += chr(c)
+            ret += c
     return ret
 
 class urlerror(ValueError):
@@ -198,34 +197,19 @@ def parurl(url, pars={}, **augment):
 
 # Wrap these, since binascii is a bit funky. :P
 def enhex(bs):
-    return base64.b16encode(bs).decode("us-ascii")
+    return base64.b16encode(bs)
 def unhex(es):
-    if not isinstance(es, collections.ByteString):
-        try:
-            es = es.encode("us-ascii")
-        except UnicodeError:
-            raise binascii.Error("non-ascii character in hex-string")
     return base64.b16decode(es)
 def enb32(bs):
-    return base64.b32encode(bs).decode("us-ascii")
+    return base64.b32encode(bs)
 def unb32(es):
-    if not isinstance(es, collections.ByteString):
-        try:
-            es = es.encode("us-ascii")
-        except UnicodeError:
-            raise binascii.Error("non-ascii character in base32-string")
     if (len(es) % 8) != 0:
         es += b"=" * (8 - (len(es) % 8))
     es = es.upper()             # The whole point of Base32 is that it's case-insensitive :P
     return base64.b32decode(es)
 def enb64(bs):
-    return base64.b64encode(bs).decode("us-ascii")
+    return base64.b64encode(bs)
 def unb64(es):
-    if not isinstance(es, collections.ByteString):
-        try:
-            es = es.encode("us-ascii")
-        except UnicodeError:
-            raise binascii.Error("non-ascii character in base64-string")
     if (len(es) % 4) != 0:
         es += b"=" * (4 - (len(es) % 4))
     return base64.b64decode(es)
index b08afae..ebc3fd8 100644 (file)
@@ -19,7 +19,7 @@ class headdict(object):
         del self.dict[key.lower()]
 
     def __iter__(self):
-        return iter((list[0] for list in self.dict.values()))
+        return iter((list[0] for list in self.dict.itervalues()))
     
     def get(self, key, default=""):
         if key.lower() in self.dict:
@@ -67,29 +67,29 @@ class limitreader(object):
             ra = min(ra, size)
         while len(self.buf) < ra:
             ret = self.bk.read(ra - len(self.buf))
-            if ret == b"":
+            if ret == "":
                 raise IOError("Unexpected EOF")
             self.buf.extend(ret)
             self.rb += len(ret)
-        ret = bytes(self.buf[:ra])
+        ret = str(self.buf[:ra])
         self.buf = self.buf[ra:]
         return ret
 
     def readline(self, size=-1):
         off = 0
         while True:
-            p = self.buf.find(b'\n', off)
+            p = self.buf.find('\n', off)
             if p >= 0:
-                ret = bytes(self.buf[:p + 1])
+                ret = str(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 = bytes(self.buf[:size])
+                ret = str(self.buf[:size])
                 self.buf = self.buf[size:]
                 return ret
             if self.rb == self.limit:
-                ret = bytes(self.buf)
+                ret = str(self.buf)
                 self.buf = bytearray()
                 return ret
             ra = self.limit - self.rb
@@ -97,7 +97,7 @@ class limitreader(object):
                 ra = min(ra, size)
             ra = min(ra, 1024)
             ret = self.bk.read(ra)
-            if ret == b"":
+            if ret == "":
                 raise IOError("Unpexpected EOF")
             self.buf.extend(ret)
             self.rb += len(ret)
@@ -109,9 +109,9 @@ class limitreader(object):
         class lineiter(object):
             def __iter__(self):
                 return self
-            def __next__(self):
+            def next(self):
                 ret = rd.readline()
-                if ret == b"":
+                if ret == "":
                     raise StopIteration()
                 return ret
         return lineiter()
@@ -148,7 +148,7 @@ class origrequest(request):
                     self.input = limitreader(env["wsgi.input"], int(clen))
                 else:
                     # XXX: What to do?
-                    self.input = io.BytesIO(b"")
+                    self.input = io.BytesIO("")
             else:
                 # Assume input is chunked and read until ordinary EOF.
                 self.input = env["wsgi.input"]
index 965df6c..7fae787 100644 (file)
@@ -1,5 +1,5 @@
-from . import dispatch, proto, env
-from .sp import xhtml
+import dispatch, proto, env
+from sp import xhtml
 h = xhtml.cons()
 
 __all__ = ["skeleton", "skelfor", "setskel", "usererror"]
@@ -28,7 +28,7 @@ def setskel(req, skel):
 
 class usererror(dispatch.restart):
     def __init__(self, message, *detail):
-        super().__init__()
+        super(usererror, self).__init__()
         self.message = message
         self.detail = detail
 
@@ -36,9 +36,9 @@ class usererror(dispatch.restart):
         return skelfor(req).error(req, self.message, *self.detail)
 
 class message(dispatch.restart):
-    def __init__(self, message, *detail):
-        super().__init__()
-        self.message = message
+    def __init__(self, msg, *detail):
+        super(message, self).__init__()
+        self.message = msg
         self.detail = detail
 
     def handle(self, req):
@@ -50,16 +50,16 @@ class httperror(usererror):
             message = proto.statusinfo[status][0]
         if detail is None:
             detail = (proto.statusinfo[status][1],)
-        super().__init__(message, *detail)
+        super(httperror, self).__init__(message, *detail)
         self.status = status
 
     def handle(self, req):
         req.status(self.status, self.message)
-        return super().handle(req)
+        return super(httperror, self).handle(req)
 
 class notfound(httperror):
     def __init__(self):
-        return super().__init__(404)
+        return super(notfound, self).__init__(404)
 
 class redirect(dispatch.restart):
     bases = {"url": proto.requrl,
@@ -67,7 +67,7 @@ class redirect(dispatch.restart):
              "site": proto.siteurl}
 
     def __init__(self, url, status=303, base="url"):
-        super().__init__()
+        super(redirect, self).__init__()
         self.url = url
         self.status = status
         self.bases[base]
index 8141827..476113a 100644 (file)
@@ -1,5 +1,9 @@
 import threading, time, pickle, random, os
+<<<<<<< HEAD
+import cookie, env
+=======
 from . import cookie, env, proto
+>>>>>>> master
 
 __all__ = ["db", "get"]
 
@@ -77,7 +81,7 @@ class db(object):
     def clean(self):
         now = int(time.time())
         with self.lock:
-            clist = list(self.live.keys())
+            clist = self.live.keys()
         for sessid in clist:
             with self.lock:
                 try:
@@ -195,7 +199,7 @@ class db(object):
         data = self.backdb[sessid]
         try:
             return pickle.loads(data)
-        except:
+        except Exception, e:
             raise KeyError()
 
     def freeze(self, sess):
index d8b30a8..1cc93ea 100644 (file)
@@ -4,18 +4,18 @@ import xml.dom.minidom
 class node(object):
     pass
 
-class text(node, str):
+class text(node, unicode):
     def __todom__(self, doc):
         return doc.createTextNode(self)
 
-class raw(node, str):
+class raw(node, unicode):
     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 = str(name)
+        self.name = unicode(name)
         self.ctx = ctx
         self.attrs = {}
         self.children = []
@@ -23,13 +23,13 @@ class element(node):
     def __call__(self, *children, **attrs):
         for child in children:
             self.ctx.addchild(self, child)
-        for k, v in attrs.items():
+        for k, v in attrs.iteritems():
             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.items():
+        for k, v in self.attrs.iteritems():
             el.setAttribute(k, v)
         for child in self.children:
             el.appendChild(child.__todom__(doc))
@@ -44,9 +44,10 @@ class context(object):
 
     def __init__(self):
         self.nodeconv = {}
-        self.nodeconv[bytes] = lambda ob: text(ob, self.charset)
-        self.nodeconv[str] = text
+        self.nodeconv[str] = lambda ob: text(ob, self.charset)
+        self.nodeconv[unicode] = text
         self.nodeconv[int] = text
+        self.nodeconv[long] = text
         self.nodeconv[float] = text
 
     def nodefrom(self, ob):
@@ -72,7 +73,7 @@ class context(object):
 
     def addattr(self, node, k, v):
         if v is not None:
-            node.attrs[str(k)] = str(v)
+            node.attrs[unicode(k)] = unicode(v)
 
 class constructor(object):
     def __init__(self, ns, elcls=element, ctx=None):
index 931cbdb..2599206 100644 (file)
@@ -1,6 +1,6 @@
-import itertools, io
-from .. import dispatch
-from . import cons
+import itertools, StringIO
+from wrw import dispatch
+import cons
 
 def findnsnames(el):
     names = {}
@@ -8,7 +8,7 @@ def findnsnames(el):
     def proc(el):
         if isinstance(el, cons.element):
             if el.ns not in names:
-                names[el.ns] = "n" + str(nid[0])
+                names[el.ns] = u"n" + unicode(nid[0])
                 nid[:] = [nid[0] + 1]
             for ch in el.children:
                 proc(ch)
@@ -56,9 +56,9 @@ class formatter(object):
         self.buf.extend(text.encode(self.charset))
 
     def quotewrite(self, buf):
-        buf = buf.replace('&', "&amp;")
-        buf = buf.replace('<', "&lt;")
-        buf = buf.replace('>', "&gt;")
+        buf = buf.replace(u'&', u"&amp;")
+        buf = buf.replace(u'<', u"&lt;")
+        buf = buf.replace(u'>', u"&gt;")
         self.write(buf)
 
     def __iter__(self):
@@ -69,53 +69,53 @@ class formatter(object):
         if ns is None:
             return el.name
         else:
-            return ns + ":" + el.name
+            return ns + u":" + el.name
 
     def attrval(self, v):
-        qc, qt = ("'", "&apos;") if '"' in v else ('"', "&quot;")
+        qc, qt = (u"'", u"&apos;") if u'"' in v else (u'"', u"&quot;")
         self.write(qc)
-        v = v.replace('&', "&amp;")
-        v = v.replace('<', "&lt;")
-        v = v.replace('>', "&gt;")
+        v = v.replace(u'&', u"&amp;")
+        v = v.replace(u'<', u"&lt;")
+        v = v.replace(u'>', u"&gt;")
         v = v.replace(qc, qt)
         self.write(v)
         self.write(qc)
 
     def attr(self, k, v):
         self.write(k)
-        self.write("=")
+        self.write(u"=")
         self.attrval(v)
 
     def attrs(self, attrs):
         for k, v in attrs:
-            self.write(" ")
+            self.write(u" ")
             self.attr(k, v)
 
     def inittag(self, el):
-        self.write("<" + self.elname(el))
-        attrs = el.attrs.items()
+        self.write(u"<" + self.elname(el))
+        attrs = el.attrs.iteritems()
         if self.first:
             nsnames = []
-            for ns, name in self.nsnames.items():
+            for ns, name in self.nsnames.iteritems():
                 if ns is None:
                     if name is not None:
                         raise Exception("null namespace must have null name, not" + name)
                     continue
-                nsnames.append(("xmlns" if name is None else ("xmlns:" + name), ns))
+                nsnames.append((u"xmlns" if name is None else (u"xmlns:" + name), ns))
             attrs = itertools.chain(attrs, iter(nsnames))
             self.first = False
         self.attrs(attrs)
 
     def starttag(self, el):
         self.inittag(el)
-        self.write(">")
+        self.write(u">")
 
     def shorttag(self, el):
         self.inittag(el)
-        self.write(" />")
+        self.write(u" />")
 
     def endtag(self, el):
-        self.write("</" + self.elname(el) + ">")
+        self.write(u"</" + self.elname(el) + u">")
 
     def text(self, el):
         self.quotewrite(el)
@@ -124,9 +124,9 @@ class formatter(object):
         self.write(el)
 
     def start(self, el):
-        self.write('<?xml version="1.0" encoding="' + self.charset + '" ?>\n')
+        self.write(u'<?xml version="1.0" encoding="' + self.charset + u'" ?>\n')
         if isinstance(el, cons.doctype):
-            self.write('<!DOCTYPE %s PUBLIC "%s" "%s">\n' % (el.rootname,
+            self.write(u'<!DOCTYPE %s PUBLIC "%s" "%s">\n' % (el.rootname,
                                                               el.pubid,
                                                               el.dtdid))
         self.first = True
@@ -150,7 +150,7 @@ class formatter(object):
         elif ev == "$":
             self.end(el)
 
-    def __next__(self):
+    def next(self):
         if self.src is None:
             raise StopIteration()
         try:
@@ -159,8 +159,8 @@ class formatter(object):
             self.src = None
             ev, el = "$", None
         self.handle(ev, el)
-        ret = bytes(self.buf)
-        self.buf[:] = b""
+        ret = str(self.buf)
+        self.buf[:] = ""
         return ret
 
     def nsname(self, el):
@@ -170,7 +170,7 @@ class formatter(object):
                 return ret
         if el.ns is None:
             return None
-        ret = "n" + str(self.nextns)
+        ret = u"n" + unicode(self.nextns)
         self.nextns += 1
         return ret
 
@@ -215,16 +215,16 @@ class formatter(object):
 
     @classmethod
     def format(cls, root, **kw):
-        buf = io.BytesIO()
+        buf = StringIO.StringIO()
         cls.output(buf, root, **kw)
         return buf.getvalue()
 
 class indenter(formatter):
-    def __init__(self, indent="  ", *args, **kw):
-        super().__init__(*args, **kw)
+    def __init__(self, indent=u"  ", *args, **kw):
+        super(indenter, self).__init__(*args, **kw)
         self.indent = indent
         self.col = 0
-        self.curind = ""
+        self.curind = u""
         self.atbreak = True
         self.inline = False
         self.stack = []
@@ -232,11 +232,11 @@ class indenter(formatter):
         self.lastendbr = True
 
     def write(self, text):
-        lines = text.split("\n")
+        lines = text.split(u"\n")
         if len(lines) > 1:
             for ln in lines[:-1]:
                 self.buf.extend(ln.encode(self.charset))
-                self.buf.extend(b"\n")
+                self.buf.extend("\n")
             self.col = 0
         self.buf.extend(lines[-1].encode(self.charset))
         self.col += len(lines[-1])
@@ -244,7 +244,7 @@ class indenter(formatter):
 
     def br(self):
         if not self.atbreak:
-            self.buf.extend(("\n" + self.curind).encode(self.charset))
+            self.buf.extend((u"\n" + self.curind).encode(self.charset))
             self.col = 0
             self.atbreak = True
 
@@ -270,12 +270,12 @@ class indenter(formatter):
         self.push(el)
         self.inline = self.inline or self.inlinep(el)
         self.curind += self.indent
-        super().starttag(el)
+        super(indenter, self).starttag(el)
 
     def shorttag(self, el):
         if not self.inline:
             self.br()
-        super().shorttag(el)
+        super(indenter, self).shorttag(el)
 
     def endtag(self, el):
         il = self.inline
@@ -285,33 +285,33 @@ class indenter(formatter):
         else:
             self.br()
             self.lastendbr = True
-        super().endtag(el)
+        super(indenter, self).endtag(el)
 
     def start(self, el):
-        super().start(el)
+        super(indenter, self).start(el)
         self.atbreak = True
 
     def end(self, el):
         self.br()
 
     def handle(self, ev, el):
-        super().handle(ev, el)
+        super(indenter, self).handle(ev, el)
         self.last = ev, el
 
 class textindenter(indenter):
     maxcol = 70
 
     def text(self, el):
-        left = str(el)
+        left = unicode(el)
         while True:
             if len(left) + self.col > self.maxcol:
                 bp = max(self.maxcol - self.col, 0)
-                for i in range(bp, -1, -1):
+                for i in xrange(bp, -1, -1):
                     if left[i].isspace():
                         while i > 0 and left[i - 1].isspace(): i -= 1
                         break
                 else:
-                    for i in range(bp + 1, len(left)):
+                    for i in xrange(bp + 1, len(left)):
                         if left[i].isspace():
                             break
                     else:
@@ -333,7 +333,7 @@ class response(dispatch.restart):
     formatter = indenter
 
     def __init__(self, root):
-        super().__init__()
+        super(response, self).__init__()
         self.root = root
 
     @property
index eb82f57..a2c1eb1 100644 (file)
@@ -1,11 +1,11 @@
-import xml.dom.minidom, io
-from . import cons as _cons
-from . import util
+import xml.dom.minidom, StringIO
+import cons as _cons
+import util
 dom = xml.dom.minidom.getDOMImplementation()
 
-ns = "http://www.w3.org/1999/xhtml"
-doctype = "-//W3C//DTD XHTML 1.1//EN"
-dtd = "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
+ns = u"http://www.w3.org/1999/xhtml"
+doctype = u"-//W3C//DTD XHTML 1.1//EN"
+dtd = u"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
 
 class htmlelement(_cons.element):
     def __todoc__(self):
@@ -15,11 +15,11 @@ class htmlelement(_cons.element):
         return doc
 
 class xhtmlcontext(_cons.context):
-    attrmap = {"klass": "class"}
+    attrmap = {u"klass": u"class"}
 
     def addattr(self, node, k, v):
-        k = str(k)
-        super().addattr(node, self.attrmap.get(k, k), v)
+        k = unicode(k)
+        super(xhtmlcontext, self).addattr(node, self.attrmap.get(k, k), v)
 
 def cons(ctx=None):
     if ctx is None: ctx = xhtmlcontext()
@@ -30,7 +30,7 @@ def head(title=None, css=None):
     head = h.head
     if title:
         head(h.title(title))
-    if isinstance(css, str) or isinstance(css, bytes):
+    if isinstance(css, str) or isinstance(css, unicode):
         head(h.link(rel="stylesheet", type="text/css", href=css))
     elif css:
         for ss in css:
@@ -38,10 +38,10 @@ def head(title=None, css=None):
     return head
 
 class htmlformatter(util.formatter):
-    allowshort = {"br", "hr", "img", "input", "meta", "link"}
+    allowshort = set([u"br", u"hr", u"img", u"input", u"meta", u"link"])
     def shorttag(self, el):
         if el.name in self.allowshort:
-            super().shorttag(el)
+            super(htmlformatter, self).shorttag(el)
         else:
             self.handle(">", el)
             self.handle("<", el)
@@ -52,7 +52,7 @@ class htmlindenter(util.textindenter, htmlformatter):
 def forreq(req, tree):
     # XXX: Use proper Content-Type for clients accepting it.
     req.ohead["Content-Type"] = "text/html; charset=utf-8"
-    buf = io.BytesIO()
+    buf = StringIO.StringIO()
     htmlindenter.output(buf, tree, doctype=(doctype, dtd), charset="utf-8")
     ret = buf.getvalue()
     req.ohead["Content-Length"] = len(ret)
index a1dcc6c..22bce9d 100644 (file)
@@ -1,5 +1,5 @@
 import inspect, math
-from . import req, dispatch, session, form, resp, proto
+import req, dispatch, session, form, resp, proto
 
 def wsgiwrap(callable):
     def wrapper(env, startreq):
@@ -20,7 +20,7 @@ def formparams(callable):
             for arg in list(args):
                 if arg not in spec.args:
                     del args[arg]
-        for i in range(len(spec.args) - (len(spec.defaults) if spec.defaults else 0)):
+        for i in xrange(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)
@@ -90,12 +90,12 @@ class preiter(object):
         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
@@ -115,16 +115,6 @@ def pregen(callable):
     wrapper.__wrapped__ = callable
     return wrapper
 
-def stringwrap(charset):
-    def dec(callable):
-        @pregen
-        def wrapper(*args, **kwargs):
-            for string in callable(*args, **kwargs):
-                yield string.encode(charset)
-        wrapper.__wrapped__ = callable
-        return wrapper
-    return dec
-
 class sessiondata(object):
     @classmethod
     def get(cls, req, create=True):
@@ -146,7 +136,7 @@ class sessiondata(object):
 class autodirty(sessiondata):
     @classmethod
     def get(cls, req):
-        ret = super().get(req)
+        ret = super(autodirty, cls).get(req)
         if "_is_dirty" not in ret.__dict__:
             ret.__dict__["_is_dirty"] = False
         return ret
@@ -158,18 +148,18 @@ class autodirty(sessiondata):
         return self._is_dirty
 
     def __setattr__(self, name, value):
-        super().__setattr__(name, value)
+        super(autodirty, self).__setattr__(name, value)
         if "_is_dirty" in self.__dict__:
             self.__dict__["_is_dirty"] = True
 
     def __delattr__(self, name):
-        super().__delattr__(name, value)
+        super(autodirty, self).__delattr__(name, value)
         if "_is_dirty" in self.__dict__:
             self.__dict__["_is_dirty"] = True
 
 class manudirty(object):
     def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
+        super(manudirty, self).__init__(*args, **kwargs)
         self.__dirty = False
 
     def sessfrozen(self):
@@ -212,7 +202,7 @@ class specslot(object):
 
 class specclass(type):
     def __init__(self, name, bases, tdict):
-        super().__init__(name, bases, tdict)
+        super(specclass, self).__init__(name, bases, tdict)
         sslots = set()
         dslots = set()
         for cls in self.__mro__:
@@ -224,7 +214,8 @@ class specclass(type):
         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):
@@ -232,7 +223,7 @@ class specdirty(sessiondata, metaclass=specclass):
 
     @staticmethod
     def __new__(cls, req, sess):
-        self = super().__new__(cls)
+        self = super(specdirty, cls).__new__(cls)
         self.session = sess
         self.__sslots__ = [specslot.unbound] * len(cls.__sslots_a__)
         self.__specinit__()
index ef886fb..13ce342 100644 (file)
@@ -1,6 +1,6 @@
 import os, threading
 from mako import template, lookup, filters
-from . import util, form, session, env, resp
+import util, form, session, env, resp
 
 # It seems Mako isn't thread-safe.
 makolock = threading.Lock()