Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: client/utils/zip_package.py

Issue 2093593002: luci-py: Making __file__ usage unicode safe. (Closed) Base URL: https://github.com/luci/luci-py.git@master
Patch Set: Small fixes. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « client/utils/oauth.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2013 The LUCI Authors. All rights reserved. 1 # Copyright 2013 The LUCI Authors. All rights reserved.
2 # Use of this source code is governed under the Apache License, Version 2.0 2 # Use of this source code is governed under the Apache License, Version 2.0
3 # that can be found in the LICENSE file. 3 # that can be found in the LICENSE file.
4 4
5 """Utilities to work with importable python zip packages.""" 5 """Utilities to work with importable python zip packages."""
6 6
7 import atexit 7 import atexit
8 import collections 8 import collections
9 import cStringIO as StringIO 9 import cStringIO as StringIO
10 import hashlib 10 import hashlib
(...skipping 17 matching lines...) Expand all
28 r'.*\.pyc$', 28 r'.*\.pyc$',
29 r'.*\.pyo$', 29 r'.*\.pyo$',
30 ) 30 )
31 31
32 32
33 # Temporary files extracted by extract_resource. Removed in atexit hook. 33 # Temporary files extracted by extract_resource. Removed in atexit hook.
34 _extracted_files = [] 34 _extracted_files = []
35 _extracted_files_lock = threading.Lock() 35 _extracted_files_lock = threading.Lock()
36 36
37 37
38 # Patch zipimport.zipimporter hook to accept unicode strings
39 def zipimporter_unicode(archivepath):
40 if isinstance(archivepath, unicode):
41 archivepath = archivepath.encode(sys.getfilesystemencoding())
42 return zipimport.zipimporter(archivepath)
43
44
45 for i, hook in enumerate(sys.path_hooks):
46 if hook is zipimport.zipimporter:
47 sys.path_hooks[i] = zipimporter_unicode
48
49
38 class ZipPackageError(RuntimeError): 50 class ZipPackageError(RuntimeError):
39 """Failed to create a zip package.""" 51 """Failed to create a zip package."""
40 52
41 53
42 class ZipPackage(object): 54 class ZipPackage(object):
43 """A set of files that can be zipped to file on disk or into memory buffer. 55 """A set of files that can be zipped to file on disk or into memory buffer.
44 56
45 Usage: 57 Usage:
46 package = ZipPackage(root) 58 package = ZipPackage(root)
47 package.add_file('some_file.py', '__main__.py') 59 package.add_file('some_file.py', '__main__.py')
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 def get_main_script_path(): 243 def get_main_script_path():
232 """If running from zip returns path to a zip file, else path to __main__. 244 """If running from zip returns path to a zip file, else path to __main__.
233 245
234 Basically returns path to a file passed to python for execution 246 Basically returns path to a file passed to python for execution
235 as in 'python <main_script>' considering a case of executable zip package. 247 as in 'python <main_script>' considering a case of executable zip package.
236 248
237 Returns path relative to a current directory of when process was started. 249 Returns path relative to a current directory of when process was started.
238 """ 250 """
239 # If running from interactive console __file__ is not defined. 251 # If running from interactive console __file__ is not defined.
240 main = sys.modules['__main__'] 252 main = sys.modules['__main__']
241 return get_module_zip_archive(main) or getattr(main, '__file__', None) 253 path = get_module_zip_archive(main)
254 if path:
255 return path
256
257 path = getattr(main, '__file__', None)
258 if path:
259 return path.decode(sys.getfilesystemencoding())
242 260
243 261
244 def _write_temp_data(name, data, temp_dir): 262 def _write_temp_data(name, data, temp_dir):
245 """Writes content-addressed file in `temp_dir` if relevant.""" 263 """Writes content-addressed file in `temp_dir` if relevant."""
246 filename = '%s-%s' % (hashlib.sha1(data).hexdigest(), name) 264 filename = '%s-%s' % (hashlib.sha1(data).hexdigest(), name)
247 filepath = os.path.join(temp_dir, filename) 265 filepath = os.path.join(temp_dir, filename)
248 if os.path.isfile(filepath): 266 if os.path.isfile(filepath):
249 with open(filepath, 'rb') as f: 267 with open(filepath, 'rb') as f:
250 if f.read() == data: 268 if f.read() == data:
251 # It already exists. 269 # It already exists.
(...skipping 20 matching lines...) Expand all
272 package: is a python module object that represents a package. 290 package: is a python module object that represents a package.
273 resource: should be a relative filename, using '/'' as the path separator. 291 resource: should be a relative filename, using '/'' as the path separator.
274 temp_dir: if set, it will extra the file in this directory with the filename 292 temp_dir: if set, it will extra the file in this directory with the filename
275 being the hash of the content. Otherwise, it uses tempfile.mkstemp(). 293 being the hash of the content. Otherwise, it uses tempfile.mkstemp().
276 294
277 Raises ValueError if no such resource. 295 Raises ValueError if no such resource.
278 """ 296 """
279 # For regular non-zip packages just construct an absolute path. 297 # For regular non-zip packages just construct an absolute path.
280 if not is_zipped_module(package): 298 if not is_zipped_module(package):
281 # Package's __file__ attribute is always an absolute path. 299 # Package's __file__ attribute is always an absolute path.
282 path = os.path.join(os.path.dirname(package.__file__), 300 ppath = package.__file__.decode(sys.getfilesystemencoding())
301 path = os.path.join(os.path.dirname(ppath),
283 resource.replace('/', os.sep)) 302 resource.replace('/', os.sep))
284 if not os.path.exists(path): 303 if not os.path.exists(path):
285 raise ValueError('No such resource in %s: %s' % (package, resource)) 304 raise ValueError('No such resource in %s: %s' % (package, resource))
286 return path 305 return path
287 306
288 # For zipped packages extract the resource into a temp file. 307 # For zipped packages extract the resource into a temp file.
289 data = pkgutil.get_data(package.__name__, resource) 308 data = pkgutil.get_data(package.__name__, resource)
290 if data is None: 309 if data is None:
291 raise ValueError('No such resource in zipped %s: %s' % (package, resource)) 310 raise ValueError('No such resource in zipped %s: %s' % (package, resource))
292 311
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 h = hashlib.sha1() 355 h = hashlib.sha1()
337 with zipfile.ZipFile(get_main_script_path(), 'r') as z: 356 with zipfile.ZipFile(get_main_script_path(), 'r') as z:
338 for name in sorted(z.namelist()): 357 for name in sorted(z.namelist()):
339 with z.open(name) as f: 358 with z.open(name) as f:
340 h.update(str(len(name))) 359 h.update(str(len(name)))
341 h.update(name) 360 h.update(name)
342 content = f.read() 361 content = f.read()
343 h.update(str(len(content))) 362 h.update(str(len(content)))
344 h.update(content) 363 h.update(content)
345 return h.hexdigest() 364 return h.hexdigest()
OLDNEW
« no previous file with comments | « client/utils/oauth.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698