183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#!/usr/bin/env python
283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh## vim:ts=4:et:nowrap
383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh"""A user-defined wrapper around string objects
483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehNote: string objects have grown methods in Python 1.6
683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThis module requires Python 1.6 or later.
783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh"""
883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport sys
983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport collections
1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh__all__ = ["UserString","MutableString"]
1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass UserString(collections.Sequence):
1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, seq):
1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if isinstance(seq, basestring):
1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data = seq
1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        elif isinstance(seq, UserString):
1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data = seq.data[:]
1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data = str(seq)
2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __str__(self): return str(self.data)
2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __repr__(self): return repr(self.data)
2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __int__(self): return int(self.data)
2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __long__(self): return long(self.data)
2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __float__(self): return float(self.data)
2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __complex__(self): return complex(self.data)
2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __hash__(self): return hash(self.data)
2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __cmp__(self, string):
3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if isinstance(string, UserString):
3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return cmp(self.data, string.data)
3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return cmp(self.data, string)
3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __contains__(self, char):
3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return char in self.data
3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __len__(self): return len(self.data)
3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __getitem__(self, index): return self.__class__(self.data[index])
3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __getslice__(self, start, end):
4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        start = max(start, 0); end = max(end, 0)
4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.__class__(self.data[start:end])
4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __add__(self, other):
4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if isinstance(other, UserString):
4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return self.__class__(self.data + other.data)
4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        elif isinstance(other, basestring):
4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return self.__class__(self.data + other)
4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return self.__class__(self.data + str(other))
5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __radd__(self, other):
5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if isinstance(other, basestring):
5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return self.__class__(other + self.data)
5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return self.__class__(str(other) + self.data)
5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __mul__(self, n):
5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.__class__(self.data*n)
5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    __rmul__ = __mul__
5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __mod__(self, args):
5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.__class__(self.data % args)
6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # the following methods are defined in alphabetical order:
6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def capitalize(self): return self.__class__(self.data.capitalize())
6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def center(self, width, *args):
6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.__class__(self.data.center(width, *args))
6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def count(self, sub, start=0, end=sys.maxint):
6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.data.count(sub, start, end)
6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def decode(self, encoding=None, errors=None): # XXX improve this?
6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if encoding:
6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if errors:
7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return self.__class__(self.data.decode(encoding, errors))
7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            else:
7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return self.__class__(self.data.decode(encoding))
7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return self.__class__(self.data.decode())
7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def encode(self, encoding=None, errors=None): # XXX improve this?
7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if encoding:
7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if errors:
7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return self.__class__(self.data.encode(encoding, errors))
7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            else:
8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                return self.__class__(self.data.encode(encoding))
8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return self.__class__(self.data.encode())
8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def endswith(self, suffix, start=0, end=sys.maxint):
8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.data.endswith(suffix, start, end)
8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def expandtabs(self, tabsize=8):
8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.__class__(self.data.expandtabs(tabsize))
8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def find(self, sub, start=0, end=sys.maxint):
8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.data.find(sub, start, end)
8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def index(self, sub, start=0, end=sys.maxint):
9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.data.index(sub, start, end)
9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def isalpha(self): return self.data.isalpha()
9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def isalnum(self): return self.data.isalnum()
9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def isdecimal(self): return self.data.isdecimal()
9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def isdigit(self): return self.data.isdigit()
9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def islower(self): return self.data.islower()
9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def isnumeric(self): return self.data.isnumeric()
9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def isspace(self): return self.data.isspace()
9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def istitle(self): return self.data.istitle()
9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def isupper(self): return self.data.isupper()
10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def join(self, seq): return self.data.join(seq)
10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def ljust(self, width, *args):
10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.__class__(self.data.ljust(width, *args))
10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def lower(self): return self.__class__(self.data.lower())
10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars))
10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def partition(self, sep):
10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.data.partition(sep)
10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def replace(self, old, new, maxsplit=-1):
10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.__class__(self.data.replace(old, new, maxsplit))
10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def rfind(self, sub, start=0, end=sys.maxint):
11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.data.rfind(sub, start, end)
11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def rindex(self, sub, start=0, end=sys.maxint):
11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.data.rindex(sub, start, end)
11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def rjust(self, width, *args):
11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.__class__(self.data.rjust(width, *args))
11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def rpartition(self, sep):
11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.data.rpartition(sep)
11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def rstrip(self, chars=None): return self.__class__(self.data.rstrip(chars))
11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def split(self, sep=None, maxsplit=-1):
11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.data.split(sep, maxsplit)
12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def rsplit(self, sep=None, maxsplit=-1):
12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.data.rsplit(sep, maxsplit)
12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def splitlines(self, keepends=0): return self.data.splitlines(keepends)
12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def startswith(self, prefix, start=0, end=sys.maxint):
12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.data.startswith(prefix, start, end)
12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def strip(self, chars=None): return self.__class__(self.data.strip(chars))
12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def swapcase(self): return self.__class__(self.data.swapcase())
12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def title(self): return self.__class__(self.data.title())
12883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def translate(self, *args):
12983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.__class__(self.data.translate(*args))
13083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def upper(self): return self.__class__(self.data.upper())
13183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def zfill(self, width): return self.__class__(self.data.zfill(width))
13283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
13383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass MutableString(UserString, collections.MutableSequence):
13483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """mutable string objects
13583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
13683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Python strings are immutable objects.  This has the advantage, that
13783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    strings may be used as dictionary keys.  If this property isn't needed
13883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    and you insist on changing string values in place instead, you may cheat
13983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    and use MutableString.
14083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
14183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    But the purpose of this class is an educational one: to prevent
14283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    people from inventing their own mutable string class derived
14383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    from UserString and than forget thereby to remove (override) the
14483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    __hash__ method inherited from UserString.  This would lead to
14583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    errors that would be very hard to track down.
14683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
14783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    A faster and better solution is to rewrite your program using lists."""
14883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, string=""):
14983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        from warnings import warnpy3k
15083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        warnpy3k('the class UserString.MutableString has been removed in '
15183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    'Python 3.0', stacklevel=2)
15283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.data = string
15383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
15483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # We inherit object.__hash__, so we must deny this explicitly
15583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    __hash__ = None
15683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
15783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __setitem__(self, index, sub):
15883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if isinstance(index, slice):
15983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if isinstance(sub, UserString):
16083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                sub = sub.data
16183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            elif not isinstance(sub, basestring):
16283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                sub = str(sub)
16383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            start, stop, step = index.indices(len(self.data))
16483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if step == -1:
16583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                start, stop = stop+1, start+1
16683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                sub = sub[::-1]
16783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            elif step != 1:
16883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # XXX(twouters): I guess we should be reimplementing
16983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # the extended slice assignment/deletion algorithm here...
17083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                raise TypeError, "invalid step in slicing assignment"
17183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            start = min(start, stop)
17283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data = self.data[:start] + sub + self.data[stop:]
17383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
17483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if index < 0:
17583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                index += len(self.data)
17683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if index < 0 or index >= len(self.data): raise IndexError
17783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data = self.data[:index] + sub + self.data[index+1:]
17883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __delitem__(self, index):
17983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if isinstance(index, slice):
18083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            start, stop, step = index.indices(len(self.data))
18183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if step == -1:
18283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                start, stop = stop+1, start+1
18383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            elif step != 1:
18483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # XXX(twouters): see same block in __setitem__
18583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                raise TypeError, "invalid step in slicing deletion"
18683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            start = min(start, stop)
18783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data = self.data[:start] + self.data[stop:]
18883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
18983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if index < 0:
19083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                index += len(self.data)
19183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if index < 0 or index >= len(self.data): raise IndexError
19283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data = self.data[:index] + self.data[index+1:]
19383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __setslice__(self, start, end, sub):
19483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        start = max(start, 0); end = max(end, 0)
19583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if isinstance(sub, UserString):
19683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data = self.data[:start]+sub.data+self.data[end:]
19783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        elif isinstance(sub, basestring):
19883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data = self.data[:start]+sub+self.data[end:]
19983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
20083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data =  self.data[:start]+str(sub)+self.data[end:]
20183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __delslice__(self, start, end):
20283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        start = max(start, 0); end = max(end, 0)
20383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.data = self.data[:start] + self.data[end:]
20483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def immutable(self):
20583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return UserString(self.data)
20683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __iadd__(self, other):
20783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if isinstance(other, UserString):
20883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data += other.data
20983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        elif isinstance(other, basestring):
21083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data += other
21183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
21283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.data += str(other)
21383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self
21483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __imul__(self, n):
21583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.data *= n
21683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self
21783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def insert(self, index, value):
21883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self[index:index] = value
21983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehif __name__ == "__main__":
22183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # execute the regression test to stdout, if called as a script:
22283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    import os
22383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    called_in_dir, called_as = os.path.split(sys.argv[0])
22483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    called_as, py = os.path.splitext(called_as)
22583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    if '-q' in sys.argv:
22683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        from test import test_support
22783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        test_support.verbose = 0
22883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    __import__('test.test_' + called_as.lower())
229