1 | Sun Jul 11 20:55:25 GMT Daylight Time 2010 david-sarah@jacaranda.org |
---|
2 | * Allow URIs passed in the initial JSON for t=mkdir-with-children, t=mkdir-immutable to be Unicode. Also pass the name of each child into nodemaker.create_from_cap for error reporting. |
---|
3 | |
---|
4 | Tue Jul 13 05:27:15 GMT Daylight Time 2010 david-sarah@jacaranda.org |
---|
5 | * Rename stringutils to encodingutil, and drop open_unicode (since the Python 'open' function works fine with Unicode paths). |
---|
6 | |
---|
7 | New patches: |
---|
8 | |
---|
9 | [Allow URIs passed in the initial JSON for t=mkdir-with-children, t=mkdir-immutable to be Unicode. Also pass the name of each child into nodemaker.create_from_cap for error reporting. |
---|
10 | david-sarah@jacaranda.org**20100711195525 |
---|
11 | Ignore-this: deac32d8b91ba26ede18905d3f7d2b93 |
---|
12 | ] { |
---|
13 | hunk ./src/allmydata/web/common.py 14 |
---|
14 | EmptyPathnameComponentError, MustBeDeepImmutableError, \ |
---|
15 | MustBeReadonlyError, MustNotBeUnknownRWError |
---|
16 | from allmydata.mutable.common import UnrecoverableFileError |
---|
17 | -from allmydata.util import abbreviate # TODO: consolidate |
---|
18 | +from allmydata.util import abbreviate |
---|
19 | +from allmydata.util.stringutils import to_str |
---|
20 | |
---|
21 | class IOpHandleTable(Interface): |
---|
22 | pass |
---|
23 | hunk ./src/allmydata/web/common.py 68 |
---|
24 | children = {} |
---|
25 | if children_json: |
---|
26 | data = simplejson.loads(children_json) |
---|
27 | - for (name, (ctype, propdict)) in data.iteritems(): |
---|
28 | - name = unicode(name) |
---|
29 | - writecap = propdict.get("rw_uri") |
---|
30 | - if writecap is not None: |
---|
31 | - writecap = str(writecap) |
---|
32 | - readcap = propdict.get("ro_uri") |
---|
33 | - if readcap is not None: |
---|
34 | - readcap = str(readcap) |
---|
35 | + for (namex, (ctype, propdict)) in data.iteritems(): |
---|
36 | + namex = unicode(namex) |
---|
37 | + writecap = to_str(propdict.get("rw_uri")) |
---|
38 | + readcap = to_str(propdict.get("ro_uri")) |
---|
39 | metadata = propdict.get("metadata", {}) |
---|
40 | hunk ./src/allmydata/web/common.py 73 |
---|
41 | - childnode = nodemaker.create_from_cap(writecap, readcap) |
---|
42 | - children[name] = (childnode, metadata) |
---|
43 | + # name= argument is just for error reporting |
---|
44 | + childnode = nodemaker.create_from_cap(writecap, readcap, name=namex) |
---|
45 | + children[namex] = (childnode, metadata) |
---|
46 | return children |
---|
47 | |
---|
48 | def abbreviate_time(data): |
---|
49 | } |
---|
50 | [Rename stringutils to encodingutil, and drop open_unicode (since the Python 'open' function works fine with Unicode paths). |
---|
51 | david-sarah@jacaranda.org**20100713042715 |
---|
52 | Ignore-this: fa2bb6b5d48ce9ba7ea2b1afc9f3b7b4 |
---|
53 | ] { |
---|
54 | move ./src/allmydata/test/test_stringutils.py ./src/allmydata/test/test_encodingutil.py |
---|
55 | move ./src/allmydata/util/stringutils.py ./src/allmydata/util/encodingutil.py |
---|
56 | hunk ./src/allmydata/dirnode.py 19 |
---|
57 | DeepCheckAndRepairResults |
---|
58 | from allmydata.monitor import Monitor |
---|
59 | from allmydata.util import hashutil, mathutil, base32, log |
---|
60 | -from allmydata.util.stringutils import quote_output |
---|
61 | +from allmydata.util.encodingutil import quote_output |
---|
62 | from allmydata.util.assertutil import precondition |
---|
63 | from allmydata.util.netstring import netstring, split_netstring |
---|
64 | from allmydata.util.consumer import download_to_data |
---|
65 | hunk ./src/allmydata/scripts/cli.py 4 |
---|
66 | import os.path, re, sys, fnmatch |
---|
67 | from twisted.python import usage |
---|
68 | from allmydata.scripts.common import BaseOptions, get_aliases |
---|
69 | -from allmydata.util.stringutils import argv_to_unicode |
---|
70 | +from allmydata.util.encodingutil import argv_to_unicode |
---|
71 | |
---|
72 | NODEURL_RE=re.compile("http(s?)://([^:]*)(:([1-9][0-9]*))?") |
---|
73 | |
---|
74 | hunk ./src/allmydata/scripts/common.py 5 |
---|
75 | import os, sys, urllib |
---|
76 | import codecs |
---|
77 | from twisted.python import usage |
---|
78 | -from allmydata.util.stringutils import unicode_to_url, quote_output |
---|
79 | +from allmydata.util.encodingutil import unicode_to_url, quote_output |
---|
80 | from allmydata.util.assertutil import precondition |
---|
81 | |
---|
82 | class BaseOptions: |
---|
83 | hunk ./src/allmydata/scripts/common_http.py 6 |
---|
84 | import urlparse, httplib |
---|
85 | import allmydata # for __full_version__ |
---|
86 | |
---|
87 | -from allmydata.util.stringutils import quote_output |
---|
88 | +from allmydata.util.encodingutil import quote_output |
---|
89 | from allmydata.scripts.common import TahoeError |
---|
90 | |
---|
91 | |
---|
92 | hunk ./src/allmydata/scripts/slow_operation.py 7 |
---|
93 | UnknownAliasError |
---|
94 | from allmydata.scripts.common_http import do_http, format_http_error |
---|
95 | from allmydata.util import base32 |
---|
96 | -from allmydata.util.stringutils import quote_output, is_printable_ascii |
---|
97 | +from allmydata.util.encodingutil import quote_output, is_printable_ascii |
---|
98 | import urllib |
---|
99 | import simplejson |
---|
100 | |
---|
101 | hunk ./src/allmydata/scripts/tahoe_add_alias.py 8 |
---|
102 | from allmydata.scripts.common_http import do_http, check_http_error |
---|
103 | from allmydata.scripts.common import get_aliases |
---|
104 | from allmydata.util.fileutil import move_into_place |
---|
105 | -from allmydata.util.stringutils import unicode_to_output, quote_output |
---|
106 | +from allmydata.util.encodingutil import unicode_to_output, quote_output |
---|
107 | |
---|
108 | |
---|
109 | def add_line_to_aliasfile(aliasfile, alias, cap): |
---|
110 | hunk ./src/allmydata/scripts/tahoe_backup.py 12 |
---|
111 | from allmydata.scripts.common_http import do_http, HTTPError, format_http_error |
---|
112 | from allmydata.util import time_format |
---|
113 | from allmydata.scripts import backupdb |
---|
114 | -from allmydata.util.stringutils import listdir_unicode, open_unicode, quote_output, to_str |
---|
115 | +from allmydata.util.encodingutil import listdir_unicode, quote_output, to_str, FilenameEncodingError |
---|
116 | from allmydata.util.assertutil import precondition |
---|
117 | |
---|
118 | |
---|
119 | hunk ./src/allmydata/scripts/tahoe_backup.py 174 |
---|
120 | self.directories_skipped += 1 |
---|
121 | self.warn("WARNING: permission denied on directory %s" % quote_output(localpath)) |
---|
122 | children = [] |
---|
123 | + except FilenameEncodingError: |
---|
124 | + self.directories_skipped += 1 |
---|
125 | + self.warn("WARNING: could not list directory %s due to a filename encoding error" % quote_output(localpath)) |
---|
126 | + children = [] |
---|
127 | |
---|
128 | for child in self.options.filter_listdir(children): |
---|
129 | assert isinstance(child, unicode), child |
---|
130 | hunk ./src/allmydata/scripts/tahoe_backup.py 299 |
---|
131 | |
---|
132 | if must_upload: |
---|
133 | self.verboseprint("uploading %s.." % quote_output(childpath)) |
---|
134 | - infileobj = open_unicode(childpath, "rb") |
---|
135 | + infileobj = open(childpath, "rb") |
---|
136 | url = self.options['node-url'] + "uri" |
---|
137 | resp = do_http("PUT", url, infileobj) |
---|
138 | if resp.status not in (200, 201): |
---|
139 | hunk ./src/allmydata/scripts/tahoe_check.py 8 |
---|
140 | from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path, \ |
---|
141 | UnknownAliasError |
---|
142 | from allmydata.scripts.common_http import do_http, format_http_error |
---|
143 | -from allmydata.util.stringutils import quote_output, quote_path |
---|
144 | +from allmydata.util.encodingutil import quote_output, quote_path |
---|
145 | |
---|
146 | class Checker: |
---|
147 | pass |
---|
148 | hunk ./src/allmydata/scripts/tahoe_cp.py 11 |
---|
149 | DefaultAliasMarker, TahoeError |
---|
150 | from allmydata.scripts.common_http import do_http, HTTPError |
---|
151 | from allmydata import uri |
---|
152 | -from allmydata.util.stringutils import unicode_to_url, listdir_unicode, open_unicode, \ |
---|
153 | - abspath_expanduser_unicode, quote_output, to_str |
---|
154 | +from allmydata.util import fileutil |
---|
155 | +from allmydata.util.encodingutil import unicode_to_url, listdir_unicode, quote_output, to_str |
---|
156 | from allmydata.util.assertutil import precondition |
---|
157 | |
---|
158 | |
---|
159 | hunk ./src/allmydata/scripts/tahoe_cp.py 16 |
---|
160 | -def _put_local_file(pathname, inf): |
---|
161 | - # TODO: create temporary file and move into place? |
---|
162 | - # TODO: move this to fileutil. |
---|
163 | - outf = open_unicode(pathname, "wb") |
---|
164 | - try: |
---|
165 | - while True: |
---|
166 | - data = inf.read(32768) |
---|
167 | - if not data: |
---|
168 | - break |
---|
169 | - outf.write(data) |
---|
170 | - finally: |
---|
171 | - outf.close() |
---|
172 | - |
---|
173 | - |
---|
174 | class MissingSourceError(TahoeError): |
---|
175 | def __init__(self, name): |
---|
176 | TahoeError.__init__(self, "No such file or directory %s" % quote_output(name)) |
---|
177 | hunk ./src/allmydata/scripts/tahoe_cp.py 70 |
---|
178 | return True |
---|
179 | |
---|
180 | def open(self, caps_only): |
---|
181 | - return open_unicode(self.pathname, "rb") |
---|
182 | + return open(os.path.expanduser(self.pathname), "rb") |
---|
183 | |
---|
184 | |
---|
185 | class LocalFileTarget: |
---|
186 | hunk ./src/allmydata/scripts/tahoe_cp.py 79 |
---|
187 | self.pathname = pathname |
---|
188 | |
---|
189 | def put_file(self, inf): |
---|
190 | - _put_local_file(self.pathname, inf) |
---|
191 | + fileutil.put_file(self.pathname, inf) |
---|
192 | |
---|
193 | |
---|
194 | class LocalMissingTarget: |
---|
195 | hunk ./src/allmydata/scripts/tahoe_cp.py 88 |
---|
196 | self.pathname = pathname |
---|
197 | |
---|
198 | def put_file(self, inf): |
---|
199 | - _put_local_file(self.pathname, inf) |
---|
200 | + fileutil.put_file(self.pathname, inf) |
---|
201 | |
---|
202 | |
---|
203 | class LocalDirectorySource: |
---|
204 | hunk ./src/allmydata/scripts/tahoe_cp.py 157 |
---|
205 | def put_file(self, name, inf): |
---|
206 | precondition(isinstance(name, unicode), name) |
---|
207 | pathname = os.path.join(self.pathname, name) |
---|
208 | - _put_local_file(pathname, inf) |
---|
209 | + fileutil.put_file(pathname, inf) |
---|
210 | |
---|
211 | def set_children(self): |
---|
212 | pass |
---|
213 | hunk ./src/allmydata/scripts/tahoe_cp.py 514 |
---|
214 | rootcap, path = get_alias(self.aliases, destination_spec, None) |
---|
215 | if rootcap == DefaultAliasMarker: |
---|
216 | # no alias, so this is a local file |
---|
217 | - pathname = abspath_expanduser_unicode(path.decode('utf-8')) |
---|
218 | + pathname = os.path.abspath(os.path.expanduser(path.decode('utf-8'))) |
---|
219 | if not os.path.exists(pathname): |
---|
220 | t = LocalMissingTarget(pathname) |
---|
221 | elif os.path.isdir(pathname): |
---|
222 | hunk ./src/allmydata/scripts/tahoe_cp.py 554 |
---|
223 | rootcap, path = get_alias(self.aliases, source_spec, None) |
---|
224 | if rootcap == DefaultAliasMarker: |
---|
225 | # no alias, so this is a local file |
---|
226 | - pathname = abspath_expanduser_unicode(path.decode('utf-8')) |
---|
227 | + pathname = os.path.abspath(os.path.expanduser(path.decode('utf-8'))) |
---|
228 | name = os.path.basename(pathname) |
---|
229 | if not os.path.exists(pathname): |
---|
230 | raise MissingSourceError(source_spec) |
---|
231 | hunk ./src/allmydata/scripts/tahoe_get.py 2 |
---|
232 | |
---|
233 | -import urllib |
---|
234 | +import os, urllib |
---|
235 | from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path, \ |
---|
236 | UnknownAliasError |
---|
237 | from allmydata.scripts.common_http import do_http, format_http_error |
---|
238 | hunk ./src/allmydata/scripts/tahoe_get.py 6 |
---|
239 | -from allmydata.util.stringutils import open_unicode |
---|
240 | |
---|
241 | def get(options): |
---|
242 | nodeurl = options['node-url'] |
---|
243 | hunk ./src/allmydata/scripts/tahoe_get.py 29 |
---|
244 | resp = do_http("GET", url) |
---|
245 | if resp.status in (200, 201,): |
---|
246 | if to_file: |
---|
247 | - outf = open_unicode(to_file, "wb") |
---|
248 | + outf = open(os.path.expanduser(to_file), "wb") |
---|
249 | else: |
---|
250 | outf = stdout |
---|
251 | while True: |
---|
252 | hunk ./src/allmydata/scripts/tahoe_ls.py 7 |
---|
253 | from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path, \ |
---|
254 | UnknownAliasError |
---|
255 | from allmydata.scripts.common_http import do_http, format_http_error |
---|
256 | -from allmydata.util.stringutils import unicode_to_output, quote_output, is_printable_ascii, to_str |
---|
257 | +from allmydata.util.encodingutil import unicode_to_output, quote_output, is_printable_ascii, to_str |
---|
258 | |
---|
259 | def list(options): |
---|
260 | nodeurl = options['node-url'] |
---|
261 | hunk ./src/allmydata/scripts/tahoe_manifest.py 9 |
---|
262 | from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path, \ |
---|
263 | UnknownAliasError |
---|
264 | from allmydata.scripts.common_http import do_http, format_http_error |
---|
265 | -from allmydata.util.stringutils import quote_output, quote_path |
---|
266 | +from allmydata.util.encodingutil import quote_output, quote_path |
---|
267 | |
---|
268 | class FakeTransport: |
---|
269 | disconnecting = False |
---|
270 | hunk ./src/allmydata/scripts/tahoe_mkdir.py 5 |
---|
271 | import urllib |
---|
272 | from allmydata.scripts.common_http import do_http, check_http_error |
---|
273 | from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, UnknownAliasError |
---|
274 | -from allmydata.util.stringutils import quote_output |
---|
275 | +from allmydata.util.encodingutil import quote_output |
---|
276 | |
---|
277 | def mkdir(options): |
---|
278 | nodeurl = options['node-url'] |
---|
279 | hunk ./src/allmydata/scripts/tahoe_mv.py 8 |
---|
280 | from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path, \ |
---|
281 | UnknownAliasError |
---|
282 | from allmydata.scripts.common_http import do_http, format_http_error |
---|
283 | -from allmydata.util.stringutils import to_str |
---|
284 | +from allmydata.util.encodingutil import to_str |
---|
285 | |
---|
286 | # this script is used for both 'mv' and 'ln' |
---|
287 | |
---|
288 | hunk ./src/allmydata/scripts/tahoe_put.py 2 |
---|
289 | |
---|
290 | +import os |
---|
291 | from cStringIO import StringIO |
---|
292 | import urllib |
---|
293 | from allmydata.scripts.common_http import do_http, format_http_success, format_http_error |
---|
294 | hunk ./src/allmydata/scripts/tahoe_put.py 8 |
---|
295 | from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path, \ |
---|
296 | UnknownAliasError |
---|
297 | -from allmydata.util.stringutils import quote_output, open_unicode |
---|
298 | +from allmydata.util.encodingutil import quote_output |
---|
299 | |
---|
300 | def put(options): |
---|
301 | """ |
---|
302 | hunk ./src/allmydata/scripts/tahoe_put.py 68 |
---|
303 | if mutable: |
---|
304 | url += "?mutable=true" |
---|
305 | if from_file: |
---|
306 | - infileobj = open_unicode(from_file, "rb") |
---|
307 | + infileobj = open(os.path.expanduser(from_file), "rb") |
---|
308 | else: |
---|
309 | # do_http() can't use stdin directly: for one thing, we need a |
---|
310 | # Content-Length field. So we currently must copy it. |
---|
311 | hunk ./src/allmydata/test/test_backupdb.py 7 |
---|
312 | from twisted.trial import unittest |
---|
313 | |
---|
314 | from allmydata.util import fileutil |
---|
315 | -from allmydata.util.stringutils import listdir_unicode, get_filesystem_encoding, unicode_platform |
---|
316 | +from allmydata.util.encodingutil import listdir_unicode, get_filesystem_encoding, unicode_platform |
---|
317 | from allmydata.util.assertutil import precondition |
---|
318 | from allmydata.scripts import backupdb |
---|
319 | |
---|
320 | hunk ./src/allmydata/test/test_cli.py 34 |
---|
321 | from twisted.python import usage |
---|
322 | |
---|
323 | from allmydata.util.assertutil import precondition |
---|
324 | -from allmydata.util.stringutils import listdir_unicode, open_unicode, unicode_platform, \ |
---|
325 | +from allmydata.util.encodingutil import listdir_unicode, unicode_platform, \ |
---|
326 | quote_output, get_output_encoding, get_argv_encoding, get_filesystem_encoding, \ |
---|
327 | unicode_to_output, to_str |
---|
328 | |
---|
329 | hunk ./src/allmydata/test/test_cli.py 442 |
---|
330 | fileutil.make_dirs(basedir) |
---|
331 | |
---|
332 | for name in filenames: |
---|
333 | - open_unicode(os.path.join(unicode(basedir), name), "wb").close() |
---|
334 | + open(os.path.join(unicode(basedir), name), "wb").close() |
---|
335 | |
---|
336 | for file in listdir_unicode(unicode(basedir)): |
---|
337 | self.failUnlessIn(normalize(file), filenames) |
---|
338 | hunk ./src/allmydata/test/test_cli.py 977 |
---|
339 | rel_fn = os.path.join(unicode(self.basedir), u"à trier.txt") |
---|
340 | # we make the file small enough to fit in a LIT file, for speed |
---|
341 | DATA = "short file" |
---|
342 | - f = open_unicode(rel_fn, "wb") |
---|
343 | - try: |
---|
344 | - f.write(DATA) |
---|
345 | - finally: |
---|
346 | - f.close() |
---|
347 | + fileutil.write(rel_fn, DATA) |
---|
348 | |
---|
349 | d = self.do_cli("create-alias", "tahoe") |
---|
350 | |
---|
351 | hunk ./src/allmydata/test/test_cli.py 1348 |
---|
352 | self.set_up_grid() |
---|
353 | |
---|
354 | DATA1 = "unicode file content" |
---|
355 | - f = open_unicode(fn1, "wb") |
---|
356 | - try: |
---|
357 | - f.write(DATA1) |
---|
358 | - finally: |
---|
359 | - f.close() |
---|
360 | + fileutil.write(fn1, DATA1) |
---|
361 | |
---|
362 | fn2 = os.path.join(self.basedir, "Metallica") |
---|
363 | DATA2 = "non-unicode file content" |
---|
364 | hunk ./src/allmydata/test/test_encodingutil.py 26 |
---|
365 | sys.exit(1) |
---|
366 | |
---|
367 | print |
---|
368 | - print "class MyWeirdOS(StringUtils, unittest.TestCase):" |
---|
369 | + print "class MyWeirdOS(EncodingUtil, unittest.TestCase):" |
---|
370 | print " uname = '%s'" % ' '.join(platform.uname()) |
---|
371 | if sys.platform != "win32": |
---|
372 | print " argv = %s" % repr(sys.argv[1]) |
---|
373 | hunk ./src/allmydata/test/test_encodingutil.py 56 |
---|
374 | |
---|
375 | from twisted.trial import unittest |
---|
376 | from mock import patch |
---|
377 | -import sys |
---|
378 | +import os, sys, locale |
---|
379 | |
---|
380 | from allmydata.test.common_util import ReallyEqualMixin |
---|
381 | hunk ./src/allmydata/test/test_encodingutil.py 59 |
---|
382 | -from allmydata.util.stringutils import argv_to_unicode, unicode_to_url, \ |
---|
383 | - unicode_to_output, unicode_platform, listdir_unicode, open_unicode, \ |
---|
384 | - FilenameEncodingError, get_output_encoding, _reload |
---|
385 | +from allmydata.util.encodingutil import argv_to_unicode, unicode_to_url, \ |
---|
386 | + unicode_to_output, unicode_platform, listdir_unicode, FilenameEncodingError, \ |
---|
387 | + get_output_encoding, get_filesystem_encoding, _reload |
---|
388 | from allmydata.dirnode import normalize |
---|
389 | |
---|
390 | from twisted.python import usage |
---|
391 | hunk ./src/allmydata/test/test_encodingutil.py 66 |
---|
392 | |
---|
393 | -class StringUtilsErrors(ReallyEqualMixin, unittest.TestCase): |
---|
394 | +class EncodingUtilErrors(ReallyEqualMixin, unittest.TestCase): |
---|
395 | def tearDown(self): |
---|
396 | _reload() |
---|
397 | |
---|
398 | hunk ./src/allmydata/test/test_encodingutil.py 87 |
---|
399 | mock_stdout.encoding = 'nonexistent_encoding' |
---|
400 | self.failUnlessRaises(AssertionError, _reload) |
---|
401 | |
---|
402 | - # TODO: mock_stdout.encoding = None |
---|
403 | + @patch('locale.getpreferredencoding') |
---|
404 | + def test_get_output_encoding_not_from_stdout(self, mock_locale_getpreferredencoding): |
---|
405 | + locale # hush pyflakes |
---|
406 | + mock_locale_getpreferredencoding.return_value = 'koi8-r' |
---|
407 | + |
---|
408 | + class DummyStdout: |
---|
409 | + pass |
---|
410 | + old_stdout = sys.stdout |
---|
411 | + sys.stdout = DummyStdout() |
---|
412 | + try: |
---|
413 | + _reload() |
---|
414 | + self.failUnlessReallyEqual(get_output_encoding(), 'koi8-r') |
---|
415 | + |
---|
416 | + sys.stdout.encoding = None |
---|
417 | + _reload() |
---|
418 | + self.failUnlessReallyEqual(get_output_encoding(), 'koi8-r') |
---|
419 | + |
---|
420 | + mock_locale_getpreferredencoding.return_value = None |
---|
421 | + _reload() |
---|
422 | + self.failUnlessReallyEqual(get_output_encoding(), 'utf-8') |
---|
423 | + finally: |
---|
424 | + sys.stdout = old_stdout |
---|
425 | |
---|
426 | @patch('sys.stdout') |
---|
427 | def test_argv_to_unicode(self, mock): |
---|
428 | hunk ./src/allmydata/test/test_encodingutil.py 139 |
---|
429 | finally: |
---|
430 | sys.platform = orig_platform |
---|
431 | |
---|
432 | -# The following tests applies only to platforms which don't store filenames as |
---|
433 | +# The following tests apply only to platforms that don't store filenames as |
---|
434 | # Unicode entities on the filesystem. |
---|
435 | hunk ./src/allmydata/test/test_encodingutil.py 141 |
---|
436 | -class StringUtilsNonUnicodePlatform(unittest.TestCase): |
---|
437 | +class EncodingUtilNonUnicodePlatform(unittest.TestCase): |
---|
438 | def setUp(self): |
---|
439 | # Mock sys.platform because unicode_platform() uses it |
---|
440 | self.original_platform = sys.platform |
---|
441 | hunk ./src/allmydata/test/test_encodingutil.py 174 |
---|
442 | listdir_unicode, |
---|
443 | u'/' + lumiere_nfc) |
---|
444 | |
---|
445 | - @patch('sys.getfilesystemencoding') |
---|
446 | - def test_open_unicode(self, mock): |
---|
447 | - mock.return_value = 'ascii' |
---|
448 | - _reload() |
---|
449 | - self.failUnlessRaises(FilenameEncodingError, |
---|
450 | - open_unicode, |
---|
451 | - lumiere_nfc, 'rb') |
---|
452 | - |
---|
453 | -class StringUtils(ReallyEqualMixin): |
---|
454 | +class EncodingUtil(ReallyEqualMixin): |
---|
455 | def setUp(self): |
---|
456 | # Mock sys.platform because unicode_platform() uses it |
---|
457 | self.original_platform = sys.platform |
---|
458 | hunk ./src/allmydata/test/test_encodingutil.py 233 |
---|
459 | |
---|
460 | mock_listdir.return_value = self.dirlist |
---|
461 | mock_getfilesystemencoding.return_value = self.filesystem_encoding |
---|
462 | - |
---|
463 | + |
---|
464 | _reload() |
---|
465 | filenames = listdir_unicode(u'/dummy') |
---|
466 | |
---|
467 | hunk ./src/allmydata/test/test_encodingutil.py 240 |
---|
468 | self.failUnlessEqual(set([normalize(fname) for fname in filenames]), |
---|
469 | set(TEST_FILENAMES)) |
---|
470 | |
---|
471 | - @patch('sys.getfilesystemencoding') |
---|
472 | - @patch('__builtin__.open') |
---|
473 | - def test_open_unicode(self, mock_open, mock_getfilesystemencoding): |
---|
474 | - mock_getfilesystemencoding.return_value = self.filesystem_encoding |
---|
475 | - fn = u'/dummy_directory/" + lumiere_nfc + ".txt' |
---|
476 | |
---|
477 | hunk ./src/allmydata/test/test_encodingutil.py 241 |
---|
478 | - try: |
---|
479 | - u"test".encode(self.filesystem_encoding) |
---|
480 | - except (LookupError, AttributeError): |
---|
481 | - raise unittest.SkipTest("This platform does not support the '%s' filesystem encoding " |
---|
482 | - "that we are testing for the benefit of a different platform." |
---|
483 | - % (self.filesystem_encoding,)) |
---|
484 | +class StdlibUnicode(unittest.TestCase): |
---|
485 | + """This mainly tests that some of the stdlib functions support Unicode paths, but also that |
---|
486 | + listdir_unicode works for valid filenames.""" |
---|
487 | + |
---|
488 | + def skip_if_cannot_represent_filename(self, u): |
---|
489 | + enc = get_filesystem_encoding() |
---|
490 | + if not unicode_platform(): |
---|
491 | + try: |
---|
492 | + u.encode(enc) |
---|
493 | + except UnicodeEncodeError: |
---|
494 | + raise unittest.SkipTest("A non-ASCII filename could not be encoded on this platform.") |
---|
495 | + |
---|
496 | + def test_mkdir_open_exists_abspath_listdir_expanduser(self): |
---|
497 | + self.skip_if_cannot_represent_filename(lumiere_nfc) |
---|
498 | |
---|
499 | hunk ./src/allmydata/test/test_encodingutil.py 256 |
---|
500 | - _reload() |
---|
501 | try: |
---|
502 | hunk ./src/allmydata/test/test_encodingutil.py 257 |
---|
503 | - open_unicode(fn, 'rb') |
---|
504 | - except FilenameEncodingError: |
---|
505 | - return |
---|
506 | + os.mkdir(lumiere_nfc) |
---|
507 | + except EnvironmentError, e: |
---|
508 | + raise unittest.SkipTest("%r\nIt is possible that the filesystem on which this test is being run " |
---|
509 | + "does not support Unicode, even though the platform does." % (e,)) |
---|
510 | + |
---|
511 | + fn = lumiere_nfc + '/' + lumiere_nfc + '.txt' |
---|
512 | + open(fn, 'wb').close() |
---|
513 | + self.failUnless(os.path.exists(fn)) |
---|
514 | + self.failUnless(os.path.exists(os.path.abspath(fn))) |
---|
515 | + filenames = listdir_unicode(lumiere_nfc) |
---|
516 | + |
---|
517 | + # We only require that the listing includes a filename that is canonically equivalent |
---|
518 | + # to lumiere_nfc (on Mac OS X, it will be the NFD equivalent). |
---|
519 | + self.failUnlessIn(lumiere_nfc + ".txt", set([normalize(fname) for fname in filenames])) |
---|
520 | |
---|
521 | hunk ./src/allmydata/test/test_encodingutil.py 272 |
---|
522 | - # Pass Unicode string to open() on Unicode platforms |
---|
523 | + expanded = os.path.expanduser("~/" + lumiere_nfc) |
---|
524 | + self.failIfIn("~", expanded) |
---|
525 | + self.failUnless(expanded.endswith(lumiere_nfc), expanded) |
---|
526 | + |
---|
527 | + @patch('sys.getfilesystemencoding') |
---|
528 | + def test_open_unrepresentable(self, mock): |
---|
529 | if unicode_platform(): |
---|
530 | hunk ./src/allmydata/test/test_encodingutil.py 279 |
---|
531 | - mock_open.assert_called_with(fn, 'rb') |
---|
532 | + raise unittest.SkipTest("This test is not applicable to platforms that represent filenames as Unicode.") |
---|
533 | |
---|
534 | hunk ./src/allmydata/test/test_encodingutil.py 281 |
---|
535 | - # Pass correctly encoded bytestrings to open() on non-Unicode platforms |
---|
536 | - else: |
---|
537 | - fn_bytestring = fn.encode(self.filesystem_encoding) |
---|
538 | - mock_open.assert_called_with(fn_bytestring, 'rb') |
---|
539 | + mock.return_value = 'ascii' |
---|
540 | + self.failUnlessRaises(UnicodeEncodeError, open, lumiere_nfc, 'rb') |
---|
541 | |
---|
542 | |
---|
543 | hunk ./src/allmydata/test/test_encodingutil.py 285 |
---|
544 | -class UbuntuKarmicUTF8(StringUtils, unittest.TestCase): |
---|
545 | +class UbuntuKarmicUTF8(EncodingUtil, unittest.TestCase): |
---|
546 | uname = 'Linux korn 2.6.31-14-generic #48-Ubuntu SMP Fri Oct 16 14:05:01 UTC 2009 x86_64' |
---|
547 | output = 'lumi\xc3\xa8re' |
---|
548 | argv = 'lumi\xc3\xa8re' |
---|
549 | hunk ./src/allmydata/test/test_encodingutil.py 295 |
---|
550 | argv_encoding = 'UTF-8' |
---|
551 | dirlist = ['test_file', '\xc3\x84rtonwall.mp3', 'Blah blah.txt'] |
---|
552 | |
---|
553 | -class UbuntuKarmicLatin1(StringUtils, unittest.TestCase): |
---|
554 | +class UbuntuKarmicLatin1(EncodingUtil, unittest.TestCase): |
---|
555 | uname = 'Linux korn 2.6.31-14-generic #48-Ubuntu SMP Fri Oct 16 14:05:01 UTC 2009 x86_64' |
---|
556 | output = 'lumi\xe8re' |
---|
557 | argv = 'lumi\xe8re' |
---|
558 | hunk ./src/allmydata/test/test_encodingutil.py 305 |
---|
559 | argv_encoding = 'ISO-8859-1' |
---|
560 | dirlist = ['test_file', 'Blah blah.txt', '\xc4rtonwall.mp3'] |
---|
561 | |
---|
562 | -class WindowsXP(StringUtils, unittest.TestCase): |
---|
563 | +class WindowsXP(EncodingUtil, unittest.TestCase): |
---|
564 | uname = 'Windows XP 5.1.2600 x86 x86 Family 15 Model 75 Step ping 2, AuthenticAMD' |
---|
565 | output = 'lumi\x8are' |
---|
566 | platform = 'win32' |
---|
567 | hunk ./src/allmydata/test/test_encodingutil.py 314 |
---|
568 | argv_encoding = 'ascii' |
---|
569 | dirlist = [u'Blah blah.txt', u'test_file', u'\xc4rtonwall.mp3'] |
---|
570 | |
---|
571 | -class WindowsXP_UTF8(StringUtils, unittest.TestCase): |
---|
572 | +class WindowsXP_UTF8(EncodingUtil, unittest.TestCase): |
---|
573 | uname = 'Windows XP 5.1.2600 x86 x86 Family 15 Model 75 Step ping 2, AuthenticAMD' |
---|
574 | output = 'lumi\xc3\xa8re' |
---|
575 | platform = 'win32' |
---|
576 | hunk ./src/allmydata/test/test_encodingutil.py 323 |
---|
577 | argv_encoding = 'ascii' |
---|
578 | dirlist = [u'Blah blah.txt', u'test_file', u'\xc4rtonwall.mp3'] |
---|
579 | |
---|
580 | -class WindowsVista(StringUtils, unittest.TestCase): |
---|
581 | +class WindowsVista(EncodingUtil, unittest.TestCase): |
---|
582 | uname = 'Windows Vista 6.0.6000 x86 x86 Family 6 Model 15 Stepping 11, GenuineIntel' |
---|
583 | output = 'lumi\x8are' |
---|
584 | platform = 'win32' |
---|
585 | hunk ./src/allmydata/test/test_encodingutil.py 332 |
---|
586 | argv_encoding = 'ascii' |
---|
587 | dirlist = [u'Blah blah.txt', u'test_file', u'\xc4rtonwall.mp3'] |
---|
588 | |
---|
589 | -class MacOSXLeopard(StringUtils, unittest.TestCase): |
---|
590 | +class MacOSXLeopard(EncodingUtil, unittest.TestCase): |
---|
591 | uname = 'Darwin g5.local 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:57:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_PPC Power Macintosh powerpc' |
---|
592 | output = 'lumi\xc3\xa8re' |
---|
593 | argv = 'lumi\xc3\xa8re' |
---|
594 | hunk ./src/allmydata/test/test_encodingutil.py 342 |
---|
595 | argv_encoding = 'UTF-8' |
---|
596 | dirlist = [u'A\u0308rtonwall.mp3', u'Blah blah.txt', u'test_file'] |
---|
597 | |
---|
598 | -class MacOSXLeopard7bit(StringUtils, unittest.TestCase): |
---|
599 | +class MacOSXLeopard7bit(EncodingUtil, unittest.TestCase): |
---|
600 | uname = 'Darwin g5.local 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:57:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_PPC Power Macintosh powerpc' |
---|
601 | platform = 'darwin' |
---|
602 | filesystem_encoding = 'utf-8' |
---|
603 | hunk ./src/allmydata/test/test_encodingutil.py 350 |
---|
604 | argv_encoding = 'US-ASCII' |
---|
605 | dirlist = [u'A\u0308rtonwall.mp3', u'Blah blah.txt', u'test_file'] |
---|
606 | |
---|
607 | -class OpenBSD(StringUtils, unittest.TestCase): |
---|
608 | +class OpenBSD(EncodingUtil, unittest.TestCase): |
---|
609 | uname = 'OpenBSD 4.1 GENERIC#187 i386 Intel(R) Celeron(R) CPU 2.80GHz ("GenuineIntel" 686-class)' |
---|
610 | platform = 'openbsd4' |
---|
611 | filesystem_encoding = '646' |
---|
612 | hunk ./src/allmydata/util/encodingutil.py 218 |
---|
613 | return os.listdir(path) |
---|
614 | else: |
---|
615 | return listdir_unicode_fallback(path) |
---|
616 | - |
---|
617 | -def open_unicode(path, mode): |
---|
618 | - """ |
---|
619 | - Wrapper around open() which provides safe access to the convenient Unicode |
---|
620 | - API even under Unix. |
---|
621 | - """ |
---|
622 | - precondition(isinstance(path, unicode), path) |
---|
623 | - |
---|
624 | - if is_unicode_platform: |
---|
625 | - return open(os.path.expanduser(path), mode) |
---|
626 | - else: |
---|
627 | - try: |
---|
628 | - return open(os.path.expanduser(path.encode(filesystem_encoding)), mode) |
---|
629 | - except UnicodeEncodeError: |
---|
630 | - raise FilenameEncodingError(path) |
---|
631 | - |
---|
632 | -def abspath_expanduser_unicode(path): |
---|
633 | - precondition(isinstance(path, unicode), path) |
---|
634 | - |
---|
635 | - if is_unicode_platform: |
---|
636 | - return os.path.abspath(os.path.expanduser(path)) |
---|
637 | - else: |
---|
638 | - try: |
---|
639 | - pathstr = path.encode(filesystem_encoding) |
---|
640 | - return os.path.abspath(os.path.expanduser(pathstr)).decode(filesystem_encoding) |
---|
641 | - except (UnicodeEncodeError, UnicodeDecodeError): |
---|
642 | - raise FilenameEncodingError(path) |
---|
643 | hunk ./src/allmydata/util/fileutil.py 212 |
---|
644 | finally: |
---|
645 | rf.close() |
---|
646 | |
---|
647 | +def put_file(pathname, inf): |
---|
648 | + # TODO: create temporary file and move into place? |
---|
649 | + outf = open(os.path.expanduser(pathname), "wb") |
---|
650 | + try: |
---|
651 | + while True: |
---|
652 | + data = inf.read(32768) |
---|
653 | + if not data: |
---|
654 | + break |
---|
655 | + outf.write(data) |
---|
656 | + finally: |
---|
657 | + outf.close() |
---|
658 | + |
---|
659 | hunk ./src/allmydata/web/common.py 15 |
---|
660 | MustBeReadonlyError, MustNotBeUnknownRWError |
---|
661 | from allmydata.mutable.common import UnrecoverableFileError |
---|
662 | from allmydata.util import abbreviate |
---|
663 | -from allmydata.util.stringutils import to_str |
---|
664 | +from allmydata.util.encodingutil import to_str |
---|
665 | |
---|
666 | class IOpHandleTable(Interface): |
---|
667 | pass |
---|
668 | } |
---|
669 | |
---|
670 | Context: |
---|
671 | |
---|
672 | [SFTP: address some of the comments in zooko's review (#1106). |
---|
673 | david-sarah@jacaranda.org**20100712025537 |
---|
674 | Ignore-this: c3921638a2d4f1de2a776ae78e4dc37e |
---|
675 | ] |
---|
676 | [docs/logging.txt: note that setting flogging vars might affect tests with race conditions. |
---|
677 | david-sarah@jacaranda.org**20100712050721 |
---|
678 | Ignore-this: fc1609d215fcd5561a57fd1226206f27 |
---|
679 | ] |
---|
680 | [test_storage.py: potential fix for failures when logging is enabled. |
---|
681 | david-sarah@jacaranda.org**19700713040546 |
---|
682 | Ignore-this: 5815693a0df3e64c52c3c6b7be2846c7 |
---|
683 | ] |
---|
684 | [upcase_since_on_welcome |
---|
685 | terrellrussell@gmail.com**20100708193903] |
---|
686 | [server_version_on_welcome_page.dpatch.txt |
---|
687 | freestorm77@gmail.com**20100605191721 |
---|
688 | Ignore-this: b450c76dc875f5ac8cca229a666cbd0a |
---|
689 | |
---|
690 | |
---|
691 | - The storage server version is 0 for all storage nodes in the Welcome Page |
---|
692 | |
---|
693 | |
---|
694 | ] |
---|
695 | [NEWS: add NEWS snippets about two recent patches |
---|
696 | zooko@zooko.com**20100708162058 |
---|
697 | Ignore-this: 6c9da6a0ad7351a960bdd60f81532899 |
---|
698 | ] |
---|
699 | [directory_html_top_banner.dpatch |
---|
700 | freestorm77@gmail.com**20100622205301 |
---|
701 | Ignore-this: 1d770d975e0c414c996564774f049bca |
---|
702 | |
---|
703 | The div tag with the link "Return to Welcome page" on the directory.xhtml page is not correct |
---|
704 | |
---|
705 | ] |
---|
706 | [tahoe_css_toolbar.dpatch |
---|
707 | freestorm77@gmail.com**20100622210046 |
---|
708 | Ignore-this: 5b3ebb2e0f52bbba718a932f80c246c0 |
---|
709 | |
---|
710 | CSS modification to be correctly diplayed with Internet Explorer 8 |
---|
711 | |
---|
712 | The links on the top of page directory.xhtml are not diplayed in the same line as display with Firefox. |
---|
713 | |
---|
714 | ] |
---|
715 | [runnin_test_tahoe_css.dpatch |
---|
716 | freestorm77@gmail.com**20100622214714 |
---|
717 | Ignore-this: e0db73d68740aad09a7b9ae60a08c05c |
---|
718 | |
---|
719 | Runnin test for changes in tahoe.css file |
---|
720 | |
---|
721 | ] |
---|
722 | [runnin_test_directory_xhtml.dpatch |
---|
723 | freestorm77@gmail.com**20100622201403 |
---|
724 | Ignore-this: f8962463fce50b9466405cb59fe11d43 |
---|
725 | |
---|
726 | Runnin test for diretory.xhtml top banner |
---|
727 | |
---|
728 | ] |
---|
729 | [stringutils.py: tolerate sys.stdout having no 'encoding' attribute. |
---|
730 | david-sarah@jacaranda.org**20100626040817 |
---|
731 | Ignore-this: f42cad81cef645ee38ac1df4660cc850 |
---|
732 | ] |
---|
733 | [quickstart.html: python 2.5 -> 2.6 as recommended version |
---|
734 | david-sarah@jacaranda.org**20100705175858 |
---|
735 | Ignore-this: bc3a14645ea1d5435002966ae903199f |
---|
736 | ] |
---|
737 | [SFTP: don't call .stopProducing on the producer registered with OverwriteableFileConsumer (which breaks with warner's new downloader). |
---|
738 | david-sarah@jacaranda.org**20100628231926 |
---|
739 | Ignore-this: 131b7a5787bc85a9a356b5740d9d996f |
---|
740 | ] |
---|
741 | [docs/how_to_make_a_tahoe-lafs_release.txt: trivial correction, install.html should now be quickstart.html. |
---|
742 | david-sarah@jacaranda.org**20100625223929 |
---|
743 | Ignore-this: 99a5459cac51bd867cc11ad06927ff30 |
---|
744 | ] |
---|
745 | [setup: in the Makefile, refuse to upload tarballs unless someone has passed the environment variable "BB_BRANCH" with value "trunk" |
---|
746 | zooko@zooko.com**20100619034928 |
---|
747 | Ignore-this: 276ddf9b6ad7ec79e27474862e0f7d6 |
---|
748 | ] |
---|
749 | [trivial: tiny update to in-line comment |
---|
750 | zooko@zooko.com**20100614045715 |
---|
751 | Ignore-this: 10851b0ed2abfed542c97749e5d280bc |
---|
752 | (I'm actually committing this patch as a test of the new eager-annotation-computation of trac-darcs.) |
---|
753 | ] |
---|
754 | [docs: about.html link to home page early on, and be decentralized storage instead of cloud storage this time around |
---|
755 | zooko@zooko.com**20100619065318 |
---|
756 | Ignore-this: dc6db03f696e5b6d2848699e754d8053 |
---|
757 | ] |
---|
758 | [docs: update about.html, especially to have a non-broken link to quickstart.html, and also to comment out the broken links to "for Paranoids" and "for Corporates" |
---|
759 | zooko@zooko.com**20100619065124 |
---|
760 | Ignore-this: e292c7f51c337a84ebfeb366fbd24d6c |
---|
761 | ] |
---|
762 | [TAG allmydata-tahoe-1.7.0 |
---|
763 | zooko@zooko.com**20100619052631 |
---|
764 | Ignore-this: d21e27afe6d85e2e3ba6a3292ba2be1 |
---|
765 | ] |
---|
766 | Patch bundle hash: |
---|
767 | 29fe9a0c6399795c94c07f81cb2771f0425bd895 |
---|