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
742ff4a6
Commit
742ff4a6
authored
Dec 18, 2010
by
willmcgugan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improved output for fsserve
parent
9076762b
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
83 additions
and
38 deletions
+83
-38
fs/commands/fsserve.py
+9
-7
fs/commands/runner.py
+4
-5
fs/expose/http.py
+6
-4
fs/opener.py
+64
-22
No files found.
fs/commands/fsserve.py
View file @
742ff4a6
...
...
@@ -15,7 +15,7 @@ Serves the contents of PATH with one of a number of methods"""
optparse
=
super
(
FSServe
,
self
)
.
get_optparse
()
optparse
.
add_option
(
'-t'
,
'--type'
,
dest
=
'type'
,
type
=
"string"
,
default
=
"http"
,
help
=
"Server type to create (http, rpc, sftp)"
,
metavar
=
"TYPE"
)
optparse
.
add_option
(
'-a'
,
'--addr'
,
dest
=
'addr'
,
type
=
"string"
,
default
=
""
,
optparse
.
add_option
(
'-a'
,
'--addr'
,
dest
=
'addr'
,
type
=
"string"
,
default
=
"
localhost
"
,
help
=
"Server address"
,
metavar
=
"ADDR"
)
optparse
.
add_option
(
'-p'
,
'--port'
,
dest
=
'port'
,
type
=
"int"
,
help
=
"Port number"
,
metavar
=
""
)
...
...
@@ -33,9 +33,8 @@ Serves the contents of PATH with one of a number of methods"""
if
fs
.
isdir
(
path
):
fs
=
fs
.
opendir
(
path
)
path
=
'/'
if
options
.
verbose
:
print
"Serving
\"
%
s
\"
in
%
s"
%
(
path
,
fs
)
self
.
output
(
"Opened
%
s
\n
"
%
fs
,
verbose
=
True
)
port
=
options
.
port
...
...
@@ -44,15 +43,17 @@ Serves the contents of PATH with one of a number of methods"""
if
options
.
type
==
'http'
:
from
fs.expose.http
import
serve_fs
if
port
is
None
:
port
=
80
serve_fs
(
fs
,
options
.
addr
,
port
)
port
=
80
self
.
output
(
"Starting http server on
%
s:
%
i
\n
"
%
(
options
.
addr
,
port
),
verbose
=
True
)
serve_fs
(
fs
,
options
.
addr
,
port
)
elif
options
.
type
==
'rpc'
:
from
fs.expose.xmlrpc
import
RPCFSServer
if
port
is
None
:
port
=
80
s
=
RPCFSServer
(
fs
,
(
options
.
addr
,
port
))
s
.
serve_forever
()
self
.
output
(
"Starting rpc server on
%
s:
%
i
\n
"
%
(
options
.
addr
,
port
),
verbose
=
True
)
s
.
serve_forever
()
elif
options
.
type
==
'sftp'
:
from
fs.expose.sftp
import
BaseSFTPServer
...
...
@@ -60,6 +61,7 @@ Serves the contents of PATH with one of a number of methods"""
port
=
22
server
=
BaseSFTPServer
((
options
.
addr
,
port
),
fs
)
try
:
self
.
output
(
"Starting sftp server on
%
s:
%
i
\n
"
%
(
options
.
addr
,
port
),
verbose
=
True
)
server
.
serve_forever
()
except
Exception
,
e
:
pass
...
...
fs/commands/runner.py
View file @
742ff4a6
...
...
@@ -147,8 +147,7 @@ class Command(object):
def
get_resources
(
self
,
fs_urls
,
dirs_only
=
False
,
files_only
=
False
,
single
=
False
):
fs_paths
=
[
self
.
open_fs
(
fs_url
)
for
fs_url
in
fs_urls
]
fs_paths
=
[
self
.
open_fs
(
fs_url
)
for
fs_url
in
fs_urls
]
resources
=
[]
for
fs
,
path
in
fs_paths
:
...
...
@@ -187,10 +186,9 @@ class Command(object):
text
=
text
.
encode
(
self
.
encoding
,
'replace'
)
return
text
def
output
(
self
,
msgs
,
verbose
=
False
):
if
verbose
and
not
self
.
verbose
:
if
verbose
and
not
self
.
options
.
verbose
:
return
if
isinstance
(
msgs
,
basestring
):
msgs
=
(
msgs
,)
...
...
@@ -281,6 +279,7 @@ class Command(object):
def
run
(
self
):
parser
=
self
.
get_optparse
()
options
,
args
=
parser
.
parse_args
()
self
.
options
=
options
if
options
.
listopeners
:
self
.
list_openers
()
...
...
fs/expose/http.py
View file @
742ff4a6
...
...
@@ -9,6 +9,7 @@ import urllib
import
posixpath
import
time
import
threading
import
socket
def
_datetime_to_epoch
(
d
):
return
mktime
(
d
.
timetuple
())
...
...
@@ -27,7 +28,10 @@ class FSHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
try
:
f
=
self
.
send_head
()
if
f
:
self
.
copyfile
(
f
,
self
.
wfile
)
try
:
self
.
copyfile
(
f
,
self
.
wfile
)
except
socket
.
error
:
pass
finally
:
if
f
is
not
None
:
f
.
close
()
...
...
@@ -44,8 +48,6 @@ class FSHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
"""
path
=
self
.
translate_path
(
self
.
path
)
#path = self.translate_path(self.path)
#print path
f
=
None
if
self
.
_fs
.
isdir
(
path
):
if
not
self
.
path
.
endswith
(
'/'
):
...
...
@@ -54,7 +56,7 @@ class FSHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
self
.
send_header
(
"Location"
,
self
.
path
+
"/"
)
self
.
end_headers
()
return
None
for
index
in
"index.html"
,
"index.htm"
:
for
index
in
(
"index.html"
,
"index.htm"
)
:
index
=
pathjoin
(
path
,
index
)
if
self
.
_fs
.
exists
(
index
):
path
=
index
...
...
fs/opener.py
View file @
742ff4a6
"""
fs.opener: open file systems from a FS url
"""
__all__
=
[
'OpenerError'
,
'NoOpenerError'
,
'OpenerRegistry'
,
'opener'
]
import
sys
from
fs.osfs
import
OSFS
from
fs.path
import
pathsplit
,
basename
,
join
,
iswildcard
...
...
@@ -12,10 +22,6 @@ class OpenerError(Exception):
class
NoOpenerError
(
OpenerError
):
pass
class
MissingParameterError
(
OpenerError
):
pass
def
_expand_syspath
(
path
):
if
path
is
None
:
return
path
...
...
@@ -64,6 +70,7 @@ def _split_url_path(url):
class
OpenerRegistry
(
object
):
"""An opener stores a number of opener objects that are used to parse FS URLs"""
re_fs_url
=
re
.
compile
(
r'''
^
...
...
@@ -95,18 +102,39 @@ class OpenerRegistry(object):
return
match
def
get_opener
(
self
,
name
):
"""Retrieve an opener for the given protocol
:param name: name of the opener to open
:raises NoOpenerError: if no opener has been registered of that name
"""
if
name
not
in
self
.
registry
:
raise
NoOpenerError
(
"No opener for
%
s"
%
name
)
index
=
self
.
registry
[
name
]
return
self
.
openers
[
index
]
def
add
(
self
,
opener
):
"""Adds an opener to the registry
:param opener: a class derived from fs.opener.Opener
"""
index
=
len
(
self
.
openers
)
self
.
openers
[
index
]
=
opener
for
name
in
opener
.
names
:
self
.
registry
[
name
]
=
index
def
parse
(
self
,
fs_url
,
default_fs_name
=
None
,
open_dir
=
True
,
writeable
=
False
,
create_dir
=
False
):
def
parse
(
self
,
fs_url
,
default_fs_name
=
None
,
writeable
=
False
,
create_dir
=
False
):
"""Parses a FS url and returns an fs object a path within that FS object
(if indicated in the path). A tuple of (<FS instance>, <path>) is returned.
:param fs_url: an FS url
:param default_fs_name: the default FS to use if none is indicated (defaults is OSFS)
:param writeable: if True, a writeable FS will be returned
:oaram create_dir: if True, then the directory in the FS will be created
"""
orig_url
=
fs_url
match
=
self
.
split_segments
(
fs_url
)
...
...
@@ -154,7 +182,7 @@ class OpenerRegistry(object):
fs
=
fs
.
opendir
(
pathname
)
fs_path
=
resourcename
return
fs
,
fs_path
return
fs
,
fs_path
or
''
def
open
(
self
,
fs_url
,
mode
=
'rb'
):
"""Opens a file from a given FS url
...
...
@@ -173,15 +201,17 @@ class OpenerRegistry(object):
fs
,
path
=
self
.
parse
(
fs_url
,
writeable
=
writeable
)
file_object
=
fs
.
open
(
path
,
mode
)
# If we just return the file, the fs goes out of scope and closes,
# If we just return the file, the
n
fs goes out of scope and closes,
# which may make the file unusable. To get around this, we store a
# reference in the file object to the FS, and patch the file's
# close method to also close the FS.
close
=
file_object
.
close
def
replace_close
():
fs
.
close
()
return
close
()
file_object
.
close
=
replace_close
close_fs
=
fs
def
replace_close
():
ret
=
close
()
close_fs
.
close
()
return
ret
file_object
.
close
=
replace_close
return
file_object
...
...
@@ -204,23 +234,35 @@ class OpenerRegistry(object):
it doesn't already exist
"""
fs
,
path
=
self
.
parse
(
fs_url
,
writable
=
writeable
,
create_dir
=
create_dir
)
fs
,
path
=
self
.
parse
(
fs_url
,
writ
e
able
=
writeable
,
create_dir
=
create_dir
)
if
path
:
return
fs
.
opendir
(
path
)
return
fs
class
Opener
(
object
):
"""The base class for openers
@classmethod
def
get_param
(
cls
,
params
,
name
,
default
=
None
):
try
:
param
=
params
.
pop
(
0
)
except
IndexError
:
if
default
is
not
None
:
return
default
raise
MissingParameterError
(
error_msg
)
return
param
Opener follow a very simple protocol. To create an opener, derive a class
from `Opener` and define a classmethod called `get_fs`, which should have the following signature::
@classmethod
def get_fs(cls, registry, fs_name, fs_name_params, fs_path, writeable, create_dir):
The parameters of `get_fs` are as follows:
* `fs_name` the name of the opener, as extracted from the protocol part of the url,
* `fs_name_params` reserved for future use
* `fs_path` the path part of the url
* `writeable` if True, then `get_fs` must return an FS that can be written to
* `create_dir` if True then `get_fs` should attempt to silently create the directory references in path
In addition to `get_fs` an opener class should contain
two class attributes; names and desc. `names` is a list of protocols that
list opener will opener. `desc` is an English description of the individual opener syntax.
"""
pass
class
OSFSOpener
(
Opener
):
...
...
@@ -299,7 +341,7 @@ rpc://www.example.org (opens an RPC server on www.example.org, default port 80)"
def
get_fs
(
cls
,
registry
,
fs_name
,
fs_name_params
,
fs_path
,
writeable
,
create_dir
):
from
fs.rpcfs
import
RPCFS
username
,
password
,
fs_path
=
_parse_credentials
(
fs_path
)
if
not
fs_path
.
startswith
(
'http://'
)
:
if
'://'
not
in
fs_path
:
fs_path
=
'http://'
+
fs_path
scheme
,
netloc
,
path
,
params
,
query
,
fragment
=
urlparse
(
fs_path
)
...
...
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