Merge branch 'master' into python3
authorFredrik Tolf <fredrik@dolda2000.com>
Sat, 28 Dec 2013 05:37:03 +0000 (06:37 +0100)
committerFredrik Tolf <fredrik@dolda2000.com>
Sat, 28 Dec 2013 05:37:03 +0000 (06:37 +0100)
Conflicts:
wrw/sp/util.py

1  2 
wrw/sp/util.py
wrw/sp/xhtml.py

diff --combined wrw/sp/util.py
@@@ -1,6 -1,6 +1,6 @@@
 -import itertools, StringIO
 -from wrw import dispatch
 -import cons
 +import itertools, io
 +from .. import dispatch
 +from . import cons
  
  def findnsnames(el):
      names = {}
@@@ -8,7 -8,7 +8,7 @@@
      def proc(el):
          if isinstance(el, cons.element):
              if el.ns not in names:
 -                names[el.ns] = u"n" + unicode(nid[0])
 +                names[el.ns] = "n" + str(nid[0])
                  nid[:] = [nid[0] + 1]
              for ch in el.children:
                  proc(ch)
@@@ -56,9 -56,9 +56,9 @@@ class formatter(object)
          self.buf.extend(text.encode(self.charset))
  
      def quotewrite(self, buf):
 -        buf = buf.replace(u'&', u"&amp;")
 -        buf = buf.replace(u'<', u"&lt;")
 -        buf = buf.replace(u'>', u"&gt;")
 +        buf = buf.replace('&', "&amp;")
 +        buf = buf.replace('<', "&lt;")
 +        buf = buf.replace('>', "&gt;")
          self.write(buf)
  
      def __iter__(self):
          if ns is None:
              return el.name
          else:
 -            return ns + u":" + el.name
 +            return ns + ":" + el.name
  
      def attrval(self, v):
 -        qc, qt = (u"'", u"&apos;") if u'"' in v else (u'"', u"&quot;")
 +        qc, qt = ("'", "&apos;") if '"' in v else ('"', "&quot;")
          self.write(qc)
 -        v = v.replace(u'&', u"&amp;")
 -        v = v.replace(u'<', u"&lt;")
 -        v = v.replace(u'>', u"&gt;")
 +        v = v.replace('&', "&amp;")
 +        v = v.replace('<', "&lt;")
 +        v = v.replace('>', "&gt;")
          v = v.replace(qc, qt)
          self.write(v)
          self.write(qc)
  
      def attr(self, k, v):
          self.write(k)
 -        self.write(u"=")
 +        self.write("=")
          self.attrval(v)
  
      def attrs(self, attrs):
          for k, v in attrs:
 -            self.write(u" ")
 +            self.write(" ")
              self.attr(k, v)
  
      def inittag(self, el):
 -        self.write(u"<" + self.elname(el))
 -        attrs = el.attrs.iteritems()
 +        self.write("<" + self.elname(el))
 +        attrs = el.attrs.items()
          if self.first:
              nsnames = []
 -            for ns, name in self.nsnames.iteritems():
 +            for ns, name in self.nsnames.items():
                  if ns is None:
                      if name is not None:
                          raise Exception("null namespace must have null name, not" + name)
                      continue
 -                nsnames.append((u"xmlns" if name is None else (u"xmlns:" + name), ns))
 +                nsnames.append(("xmlns" if name is None else ("xmlns:" + name), ns))
              attrs = itertools.chain(attrs, iter(nsnames))
              self.first = False
          self.attrs(attrs)
  
      def starttag(self, el):
          self.inittag(el)
 -        self.write(u">")
 +        self.write(">")
  
      def shorttag(self, el):
          self.inittag(el)
 -        self.write(u" />")
 +        self.write(" />")
  
      def endtag(self, el):
 -        self.write(u"</" + self.elname(el) + u">")
 +        self.write("</" + self.elname(el) + ">")
  
      def text(self, el):
          self.quotewrite(el)
          self.write(el)
  
      def start(self, el):
 -        self.write(u'<?xml version="1.0" encoding="' + self.charset + u'" ?>\n')
 +        self.write('<?xml version="1.0" encoding="' + self.charset + '" ?>\n')
          if isinstance(el, cons.doctype):
 -            self.write(u'<!DOCTYPE %s PUBLIC "%s" "%s">\n' % (el.rootname,
 +            self.write('<!DOCTYPE %s PUBLIC "%s" "%s">\n' % (el.rootname,
                                                                el.pubid,
                                                                el.dtdid))
          self.first = True
      def end(self, el):
          pass
  
-     def __next__(self):
-         if self.src is None:
-             raise StopIteration()
-         try:
-             ev, el = next(self.src)
-         except StopIteration:
-             self.src = None
-             ev, el = "$", None
+     def handle(self, ev, el):
          if ev == ">":
              self.starttag(el)
          elif ev == "/":
              self.start(el)
          elif ev == "$":
              self.end(el)
 -    def next(self):
 -        ret = str(self.buf)
 -        self.buf[:] = ""
++    def __next__(self):
+         if self.src is None:
+             raise StopIteration()
+         try:
+             ev, el = next(self.src)
+         except StopIteration:
+             self.src = None
+             ev, el = "$", None
+         self.handle(ev, el)
 +        ret = bytes(self.buf)
 +        self.buf[:] = b""
          return ret
  
      def nsname(self, el):
                  return ret
          if el.ns is None:
              return None
 -        ret = u"n" + unicode(self.nextns)
 +        ret = "n" + str(self.nextns)
          self.nextns += 1
          return ret
  
  
      @classmethod
      def format(cls, root, **kw):
 -        buf = StringIO.StringIO()
 +        buf = io.BytesIO()
          cls.output(buf, root, **kw)
          return buf.getvalue()
  
  class indenter(formatter):
 -    def __init__(self, indent=u"  ", *args, **kw):
 -        super(indenter, self).__init__(*args, **kw)
 +    def __init__(self, indent="  ", *args, **kw):
 +        super().__init__(*args, **kw)
          self.indent = indent
          self.col = 0
 -        self.curind = u""
 +        self.curind = ""
          self.atbreak = True
          self.inline = False
          self.stack = []
+         self.last = None, None
  
      def write(self, text):
 -        lines = text.split(u"\n")
 +        lines = text.split("\n")
          if len(lines) > 1:
              for ln in lines[:-1]:
                  self.buf.extend(ln.encode(self.charset))
 -                self.buf.extend("\n")
 +                self.buf.extend(b"\n")
              self.col = 0
          self.buf.extend(lines[-1].encode(self.charset))
          self.col += len(lines[-1])
  
      def br(self):
          if not self.atbreak:
 -            self.buf.extend((u"\n" + self.curind).encode(self.charset))
 +            self.buf.extend(("\n" + self.curind).encode(self.charset))
              self.col = 0
              self.atbreak = True
  
  
      def starttag(self, el):
          if not self.inline:
-             self.br()
+             if self.last[0] == "<" and self.last[1].name == el.name:
+                 pass
+             else:
+                 self.br()
          self.push(el)
          self.inline = self.inline or self.inlinep(el)
          self.curind += self.indent
 -        super(indenter, self).starttag(el)
 +        super().starttag(el)
  
      def shorttag(self, el):
          if not self.inline:
              self.br()
 -        super(indenter, self).shorttag(el)
 +        super().shorttag(el)
  
      def endtag(self, el):
          il = self.inline
          self.pop()
          if not il:
              self.br()
 -        super(indenter, self).endtag(el)
 +        super().endtag(el)
  
      def start(self, el):
 -        super(indenter, self).start(el)
 +        super().start(el)
          self.atbreak = True
  
      def end(self, el):
          self.br()
  
 -        super(indenter, self).handle(ev, el)
+     def handle(self, ev, el):
++        super().handle(ev, el)
+         self.last = ev, el
  class textindenter(indenter):
      maxcol = 70
  
      def text(self, el):
 -        left = unicode(el)
 +        left = str(el)
          while True:
              if len(left) + self.col > self.maxcol:
                  bp = max(self.maxcol - self.col, 0)
 -                for i in xrange(bp, -1, -1):
 +                for i in range(bp, -1, -1):
                      if left[i].isspace():
                          while i > 0 and left[i - 1].isspace(): i -= 1
                          break
                  else:
 -                    for i in xrange(bp + 1, len(left)):
 +                    for i in range(bp + 1, len(left)):
                          if left[i].isspace():
                              break
                      else:
@@@ -318,7 -329,7 +329,7 @@@ class response(dispatch.restart)
      formatter = indenter
  
      def __init__(self, root):
 -        super(response, self).__init__()
 +        super().__init__()
          self.root = root
  
      @property
diff --combined wrw/sp/xhtml.py
@@@ -1,11 -1,11 +1,11 @@@
 -import xml.dom.minidom, StringIO
 -import cons as _cons
 -import util
 +import xml.dom.minidom, io
 +from . import cons as _cons
 +from . import util
  dom = xml.dom.minidom.getDOMImplementation()
  
 -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"
 +ns = "http://www.w3.org/1999/xhtml"
 +doctype = "-//W3C//DTD XHTML 1.1//EN"
 +dtd = "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
  
  class htmlelement(_cons.element):
      def __todoc__(self):
          return doc
  
  class xhtmlcontext(_cons.context):
 -    attrmap = {u"klass": u"class"}
 +    attrmap = {"klass": "class"}
  
      def addattr(self, node, k, v):
 -        k = unicode(k)
 -        super(xhtmlcontext, self).addattr(node, self.attrmap.get(k, k), v)
 +        k = str(k)
 +        super().addattr(node, self.attrmap.get(k, k), v)
  
  def cons(ctx=None):
      if ctx is None: ctx = xhtmlcontext()
@@@ -30,7 -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, unicode):
 +    if isinstance(css, str) or isinstance(css, bytes):
          head(h.link(rel="stylesheet", type="text/css", href=css))
      elif css:
          for ss in css:
      return head
  
  class htmlformatter(util.formatter):
 -    allowshort = set([u"br", u"hr", u"img", u"input", u"meta", u"link"])
 +    allowshort = {"br", "hr", "img", "input", "meta", "link"}
      def shorttag(self, el):
          if el.name in self.allowshort:
 -            super(htmlformatter, self).shorttag(el)
 +            super().shorttag(el)
          else:
-             self.starttag(el)
-             self.endtag(el)
+             self.handle(">", el)
+             self.handle("<", el)
  
  class htmlindenter(util.textindenter, htmlformatter):
      pass
@@@ -52,7 -52,7 +52,7 @@@
  def forreq(req, tree):
      # XXX: Use proper Content-Type for clients accepting it.
      req.ohead["Content-Type"] = "text/html; charset=utf-8"
 -    buf = StringIO.StringIO()
 +    buf = io.BytesIO()
      htmlindenter.output(buf, tree, doctype=(doctype, dtd), charset="utf-8")
      ret = buf.getvalue()
      req.ohead["Content-Length"] = len(ret)