4 from __future__ import with_statement
11 from xml.sax import saxutils
14 import cStringIO as StringIO
19 @contextlib.contextmanager
20 def change_directory(directory):
21 previousDirectory = os.getcwd()
23 currentDirectory = os.getcwd()
26 yield previousDirectory, currentDirectory
28 os.chdir(previousDirectory)
31 @contextlib.contextmanager
32 def pickled(filename):
34 Here is an example usage:
35 with pickled("foo.db") as p:
36 p("users", list).append(["srid", "passwd", 23])
39 if os.path.isfile(filename):
40 data = pickle.load(open(filename))
44 def getter(item, factory):
48 data[item] = factory()
53 pickle.dump(data, open(filename, "w"))
56 @contextlib.contextmanager
57 def redirect(object_, attr, value):
60 ... with redirect(sys, 'stdout', open('stdout', 'w')):
63 >>> print "we're back"
66 orig = getattr(object_, attr)
67 setattr(object_, attr, value)
71 setattr(object_, attr, orig)
76 >>> pathsplit("/a/b/c")
78 >>> pathsplit("./plugins/builtins.ini")
79 ['.', 'plugins', 'builtins.ini']
81 pathParts = path.split(os.path.sep)
85 def commonpath(l1, l2, common=None):
87 >>> commonpath(pathsplit('/a/b/c/d'), pathsplit('/a/b/c1/d1'))
88 (['', 'a', 'b'], ['c', 'd'], ['c1', 'd1'])
89 >>> commonpath(pathsplit("./plugins/"), pathsplit("./plugins/builtins.ini"))
90 (['.', 'plugins'], [''], ['builtins.ini'])
91 >>> commonpath(pathsplit("./plugins/builtins"), pathsplit("./plugins"))
92 (['.', 'plugins'], ['builtins'], [])
100 for i, (leftDir, rightDir) in enumerate(zip(l1, l2)):
101 if leftDir != rightDir:
102 return l1[0:i], l1[i:], l2[i:]
104 if leftDir == rightDir:
106 return l1[0:i], l1[i:], l2[i:]
111 >>> relpath('/', '/')
113 >>> relpath('/a/b/c/d', '/')
115 >>> relpath('/a/b/c/d', '/a/b/c1/d1')
117 >>> relpath('/a/b/c/d', '/a/b/c1/d1/')
119 >>> relpath("./plugins/builtins", "./plugins")
121 >>> relpath("./plugins/", "./plugins/builtins.ini")
124 sourcePath = os.path.normpath(p1)
125 destPath = os.path.normpath(p2)
127 (common, sourceOnly, destOnly) = commonpath(pathsplit(sourcePath), pathsplit(destPath))
128 if len(sourceOnly) or len(destOnly):
129 relParts = itertools.chain(
130 (('..' + os.sep) * len(sourceOnly), ),
133 return os.path.join(*relParts)
138 class UTF8Recoder(object):
140 Iterator that reads an encoded stream and reencodes the input to UTF-8
142 def __init__(self, f, encoding):
143 self.reader = codecs.getreader(encoding)(f)
149 return self.reader.next().encode("utf-8")
152 class UnicodeReader(object):
154 A CSV reader which will iterate over lines in the CSV file "f",
155 which is encoded in the given encoding.
158 def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
159 f = UTF8Recoder(f, encoding)
160 self.reader = csv.reader(f, dialect=dialect, **kwds)
163 row = self.reader.next()
164 return [unicode(s, "utf-8") for s in row]
169 class UnicodeWriter(object):
171 A CSV writer which will write rows to CSV file "f",
172 which is encoded in the given encoding.
175 def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
176 # Redirect output to a queue
177 self.queue = StringIO.StringIO()
178 self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
180 self.encoder = codecs.getincrementalencoder(encoding)()
182 def writerow(self, row):
183 self.writer.writerow([s.encode("utf-8") for s in row])
184 # Fetch UTF-8 output from the queue ...
185 data = self.queue.getvalue()
186 data = data.decode("utf-8")
187 # ... and reencode it into the target encoding
188 data = self.encoder.encode(data)
189 # write to the target stream
190 self.stream.write(data)
192 self.queue.truncate(0)
194 def writerows(self, rows):
199 def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs):
200 # csv.py doesn't do Unicode; encode temporarily as UTF-8:
201 csv_reader = csv.reader(utf_8_encoder(unicode_csv_data),
202 dialect=dialect, **kwargs)
203 for row in csv_reader:
204 # decode UTF-8 back to Unicode, cell by cell:
205 yield [unicode(cell, 'utf-8') for cell in row]
208 def utf_8_encoder(unicode_csv_data):
209 for line in unicode_csv_data:
210 yield line.encode('utf-8')
213 _UNESCAPE_ENTITIES = {
220 _ESCAPE_ENTITIES = dict((v, k) for (v, k) in zip(_UNESCAPE_ENTITIES.itervalues(), _UNESCAPE_ENTITIES.iterkeys()))
221 del _ESCAPE_ENTITIES[" "]
225 plain = saxutils.unescape(text, _UNESCAPE_ENTITIES)
230 fancy = saxutils.escape(text, _ESCAPE_ENTITIES)