Spaces:
Running
Running
| # -*- coding: utf-8 -*- | |
| from __future__ import with_statement | |
| import logging | |
| from contextlib import contextmanager | |
| logger = logging.getLogger(__name__) | |
| def open_storage(path, mode='r', default_storage_factory=None): | |
| import os.path | |
| import zipfile | |
| import fs | |
| import _zipfile | |
| if os.path.exists(path): | |
| if os.path.isdir(path): | |
| return fs.FileSystemStorage(path) | |
| elif zipfile.is_zipfile(path): | |
| return _zipfile.ZipFileStorage(path, mode) | |
| raise IOError('%s: unsupported storage' % path) | |
| elif callable(default_storage_factory): | |
| return default_storage_factory(path, mode) | |
| else: | |
| raise IOError('%s: cannot open' % path) | |
| def resolve_path(folder, path): | |
| ''' resolve path in a folder | |
| :param folder: a folder (should have ``__getitem__``) | |
| :param path: path to resolve | |
| :returns: a node or None | |
| ''' | |
| if path in ('', '/'): | |
| return folder | |
| import os | |
| path_segments = path.split(os.sep) | |
| assert len(path_segments) > 0 | |
| for seg in path_segments: | |
| if not hasattr(folder, '__getitem__'): | |
| return None | |
| try: | |
| node = folder[seg] | |
| except KeyError: | |
| return None | |
| else: | |
| folder = node | |
| return node | |
| def makedirs(folder, path): | |
| from path import split as path_split | |
| path_segments = path_split(path) | |
| for seg in path_segments: | |
| if seg in folder: | |
| folder = folder[seg] | |
| else: | |
| folder = folder.folder(seg) | |
| return folder | |
| def makedirs_to_file(folder, path): | |
| import os.path | |
| dirname, name = os.path.split(path) | |
| if name == '': | |
| msg = '%s: invalid path' % path | |
| raise ValueError(msg) | |
| folder = makedirs(folder, dirname) | |
| return folder.file(name) | |
| def put_file(node, path, **kwargs): | |
| if hasattr(node, 'put'): | |
| node.put(path, **kwargs) | |
| elif hasattr(node, 'open'): | |
| with file(path, 'rb') as f: | |
| with node.open('w') as g: | |
| stream_copy(f, g) | |
| else: | |
| raise IOError('node supports neither put nor open') | |
| def get_file(node, path): | |
| if hasattr(node, 'get'): | |
| node.get(path) | |
| elif hasattr(node, 'open'): | |
| with node.open() as f: | |
| with file(path, 'wb') as g: | |
| stream_copy(f, g) | |
| else: | |
| raise IOError('node supports neither get nor open') | |
| def openable_path_on_filesystem(node, writeback=False): | |
| if hasattr(node, 'path_on_filesystem'): | |
| with node.path_on_filesystem() as path: | |
| yield path | |
| else: | |
| import os | |
| from tempfile import mkstemp | |
| fd, path = mkstemp() | |
| try: | |
| with node.open() as f: | |
| with os.fdopen(fd, 'w+') as g: | |
| fd = None | |
| stream_copy(f, g) | |
| # fd closed | |
| yield path | |
| if writeback: | |
| put_file(node, path) | |
| finally: | |
| if fd is not None: | |
| os.close(fd) | |
| os.unlink(path) | |
| def copy_file(src_node, dst_node): | |
| if (hasattr(dst_node, 'path_on_filesystem') and | |
| hasattr(src_node, 'get')): | |
| with openable_path_on_filesystem(dst_node, writeback=True) as dst_path: | |
| get_file(src_node, dst_path) | |
| with openable_path_on_filesystem(src_node) as src_path: | |
| put_file(dst_node, src_path) | |
| def stream_copy(src, dst): | |
| while True: | |
| data = src.read(4096) | |
| if len(data) == 0: | |
| return | |
| dst.write(data) | |
| def iterate_nodes_recursively(folder, folder_path=''): | |
| import os.path | |
| for name in folder: | |
| node = folder[name] | |
| node_path = os.path.join(folder_path, name) | |
| yield node_path, node | |
| if hasattr(node, '__iter__') and hasattr(node, '__getitem__'): | |
| for x in iterate_nodes_recursively(node, node_path): | |
| yield x | |
| def iterate_files_recursively(folder, folder_path=''): | |
| for path, node in iterate_nodes_recursively(folder, folder_path): | |
| if hasattr(node, 'open'): | |
| yield path, node | |
| def ls_main(): | |
| doc = '''Usage: storage-ls [options] <storage> | |
| --help Show this screen. | |
| ''' | |
| from docopt import docopt | |
| args = docopt(doc) | |
| root_path = args['<storage>'] or '.' | |
| with open_storage(root_path, 'r') as stg: | |
| for path, node in iterate_files_recursively(stg): | |
| print path | |
| def put_main(): | |
| doc = '''Usage: storage-put [options] <storage> <path> <file> | |
| --help Show this screen. | |
| ''' | |
| from docopt import docopt | |
| args = docopt(doc) | |
| import os.path | |
| root_path = args['<storage>'] or '.' | |
| with open_storage(root_path, 'a') as stg: | |
| path = args['<path>'] | |
| file_path = args['<file>'] | |
| if os.path.exists(file_path): | |
| node = makedirs_to_file(stg, path) | |
| put_file(node, file_path) | |
| else: | |
| logger.error('%s: not found', file_path) | |
| raise SystemExit(1) | |
| def get_main(): | |
| doc = '''Usage: storage-get [options] <storage> <path> <file> | |
| --help Show this screen. | |
| ''' | |
| from docopt import docopt | |
| args = docopt(doc) | |
| root_path = args['<storage>'] or '.' | |
| with open_storage(root_path, 'a') as stg: | |
| path = args['<path>'] | |
| file_path = args['<file>'] | |
| node = resolve_path(stg, path) | |
| if node: | |
| get_file(node, file_path) | |
| else: | |
| logger.error('%s: not found', path) | |
| raise SystemExit(1) | |