| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | from __future__ import absolute_import |
| | from __future__ import print_function |
| | from __future__ import unicode_literals |
| | import io |
| | import os.path |
| | import sys |
| |
|
| |
|
| | PY3 = sys.version_info.major == 3 |
| | if PY3: |
| | basestring = str |
| |
|
| |
|
| | def is_storage(item): |
| | return hasattr(item, '__iter__') and hasattr(item, '__getitem__') |
| |
|
| |
|
| | def is_stream(item): |
| | return hasattr(item, 'open') and callable(item.open) |
| |
|
| |
|
| | class ItemWrapper(object): |
| | def __init__(self, wrapped): |
| | self.wrapped = wrapped |
| |
|
| | def __getattr__(self, name): |
| | return getattr(self.wrapped, name) |
| |
|
| |
|
| | class StorageWrapper(ItemWrapper): |
| | def __iter__(self): |
| | return iter(self.wrapped) |
| |
|
| | def __getitem__(self, name): |
| | return self.wrapped[name] |
| |
|
| |
|
| | class ItemConversionStorage(StorageWrapper): |
| |
|
| | def __getitem__(self, name): |
| | item = self.wrapped[name] |
| | |
| | conversion = self.resolve_conversion_for(name) |
| | if conversion: |
| | return conversion(item) |
| | return item |
| |
|
| | def resolve_conversion_for(self, name): |
| | ''' return a conversion function for the specified storage item ''' |
| | pass |
| |
|
| |
|
| | class ExtraItemStorage(StorageWrapper): |
| |
|
| | def __iter__(self): |
| | for name in self.wrapped: |
| | yield name |
| |
|
| | item = self.wrapped[name] |
| | if hasattr(item, 'other_formats'): |
| | other_formats = item.other_formats() |
| | if other_formats: |
| | for ext in other_formats: |
| | yield name + ext |
| |
|
| | def __getitem__(self, name): |
| | try: |
| | item = self.wrapped[name] |
| | if is_storage(item): |
| | item = ExtraItemStorage(item) |
| | return item |
| | except KeyError: |
| | |
| | for root in self.wrapped: |
| | item = self.wrapped[root] |
| | if hasattr(item, 'other_formats'): |
| | other_formats = item.other_formats() |
| | if other_formats: |
| | for ext, func in other_formats.items(): |
| | if root + ext == name: |
| | return Open2Stream(func) |
| | raise |
| |
|
| |
|
| | class Open2Stream(object): |
| |
|
| | def __init__(self, open): |
| | self.open = open |
| |
|
| |
|
| | def iter_storage_leafs(stg, basepath=''): |
| | ''' iterate every leaf nodes in the storage |
| | |
| | stg: an instance of Storage |
| | ''' |
| | for name in stg: |
| | path = basepath + name |
| | item = stg[name] |
| | if is_storage(item): |
| | for x in iter_storage_leafs(item, path + '/'): |
| | yield x |
| | else: |
| | yield path |
| |
|
| |
|
| | def unpack(stg, outbase): |
| | ''' unpack a storage into outbase directory |
| | |
| | stg: an instance of Storage |
| | outbase: path to a directory in filesystem (should not end with '/') |
| | ''' |
| | for name in stg: |
| | outpath = os.path.join(outbase, name) |
| | item = stg[name] |
| | if is_storage(item): |
| | if not os.path.exists(outpath): |
| | os.mkdir(outpath) |
| | unpack(item, outpath) |
| | else: |
| | f = item.open() |
| | try: |
| | outpath = outpath.replace('\x05', '_05') |
| | with io.open(outpath, 'wb') as outfile: |
| | outfile.write(f.read()) |
| | finally: |
| | f.close() |
| |
|
| |
|
| | def open_storage_item(stg, path): |
| | if isinstance(path, basestring): |
| | path_segments = path.split('/') |
| | else: |
| | path_segments = path |
| |
|
| | item = stg |
| | for name in path_segments: |
| | item = item[name] |
| | return item |
| |
|
| |
|
| | def printstorage(stg, basepath=''): |
| | names = list(stg) |
| | names.sort() |
| | for name in names: |
| | path = basepath + name |
| | item = stg[name] |
| | if is_storage(item): |
| | printstorage(item, path + '/') |
| | elif is_stream(item): |
| | print(path.encode('unicode_escape').decode('utf-8')) |
| |
|