""" open/DurusWorks/qpy/quoted.py """ import sys if not sys.version.startswith('3'): from __builtin__ import unicode, basestring, long # for checker. unicode_str = unicode number_classes = (int, long, float) string = basestring else: number_classes = (int, float) string = str unicode_str = str def xml_quote(x): """(x:anything) -> xml """ if isinstance(x, xml): return x if x is None: return xml() if type(x) is unicode_str: s = x elif isinstance(x, string): s = unicode_str(x, 'utf-8') else: s = unicode_str(x) s = s.replace("&", "&") s = s.replace("<", "<") s = s.replace(">", ">") s = s.replace('"', """) s = s.replace("'", "'") # ' is not HTML. return xml(s) class _xml_quote_wrapper (object): """ Not for outside code. For values that are used as arguments to the % operator, this allows str(value) and repr(value), if called as part of the formatting, to produce quoted results. Supports positional and named arguments, including attribute access, as required by the string format() method. """ __slots__ = ['value'] def __init__(self, value): self.value = value def __str__(self): return xml_quote(self.value) def __repr__(self): return xml_quote(repr(self.value)) def __getitem__(self, key): return _quote_wrap(self.value[key]) def __getattr__(self, name): return _quote_wrap(getattr(self.value, name)) def keys(self): return list(self.value.keys()) def _quote_wrap(x): """(x) -> _xml_quote_wrapper | x Not for outside code. Return a value v for which str(v) and repr(v) will produce quoted strings, or, if x is a dict, for which str(v[key]) and repr(v[key]) will produce quoted strings. """ if isinstance(x, number_classes): return x else: return _xml_quote_wrapper(x) class xml (unicode_str): """ This subclass of str is designated as needing no more xml quoting. """ __slots__ = [] def __new__(klass, string=None, encoding=sys.getdefaultencoding(), errors='strict'): if string is None: return xml('') elif isinstance(string, unicode_str): string = string.encode('utf-8') encoding = 'utf-8' return unicode_str.__new__(klass, string, encoding, errors) def __add__(self, other): """(other) -> xml """ return xml(unicode_str.__add__(self, xml_quote(other))) def __radd__(self, other): """(other:str) -> xml """ if isinstance(other, string): return xml(unicode_str.__add__(xml_quote(other), self)) else: return NotImplemented def __mul__(self, other): """(other) -> xml """ return xml(unicode_str.__mul__(self, other)) def __rmul__(self, other): """(other) -> xml """ return xml(unicode_str.__mul__(self, other)) def __mod__(self, other): """(other) -> xml """ if isinstance(other, tuple): target = tuple([_quote_wrap(item) for item in other]) else: target = _quote_wrap(other) return xml(unicode_str.__mod__(self, target)) def __html__(self): """ Returns this xml instance. Included for compatibility with other software packages that have designated this method to return html that needs no more quoting. """ return self def format(self, *args, **kwargs): quoted_args = tuple([_quote_wrap(arg) for arg in args]) quoted_kwargs = _xml_quote_wrapper(kwargs) return xml(unicode_str.format(self, *quoted_args, **quoted_kwargs)) def join(self, items): """(items) -> xml """ return xml(unicode_str.join(self, [xml_quote(item) for item in items])) join_xml = xml().join xml.quote = staticmethod(xml_quote) def join_str(args): return ''.join([unicode_str(arg) for arg in args if arg is not None]) __all__ = ['xml', 'join_xml', 'join_str', 'xml_quote']