mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Bug 1016929 - [mozlog] html formatter imports py.xml, doesn't declare it as a dependency. r=jgraham
--HG-- extra : rebase_source : 249b6ee7f576ce466f77fc063fef4c7fddffa9ec
This commit is contained in:
parent
9da642763f
commit
337d9012ea
@ -21,7 +21,7 @@ def do_defered_imports():
|
|||||||
global html
|
global html
|
||||||
global raw
|
global raw
|
||||||
|
|
||||||
from py.xml import html, raw
|
from .xmlgen import html, raw
|
||||||
|
|
||||||
|
|
||||||
class HTMLFormatter(base.BaseFormatter):
|
class HTMLFormatter(base.BaseFormatter):
|
||||||
|
@ -0,0 +1,267 @@
|
|||||||
|
"""
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
This file is originally from: https://bitbucket.org/hpk42/py, specifically:
|
||||||
|
https://bitbucket.org/hpk42/py/src/980c8d526463958ee7cae678a7e4e9b054f36b94/py/_xmlgen.py?at=default
|
||||||
|
by holger krekel, holger at merlinux eu. 2009
|
||||||
|
"""
|
||||||
|
import sys, re
|
||||||
|
|
||||||
|
if sys.version_info >= (3,0):
|
||||||
|
def u(s):
|
||||||
|
return s
|
||||||
|
def unicode(x):
|
||||||
|
if hasattr(x, '__unicode__'):
|
||||||
|
return x.__unicode__()
|
||||||
|
return str(x)
|
||||||
|
else:
|
||||||
|
def u(s):
|
||||||
|
return unicode(s)
|
||||||
|
unicode = unicode
|
||||||
|
|
||||||
|
|
||||||
|
class NamespaceMetaclass(type):
|
||||||
|
def __getattr__(self, name):
|
||||||
|
if name[:1] == '_':
|
||||||
|
raise AttributeError(name)
|
||||||
|
if self == Namespace:
|
||||||
|
raise ValueError("Namespace class is abstract")
|
||||||
|
tagspec = self.__tagspec__
|
||||||
|
if tagspec is not None and name not in tagspec:
|
||||||
|
raise AttributeError(name)
|
||||||
|
classattr = {}
|
||||||
|
if self.__stickyname__:
|
||||||
|
classattr['xmlname'] = name
|
||||||
|
cls = type(name, (self.__tagclass__,), classattr)
|
||||||
|
setattr(self, name, cls)
|
||||||
|
return cls
|
||||||
|
|
||||||
|
class Tag(list):
|
||||||
|
class Attr(object):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self.__dict__.update(kwargs)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(Tag, self).__init__(args)
|
||||||
|
self.attr = self.Attr(**kwargs)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return self.unicode(indent=0)
|
||||||
|
__str__ = __unicode__
|
||||||
|
|
||||||
|
def unicode(self, indent=2):
|
||||||
|
l = []
|
||||||
|
SimpleUnicodeVisitor(l.append, indent).visit(self)
|
||||||
|
return u("").join(l)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
name = self.__class__.__name__
|
||||||
|
return "<%r tag object %d>" % (name, id(self))
|
||||||
|
|
||||||
|
Namespace = NamespaceMetaclass('Namespace', (object, ), {
|
||||||
|
'__tagspec__': None,
|
||||||
|
'__tagclass__': Tag,
|
||||||
|
'__stickyname__': False,
|
||||||
|
})
|
||||||
|
|
||||||
|
class HtmlTag(Tag):
|
||||||
|
def unicode(self, indent=2):
|
||||||
|
l = []
|
||||||
|
HtmlVisitor(l.append, indent, shortempty=False).visit(self)
|
||||||
|
return u("").join(l)
|
||||||
|
|
||||||
|
# exported plain html namespace
|
||||||
|
class html(Namespace):
|
||||||
|
__tagclass__ = HtmlTag
|
||||||
|
__stickyname__ = True
|
||||||
|
__tagspec__ = dict([(x,1) for x in (
|
||||||
|
'a,abbr,acronym,address,applet,area,b,bdo,big,blink,'
|
||||||
|
'blockquote,body,br,button,caption,center,cite,code,col,'
|
||||||
|
'colgroup,comment,dd,del,dfn,dir,div,dl,dt,em,embed,'
|
||||||
|
'fieldset,font,form,frameset,h1,h2,h3,h4,h5,h6,head,html,'
|
||||||
|
'i,iframe,img,input,ins,kbd,label,legend,li,link,listing,'
|
||||||
|
'map,marquee,menu,meta,multicol,nobr,noembed,noframes,'
|
||||||
|
'noscript,object,ol,optgroup,option,p,pre,q,s,script,'
|
||||||
|
'select,small,span,strike,strong,style,sub,sup,table,'
|
||||||
|
'tbody,td,textarea,tfoot,th,thead,title,tr,tt,u,ul,xmp,'
|
||||||
|
'base,basefont,frame,hr,isindex,param,samp,var'
|
||||||
|
).split(',') if x])
|
||||||
|
|
||||||
|
class Style(object):
|
||||||
|
def __init__(self, **kw):
|
||||||
|
for x, y in kw.items():
|
||||||
|
x = x.replace('_', '-')
|
||||||
|
setattr(self, x, y)
|
||||||
|
|
||||||
|
|
||||||
|
class raw(object):
|
||||||
|
"""just a box that can contain a unicode string that will be
|
||||||
|
included directly in the output"""
|
||||||
|
def __init__(self, uniobj):
|
||||||
|
self.uniobj = uniobj
|
||||||
|
|
||||||
|
class SimpleUnicodeVisitor(object):
|
||||||
|
""" recursive visitor to write unicode. """
|
||||||
|
def __init__(self, write, indent=0, curindent=0, shortempty=True):
|
||||||
|
self.write = write
|
||||||
|
self.cache = {}
|
||||||
|
self.visited = {} # for detection of recursion
|
||||||
|
self.indent = indent
|
||||||
|
self.curindent = curindent
|
||||||
|
self.parents = []
|
||||||
|
self.shortempty = shortempty # short empty tags or not
|
||||||
|
|
||||||
|
def visit(self, node):
|
||||||
|
""" dispatcher on node's class/bases name. """
|
||||||
|
cls = node.__class__
|
||||||
|
try:
|
||||||
|
visitmethod = self.cache[cls]
|
||||||
|
except KeyError:
|
||||||
|
for subclass in cls.__mro__:
|
||||||
|
visitmethod = getattr(self, subclass.__name__, None)
|
||||||
|
if visitmethod is not None:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
visitmethod = self.__object
|
||||||
|
self.cache[cls] = visitmethod
|
||||||
|
visitmethod(node)
|
||||||
|
|
||||||
|
# the default fallback handler is marked private
|
||||||
|
# to avoid clashes with the tag name object
|
||||||
|
def __object(self, obj):
|
||||||
|
#self.write(obj)
|
||||||
|
self.write(escape(unicode(obj)))
|
||||||
|
|
||||||
|
def raw(self, obj):
|
||||||
|
self.write(obj.uniobj)
|
||||||
|
|
||||||
|
def list(self, obj):
|
||||||
|
assert id(obj) not in self.visited
|
||||||
|
self.visited[id(obj)] = 1
|
||||||
|
for elem in obj:
|
||||||
|
self.visit(elem)
|
||||||
|
|
||||||
|
def Tag(self, tag):
|
||||||
|
assert id(tag) not in self.visited
|
||||||
|
try:
|
||||||
|
tag.parent = self.parents[-1]
|
||||||
|
except IndexError:
|
||||||
|
tag.parent = None
|
||||||
|
self.visited[id(tag)] = 1
|
||||||
|
tagname = getattr(tag, 'xmlname', tag.__class__.__name__)
|
||||||
|
if self.curindent and not self._isinline(tagname):
|
||||||
|
self.write("\n" + u(' ') * self.curindent)
|
||||||
|
if tag:
|
||||||
|
self.curindent += self.indent
|
||||||
|
self.write(u('<%s%s>') % (tagname, self.attributes(tag)))
|
||||||
|
self.parents.append(tag)
|
||||||
|
for x in tag:
|
||||||
|
self.visit(x)
|
||||||
|
self.parents.pop()
|
||||||
|
self.write(u('</%s>') % tagname)
|
||||||
|
self.curindent -= self.indent
|
||||||
|
else:
|
||||||
|
nameattr = tagname+self.attributes(tag)
|
||||||
|
if self._issingleton(tagname):
|
||||||
|
self.write(u('<%s/>') % (nameattr,))
|
||||||
|
else:
|
||||||
|
self.write(u('<%s></%s>') % (nameattr, tagname))
|
||||||
|
|
||||||
|
def attributes(self, tag):
|
||||||
|
# serialize attributes
|
||||||
|
attrlist = dir(tag.attr)
|
||||||
|
attrlist.sort()
|
||||||
|
l = []
|
||||||
|
for name in attrlist:
|
||||||
|
res = self.repr_attribute(tag.attr, name)
|
||||||
|
if res is not None:
|
||||||
|
l.append(res)
|
||||||
|
l.extend(self.getstyle(tag))
|
||||||
|
return u("").join(l)
|
||||||
|
|
||||||
|
def repr_attribute(self, attrs, name):
|
||||||
|
if name[:2] != '__':
|
||||||
|
value = getattr(attrs, name)
|
||||||
|
if name.endswith('_'):
|
||||||
|
name = name[:-1]
|
||||||
|
if isinstance(value, raw):
|
||||||
|
insert = value.uniobj
|
||||||
|
else:
|
||||||
|
insert = escape(unicode(value))
|
||||||
|
return ' %s="%s"' % (name, insert)
|
||||||
|
|
||||||
|
def getstyle(self, tag):
|
||||||
|
""" return attribute list suitable for styling. """
|
||||||
|
try:
|
||||||
|
styledict = tag.style.__dict__
|
||||||
|
except AttributeError:
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
stylelist = [x+': ' + y for x,y in styledict.items()]
|
||||||
|
return [u(' style="%s"') % u('; ').join(stylelist)]
|
||||||
|
|
||||||
|
def _issingleton(self, tagname):
|
||||||
|
"""can (and will) be overridden in subclasses"""
|
||||||
|
return self.shortempty
|
||||||
|
|
||||||
|
def _isinline(self, tagname):
|
||||||
|
"""can (and will) be overridden in subclasses"""
|
||||||
|
return False
|
||||||
|
|
||||||
|
class HtmlVisitor(SimpleUnicodeVisitor):
|
||||||
|
|
||||||
|
single = dict([(x, 1) for x in
|
||||||
|
('br,img,area,param,col,hr,meta,link,base,'
|
||||||
|
'input,frame').split(',')])
|
||||||
|
inline = dict([(x, 1) for x in
|
||||||
|
('a abbr acronym b basefont bdo big br cite code dfn em font '
|
||||||
|
'i img input kbd label q s samp select small span strike '
|
||||||
|
'strong sub sup textarea tt u var'.split(' '))])
|
||||||
|
|
||||||
|
def repr_attribute(self, attrs, name):
|
||||||
|
if name == 'class_':
|
||||||
|
value = getattr(attrs, name)
|
||||||
|
if value is None:
|
||||||
|
return
|
||||||
|
return super(HtmlVisitor, self).repr_attribute(attrs, name)
|
||||||
|
|
||||||
|
def _issingleton(self, tagname):
|
||||||
|
return tagname in self.single
|
||||||
|
|
||||||
|
def _isinline(self, tagname):
|
||||||
|
return tagname in self.inline
|
||||||
|
|
||||||
|
|
||||||
|
class _escape:
|
||||||
|
def __init__(self):
|
||||||
|
self.escape = {
|
||||||
|
u('"') : u('"'), u('<') : u('<'), u('>') : u('>'),
|
||||||
|
u('&') : u('&'), u("'") : u('''),
|
||||||
|
}
|
||||||
|
self.charef_rex = re.compile(u("|").join(self.escape.keys()))
|
||||||
|
|
||||||
|
def _replacer(self, match):
|
||||||
|
return self.escape[match.group(0)]
|
||||||
|
|
||||||
|
def __call__(self, ustring):
|
||||||
|
""" xml-escape the given unicode string. """
|
||||||
|
ustring = unicode(ustring)
|
||||||
|
return self.charef_rex.sub(self._replacer, ustring)
|
||||||
|
|
||||||
|
escape = _escape()
|
Loading…
Reference in New Issue
Block a user