From 5142e4da3e4a838b256c5c582a25ad0fdbb9bf49 Mon Sep 17 00:00:00 2001 From: "willmcgugan@gmail.com" Date: Thu, 27 Feb 2014 15:38:30 +0000 Subject: Fixes for fs commands in PY3 git-svn-id: http://pyfilesystem.googlecode.com/svn/trunk@886 67cdc799-7952-0410-af00-57a81ceafa0f --- fs/commands/fsls.py | 137 +++++++++++++++++++++++++------------------------- fs/commands/runner.py | 26 +++++----- fs/utils.py | 9 ++-- tox.ini | 19 +++++++ 4 files changed, 104 insertions(+), 87 deletions(-) diff --git a/fs/commands/fsls.py b/fs/commands/fsls.py index d1ee324..b98da79 100644 --- a/fs/commands/fsls.py +++ b/fs/commands/fsls.py @@ -8,17 +8,17 @@ from collections import defaultdict import sys class FSls(Command): - + usage = """fsls [OPTIONS]... [PATH] List contents of [PATH]""" - - + + def get_optparse(self): - optparse = super(FSls, self).get_optparse() + optparse = super(FSls, self).get_optparse() optparse.add_option('-u', '--full', dest='fullpath', action="store_true", default=False, help="output full path", metavar="FULL") optparse.add_option('-s', '--syspath', dest='syspath', action="store_true", default=False, - help="output system path (if one exists)", metavar="SYSPATH") + help="output system path (if one exists)", metavar="SYSPATH") optparse.add_option('-r', '--url', dest='url', action="store_true", default=False, help="output URL in place of path (if one exists)", metavar="URL") optparse.add_option('-d', '--dirsonly', dest='dirsonly', action="store_true", default=False, @@ -29,73 +29,73 @@ List contents of [PATH]""" help="use a long listing format", metavar="LONG") optparse.add_option('-a', '--all', dest='all', action='store_true', default=False, help="do not hide dot files") - + return optparse - - - def do_run(self, options, args): + + + def do_run(self, options, args): output = self.output - + if not args: args = [u'.'] - - dir_paths = [] + + dir_paths = [] file_paths = [] - fs_used = set() + fs_used = set() for fs_url in args: - fs, path = self.open_fs(fs_url) - fs_used.add(fs) + fs, path = self.open_fs(fs_url) + fs_used.add(fs) path = path or '.' wildcard = None - + if iswildcard(path): path, wildcard = pathsplit(path) - - if path != '.' and fs.isfile(path): - if not options.dirsonly: + + if path != '.' and fs.isfile(path): + if not options.dirsonly: file_paths.append(path) - else: + else: if not options.filesonly: dir_paths += fs.listdir(path, wildcard=wildcard, full=options.fullpath or options.url, dirs_only=True) - - if not options.dirsonly: + + if not options.dirsonly: file_paths += fs.listdir(path, wildcard=wildcard, - full=options.fullpath or options.url, + full=options.fullpath or options.url, files_only=True) - + for fs in fs_used: try: fs.close() except FSError: pass - + if options.syspath: # Path without a syspath, just won't be displayed dir_paths = filter(None, [fs.getsyspath(path, allow_none=True) for path in dir_paths]) file_paths = filter(None, [fs.getsyspath(path, allow_none=True) for path in file_paths]) - + if options.url: # Path without a syspath, just won't be displayed dir_paths = filter(None, [fs.getpathurl(path, allow_none=True) for path in dir_paths]) file_paths = filter(None, [fs.getpathurl(path, allow_none=True) for path in file_paths]) - + dirs = frozenset(dir_paths) - paths = sorted(dir_paths + file_paths, key=lambda p:p.lower()) - - if not options.all: + paths = sorted(dir_paths + file_paths, key=lambda p: p.lower()) + + if not options.all: paths = [path for path in paths if not isdotfile(path)] - + if not paths: - return - + return + def columnize(paths, num_columns): - - col_height = (len(paths) + num_columns - 1) / num_columns - columns = [[] for _ in xrange(num_columns)] + + col_height = (len(paths) + num_columns - 1) / num_columns + columns = [[] for _ in xrange(num_columns)] col_no = 0 col_pos = 0 for path in paths: @@ -104,73 +104,72 @@ List contents of [PATH]""" if col_pos >= col_height: col_no += 1 col_pos = 0 - + padded_columns = [] - + wrap_filename = self.wrap_filename wrap_dirname = self.wrap_dirname - def wrap(path): + + def wrap(path): if path in dirs: return wrap_dirname(path.ljust(max_width)) else: return wrap_filename(path.ljust(max_width)) - + for column in columns: if column: max_width = max([len(path) for path in column]) else: max_width = 1 - max_width = min(max_width, terminal_width) + max_width = min(max_width, terminal_width) padded_columns.append([wrap(path) for path in column]) - + return padded_columns - def condense_columns(columns): max_column_height = max([len(col) for col in columns]) lines = [[] for _ in xrange(max_column_height)] for column in columns: for line, path in zip(lines, column): - line.append(path) + line.append(path) return '\n'.join(u' '.join(line) for line in lines) - - if options.long: + + if options.long: for path in paths: if path in dirs: output((self.wrap_dirname(path), '\n')) else: - output((self.wrap_filename(path), '\n')) - - else: + output((self.wrap_filename(path), '\n')) + + else: terminal_width = self.terminal_width path_widths = [len(path) for path in paths] - smallest_paths = min(path_widths) - num_paths = len(paths) - - num_cols = min(terminal_width / (smallest_paths + 2), num_paths) - while num_cols: - col_height = (num_paths + num_cols - 1) / num_cols - line_width = 0 - for col_no in xrange(num_cols): - try: - col_width = max(path_widths[col_no*col_height:(col_no + 1) * col_height]) + smallest_paths = min(path_widths) + num_paths = len(paths) + + num_cols = min(terminal_width // (smallest_paths + 2), num_paths) + while num_cols: + col_height = (num_paths + num_cols - 1) // num_cols + line_width = 0 + for col_no in xrange(num_cols): + try: + col_width = max(path_widths[col_no * col_height: (col_no + 1) * col_height]) except ValueError: continue - line_width += col_width - if line_width > terminal_width: - break; + line_width += col_width + if line_width > terminal_width: + break line_width += 2 else: if line_width - 1 <= terminal_width: break - num_cols -= 1 - num_cols = max(1, num_cols) - columns = columnize(paths, num_cols) - output((condense_columns(columns), '\n')) + num_cols -= 1 + num_cols = max(1, num_cols) + columns = columnize(paths, num_cols) + output((condense_columns(columns), '\n')) def run(): - return FSls().run() - + return FSls().run() + if __name__ == "__main__": sys.exit(run()) - \ No newline at end of file diff --git a/fs/commands/runner.py b/fs/commands/runner.py index e32d036..c5c7e6f 100644 --- a/fs/commands/runner.py +++ b/fs/commands/runner.py @@ -8,7 +8,7 @@ from fs.errors import FSError from fs.path import splitext, pathsplit, isdotfile, iswildcard import platform from collections import defaultdict -import re +import six if platform.system() == 'Windows': @@ -76,8 +76,12 @@ class Command(object): version = '' def __init__(self, usage='', version=''): - self.output_file = sys.stdout - self.error_file = sys.stderr + if six.PY3: + self.output_file = sys.stdout.buffer + self.error_file = sys.stderr.buffer + else: + self.output_file = sys.stdout + self.error_file = sys.stderr self.encoding = getattr(self.output_file, 'encoding', 'utf-8') or 'utf-8' self.verbosity_level = 0 self.terminal_colors = not sys.platform.startswith('win') and self.is_terminal() @@ -210,11 +214,9 @@ class Command(object): return raw_input('%s: %s ' % (self.name, msg)) def text_encode(self, text): - if not isinstance(text, unicode): text = text.decode('ascii', 'replace') text = text.encode(self.encoding, 'replace') - return text def output(self, msgs, verbose=False): @@ -226,10 +228,8 @@ class Command(object): self.output_file.write(self.text_encode(msg)) def output_table(self, table, col_process=None, verbose=False): - if verbose and not self.verbose: return - if col_process is None: col_process = {} @@ -248,7 +248,9 @@ class Command(object): td = col_process[col_no](td) out_col.append(td) lines.append(self.text_encode('%s\n' % ' '.join(out_col).rstrip())) - self.output(''.join(lines)) + for l in lines: + self.output_file.write(l) + #self.output(''.join(lines)) def error(self, *msgs): for msg in msgs: @@ -275,7 +277,7 @@ class Command(object): desc = getattr(fs_opener, 'desc', '') opener_table.append((names, desc)) - opener_table.sort(key = lambda r:r[0]) + opener_table.sort(key=lambda r: r[0]) def wrap_line(text): @@ -298,14 +300,13 @@ class Command(object): for names, desc in opener_table: self.output(('-' * self.terminal_width, '\n')) - proto = ', '.join([n+'://' for n in names]) + proto = ', '.join([n + '://' for n in names]) self.output((self.wrap_dirname('[%s]' % proto), '\n\n')) if not desc.strip(): desc = "No information available" wrap_line(desc) self.output('\n') - def run(self): parser = self.get_optparse() options, args = parser.parse_args() @@ -340,7 +341,8 @@ class Command(object): opener.add(new_opener) - args = [unicode(arg, sys.getfilesystemencoding()) for arg in args] + if not six.PY3: + args = [unicode(arg, sys.getfilesystemencoding()) for arg in args] self.verbose = options.verbose try: return self.do_run(options, args) or 0 diff --git a/fs/utils.py b/fs/utils.py index 28e6538..e0ab693 100644 --- a/fs/utils.py +++ b/fs/utils.py @@ -18,15 +18,16 @@ __all__ = ['copyfile', 'find_duplicates', 'print_fs'] -import os import sys import stat +import six from fs.mountfs import MountFS from fs.path import pathjoin from fs.errors import DestinationExistsError, RemoveRootError from fs.base import FS + def copyfile(src_fs, src_path, dst_fs, dst_path, overwrite=True, chunk_size=64*1024): """Copy a file from one filesystem to another. Will use system copyfile, if both files have a syspath. Otherwise file will be copied a chunk at a time. @@ -491,7 +492,7 @@ def print_fs(fs, terminal_colors = hasattr(file_out, 'isatty') and file_out.isatty() def write(line): - file_out.write(line.encode(file_encoding, 'replace')+'\n') + file_out.write(line.encode(file_encoding, 'replace') + b'\n') def wrap_prefix(prefix): if not terminal_colors: @@ -511,11 +512,7 @@ def print_fs(fs, def wrap_filename(fname): if not terminal_colors: return fname -# if '.' in fname: -# name, ext = os.path.splitext(fname) -# fname = '%s\x1b[36m%s\x1b[0m' % (name, ext) if fname.startswith('.'): - #fname = '\x1b[2m%s\x1b[0m' % fname fname = '\x1b[33m%s\x1b[0m' % fname return fname dircount = [0] diff --git a/tox.ini b/tox.ini index 06f76eb..849eea8 100644 --- a/tox.ini +++ b/tox.ini @@ -15,6 +15,16 @@ changedir=.tox commands = nosetests fs.tests -v \ [] + +[testenv:py31] +commands = nosetests fs.tests -v \ + [] +deps = distribute + six + dexml + nose + winpdb + [testenv:py32] commands = nosetests fs.tests -v \ [] @@ -24,3 +34,12 @@ deps = distribute nose winpdb +[testenv:py33] +commands = nosetests fs.tests -v \ + [] +deps = distribute + six + dexml + nose + winpdb + -- cgit v1.2.1