launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #29657
[Merge] ~cjwatson/txpkgupload:remove-zope.server into txpkgupload:master
Colin Watson has proposed merging ~cjwatson/txpkgupload:remove-zope.server into txpkgupload:master.
Commit message:
Remove dependencies on zope.{component,security,server}
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/txpkgupload/+git/txpkgupload/+merge/437107
Once upon a time, the code in Launchpad that grew into txpkgupload relied on the FTP server in `zope.server`. That was replaced by a dependency on Twisted in 2011 or so, but we retained a vestigial dependency on `zope.server` and a good deal of leftover support code in `UploadFileSystem` that's no longer called by anything. Get rid of all this.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/txpkgupload:remove-zope.server into txpkgupload:master.
diff --git a/requirements.txt b/requirements.txt
index ab7562f..b2cf037 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -35,7 +35,6 @@ pycparser==2.18
PyHamcrest==1.10.1
PyNaCl==1.3.0
python-dateutil==2.8.1
-python-gettext==4.0
python-mimeparse==0.1.4
pytz==2017.2
PyYAML==3.10
@@ -47,21 +46,10 @@ Twisted[conch]==20.3.0+lp8
unittest2==1.1.0+lp1
wadllib==1.3.2
zipp==1.2.0
-zope.browser==2.3
zope.component==4.6.1
-zope.configuration==4.4.0
-zope.contenttype==4.5.0
zope.deferredimport==4.3.1
zope.deprecation==4.4.0
zope.event==4.4
-zope.exceptions==4.3
zope.hookable==5.0.1
-zope.i18n==4.7.0
-zope.i18nmessageid==5.0.1
zope.interface==5.0.2
-zope.location==4.2
zope.proxy==4.3.5
-zope.publisher==5.2.0
-zope.schema==6.0.0
-zope.security==5.1.1
-zope.server==4.0.2
diff --git a/setup.py b/setup.py
index 246ba61..fc284de 100755
--- a/setup.py
+++ b/setup.py
@@ -61,10 +61,7 @@ setup(
'setuptools',
'six>=1.12.0',
'Twisted[conch_nacl]',
- 'zope.component',
'zope.interface>=3.6.0',
- 'zope.security',
- 'zope.server',
],
url='https://launchpad.net/txpkgupload',
download_url='https://launchpad.net/txpkgupload/+download',
diff --git a/src/txpkgupload/NEWS.txt b/src/txpkgupload/NEWS.txt
index c1fa967..59d1713 100644
--- a/src/txpkgupload/NEWS.txt
+++ b/src/txpkgupload/NEWS.txt
@@ -9,6 +9,8 @@ NEWS for txpkgupload
- Adjust directory creation to work around a change in ``os.makedirs`` in
Python 3.7.
- Add Python 3.8 support.
+- Remove dependencies on ``zope.component``, ``zope.security``, and
+ ``zope.server``.
0.4 (2021-01-04)
================
diff --git a/src/txpkgupload/filesystem.py b/src/txpkgupload/filesystem.py
index a598184..9a913e0 100644
--- a/src/txpkgupload/filesystem.py
+++ b/src/txpkgupload/filesystem.py
@@ -6,16 +6,9 @@ __all__ = [
'UploadFileSystem',
]
-import datetime
import os
-import stat
-from zope.interface import implementer
-from zope.security.interfaces import Unauthorized
-from zope.server.interfaces.ftp import IFileSystem
-
-@implementer(IFileSystem)
class UploadFileSystem:
def __init__(self, rootpath):
@@ -30,10 +23,8 @@ class UploadFileSystem:
def _sanitize(self, path):
if isinstance(path, bytes):
- # zope.server's FTP implementation seems to decode all commands
- # (including the paths they contain) to text using UTF-8,
- # effectively assuming the recommendation in RFC 2640 except
- # without the feature negotiation part. However, Twisted's SFTP
+ # RFC 2640 recommends that paths are exchanged using UTF-8,
+ # albeit with some feature negotiation. However, Twisted's SFTP
# implementation leaves paths as bytes. Since in practice
# legitimate uses of txpkgupload will only involve ASCII paths,
# and since UTF-8 has low risk of undetected decoding errors,
@@ -47,98 +38,6 @@ class UploadFileSystem:
path = os.path.normpath(path)
return path
- def type(self, path):
- """Return the file type at path
-
- The 'type' command returns 'f' for a file, 'd' for a directory and
- None if there is no file.
- """
- path = self._sanitize(path)
- full_path = self._full(path)
- if os.path.exists(full_path):
- if os.path.isdir(full_path):
- return 'd'
- elif os.path.isfile(full_path):
- return 'f'
-
- def names(self, path, filter=None):
- """Return a sequence of the names in a directory
-
- If the filter is not None, include only those names for which
- the filter returns a true value.
- """
- path = self._sanitize(path)
- full_path = self._full(path)
- if not os.path.exists(full_path):
- raise OSError("Not exists:", path)
- filenames = os.listdir(os.path.join(self.rootpath, path))
- files = []
- for filename in filenames:
- if not filter or filter(filename):
- files.append(filename)
- return files
-
- def ls(self, path, filter=None):
- """Return a sequence of information objects.
-
- It considers the names in the given path (returned self.name())
- and builds file information using self.lsinfo().
- """
- return [self.lsinfo(name) for name in self.names(path, filter)]
-
- def readfile(self, path, outstream, start=0, end=None):
- """Outputs the file at path to a stream.
-
- Not allowed - see filesystem.txt.
- """
- raise Unauthorized
-
- def lsinfo(self, path):
- """Return information for a unix-style ls listing for the path
-
- See zope3's interfaces/ftp.py:IFileSystem for details of the
- dictionary's content.
- """
- path = self._sanitize(path)
- full_path = self._full(path)
- if not os.path.exists(full_path):
- raise OSError("Not exists:", path)
-
- info = {"owner_name": "upload",
- "group_name": "upload",
- "name": path.split("/")[-1]}
-
- s = os.stat(full_path)
-
- info["owner_readable"] = bool(s.st_mode & stat.S_IRUSR)
- info["owner_writable"] = bool(s.st_mode & stat.S_IWUSR)
- info["owner_executable"] = bool(s.st_mode & stat.S_IXUSR)
- info["group_readable"] = bool(s.st_mode & stat.S_IRGRP)
- info["group_writable"] = bool(s.st_mode & stat.S_IWGRP)
- info["group_executable"] = bool(s.st_mode & stat.S_IXGRP)
- info["other_readable"] = bool(s.st_mode & stat.S_IROTH)
- info["other_writable"] = bool(s.st_mode & stat.S_IWOTH)
- info["other_executable"] = bool(s.st_mode & stat.S_IXOTH)
- info["mtime"] = datetime.datetime.fromtimestamp(self.mtime(path))
- info["size"] = self.size(path)
- info["type"] = self.type(path)
- info["nlinks"] = s.st_nlink
- return info
-
- def mtime(self, path):
- """Return the modification time for the file"""
- path = self._sanitize(path)
- full_path = self._full(path)
- if os.path.exists(full_path):
- return os.path.getmtime(full_path)
-
- def size(self, path):
- """Return the size of the file at path"""
- path = self._sanitize(path)
- full_path = self._full(path)
- if os.path.exists(full_path):
- return os.path.getsize(full_path)
-
def mkdir(self, path):
"""Create a directory."""
path = self._sanitize(path)
@@ -156,18 +55,6 @@ class UploadFileSystem:
finally:
os.umask(old_mask)
- def remove(self, path):
- """Remove a file."""
- path = self._sanitize(path)
- full_path = self._full(path)
- if os.path.exists(full_path):
- if os.path.isfile(full_path):
- os.unlink(full_path)
- elif os.path.isdir(full_path):
- raise OSError("Is a directory:", path)
- else:
- raise OSError("Not exists:", path)
-
def rmdir(self, path):
"""Remove a directory.
@@ -179,81 +66,3 @@ class UploadFileSystem:
os.rmdir(full_path)
else:
raise OSError("Not exists:", path)
-
- def rename(self, old, new):
- """Rename a file."""
- old = self._sanitize(old)
- new = self._sanitize(new)
- full_old = self._full(old)
- full_new = self._full(new)
-
- if os.path.isdir(full_new):
- raise OSError("Is a directory:", new)
-
- if os.path.exists(full_old):
- if os.path.isfile(full_old):
- os.rename(full_old, full_new)
- elif os.path.isdir(full_old):
- raise OSError("Is a directory:", old)
- else:
- raise OSError("Not exists:", old)
-
- def writefile(self, path, instream, start=None, end=None, append=False):
- """Write data to a file.
-
- See zope3's interfaces/ftp.py:IFileSystem for details of the
- handling of the various arguments.
- """
- path = self._sanitize(path)
- full_path = self._full(path)
- if os.path.exists(full_path):
- if os.path.isdir(full_path):
- raise OSError("Is a directory:", path)
- else:
- dirname = os.path.dirname(full_path)
- if dirname:
- if not os.path.exists(dirname):
- old_mask = os.umask(0o002)
- try:
- os.makedirs(dirname)
- finally:
- os.umask(old_mask)
-
- if start and start < 0:
- raise ValueError("Negative start argument:", start)
- if end and end < 0:
- raise ValueError("Negative end argument:", end)
- if start and end and end <= start:
- return
- if append:
- open_flag = 'ab'
- elif start or end:
- open_flag = "r+b"
- if not os.path.exists(full_path):
- with open(full_path, 'wb'):
- pass
-
- else:
- open_flag = 'wb'
- with open(full_path, open_flag) as outstream:
- if start:
- outstream.seek(start)
- chunk = instream.read()
- while chunk:
- outstream.write(chunk)
- chunk = instream.read()
- if not end:
- outstream.truncate()
- instream.close()
-
- def writable(self, path):
- """Return boolean indicating whether a file at path is writable."""
- path = self._sanitize(path)
- full_path = self._full(path)
- if os.path.exists(full_path):
- if os.path.isfile(full_path):
- return True
- elif os.path.isdir(full_path):
- return False
- else:
- return True
diff --git a/src/txpkgupload/tests/filesystem.txt b/src/txpkgupload/tests/filesystem.txt
index 20b80d9..2dcd81c 100644
--- a/src/txpkgupload/tests/filesystem.txt
+++ b/src/txpkgupload/tests/filesystem.txt
@@ -1,15 +1,8 @@
-
-This is an implementation of IFileSystem which the FTP Server in Zope3
-uses to know what to do when people make FTP commands.
+`UploadFileSystem` provides logic for the few limited interactions with the
+part of the file system we expose over FTP/SFTP.
>>> from txpkgupload.filesystem import UploadFileSystem
-The UploadFileSystem class implements the interface IFileSystem.
-
- >>> from zope.server.interfaces.ftp import IFileSystem
- >>> IFileSystem.implementedBy(UploadFileSystem)
- True
-
First we need to setup our test environment.
>>> import os
@@ -38,12 +31,6 @@ to use.
>>> ufs = UploadFileSystem(rootpath)
-An UploadFileSystem object provides the interface IFileSystem.
-
- >>> from zope.interface.verify import verifyObject
- >>> verifyObject(IFileSystem, ufs)
- True
-
mkdir
=====
@@ -88,434 +75,13 @@ Check if it works as expected after the directory creation:
>>> os.path.exists(os.path.join(rootpath, "new-dir"))
False
-
-lsinfo
-======
-
-Return information for a unix-style ls listing for the path.
-
-See zope3's interfaces/ftp.py:IFileSystem for details of the
-dictionary's content.
-
-Setup a default dictionary used for generating the dictionaries we
-expect lsinfo to return.
-
- >>> def clean_mtime(stat_info):
- ... """Return a datetime from an mtime, sans microseconds."""
- ... mtime = stat_info.st_mtime
- ... datestamp = datetime.datetime.fromtimestamp(mtime)
- ... datestamp.replace(microsecond=0)
- ... return datestamp
-
- >>> import copy
- >>> import datetime
- >>> import stat
- >>> def_exp = {"type": 'f',
- ... "owner_name": "upload",
- ... "owner_readable": True,
- ... "owner_writable": True,
- ... "owner_executable": False,
- ... "group_name": "upload",
- ... "group_readable": True,
- ... "group_writable": False,
- ... "group_executable": False,
- ... "other_readable": True,
- ... "other_writable": False,
- ... "other_executable": False,
- ... "nlinks": 1}
- ...
-
- >>> os.chmod(full_testfile, stat.S_IRUSR | stat.S_IWUSR | \
- ... stat.S_IRGRP | stat.S_IROTH)
- >>> exp = copy.copy(def_exp)
- >>> s = os.stat(full_testfile)
- >>> exp["name"] = testfile
- >>> exp["mtime"] = clean_mtime(s)
- >>> exp["size"] = s[stat.ST_SIZE]
- >>> info = ufs.lsinfo(testfile)
- >>> info == exp
- True
-
-ls
-==
-
-`ls` a sequence of item info objects (see ls_info) for the files in a
-directory.
-
- >>> expected = [exp]
- >>> for i in [ "foo", "bar" ]:
- ... filename = os.path.join(rootpath, i)
- ... with open(filename, 'w'):
- ... pass
- ... os.chmod(filename, stat.S_IRUSR | stat.S_IWUSR | \
- ... stat.S_IRGRP | stat.S_IROTH)
- ... exp = copy.copy(def_exp)
- ... s = os.stat(filename)
- ... exp["name"] = i
- ... exp["mtime"] = clean_mtime(s)
- ... exp["size"] = s[stat.ST_SIZE]
- ... expected.append(exp)
- ...
-
- >>> dir_exp = copy.copy(def_exp)
- >>> s = os.stat(full_testdir)
- >>> dir_exp["type"] = "d"
- >>> dir_exp["name"] = testdir
- >>> dir_exp["mtime"] = clean_mtime(s)
- >>> dir_exp["size"] = s[stat.ST_SIZE]
- >>> dir_exp["nlinks"] = s[stat.ST_NLINK]
- >>> dir_exp["owner_executable"] = True
- >>> dir_exp["other_executable"] = True
- >>> dir_exp["group_executable"] = True
- >>> expected.append(dir_exp)
-
-We need a helper function to turn the returned and expected data into reliably
-sorted orders for comparison.
-
- >>> from operator import itemgetter
- >>> def sorted_listings(ls_infos):
- ... # ls_infos will be a sequence of dictionaries. They need to be
- ... # sorted for the sequences to compare equal, so do that on the
- ... # dictionary's 'name' key. The equality test used here
- ... # doesn't care about the sort order of the dictionaries.
- ... return sorted(ls_infos, key=itemgetter('name'))
-
- >>> returned = ufs.ls(".")
- >>> sorted_listings(expected) == sorted_listings(returned)
- True
-
-If `filter` is not None, include only those names for which `filter`
-returns a true value.
-
- >>> def always_false_filter(name):
- ... return False
- >>> def always_true_filter(name):
- ... return True
- >>> def arbitrary_filter(name):
- ... if name == "foo" or name == "baz":
- ... return True
- ... else:
- ... return False
- ...
- >>> for i in expected:
- ... if i["name"] == "foo":
- ... filtered_expected = [i];
- >>> returned = ufs.ls(".", always_true_filter)
- >>> sorted_listings(expected) == sorted_listings(returned)
- True
- >>> returned = ufs.ls(".", always_false_filter)
- >>> returned == []
- True
- >>> returned = ufs.ls(".", arbitrary_filter)
- >>> sorted_listings(filtered_expected) == sorted_listings(returned)
- True
- >>> for i in [ "foo", "bar" ]:
- ... ufs.remove(i)
- ...
-
-readfile
-========
-
-We are not implementing `readfile` as a precautionary measure, i.e. in
-case anyone bypasses the per-session separate directories they still
-aren't able to read any other files and therefore can't abuse the
-server for warez/child porn etc.
-
-Unlike `mkdir` and `rmdir` we will raise an exception so that the
-server returns an error to the client and the client does not receive
-bogus or empty data.
-
- >>> ufs.readfile(testfile, None)
- ... # doctest: +IGNORE_EXCEPTION_DETAIL
- Traceback (most recent call last):
- ...
- Unauthorized
-
-The 'type' command returns 'f' for a file, 'd' for a directory and
-None if there is no file.
-
- >>> ufs.type(testfile)
- 'f'
-
- >>> ufs.type(testdir)
- 'd'
-
- >>> ufs.type("does-not-exist") is None
- True
-
-size
-====
-
-The 'size' command returns the size of the file. If the file does not
-exist None is returned.
-
- >>> ufs.size("does-not-exist") is None
- True
-
- >>> ufs.size(testfile) == os.path.getsize(full_testfile)
- True
-
- >>> ufs.size(testdir) == os.path.getsize(full_testdir)
- True
-
-mtime
-=====
-
-The 'mtime' command returns the mtime of the file. If the file does not
-exist None is returned.
-
- >>> ufs.size("does-not-exist") is None
- True
-
- >>> ufs.mtime(testfile) == os.path.getmtime(full_testfile)
- True
-
- >>> ufs.mtime(testdir) == os.path.getmtime(full_testdir)
- True
-
-remove
-======
-
-The 'remove' command removes a file. An exception is raised if the
-file does not exist or is a directory.
-
- >>> ufs.remove("does-not-exist")
- Traceback (most recent call last):
- ...
- OSError: [Errno Not exists:] does-not-exist
-
- >>> ufs.remove(testfile)
- >>> os.path.exists(full_testfile)
- False
- >>> with open(full_testfile, 'wb') as f:
- ... _ = f.write(b"contents of the file")
-
- >>> ufs.remove(testdir)
- Traceback (most recent call last):
- ...
- OSError: [Errno Is a directory:] testdir
-
-rename
-======
-
-The 'rename' command renames a file. An exception is raised if the
-old filename doesn't exist or if the old or new filename is a
-directory.
-
- >>> new_testfile = "baz"
- >>> new_full_testfile = os.path.join(rootpath, new_testfile)
-
- >>> ufs.rename("does-not-exist", new_testfile)
- Traceback (most recent call last):
- ...
- OSError: [Errno Not exists:] does-not-exist
-
- >>> new_testfile = "baz"
- >>> new_full_testfile = os.path.join(rootpath, new_testfile)
- >>> ufs.rename(testfile, new_testfile)
- >>> os.path.exists(full_testfile)
- False
- >>> os.path.exists(new_full_testfile)
- True
- >>> with open(new_full_testfile, "rb") as f:
- ... f.read() == testfile_contents
- True
- >>> ufs.rename(new_testfile, testfile)
-
- >>> ufs.rename(testdir, new_testfile)
- Traceback (most recent call last):
- ...
- OSError: [Errno Is a directory:] testdir
-
- >>> ufs.rename(testfile, testdir)
- Traceback (most recent call last):
- ...
- OSError: [Errno Is a directory:] testdir
-
-names
-=====
-
-The `names` command returns a sequence of the names in the `path`.
-
- >>> for name in sorted(ufs.names(".")):
- ... print(name)
- testdir
- testfile
-
-`path` is normalized before used.
-
- >>> for name in sorted(ufs.names("some-directory/..")):
- ... print(name)
- testdir
- testfile
-
-'path' under the server root is not allowed:
-
- >>> ufs.names("..")
- Traceback (most recent call last):
- ...
- OSError: [Errno Path not allowed:] ..
-
-
-If the `filter` argument is provided, each name is only returned if
-the given `filter` function returns True for it.
-
- >>> ufs.names(".", always_false_filter)
- []
-
- >>> for name in sorted(ufs.names(".", always_true_filter)):
- ... print(name)
- testdir
- testfile
-
- >>> for i in [ "foo", "bar", "baz", "bat" ]:
- ... with open(os.path.join(rootpath, i), 'w'):
- ... pass
- >>> names = ufs.names(".", arbitrary_filter)
- >>> names.sort()
- >>> names == ['baz', 'foo']
- True
- >>> for i in [ "foo", "bar", "baz", "bat" ]:
- ... os.unlink(os.path.join(rootpath, i))
-
-writefile
-=========
-
-`writefile` writes data to a file.
-
- >>> import io
- >>> ufs.writefile("upload", io.BytesIO(propaganda))
- >>> with open(os.path.join(rootpath, "upload"), "rb") as f:
- ... f.read() == propaganda
- True
- >>> ufs.remove("upload")
-
-If neither `start` nor `end` are specified, then the file contents
-are overwritten.
-
- >>> ufs.writefile(testfile, io.BytesIO(b"MOO"))
- >>> with open(full_testfile, "rb") as f:
- ... f.read() == b"MOO"
- True
- >>> ufs.writefile(testfile, io.BytesIO(testfile_contents))
-
-If `start` or `end` are specified, they must be non-negative.
-
- >>> ufs.writefile("upload", io.BytesIO(propaganda), -37)
- Traceback (most recent call last):
- ...
- ValueError: ('Negative start argument:', -37)
-
- >>> ufs.writefile("upload", io.BytesIO(propaganda), 1, -43)
- Traceback (most recent call last):
- ...
- ValueError: ('Negative end argument:', -43)
-
-If `start` or `end` is not None, then only part of the file is
-written. The remainder of the file is unchanged.
-
- >>> ufs.writefile(testfile, io.BytesIO(b"MOO"), 9, 12)
- >>> with open(full_testfile, "rb") as f:
- ... f.read() == b"contents MOOthe file"
- True
- >>> ufs.writefile(testfile, io.BytesIO(testfile_contents))
-
-If `end` is None, then the file is truncated after the data are
-written.
-
- >>> ufs.writefile(testfile, io.BytesIO(b"MOO"), 9)
- >>> with open(full_testfile, "rb") as f:
- ... f.read() == b"contents MOO"
- True
- >>> ufs.writefile(testfile, io.BytesIO(testfile_contents))
-
-If `start` is specified and the file doesn't exist or is shorter
-than start, the file will contain undefined data before start.
-
- >>> ufs.writefile("didnt-exist", io.BytesIO(b"MOO"), 9)
- >>> with open(os.path.join(rootpath, "didnt-exist"), "rb") as f:
- ... f.read() == b"\x00\x00\x00\x00\x00\x00\x00\x00\x00MOO"
- True
- >>> ufs.remove("didnt-exist")
-
-If `end` is not None and there isn't enough data in `instream` to fill
-out the file, then the missing data is undefined.
-
- >>> ufs.writefile(testfile, io.BytesIO(b"MOO"), 9, 15)
- >>> with open(full_testfile, "rb") as f:
- ... f.read() == b"contents MOOthe file"
- True
- >>> ufs.writefile(testfile, io.BytesIO(testfile_contents))
-
-If `end` is less than or the same as `start no data is writen to the file.
-
- >>> ufs.writefile(testfile, io.BytesIO(b"MOO"), 9, 4)
- >>> with open(full_testfile, "rb") as f:
- ... f.read() == b"contents of the file"
- True
-
- >>> ufs.writefile(testfile, io.BytesIO(b"MOO"), 9, 9)
- >>> with open(full_testfile, "rb") as f:
- ... f.read() == b"contents of the file"
- True
-
-If `append` is true the file is appended to rather than being
-overwritten.
-
- >>> ufs.writefile(testfile, io.BytesIO(b"MOO"), append=True)
- >>> with open(full_testfile, "rb") as f:
- ... f.read() == b"contents of the fileMOO"
- True
- >>> ufs.writefile(testfile, io.BytesIO(testfile_contents))
-
-Additionally, if `append` is true, `start` and `end` are ignored.
-
- >>> ufs.writefile(testfile, io.BytesIO(b"MOO"), 10, 13, append=True)
- >>> with open(full_testfile, "rb") as f:
- ... f.read() == b"contents of the fileMOO"
- True
- >>> ufs.writefile(testfile, io.BytesIO(testfile_contents))
-
-'writefile' is able to create inexistent directories in a requested
-path:
-
- >>> os.path.exists(os.path.join(rootpath, "foo"))
- False
- >>> ufs.writefile("foo/bar", io.BytesIO(b"fake"))
- >>> os.path.exists(os.path.join(rootpath, "foo/bar"))
- True
- >>> with open(os.path.join(rootpath, "foo/bar"), "rb") as f:
- ... f.read() == b"fake"
- True
-
-
-writable
-========
-
-`writable` returns a boolean indicating whether `path` is writable or
-not.
-
- >>> ufs.writable(testfile)
- True
-
-`writable` returns True if `path` is a non-existent file.
-
- >>> ufs.writable("does-not-exist")
- True
-
-`writable` returns False if `path` is a directory as we don't allow
-the creation of sub-directories.
-
- >>> ufs.writable(testdir)
- False
-
path checking
=============
`path` arguments must be normalized.
- >>> ufs.type(os.path.join("non-existent-dir", "..", testfile))
- 'f'
+ >>> ufs._sanitize(os.path.join("non-existent-dir", "..", testfile))
+ 'testfile'
Cleanup the server root:
@@ -528,84 +94,8 @@ Cleanup the server root:
... os.remove(full_path)
-Dealing with inexistent path:
-
- >>> ufs.type("foo/bar") is None
- True
- >>> ufs.mtime("foo/bar") is None
- True
- >>> ufs.size("foo/bar") is None
- True
- >>> ufs.writable("foo/bar")
- True
- >>> ufs.names("foo/bar")
- Traceback (most recent call last):
- ...
- OSError: [Errno Not exists:] foo/bar
- >>> ufs.ls("foo/bar")
- Traceback (most recent call last):
- ...
- OSError: [Errno Not exists:] foo/bar
- >>> ufs.lsinfo("foo/bar")
- Traceback (most recent call last):
- ...
- OSError: [Errno Not exists:] foo/bar
- >>> ufs.remove("foo/bar")
- Traceback (most recent call last):
- ...
- OSError: [Errno Not exists:] foo/bar
- >>> ufs.rename("foo/bar", "baz")
- Traceback (most recent call last):
- ...
- OSError: [Errno Not exists:] foo/bar
- >>> ufs.rename("baz", "foo/bar")
- Traceback (most recent call last):
- ...
- OSError: [Errno Not exists:] baz
-
-
Dealing with paths outside the server root directory:
- >>> ufs.type("..")
- Traceback (most recent call last):
- ...
- OSError: [Errno Path not allowed:] ..
- >>> ufs.mtime("..")
- Traceback (most recent call last):
- ...
- OSError: [Errno Path not allowed:] ..
- >>> ufs.size("..")
- Traceback (most recent call last):
- ...
- OSError: [Errno Path not allowed:] ..
- >>> ufs.writable("..")
- Traceback (most recent call last):
- ...
- OSError: [Errno Path not allowed:] ..
- >>> ufs.names("..")
- Traceback (most recent call last):
- ...
- OSError: [Errno Path not allowed:] ..
- >>> ufs.ls("..")
- Traceback (most recent call last):
- ...
- OSError: [Errno Path not allowed:] ..
- >>> ufs.lsinfo("..")
- Traceback (most recent call last):
- ...
- OSError: [Errno Path not allowed:] ..
- >>> ufs.remove("..")
- Traceback (most recent call last):
- ...
- OSError: [Errno Path not allowed:] ..
- >>> ufs.rename("..", "baz")
- Traceback (most recent call last):
- ...
- OSError: [Errno Path not allowed:] ..
- >>> ufs.rename("baz", "..")
- Traceback (most recent call last):
- ...
- OSError: [Errno Path not allowed:] ..
>>> ufs.mkdir("..")
Traceback (most recent call last):
...
@@ -621,4 +111,3 @@ Dealing with paths outside the server root directory:
Finally, cleanup after ourselves.
>>> shutil.rmtree(rootpath)
-