0001# -*- coding: utf-8 -*-
0002
0003"""Utility functions for Kid."""
0004
0005__revision__ = "$Rev: 492 $"
0006__date__ = "$Date: 2007-07-06 21:38:45 -0400 (Fri, 06 Jul 2007) $"
0007__author__ = "Ryan Tomayko (rtomayko@gmail.com)"
0008__copyright__ = "Copyright 2004-2005, Ryan Tomayko"
0009__license__ = "MIT <http://www.opensource.org/licenses/mit-license.php>"
0010
0011
0012from urllib import splittype
0013
0014
0015class QuickTextReader(object):
0016
0017    def __init__(self, text):
0018        self.text = text
0019        self.len = len(self.text)
0020        self.pos = 0
0021        self.lines = None
0022
0023    def __iter__(self):
0024        while 1:
0025            if self.lines is None:
0026                self.lines = self.text.splitlines(True)
0027            if not self.lines:
0028                break
0029            yield self.lines.pop(0)
0030
0031    def close(self):
0032        self.text = None
0033        self.pos = self.len = 0
0034        self.lines = None
0035
0036    def read(self, size=None):
0037        if size is not None:
0038            try:
0039                size = int(size)
0040            except:
0041                size = None
0042            else:
0043                if not 0 <= size < self.len:
0044                    size = None
0045        pos = self.pos
0046        if size is None:
0047            self.pos = self.len
0048            return self.text[pos:]
0049        else:
0050            self.pos += size
0051            if self.pos > self.len:
0052                self.pos = self.len
0053            return self.text[pos:self.pos]
0054
0055    def seek(self, offset, whence=0):
0056        if whence:
0057            if whence == 2:
0058                self.pos = self.len - offset
0059            else:
0060                self.pos += offset
0061        else:
0062            self.pos = offset
0063            self.lines = None
0064        if self.pos < 0:
0065            self.pos = 0
0066        elif self.pos > self.len:
0067            self.pos = self.len
0068
0069        def tell(self):
0070            return self.pos
0071
0072        def next(self):
0073            if not self.lineno:
0074                self.lines = self.splitlines(True)
0075            self.lineno += 1
0076            if not self.lines:
0077                raise StopIteration
0078            return self.lines.pop(0)
0079
0080def xml_sniff(text):
0081    """Sniff text to see if it looks like XML.
0082
0083    Return True if text looks like XML, otherwise return False.
0084
0085    """
0086    for x in text:
0087        if x in '\t\r\n ':
0088            continue
0089        elif x == '<':
0090            return True
0091        else:
0092            return False
0093
0094def open_resource(uri, mode='rb'):
0095    """Generic resource opener."""
0096    scheme, rest = splittype(uri)
0097    if not scheme or (len(scheme) == 1 and rest.startswith('\\')):
0098        return open(uri, mode)
0099    else:
0100        import urllib2
0101        return urllib2.urlopen(uri)
0102
0103def get_expat_error(error):
0104    """Return text showing the position of an Expat error."""
0105    source, lineno, offset = error.source, error.lineno, error.offset
0106    if lineno < 1:
0107        lineno = 1
0108        offset = 0
0109    source.seek(0)
0110    nlines = 0
0111    for line in source:
0112        lineno -= 1
0113        nlines += 1
0114        if not lineno:
0115            break
0116    else:
0117        offset = 0
0118    if nlines:
0119        if nlines == 1:
0120            if line.startswith('\xef\xbb\xbf'):
0121                line = line[3:]
0122        if line:
0123            if offset < 0:
0124                offset = 0
0125            elif offset > len(line):
0126                offset = len(line)
0127            if offset > 75:
0128                if len(line) - offset > 37:
0129                    line = line[offset-38:offset+38]
0130                    offset = 38
0131                else:
0132                    offset -= len(line) - 76
0133                    line = line[-76:]
0134            else:
0135                line = line[:76]
0136            if line:
0137                line = '%s\n%%%ds\n' % (line.rstrip(), offset + 1)
0138                line = line % '^'
0139    return line