Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pyfs
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
pyfs
Commits
0cae6ca1
Commit
0cae6ca1
authored
Feb 27, 2014
by
willmcgugan@gmail.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixes for fs commands in PY3
parent
747c7b9b
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
104 additions
and
88 deletions
+104
-88
fs/commands/fsls.py
+68
-70
fs/commands/runner.py
+14
-12
fs/utils.py
+3
-6
tox.ini
+19
-0
No files found.
fs/commands/fsls.py
View file @
0cae6ca1
...
...
@@ -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
fs/commands/runner.py
View file @
0cae6ca1
...
...
@@ -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
...
...
fs/utils.py
View file @
0cae6ca1
...
...
@@ -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
]
...
...
tox.ini
View file @
0cae6ca1
...
...
@@ -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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment