1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh#!/usr/bin/env python
2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh## vim:ts=4:et:nowrap
3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""A user-defined wrapper around string objects
4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehNote: string objects have grown methods in Python 1.6
6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehThis module requires Python 1.6 or later.
7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""
8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport sys
9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport collections
10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh__all__ = ["UserString","MutableString"]
12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass UserString(collections.Sequence):
14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __init__(self, seq):
15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if isinstance(seq, basestring):
16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data = seq
17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        elif isinstance(seq, UserString):
18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data = seq.data[:]
19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data = str(seq)
21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __str__(self): return str(self.data)
22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __repr__(self): return repr(self.data)
23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __int__(self): return int(self.data)
24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __long__(self): return long(self.data)
25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __float__(self): return float(self.data)
26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __complex__(self): return complex(self.data)
27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __hash__(self): return hash(self.data)
28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __cmp__(self, string):
30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if isinstance(string, UserString):
31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return cmp(self.data, string.data)
32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return cmp(self.data, string)
34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __contains__(self, char):
35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return char in self.data
36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __len__(self): return len(self.data)
38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __getitem__(self, index): return self.__class__(self.data[index])
39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __getslice__(self, start, end):
40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        start = max(start, 0); end = max(end, 0)
41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.__class__(self.data[start:end])
42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __add__(self, other):
44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if isinstance(other, UserString):
45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return self.__class__(self.data + other.data)
46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        elif isinstance(other, basestring):
47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return self.__class__(self.data + other)
48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return self.__class__(self.data + str(other))
50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __radd__(self, other):
51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if isinstance(other, basestring):
52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return self.__class__(other + self.data)
53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return self.__class__(str(other) + self.data)
55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __mul__(self, n):
56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.__class__(self.data*n)
57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    __rmul__ = __mul__
58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __mod__(self, args):
59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.__class__(self.data % args)
60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # the following methods are defined in alphabetical order:
62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def capitalize(self): return self.__class__(self.data.capitalize())
63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def center(self, width, *args):
64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.__class__(self.data.center(width, *args))
65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def count(self, sub, start=0, end=sys.maxint):
66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.data.count(sub, start, end)
67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def decode(self, encoding=None, errors=None): # XXX improve this?
68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if encoding:
69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if errors:
70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                return self.__class__(self.data.decode(encoding, errors))
71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                return self.__class__(self.data.decode(encoding))
73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return self.__class__(self.data.decode())
75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def encode(self, encoding=None, errors=None): # XXX improve this?
76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if encoding:
77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if errors:
78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                return self.__class__(self.data.encode(encoding, errors))
79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                return self.__class__(self.data.encode(encoding))
81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return self.__class__(self.data.encode())
83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def endswith(self, suffix, start=0, end=sys.maxint):
84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.data.endswith(suffix, start, end)
85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def expandtabs(self, tabsize=8):
86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.__class__(self.data.expandtabs(tabsize))
87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def find(self, sub, start=0, end=sys.maxint):
88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.data.find(sub, start, end)
89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def index(self, sub, start=0, end=sys.maxint):
90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.data.index(sub, start, end)
91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def isalpha(self): return self.data.isalpha()
92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def isalnum(self): return self.data.isalnum()
93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def isdecimal(self): return self.data.isdecimal()
94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def isdigit(self): return self.data.isdigit()
95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def islower(self): return self.data.islower()
96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def isnumeric(self): return self.data.isnumeric()
97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def isspace(self): return self.data.isspace()
98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def istitle(self): return self.data.istitle()
99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def isupper(self): return self.data.isupper()
100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def join(self, seq): return self.data.join(seq)
101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def ljust(self, width, *args):
102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.__class__(self.data.ljust(width, *args))
103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def lower(self): return self.__class__(self.data.lower())
104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars))
105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def partition(self, sep):
106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.data.partition(sep)
107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def replace(self, old, new, maxsplit=-1):
108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.__class__(self.data.replace(old, new, maxsplit))
109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def rfind(self, sub, start=0, end=sys.maxint):
110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.data.rfind(sub, start, end)
111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def rindex(self, sub, start=0, end=sys.maxint):
112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.data.rindex(sub, start, end)
113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def rjust(self, width, *args):
114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.__class__(self.data.rjust(width, *args))
115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def rpartition(self, sep):
116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.data.rpartition(sep)
117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def rstrip(self, chars=None): return self.__class__(self.data.rstrip(chars))
118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def split(self, sep=None, maxsplit=-1):
119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.data.split(sep, maxsplit)
120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def rsplit(self, sep=None, maxsplit=-1):
121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.data.rsplit(sep, maxsplit)
122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def splitlines(self, keepends=0): return self.data.splitlines(keepends)
123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def startswith(self, prefix, start=0, end=sys.maxint):
124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.data.startswith(prefix, start, end)
125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def strip(self, chars=None): return self.__class__(self.data.strip(chars))
126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def swapcase(self): return self.__class__(self.data.swapcase())
127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def title(self): return self.__class__(self.data.title())
128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def translate(self, *args):
129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.__class__(self.data.translate(*args))
130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def upper(self): return self.__class__(self.data.upper())
131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def zfill(self, width): return self.__class__(self.data.zfill(width))
132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass MutableString(UserString, collections.MutableSequence):
134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    """mutable string objects
135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    Python strings are immutable objects.  This has the advantage, that
137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    strings may be used as dictionary keys.  If this property isn't needed
138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    and you insist on changing string values in place instead, you may cheat
139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    and use MutableString.
140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    But the purpose of this class is an educational one: to prevent
142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    people from inventing their own mutable string class derived
143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    from UserString and than forget thereby to remove (override) the
144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    __hash__ method inherited from UserString.  This would lead to
145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    errors that would be very hard to track down.
146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    A faster and better solution is to rewrite your program using lists."""
148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __init__(self, string=""):
149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        from warnings import warnpy3k
150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        warnpy3k('the class UserString.MutableString has been removed in '
151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    'Python 3.0', stacklevel=2)
152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.data = string
153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # We inherit object.__hash__, so we must deny this explicitly
155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    __hash__ = None
156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __setitem__(self, index, sub):
158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if isinstance(index, slice):
159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if isinstance(sub, UserString):
160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                sub = sub.data
161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif not isinstance(sub, basestring):
162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                sub = str(sub)
163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            start, stop, step = index.indices(len(self.data))
164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if step == -1:
165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                start, stop = stop+1, start+1
166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                sub = sub[::-1]
167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif step != 1:
168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                # XXX(twouters): I guess we should be reimplementing
169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                # the extended slice assignment/deletion algorithm here...
170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                raise TypeError, "invalid step in slicing assignment"
171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            start = min(start, stop)
172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data = self.data[:start] + sub + self.data[stop:]
173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if index < 0:
175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                index += len(self.data)
176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if index < 0 or index >= len(self.data): raise IndexError
177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data = self.data[:index] + sub + self.data[index+1:]
178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __delitem__(self, index):
179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if isinstance(index, slice):
180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            start, stop, step = index.indices(len(self.data))
181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if step == -1:
182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                start, stop = stop+1, start+1
183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            elif step != 1:
184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                # XXX(twouters): see same block in __setitem__
185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                raise TypeError, "invalid step in slicing deletion"
186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            start = min(start, stop)
187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data = self.data[:start] + self.data[stop:]
188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if index < 0:
190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                index += len(self.data)
191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if index < 0 or index >= len(self.data): raise IndexError
192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data = self.data[:index] + self.data[index+1:]
193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __setslice__(self, start, end, sub):
194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        start = max(start, 0); end = max(end, 0)
195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if isinstance(sub, UserString):
196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data = self.data[:start]+sub.data+self.data[end:]
197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        elif isinstance(sub, basestring):
198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data = self.data[:start]+sub+self.data[end:]
199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data =  self.data[:start]+str(sub)+self.data[end:]
201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __delslice__(self, start, end):
202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        start = max(start, 0); end = max(end, 0)
203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.data = self.data[:start] + self.data[end:]
204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def immutable(self):
205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return UserString(self.data)
206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __iadd__(self, other):
207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if isinstance(other, UserString):
208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data += other.data
209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        elif isinstance(other, basestring):
210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data += other
211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.data += str(other)
213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self
214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __imul__(self, n):
215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.data *= n
216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self
217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def insert(self, index, value):
218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self[index:index] = value
219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif __name__ == "__main__":
221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # execute the regression test to stdout, if called as a script:
222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    import os
223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    called_in_dir, called_as = os.path.split(sys.argv[0])
224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    called_as, py = os.path.splitext(called_as)
225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    if '-q' in sys.argv:
226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        from test import test_support
227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        test_support.verbose = 0
228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    __import__('test.test_' + called_as.lower())
229