blob: 500cd12c15dd4062a1dda5de576adb91c94c8b08 [file] [log] [blame]
Fred Drakea22b5762000-04-03 03:51:50 +00001#!/usr/bin/env python
2## vim:ts=4:et:nowrap
3"""A user-defined wrapper around string objects
4
Tim Peterse1190062001-01-15 03:34:38 +00005Note: string objects have grown methods in Python 1.6
Fred Drakea22b5762000-04-03 03:51:50 +00006This module requires Python 1.6 or later.
7"""
Fred Drakea22b5762000-04-03 03:51:50 +00008import sys
9
Skip Montanaroe99d5ea2001-01-20 19:54:20 +000010__all__ = ["UserString","MutableString"]
11
Fred Drakea22b5762000-04-03 03:51:50 +000012class UserString:
13 def __init__(self, seq):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000014 if isinstance(seq, basestring):
Fred Drakea22b5762000-04-03 03:51:50 +000015 self.data = seq
16 elif isinstance(seq, UserString):
17 self.data = seq.data[:]
Tim Peterse1190062001-01-15 03:34:38 +000018 else:
Fred Drakea22b5762000-04-03 03:51:50 +000019 self.data = str(seq)
20 def __str__(self): return str(self.data)
21 def __repr__(self): return repr(self.data)
22 def __int__(self): return int(self.data)
Guido van Rossume2a383d2007-01-15 16:59:06 +000023 def __long__(self): return int(self.data)
Fred Drakea22b5762000-04-03 03:51:50 +000024 def __float__(self): return float(self.data)
25 def __complex__(self): return complex(self.data)
26 def __hash__(self): return hash(self.data)
27
Guido van Rossum47b9ff62006-08-24 00:41:19 +000028 def __eq__(self, string):
Fred Drakea22b5762000-04-03 03:51:50 +000029 if isinstance(string, UserString):
Guido van Rossum47b9ff62006-08-24 00:41:19 +000030 return self.data == string.data
Fred Drakea22b5762000-04-03 03:51:50 +000031 else:
Guido van Rossum47b9ff62006-08-24 00:41:19 +000032 return self.data == string
33 def __ne__(self, string):
34 if isinstance(string, UserString):
35 return self.data != string.data
36 else:
37 return self.data != string
38 def __lt__(self, string):
39 if isinstance(string, UserString):
40 return self.data < string.data
41 else:
42 return self.data < string
43 def __le__(self, string):
44 if isinstance(string, UserString):
45 return self.data <= string.data
46 else:
47 return self.data <= string
48 def __gt__(self, string):
49 if isinstance(string, UserString):
50 return self.data > string.data
51 else:
52 return self.data > string
53 def __ge__(self, string):
54 if isinstance(string, UserString):
55 return self.data >= string.data
56 else:
57 return self.data >= string
58
Fred Drakea22b5762000-04-03 03:51:50 +000059 def __contains__(self, char):
Guido van Rossum98b349f2007-08-27 21:47:52 +000060 if isinstance(char, UserString):
61 char = char.data
Fred Drakea22b5762000-04-03 03:51:50 +000062 return char in self.data
63
64 def __len__(self): return len(self.data)
65 def __getitem__(self, index): return self.__class__(self.data[index])
66 def __getslice__(self, start, end):
67 start = max(start, 0); end = max(end, 0)
68 return self.__class__(self.data[start:end])
69
70 def __add__(self, other):
71 if isinstance(other, UserString):
72 return self.__class__(self.data + other.data)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000073 elif isinstance(other, basestring):
Fred Drakea22b5762000-04-03 03:51:50 +000074 return self.__class__(self.data + other)
75 else:
76 return self.__class__(self.data + str(other))
77 def __radd__(self, other):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000078 if isinstance(other, basestring):
Fred Drakea22b5762000-04-03 03:51:50 +000079 return self.__class__(other + self.data)
80 else:
81 return self.__class__(str(other) + self.data)
82 def __mul__(self, n):
83 return self.__class__(self.data*n)
84 __rmul__ = __mul__
Neil Schemenauerfe4f7692002-11-18 16:12:54 +000085 def __mod__(self, args):
86 return self.__class__(self.data % args)
Fred Drakea22b5762000-04-03 03:51:50 +000087
88 # the following methods are defined in alphabetical order:
89 def capitalize(self): return self.__class__(self.data.capitalize())
Raymond Hettinger4f8f9762003-11-26 08:21:35 +000090 def center(self, width, *args):
91 return self.__class__(self.data.center(width, *args))
Fred Drakea22b5762000-04-03 03:51:50 +000092 def count(self, sub, start=0, end=sys.maxint):
Guido van Rossum98b349f2007-08-27 21:47:52 +000093 if isinstance(sub, UserString):
94 sub = sub.data
Fred Drakea22b5762000-04-03 03:51:50 +000095 return self.data.count(sub, start, end)
Marc-André Lemburg2d920412001-05-15 12:00:02 +000096 def decode(self, encoding=None, errors=None): # XXX improve this?
97 if encoding:
98 if errors:
99 return self.__class__(self.data.decode(encoding, errors))
100 else:
101 return self.__class__(self.data.decode(encoding))
102 else:
103 return self.__class__(self.data.decode())
Fred Drakea22b5762000-04-03 03:51:50 +0000104 def encode(self, encoding=None, errors=None): # XXX improve this?
105 if encoding:
106 if errors:
107 return self.__class__(self.data.encode(encoding, errors))
108 else:
109 return self.__class__(self.data.encode(encoding))
Tim Peterse1190062001-01-15 03:34:38 +0000110 else:
Fred Drakea22b5762000-04-03 03:51:50 +0000111 return self.__class__(self.data.encode())
112 def endswith(self, suffix, start=0, end=sys.maxint):
113 return self.data.endswith(suffix, start, end)
Tim Peterse1190062001-01-15 03:34:38 +0000114 def expandtabs(self, tabsize=8):
Fred Drakea22b5762000-04-03 03:51:50 +0000115 return self.__class__(self.data.expandtabs(tabsize))
Tim Peterse1190062001-01-15 03:34:38 +0000116 def find(self, sub, start=0, end=sys.maxint):
Guido van Rossum98b349f2007-08-27 21:47:52 +0000117 if isinstance(sub, UserString):
118 sub = sub.data
Fred Drakea22b5762000-04-03 03:51:50 +0000119 return self.data.find(sub, start, end)
Tim Peterse1190062001-01-15 03:34:38 +0000120 def index(self, sub, start=0, end=sys.maxint):
Fred Drakea22b5762000-04-03 03:51:50 +0000121 return self.data.index(sub, start, end)
Jeremy Hyltonfd547572000-07-10 17:07:17 +0000122 def isalpha(self): return self.data.isalpha()
123 def isalnum(self): return self.data.isalnum()
Fred Drakea22b5762000-04-03 03:51:50 +0000124 def isdecimal(self): return self.data.isdecimal()
125 def isdigit(self): return self.data.isdigit()
126 def islower(self): return self.data.islower()
127 def isnumeric(self): return self.data.isnumeric()
128 def isspace(self): return self.data.isspace()
129 def istitle(self): return self.data.istitle()
130 def isupper(self): return self.data.isupper()
131 def join(self, seq): return self.data.join(seq)
Raymond Hettinger4f8f9762003-11-26 08:21:35 +0000132 def ljust(self, width, *args):
133 return self.__class__(self.data.ljust(width, *args))
Fred Drakea22b5762000-04-03 03:51:50 +0000134 def lower(self): return self.__class__(self.data.lower())
Neal Norwitzffe33b72003-04-10 22:35:32 +0000135 def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000136 def partition(self, sep):
137 return self.data.partition(sep)
Tim Peterse1190062001-01-15 03:34:38 +0000138 def replace(self, old, new, maxsplit=-1):
Guido van Rossum98b349f2007-08-27 21:47:52 +0000139 if isinstance(old, UserString):
140 old = old.data
141 if isinstance(new, UserString):
142 new = new.data
Fred Drakea22b5762000-04-03 03:51:50 +0000143 return self.__class__(self.data.replace(old, new, maxsplit))
Tim Peterse1190062001-01-15 03:34:38 +0000144 def rfind(self, sub, start=0, end=sys.maxint):
Fred Drakea22b5762000-04-03 03:51:50 +0000145 return self.data.rfind(sub, start, end)
Tim Peterse1190062001-01-15 03:34:38 +0000146 def rindex(self, sub, start=0, end=sys.maxint):
Fred Drakea22b5762000-04-03 03:51:50 +0000147 return self.data.rindex(sub, start, end)
Raymond Hettinger4f8f9762003-11-26 08:21:35 +0000148 def rjust(self, width, *args):
149 return self.__class__(self.data.rjust(width, *args))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000150 def rpartition(self, sep):
151 return self.data.rpartition(sep)
Neal Norwitzffe33b72003-04-10 22:35:32 +0000152 def rstrip(self, chars=None): return self.__class__(self.data.rstrip(chars))
Tim Peterse1190062001-01-15 03:34:38 +0000153 def split(self, sep=None, maxsplit=-1):
Fred Drakea22b5762000-04-03 03:51:50 +0000154 return self.data.split(sep, maxsplit)
Hye-Shik Changeebb6412003-12-15 19:46:09 +0000155 def rsplit(self, sep=None, maxsplit=-1):
156 return self.data.rsplit(sep, maxsplit)
Guido van Rossum86662912000-04-11 15:38:46 +0000157 def splitlines(self, keepends=0): return self.data.splitlines(keepends)
Tim Peterse1190062001-01-15 03:34:38 +0000158 def startswith(self, prefix, start=0, end=sys.maxint):
Fred Drakea22b5762000-04-03 03:51:50 +0000159 return self.data.startswith(prefix, start, end)
Neal Norwitzffe33b72003-04-10 22:35:32 +0000160 def strip(self, chars=None): return self.__class__(self.data.strip(chars))
Fred Drakea22b5762000-04-03 03:51:50 +0000161 def swapcase(self): return self.__class__(self.data.swapcase())
162 def title(self): return self.__class__(self.data.title())
Tim Peterse1190062001-01-15 03:34:38 +0000163 def translate(self, *args):
Fred Drakea8939572000-08-21 21:47:20 +0000164 return self.__class__(self.data.translate(*args))
Fred Drakea22b5762000-04-03 03:51:50 +0000165 def upper(self): return self.__class__(self.data.upper())
Walter Dörwald068325e2002-04-15 13:36:47 +0000166 def zfill(self, width): return self.__class__(self.data.zfill(width))
Fred Drakea22b5762000-04-03 03:51:50 +0000167
168class MutableString(UserString):
169 """mutable string objects
170
171 Python strings are immutable objects. This has the advantage, that
172 strings may be used as dictionary keys. If this property isn't needed
173 and you insist on changing string values in place instead, you may cheat
174 and use MutableString.
175
176 But the purpose of this class is an educational one: to prevent
177 people from inventing their own mutable string class derived
178 from UserString and than forget thereby to remove (override) the
Thomas Heller611dbc32003-08-27 10:48:12 +0000179 __hash__ method inherited from UserString. This would lead to
Fred Drakea22b5762000-04-03 03:51:50 +0000180 errors that would be very hard to track down.
181
182 A faster and better solution is to rewrite your program using lists."""
183 def __init__(self, string=""):
184 self.data = string
Tim Peterse1190062001-01-15 03:34:38 +0000185 def __hash__(self):
Fred Drakea22b5762000-04-03 03:51:50 +0000186 raise TypeError, "unhashable type (it is mutable)"
187 def __setitem__(self, index, sub):
Walter Dörwaldaf3b39a2005-02-18 13:22:43 +0000188 if index < 0:
Tim Peterseba28be2005-03-28 01:08:02 +0000189 index += len(self.data)
Fred Drakea22b5762000-04-03 03:51:50 +0000190 if index < 0 or index >= len(self.data): raise IndexError
191 self.data = self.data[:index] + sub + self.data[index+1:]
192 def __delitem__(self, index):
Walter Dörwaldaf3b39a2005-02-18 13:22:43 +0000193 if index < 0:
Tim Peterseba28be2005-03-28 01:08:02 +0000194 index += len(self.data)
Fred Drakea22b5762000-04-03 03:51:50 +0000195 if index < 0 or index >= len(self.data): raise IndexError
196 self.data = self.data[:index] + self.data[index+1:]
197 def __setslice__(self, start, end, sub):
198 start = max(start, 0); end = max(end, 0)
199 if isinstance(sub, UserString):
200 self.data = self.data[:start]+sub.data+self.data[end:]
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000201 elif isinstance(sub, basestring):
Fred Drakea22b5762000-04-03 03:51:50 +0000202 self.data = self.data[:start]+sub+self.data[end:]
203 else:
204 self.data = self.data[:start]+str(sub)+self.data[end:]
205 def __delslice__(self, start, end):
206 start = max(start, 0); end = max(end, 0)
207 self.data = self.data[:start] + self.data[end:]
208 def immutable(self):
209 return UserString(self.data)
Raymond Hettingerc35491e2002-08-09 01:37:06 +0000210 def __iadd__(self, other):
211 if isinstance(other, UserString):
212 self.data += other.data
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000213 elif isinstance(other, basestring):
Raymond Hettingerc35491e2002-08-09 01:37:06 +0000214 self.data += other
215 else:
216 self.data += str(other)
217 return self
218 def __imul__(self, n):
219 self.data *= n
220 return self
Tim Peterse1190062001-01-15 03:34:38 +0000221
Fred Drakea22b5762000-04-03 03:51:50 +0000222if __name__ == "__main__":
223 # execute the regression test to stdout, if called as a script:
224 import os
225 called_in_dir, called_as = os.path.split(sys.argv[0])
Fred Drakea22b5762000-04-03 03:51:50 +0000226 called_as, py = os.path.splitext(called_as)
Fred Drakea22b5762000-04-03 03:51:50 +0000227 if '-q' in sys.argv:
Barry Warsaw408b6d32002-07-30 23:27:12 +0000228 from test import test_support
Fred Drakea22b5762000-04-03 03:51:50 +0000229 test_support.verbose = 0
Barry Warsaw408b6d32002-07-30 23:27:12 +0000230 __import__('test.test_' + called_as.lower())