blob: 62e73bbc9df9b4ca2819adc717299c1ff489270b [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):
60 return char in self.data
61
62 def __len__(self): return len(self.data)
63 def __getitem__(self, index): return self.__class__(self.data[index])
64 def __getslice__(self, start, end):
65 start = max(start, 0); end = max(end, 0)
66 return self.__class__(self.data[start:end])
67
68 def __add__(self, other):
69 if isinstance(other, UserString):
70 return self.__class__(self.data + other.data)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000071 elif isinstance(other, basestring):
Fred Drakea22b5762000-04-03 03:51:50 +000072 return self.__class__(self.data + other)
73 else:
74 return self.__class__(self.data + str(other))
75 def __radd__(self, other):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000076 if isinstance(other, basestring):
Fred Drakea22b5762000-04-03 03:51:50 +000077 return self.__class__(other + self.data)
78 else:
79 return self.__class__(str(other) + self.data)
80 def __mul__(self, n):
81 return self.__class__(self.data*n)
82 __rmul__ = __mul__
Neil Schemenauerfe4f7692002-11-18 16:12:54 +000083 def __mod__(self, args):
84 return self.__class__(self.data % args)
Fred Drakea22b5762000-04-03 03:51:50 +000085
86 # the following methods are defined in alphabetical order:
87 def capitalize(self): return self.__class__(self.data.capitalize())
Raymond Hettinger4f8f9762003-11-26 08:21:35 +000088 def center(self, width, *args):
89 return self.__class__(self.data.center(width, *args))
Fred Drakea22b5762000-04-03 03:51:50 +000090 def count(self, sub, start=0, end=sys.maxint):
91 return self.data.count(sub, start, end)
Marc-André Lemburg2d920412001-05-15 12:00:02 +000092 def decode(self, encoding=None, errors=None): # XXX improve this?
93 if encoding:
94 if errors:
95 return self.__class__(self.data.decode(encoding, errors))
96 else:
97 return self.__class__(self.data.decode(encoding))
98 else:
99 return self.__class__(self.data.decode())
Fred Drakea22b5762000-04-03 03:51:50 +0000100 def encode(self, encoding=None, errors=None): # XXX improve this?
101 if encoding:
102 if errors:
103 return self.__class__(self.data.encode(encoding, errors))
104 else:
105 return self.__class__(self.data.encode(encoding))
Tim Peterse1190062001-01-15 03:34:38 +0000106 else:
Fred Drakea22b5762000-04-03 03:51:50 +0000107 return self.__class__(self.data.encode())
108 def endswith(self, suffix, start=0, end=sys.maxint):
109 return self.data.endswith(suffix, start, end)
Tim Peterse1190062001-01-15 03:34:38 +0000110 def expandtabs(self, tabsize=8):
Fred Drakea22b5762000-04-03 03:51:50 +0000111 return self.__class__(self.data.expandtabs(tabsize))
Tim Peterse1190062001-01-15 03:34:38 +0000112 def find(self, sub, start=0, end=sys.maxint):
Fred Drakea22b5762000-04-03 03:51:50 +0000113 return self.data.find(sub, start, end)
Tim Peterse1190062001-01-15 03:34:38 +0000114 def index(self, sub, start=0, end=sys.maxint):
Fred Drakea22b5762000-04-03 03:51:50 +0000115 return self.data.index(sub, start, end)
Jeremy Hyltonfd547572000-07-10 17:07:17 +0000116 def isalpha(self): return self.data.isalpha()
117 def isalnum(self): return self.data.isalnum()
Fred Drakea22b5762000-04-03 03:51:50 +0000118 def isdecimal(self): return self.data.isdecimal()
119 def isdigit(self): return self.data.isdigit()
120 def islower(self): return self.data.islower()
121 def isnumeric(self): return self.data.isnumeric()
122 def isspace(self): return self.data.isspace()
123 def istitle(self): return self.data.istitle()
124 def isupper(self): return self.data.isupper()
125 def join(self, seq): return self.data.join(seq)
Raymond Hettinger4f8f9762003-11-26 08:21:35 +0000126 def ljust(self, width, *args):
127 return self.__class__(self.data.ljust(width, *args))
Fred Drakea22b5762000-04-03 03:51:50 +0000128 def lower(self): return self.__class__(self.data.lower())
Neal Norwitzffe33b72003-04-10 22:35:32 +0000129 def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000130 def partition(self, sep):
131 return self.data.partition(sep)
Tim Peterse1190062001-01-15 03:34:38 +0000132 def replace(self, old, new, maxsplit=-1):
Fred Drakea22b5762000-04-03 03:51:50 +0000133 return self.__class__(self.data.replace(old, new, maxsplit))
Tim Peterse1190062001-01-15 03:34:38 +0000134 def rfind(self, sub, start=0, end=sys.maxint):
Fred Drakea22b5762000-04-03 03:51:50 +0000135 return self.data.rfind(sub, start, end)
Tim Peterse1190062001-01-15 03:34:38 +0000136 def rindex(self, sub, start=0, end=sys.maxint):
Fred Drakea22b5762000-04-03 03:51:50 +0000137 return self.data.rindex(sub, start, end)
Raymond Hettinger4f8f9762003-11-26 08:21:35 +0000138 def rjust(self, width, *args):
139 return self.__class__(self.data.rjust(width, *args))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000140 def rpartition(self, sep):
141 return self.data.rpartition(sep)
Neal Norwitzffe33b72003-04-10 22:35:32 +0000142 def rstrip(self, chars=None): return self.__class__(self.data.rstrip(chars))
Tim Peterse1190062001-01-15 03:34:38 +0000143 def split(self, sep=None, maxsplit=-1):
Fred Drakea22b5762000-04-03 03:51:50 +0000144 return self.data.split(sep, maxsplit)
Hye-Shik Changeebb6412003-12-15 19:46:09 +0000145 def rsplit(self, sep=None, maxsplit=-1):
146 return self.data.rsplit(sep, maxsplit)
Guido van Rossum86662912000-04-11 15:38:46 +0000147 def splitlines(self, keepends=0): return self.data.splitlines(keepends)
Tim Peterse1190062001-01-15 03:34:38 +0000148 def startswith(self, prefix, start=0, end=sys.maxint):
Fred Drakea22b5762000-04-03 03:51:50 +0000149 return self.data.startswith(prefix, start, end)
Neal Norwitzffe33b72003-04-10 22:35:32 +0000150 def strip(self, chars=None): return self.__class__(self.data.strip(chars))
Fred Drakea22b5762000-04-03 03:51:50 +0000151 def swapcase(self): return self.__class__(self.data.swapcase())
152 def title(self): return self.__class__(self.data.title())
Tim Peterse1190062001-01-15 03:34:38 +0000153 def translate(self, *args):
Fred Drakea8939572000-08-21 21:47:20 +0000154 return self.__class__(self.data.translate(*args))
Fred Drakea22b5762000-04-03 03:51:50 +0000155 def upper(self): return self.__class__(self.data.upper())
Walter Dörwald068325e2002-04-15 13:36:47 +0000156 def zfill(self, width): return self.__class__(self.data.zfill(width))
Fred Drakea22b5762000-04-03 03:51:50 +0000157
158class MutableString(UserString):
159 """mutable string objects
160
161 Python strings are immutable objects. This has the advantage, that
162 strings may be used as dictionary keys. If this property isn't needed
163 and you insist on changing string values in place instead, you may cheat
164 and use MutableString.
165
166 But the purpose of this class is an educational one: to prevent
167 people from inventing their own mutable string class derived
168 from UserString and than forget thereby to remove (override) the
Thomas Heller611dbc32003-08-27 10:48:12 +0000169 __hash__ method inherited from UserString. This would lead to
Fred Drakea22b5762000-04-03 03:51:50 +0000170 errors that would be very hard to track down.
171
172 A faster and better solution is to rewrite your program using lists."""
173 def __init__(self, string=""):
174 self.data = string
Tim Peterse1190062001-01-15 03:34:38 +0000175 def __hash__(self):
Fred Drakea22b5762000-04-03 03:51:50 +0000176 raise TypeError, "unhashable type (it is mutable)"
177 def __setitem__(self, index, sub):
Walter Dörwaldaf3b39a2005-02-18 13:22:43 +0000178 if index < 0:
Tim Peterseba28be2005-03-28 01:08:02 +0000179 index += len(self.data)
Fred Drakea22b5762000-04-03 03:51:50 +0000180 if index < 0 or index >= len(self.data): raise IndexError
181 self.data = self.data[:index] + sub + self.data[index+1:]
182 def __delitem__(self, index):
Walter Dörwaldaf3b39a2005-02-18 13:22:43 +0000183 if index < 0:
Tim Peterseba28be2005-03-28 01:08:02 +0000184 index += len(self.data)
Fred Drakea22b5762000-04-03 03:51:50 +0000185 if index < 0 or index >= len(self.data): raise IndexError
186 self.data = self.data[:index] + self.data[index+1:]
187 def __setslice__(self, start, end, sub):
188 start = max(start, 0); end = max(end, 0)
189 if isinstance(sub, UserString):
190 self.data = self.data[:start]+sub.data+self.data[end:]
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000191 elif isinstance(sub, basestring):
Fred Drakea22b5762000-04-03 03:51:50 +0000192 self.data = self.data[:start]+sub+self.data[end:]
193 else:
194 self.data = self.data[:start]+str(sub)+self.data[end:]
195 def __delslice__(self, start, end):
196 start = max(start, 0); end = max(end, 0)
197 self.data = self.data[:start] + self.data[end:]
198 def immutable(self):
199 return UserString(self.data)
Raymond Hettingerc35491e2002-08-09 01:37:06 +0000200 def __iadd__(self, other):
201 if isinstance(other, UserString):
202 self.data += other.data
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000203 elif isinstance(other, basestring):
Raymond Hettingerc35491e2002-08-09 01:37:06 +0000204 self.data += other
205 else:
206 self.data += str(other)
207 return self
208 def __imul__(self, n):
209 self.data *= n
210 return self
Tim Peterse1190062001-01-15 03:34:38 +0000211
Fred Drakea22b5762000-04-03 03:51:50 +0000212if __name__ == "__main__":
213 # execute the regression test to stdout, if called as a script:
214 import os
215 called_in_dir, called_as = os.path.split(sys.argv[0])
Fred Drakea22b5762000-04-03 03:51:50 +0000216 called_as, py = os.path.splitext(called_as)
Fred Drakea22b5762000-04-03 03:51:50 +0000217 if '-q' in sys.argv:
Barry Warsaw408b6d32002-07-30 23:27:12 +0000218 from test import test_support
Fred Drakea22b5762000-04-03 03:51:50 +0000219 test_support.verbose = 0
Barry Warsaw408b6d32002-07-30 23:27:12 +0000220 __import__('test.test_' + called_as.lower())