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
bc30657b
Commit
bc30657b
authored
Nov 24, 2012
by
willmcgugan@gmail.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixes for backslashes on Linux issue, see Issue #139
parent
2fbb136c
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
50 additions
and
27 deletions
+50
-27
fs/commands/runner.py
+0
-0
fs/errors.py
+5
-0
fs/osfs/__init__.py
+14
-15
fs/path.py
+28
-9
fs/tests/test_path.py
+3
-3
No files found.
fs/commands/runner.py
View file @
bc30657b
fs/errors.py
View file @
bc30657b
...
...
@@ -42,6 +42,10 @@ from fs.path import *
from
fs.local_functools
import
wraps
class
InvalidPathError
(
Exception
):
pass
class
FSError
(
Exception
):
"""Base exception class for the FS module."""
default_message
=
"Unspecified error"
...
...
@@ -184,6 +188,7 @@ class ResourceLockedError(ResourceError):
"""Exception raised when a resource can't be used because it is locked."""
default_message
=
"Resource is locked:
%(path)
s"
class
NoMMapError
(
ResourceError
):
"""Exception raise when getmmap fails to create a mmap"""
default_message
=
"Can't get mmap for
%(path)
s"
...
...
fs/osfs/__init__.py
View file @
bc30657b
...
...
@@ -35,10 +35,12 @@ def _os_stat(path):
"""Replacement for os.stat that raises FSError subclasses."""
return
os
.
stat
(
path
)
@convert_os_errors
def
_os_mkdir
(
name
,
mode
=
0777
):
"""Replacement for os.mkdir that raises FSError subclasses."""
return
os
.
mkdir
(
name
,
mode
)
return
os
.
mkdir
(
name
,
mode
)
@convert_os_errors
def
_os_makedirs
(
name
,
mode
=
0777
):
...
...
@@ -66,7 +68,6 @@ def _os_makedirs(name, mode=0777):
os
.
mkdir
(
name
,
mode
)
class
OSFS
(
OSFSXAttrMixin
,
OSFSWatchMixin
,
FS
):
"""Expose the underlying operating-system filesystem as an FS object.
...
...
@@ -126,9 +127,9 @@ class OSFS(OSFSXAttrMixin, OSFSWatchMixin, FS):
pass
if
not
os
.
path
.
exists
(
root_path
):
raise
ResourceNotFoundError
(
root_path
,
msg
=
"Root directory does not exist:
%(path)
s"
)
raise
ResourceNotFoundError
(
root_path
,
msg
=
"Root directory does not exist:
%(path)
s"
)
if
not
os
.
path
.
isdir
(
root_path
):
raise
ResourceInvalidError
(
root_path
,
msg
=
"Root path is not a directory:
%(path)
s"
)
raise
ResourceInvalidError
(
root_path
,
msg
=
"Root path is not a directory:
%(path)
s"
)
self
.
root_path
=
root_path
self
.
dir_mode
=
dir_mode
...
...
@@ -147,10 +148,10 @@ class OSFS(OSFSXAttrMixin, OSFSWatchMixin, FS):
return
p
.
decode
(
self
.
encoding
,
'replace'
)
def
getsyspath
(
self
,
path
,
allow_none
=
False
):
path
=
relpath
(
normpath
(
path
))
.
replace
(
"/"
,
os
.
sep
)
path
=
relpath
(
normpath
(
path
))
.
replace
(
"/"
,
os
.
sep
)
path
=
os
.
path
.
join
(
self
.
root_path
,
path
)
if
not
path
.
startswith
(
self
.
root_path
):
raise
PathError
(
path
,
msg
=
"OSFS given path outside root:
%(path)
s"
)
raise
PathError
(
path
,
msg
=
"OSFS given path outside root:
%(path)
s"
)
path
=
self
.
_decode_path
(
path
)
return
path
...
...
@@ -173,7 +174,7 @@ class OSFS(OSFSXAttrMixin, OSFSWatchMixin, FS):
if
not
prefix
.
endswith
(
os
.
path
.
sep
):
prefix
+=
os
.
path
.
sep
if
not
os
.
path
.
normcase
(
path
)
.
startswith
(
prefix
):
raise
ValueError
(
"path not within this FS:
%
s (
%
s)"
%
(
os
.
path
.
normcase
(
path
),
prefix
))
raise
ValueError
(
"path not within this FS:
%
s (
%
s)"
%
(
os
.
path
.
normcase
(
path
),
prefix
))
return
normpath
(
path
[
len
(
self
.
root_path
):])
def
getmeta
(
self
,
meta_name
,
default
=
NoDefaultMeta
):
...
...
@@ -221,8 +222,8 @@ class OSFS(OSFSXAttrMixin, OSFSWatchMixin, FS):
raise
@convert_os_errors
def
setcontents
(
self
,
path
,
contents
,
chunk_size
=
64
*
1024
):
return
super
(
OSFS
,
self
)
.
setcontents
(
path
,
contents
,
chunk_size
)
def
setcontents
(
self
,
path
,
contents
,
chunk_size
=
64
*
1024
):
return
super
(
OSFS
,
self
)
.
setcontents
(
path
,
contents
,
chunk_size
)
@convert_os_errors
def
exists
(
self
,
path
):
...
...
@@ -252,9 +253,9 @@ class OSFS(OSFSXAttrMixin, OSFSWatchMixin, FS):
_os_mkdir
(
sys_path
,
self
.
dir_mode
)
except
DestinationExistsError
:
if
self
.
isfile
(
path
):
raise
ResourceInvalidError
(
path
,
msg
=
"Cannot create directory, there's already a file of that name:
%(path)
s"
)
raise
ResourceInvalidError
(
path
,
msg
=
"Cannot create directory, there's already a file of that name:
%(path)
s"
)
if
not
allow_recreate
:
raise
DestinationExistsError
(
path
,
msg
=
"Can not create a directory that already exists (try allow_recreate=True):
%(path)
s"
)
raise
DestinationExistsError
(
path
,
msg
=
"Can not create a directory that already exists (try allow_recreate=True):
%(path)
s"
)
except
ResourceNotFoundError
:
raise
ParentDirectoryMissingError
(
path
)
...
...
@@ -297,7 +298,7 @@ class OSFS(OSFSXAttrMixin, OSFSWatchMixin, FS):
if
recursive
:
try
:
if
dirname
(
path
)
not
in
(
''
,
'/'
):
self
.
removedir
(
dirname
(
path
),
recursive
=
True
)
self
.
removedir
(
dirname
(
path
),
recursive
=
True
)
except
DirectoryNotEmptyError
:
pass
...
...
@@ -322,7 +323,7 @@ class OSFS(OSFSXAttrMixin, OSFSWatchMixin, FS):
raise
ParentDirectoryMissingError
(
dst
)
raise
def
_stat
(
self
,
path
):
def
_stat
(
self
,
path
):
"""Stat the given path, normalising error codes."""
sys_path
=
self
.
getsyspath
(
path
)
try
:
...
...
@@ -350,5 +351,3 @@ class OSFS(OSFSXAttrMixin, OSFSWatchMixin, FS):
@convert_os_errors
def
getsize
(
self
,
path
):
return
self
.
_stat
(
path
)
.
st_size
fs/path.py
View file @
bc30657b
from
__future__
import
unicode_literals
"""
fs.path
=======
...
...
@@ -11,22 +13,23 @@ by forward slashes and with an optional leading slash).
"""
import
re
import
os
_requires_normalization
=
re
.
compile
(
r'/\.\.|\./|\.|//'
)
.
search
_requires_normalization
=
re
.
compile
(
r'/\.\.|\./|\.|//|\\'
)
.
search
def
normpath
(
path
):
"""Normalizes a path to be in the format expected by FS objects.
This function remove any leading or trailing slashes, collapses
duplicate slashes,
replaces backward with forward slashes, and generally
tries very hard to return a new path string
the canonical FS format.
duplicate slashes,
and generally tries very hard to return a new path
in
the canonical FS format.
If the path is invalid, ValueError will be raised.
:param path: path to normalize
:returns: a valid FS path
>>> normpath(r"foo
\\
bar
\\
baz")
'foo/bar/baz'
>>> normpath("/foo//bar/frob/../baz")
'/foo/bar/baz'
...
...
@@ -40,8 +43,6 @@ def normpath(path):
if
path
in
(
''
,
'/'
):
return
path
path
=
path
.
replace
(
'
\\
'
,
'/'
)
# An early out if there is no need to normalize this path
if
not
_requires_normalization
(
path
):
return
path
.
rstrip
(
'/'
)
...
...
@@ -66,6 +67,21 @@ def normpath(path):
return
'/'
.
join
(
components
)
if
os
.
sep
!=
'/'
:
def
ospath
(
path
):
"""Replace path separators in an OS path if required"""
return
path
.
replace
(
os
.
sep
,
'/'
)
else
:
def
ospath
(
path
):
"""Replace path separators in an OS path if required"""
return
path
def
normospath
(
path
):
"""Normalizes a path with os separators"""
return
normpath
(
ospath
)
def
iteratepath
(
path
,
numsplits
=
None
):
"""Iterate over the individual components of a path.
...
...
@@ -117,6 +133,7 @@ def isabs(path):
"""Return True if path is an absolute path."""
return
path
.
startswith
(
'/'
)
def
abspath
(
path
):
"""Convert the given path to an absolute path.
...
...
@@ -163,7 +180,7 @@ def pathjoin(*paths):
relpaths
=
[]
for
p
in
paths
:
if
p
:
if
p
[
0
]
in
'
\\
/'
:
if
p
[
0
]
==
'
/'
:
del
relpaths
[:]
absolute
=
True
relpaths
.
append
(
p
)
...
...
@@ -173,6 +190,7 @@ def pathjoin(*paths):
path
=
abspath
(
path
)
return
path
def
pathcombine
(
path1
,
path2
):
"""Joins two paths together.
...
...
@@ -185,6 +203,7 @@ def pathcombine(path1, path2):
"""
return
"
%
s/
%
s"
%
(
path1
.
rstrip
(
'/'
),
path2
.
lstrip
(
'/'
))
def
join
(
*
paths
):
"""Joins any number of paths together, returning a new path string.
...
...
fs/tests/test_path.py
View file @
bc30657b
...
...
@@ -14,7 +14,7 @@ class TestPathFunctions(unittest.TestCase):
"""Testcases for FS path functions."""
def
test_normpath
(
self
):
tests
=
[
(
"
\\
a
\\
b
\\
c"
,
"
/a/b/
c"
),
tests
=
[
(
"
\\
a
\\
b
\\
c"
,
"
\\
a
\\
b
\\
c"
),
(
"."
,
""
),
(
"./"
,
""
),
(
""
,
""
),
...
...
@@ -22,7 +22,7 @@ class TestPathFunctions(unittest.TestCase):
(
"a/b/c"
,
"a/b/c"
),
(
"a/b/../c/"
,
"a/c"
),
(
"/"
,
"/"
),
(
u"a/
\N{GREEK SMALL LETTER BETA}
\\
c"
,
u"a/
\N{GREEK SMALL LETTER BETA}
/c"
),
(
u"a/
\N{GREEK SMALL LETTER BETA}
/
c"
,
u"a/
\N{GREEK SMALL LETTER BETA}
/c"
),
]
for
path
,
result
in
tests
:
self
.
assertEqual
(
normpath
(
path
),
result
)
...
...
@@ -38,7 +38,7 @@ class TestPathFunctions(unittest.TestCase):
(
"a/b/c"
,
"../d"
,
"c"
,
"a/b/d/c"
),
(
"a/b/c"
,
"../d"
,
"/a"
,
"/a"
),
(
"aaa"
,
"bbb/ccc"
,
"aaa/bbb/ccc"
),
(
"aaa"
,
"bbb
\
ccc"
,
"aaa/bbb/
ccc"
),
(
"aaa"
,
"bbb
\
\
ccc"
,
"aaa/bbb
\\
ccc"
),
(
"aaa"
,
"bbb"
,
"ccc"
,
"/aaa"
,
"eee"
,
"/aaa/eee"
),
(
"a/b"
,
"./d"
,
"e"
,
"a/b/d/e"
),
(
"/"
,
"/"
,
"/"
),
...
...
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