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
44dcc3bf
Commit
44dcc3bf
authored
Jun 20, 2010
by
willmcgugan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added settimes to a few FS impementations, and added a settimes test case
parent
1a8f4d8b
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
68 additions
and
27 deletions
+68
-27
fs/base.py
+20
-25
fs/expose/xmlrpc.py
+4
-0
fs/mountfs.py
+10
-1
fs/multifs.py
+8
-0
fs/rpcfs.py
+4
-0
fs/tests/__init__.py
+21
-0
fs/wrapfs/__init__.py
+1
-1
No files found.
fs/base.py
View file @
44dcc3bf
...
@@ -110,6 +110,7 @@ try:
...
@@ -110,6 +110,7 @@ try:
except
ImportError
:
except
ImportError
:
wraps
=
lambda
f
:
f
wraps
=
lambda
f
:
f
def
synchronize
(
func
):
def
synchronize
(
func
):
"""Decorator to synchronize a method on self._lock."""
"""Decorator to synchronize a method on self._lock."""
@wraps
(
func
)
@wraps
(
func
)
...
@@ -121,7 +122,6 @@ def synchronize(func):
...
@@ -121,7 +122,6 @@ def synchronize(func):
self
.
_lock
.
release
()
self
.
_lock
.
release
()
return
acquire_lock
return
acquire_lock
class
FS
(
object
):
class
FS
(
object
):
"""The base class for Filesystem abstraction objects.
"""The base class for Filesystem abstraction objects.
...
@@ -183,7 +183,6 @@ class FS(object):
...
@@ -183,7 +183,6 @@ class FS(object):
else
:
else
:
self
.
_lock
=
DummyLock
()
self
.
_lock
=
DummyLock
()
def
getsyspath
(
self
,
path
,
allow_none
=
False
):
def
getsyspath
(
self
,
path
,
allow_none
=
False
):
"""Returns the system path (a path recognised by the OS) if present.
"""Returns the system path (a path recognised by the OS) if present.
...
@@ -417,21 +416,28 @@ class FS(object):
...
@@ -417,21 +416,28 @@ class FS(object):
raise
UnsupportedError
(
"rename resource"
)
raise
UnsupportedError
(
"rename resource"
)
def
settimes
(
self
,
path
,
accessed_time
=
None
,
modified_time
=
None
):
def
settimes
(
self
,
path
,
accessed_time
=
None
,
modified_time
=
None
):
"""Set the access
time and modifie
time of a file
"""Set the access
ed time and modified
time of a file
:param path: path to a file
:param path: path to a file
:param access_time: epoch time of file access
:param accessed_time: a datetime object the file was accessed (defaults to current time)
:param modified_time: epock time of file modification
:param modified_time: a datetime object the file was modified (defaults to current time)
"""
if
self
.
hassyspath
(
path
):
"""
sys_path
=
self
.
getsyspath
(
path
)
os
.
utime
(
sys_path
,
accessed_time
,
modified_time
)
sys_path
=
self
.
getsyspath
(
path
,
allow_none
=
True
)
if
sys_path
is
not
None
:
now
=
datetime
.
datetime
.
now
()
if
accessed_time
is
None
:
accessed_time
=
now
if
modified_time
is
None
:
modified_time
=
now
accessed_time
=
int
(
time
.
mktime
(
accessed_time
.
timetuple
()))
modified_time
=
int
(
time
.
mktime
(
modified_time
.
timetuple
()))
os
.
utime
(
sys_path
,
(
accessed_time
,
modified_time
))
return
True
return
True
else
:
else
:
raise
UnsupportedError
(
"settimes"
)
raise
UnsupportedError
(
"settimes"
)
def
getinfo
(
self
,
path
):
def
getinfo
(
self
,
path
):
"""Returns information for a path as a dictionary. The exact content of
"""Returns information for a path as a dictionary. The exact content of
this dictionary will vary depending on the implementation, but will
this dictionary will vary depending on the implementation, but will
...
@@ -442,7 +448,6 @@ class FS(object):
...
@@ -442,7 +448,6 @@ class FS(object):
"""
"""
raise
UnsupportedError
(
"get resource info"
)
raise
UnsupportedError
(
"get resource info"
)
def
desc
(
self
,
path
):
def
desc
(
self
,
path
):
"""Returns short descriptive text regarding a path. Intended mainly as
"""Returns short descriptive text regarding a path. Intended mainly as
a debugging aid
a debugging aid
...
@@ -462,7 +467,6 @@ class FS(object):
...
@@ -462,7 +467,6 @@ class FS(object):
else
:
else
:
return
"OS file, maps to
%
s"
%
sys_path
return
"OS file, maps to
%
s"
%
sys_path
def
getcontents
(
self
,
path
):
def
getcontents
(
self
,
path
):
"""Returns the contents of a file as a string.
"""Returns the contents of a file as a string.
...
@@ -512,7 +516,6 @@ class FS(object):
...
@@ -512,7 +516,6 @@ class FS(object):
sub_fs
=
SubFS
(
self
,
path
)
sub_fs
=
SubFS
(
self
,
path
)
return
sub_fs
return
sub_fs
def
walk
(
self
,
def
walk
(
self
,
path
=
"/"
,
path
=
"/"
,
wildcard
=
None
,
wildcard
=
None
,
...
@@ -578,7 +581,6 @@ class FS(object):
...
@@ -578,7 +581,6 @@ class FS(object):
else
:
else
:
raise
ValueError
(
"Search should be 'breadth' or 'depth'"
)
raise
ValueError
(
"Search should be 'breadth' or 'depth'"
)
def
walkfiles
(
self
,
def
walkfiles
(
self
,
path
=
"/"
,
path
=
"/"
,
wildcard
=
None
,
wildcard
=
None
,
...
@@ -597,7 +599,6 @@ class FS(object):
...
@@ -597,7 +599,6 @@ class FS(object):
for
f
in
files
:
for
f
in
files
:
yield
pathjoin
(
path
,
f
)
yield
pathjoin
(
path
,
f
)
def
walkdirs
(
self
,
def
walkdirs
(
self
,
path
=
"/"
,
path
=
"/"
,
wildcard
=
None
,
wildcard
=
None
,
...
@@ -613,8 +614,6 @@ class FS(object):
...
@@ -613,8 +614,6 @@ class FS(object):
for
p
,
files
in
self
.
walk
(
path
,
wildcard
=
wildcard
,
search
=
search
,
ignore_errors
=
ignore_errors
):
for
p
,
files
in
self
.
walk
(
path
,
wildcard
=
wildcard
,
search
=
search
,
ignore_errors
=
ignore_errors
):
yield
p
yield
p
def
getsize
(
self
,
path
):
def
getsize
(
self
,
path
):
"""Returns the size (in bytes) of a resource.
"""Returns the size (in bytes) of a resource.
...
@@ -714,7 +713,6 @@ class FS(object):
...
@@ -714,7 +713,6 @@ class FS(object):
self
.
copy
(
src
,
dst
,
overwrite
=
overwrite
,
chunk_size
=
chunk_size
)
self
.
copy
(
src
,
dst
,
overwrite
=
overwrite
,
chunk_size
=
chunk_size
)
self
.
remove
(
src
)
self
.
remove
(
src
)
def
movedir
(
self
,
src
,
dst
,
overwrite
=
False
,
ignore_errors
=
False
,
chunk_size
=
16384
):
def
movedir
(
self
,
src
,
dst
,
overwrite
=
False
,
ignore_errors
=
False
,
chunk_size
=
16384
):
"""moves a directory from one location to another.
"""moves a directory from one location to another.
...
@@ -772,8 +770,6 @@ class FS(object):
...
@@ -772,8 +770,6 @@ class FS(object):
self
.
removedir
(
dirname
)
self
.
removedir
(
dirname
)
def
copydir
(
self
,
src
,
dst
,
overwrite
=
False
,
ignore_errors
=
False
,
chunk_size
=
16384
):
def
copydir
(
self
,
src
,
dst
,
overwrite
=
False
,
ignore_errors
=
False
,
chunk_size
=
16384
):
"""copies a directory from one location to another.
"""copies a directory from one location to another.
...
@@ -820,7 +816,6 @@ class FS(object):
...
@@ -820,7 +816,6 @@ class FS(object):
dst_filename
=
pathjoin
(
dst_dirpath
,
filename
)
dst_filename
=
pathjoin
(
dst_dirpath
,
filename
)
copyfile
(
src_filename
,
dst_filename
,
overwrite
=
overwrite
,
chunk_size
=
chunk_size
)
copyfile
(
src_filename
,
dst_filename
,
overwrite
=
overwrite
,
chunk_size
=
chunk_size
)
def
isdirempty
(
self
,
path
):
def
isdirempty
(
self
,
path
):
"""Check if a directory is empty (contains no files or sub-directories)
"""Check if a directory is empty (contains no files or sub-directories)
...
@@ -835,7 +830,6 @@ class FS(object):
...
@@ -835,7 +830,6 @@ class FS(object):
return
True
return
True
return
False
return
False
def
makeopendir
(
self
,
path
,
recursive
=
False
):
def
makeopendir
(
self
,
path
,
recursive
=
False
):
"""makes a directory (if it doesn't exist) and returns an FS object for
"""makes a directory (if it doesn't exist) and returns an FS object for
the newly created directory.
the newly created directory.
...
@@ -858,8 +852,6 @@ class FS(object):
...
@@ -858,8 +852,6 @@ class FS(object):
"""
"""
from
fs.utils
import
print_fs
from
fs.utils
import
print_fs
print_fs
(
self
,
max_levels
=
max_levels
)
print_fs
(
self
,
max_levels
=
max_levels
)
def
browse
(
self
):
def
browse
(
self
):
"""Displays the FS tree in a graphical window (requires wxWidgets)"""
"""Displays the FS tree in a graphical window (requires wxWidgets)"""
...
@@ -965,6 +957,9 @@ class SubFS(FS):
...
@@ -965,6 +957,9 @@ class SubFS(FS):
except
DirectoryNotEmptyError
:
except
DirectoryNotEmptyError
:
pass
pass
def
settimes
(
self
,
path
,
accessed_time
=
None
,
modified_time
=
None
):
return
self
.
parent
.
settimes
(
self
.
_delegate
(
path
),
accessed_time
,
modified_time
)
def
getinfo
(
self
,
path
):
def
getinfo
(
self
,
path
):
return
self
.
parent
.
getinfo
(
self
.
_delegate
(
path
))
return
self
.
parent
.
getinfo
(
self
.
_delegate
(
path
))
...
...
fs/expose/xmlrpc.py
View file @
44dcc3bf
...
@@ -85,6 +85,10 @@ class RPCFSInterface(object):
...
@@ -85,6 +85,10 @@ class RPCFSInterface(object):
dst
=
self
.
decode_path
(
dst
)
dst
=
self
.
decode_path
(
dst
)
return
self
.
fs
.
rename
(
src
,
dst
)
return
self
.
fs
.
rename
(
src
,
dst
)
def
settimes
(
self
,
path
,
accessed_time
,
modified_time
):
path
=
self
.
decode_path
(
path
)
return
self
.
fs
.
settimes
(
path
,
accessed_time
,
modified_time
)
def
getinfo
(
self
,
path
):
def
getinfo
(
self
,
path
):
path
=
self
.
decode_path
(
path
)
path
=
self
.
decode_path
(
path
)
return
self
.
fs
.
getinfo
(
path
)
return
self
.
fs
.
getinfo
(
path
)
...
...
fs/mountfs.py
View file @
44dcc3bf
...
@@ -326,7 +326,7 @@ class MountFS(FS):
...
@@ -326,7 +326,7 @@ class MountFS(FS):
@synchronize
@synchronize
def
unmount
(
self
,
path
):
def
unmount
(
self
,
path
):
"""Unmoun
d
s a path.
"""Unmoun
t
s a path.
:param path: Path to unmount
:param path: Path to unmount
...
@@ -334,6 +334,15 @@ class MountFS(FS):
...
@@ -334,6 +334,15 @@ class MountFS(FS):
path
=
normpath
(
path
)
path
=
normpath
(
path
)
del
self
.
mount_tree
[
path
]
del
self
.
mount_tree
[
path
]
def
settimes
(
self
,
path
,
accessed_time
=
None
,
modified_time
=
None
):
path
=
normpath
(
path
)
fs
,
mount_path
,
delegate_path
=
self
.
_delegate
(
path
)
if
fs
is
None
:
raise
ResourceNotFoundError
(
path
)
if
fs
is
self
:
raise
UnsupportedError
(
"settimes"
)
fs
.
settimes
(
delegate_path
,
accessed_time
,
modified_time
)
@synchronize
@synchronize
def
getinfo
(
self
,
path
):
def
getinfo
(
self
,
path
):
path
=
normpath
(
path
)
path
=
normpath
(
path
)
...
...
fs/multifs.py
View file @
44dcc3bf
...
@@ -78,6 +78,7 @@ class MultiFS(FS):
...
@@ -78,6 +78,7 @@ class MultiFS(FS):
__repr__
=
__str__
__repr__
=
__str__
@synchronize
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
u"<MultiFS:
%
s>"
%
", "
.
join
(
unicode
(
fs
)
for
fs
in
self
.
fs_sequence
)
return
u"<MultiFS:
%
s>"
%
", "
.
join
(
unicode
(
fs
)
for
fs
in
self
.
fs_sequence
)
...
@@ -218,6 +219,13 @@ class MultiFS(FS):
...
@@ -218,6 +219,13 @@ class MultiFS(FS):
raise
ResourceNotFoundError
(
path
)
raise
ResourceNotFoundError
(
path
)
@synchronize
@synchronize
def
settimes
(
self
,
path
,
accessed_time
=
None
,
modified_time
=
None
):
for
fs
in
self
:
if
fs
.
exists
(
path
):
return
fs
.
settimes
(
path
,
accessed_time
,
modified_time
)
raise
ResourceNotFoundError
(
path
)
@synchronize
def
getinfo
(
self
,
path
):
def
getinfo
(
self
,
path
):
for
fs
in
self
:
for
fs
in
self
:
if
fs
.
exists
(
path
):
if
fs
.
exists
(
path
):
...
...
fs/rpcfs.py
View file @
44dcc3bf
...
@@ -215,6 +215,10 @@ class RPCFS(FS):
...
@@ -215,6 +215,10 @@ class RPCFS(FS):
dst
=
self
.
encode_path
(
dst
)
dst
=
self
.
encode_path
(
dst
)
return
self
.
proxy
.
rename
(
src
,
dst
)
return
self
.
proxy
.
rename
(
src
,
dst
)
def
settimes
(
self
,
path
,
accessed_time
,
modified_time
):
path
=
self
.
encode_path
(
path
)
return
self
.
proxy
.
settimes
(
path
,
accessed_time
,
modified_time
)
def
getinfo
(
self
,
path
):
def
getinfo
(
self
,
path
):
path
=
self
.
encode_path
(
path
)
path
=
self
.
encode_path
(
path
)
return
self
.
proxy
.
getinfo
(
path
)
return
self
.
proxy
.
getinfo
(
path
)
...
...
fs/tests/__init__.py
View file @
44dcc3bf
...
@@ -13,6 +13,7 @@ logging.basicConfig(level=logging.ERROR, stream=sys.stdout)
...
@@ -13,6 +13,7 @@ logging.basicConfig(level=logging.ERROR, stream=sys.stdout)
from
fs.base
import
*
from
fs.base
import
*
import
datetime
import
unittest
import
unittest
import
os
,
os
.
path
import
os
,
os
.
path
import
pickle
import
pickle
...
@@ -561,6 +562,26 @@ class FSTestCases(object):
...
@@ -561,6 +562,26 @@ class FSTestCases(object):
finally
:
finally
:
f
.
close
()
f
.
close
()
def
test_settimes
(
self
):
def
cmp_datetimes
(
d1
,
d2
):
"""Test datetime objects are the same to within the timestamp accuracy"""
dts1
=
time
.
mktime
(
d1
.
timetuple
())
dts2
=
time
.
mktime
(
d2
.
timetuple
())
return
dts1
==
dts2
d1
=
datetime
.
datetime
(
2010
,
6
,
20
,
11
,
0
,
9
,
987699
)
d2
=
datetime
.
datetime
(
2010
,
7
,
5
,
11
,
0
,
9
,
500000
)
self
.
fs
.
createfile
(
'/dates.txt'
,
'check dates'
)
# If the implementation supports settimes, check that the times
# can be set and then retrieved
try
:
self
.
fs
.
settimes
(
'/dates.txt'
,
d1
,
d2
)
except
UnsupportedError
:
pass
else
:
info
=
self
.
fs
.
getinfo
(
'/dates.txt'
)
self
.
assertTrue
(
cmp_datetimes
(
d1
,
info
[
'accessed_time'
]))
self
.
assertTrue
(
cmp_datetimes
(
d2
,
info
[
'modified_time'
]))
class
ThreadingTestCases
:
class
ThreadingTestCases
:
"""Testcases for thread-safety of FS implementations."""
"""Testcases for thread-safety of FS implementations."""
...
...
fs/wrapfs/__init__.py
View file @
44dcc3bf
...
@@ -181,7 +181,7 @@ class WrapFS(FS):
...
@@ -181,7 +181,7 @@ class WrapFS(FS):
@rewrite_errors
@rewrite_errors
def
settimes
(
self
,
path
,
*
args
,
**
kwds
):
def
settimes
(
self
,
path
,
*
args
,
**
kwds
):
return
self
.
wrapped_fs
.
settimes
(
*
args
,
**
kwds
)
return
self
.
wrapped_fs
.
settimes
(
self
.
_encode
(
path
),
*
args
,
**
kwds
)
@rewrite_errors
@rewrite_errors
def
desc
(
self
,
path
):
def
desc
(
self
,
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