Commit 0cae6ca1 by willmcgugan@gmail.com

Fixes for fs commands in PY3

parent 747c7b9b
......@@ -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
......@@ -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
......
......@@ -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]
......
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment