New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
experimental api refresh #248
Changes from 11 commits
a27a9e9
ee8e819
890ad7b
1de2cbd
ab636e7
0862089
fb1f734
4e86de2
932f599
9ca0cf8
57b514b
52b8dc8
5b4ce71
53737ab
699c343
5b51550
061d7f1
5476ac5
309d61e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,8 @@ | |
import time | ||
import typing | ||
from contextlib import closing | ||
from functools import partial | ||
from functools import partial, wraps | ||
import warnings | ||
|
||
import six | ||
|
||
|
@@ -61,6 +62,22 @@ | |
__all__ = ["FS"] | ||
|
||
|
||
def _new_name(method, old_name): | ||
"""Return a method with a deprecation warning.""" | ||
# Looks suspiciously like a decorator, but isn't! | ||
@wraps(method) | ||
def _method(*args, **kwargs): | ||
warnings.warn( | ||
"method '{}' has been deprecated, please rename to '{}'".format( | ||
old_name, method.__name__ | ||
), | ||
DeprecationWarning, | ||
) | ||
return method(*args, **kwargs) | ||
|
||
return _method | ||
|
||
|
||
@six.add_metaclass(abc.ABCMeta) | ||
class FS(object): | ||
"""Base class for FS objects. | ||
|
@@ -346,7 +363,7 @@ def close(self): | |
|
||
Example: | ||
>>> with OSFS('~/Desktop') as desktop_fs: | ||
... desktop_fs.settext( | ||
... desktop_fs.writetext( | ||
... 'note.txt', | ||
... "Don't forget to tape Game of Thrones" | ||
... ) | ||
|
@@ -379,7 +396,7 @@ def copy(self, src_path, dst_path, overwrite=False): | |
raise errors.DestinationExists(dst_path) | ||
with closing(self.open(src_path, "rb")) as read_file: | ||
# FIXME(@althonos): typing complains because open return IO | ||
self.setbinfile(dst_path, read_file) # type: ignore | ||
self.upload(dst_path, read_file) # type: ignore | ||
|
||
def copydir(self, src_path, dst_path, create=False): | ||
# type: (Text, Text, bool) -> None | ||
|
@@ -550,7 +567,7 @@ def exclude_file(patterns, info): | |
iter_info = itertools.islice(iter_info, start, end) | ||
return iter_info | ||
|
||
def getbytes(self, path): | ||
def readbytes(self, path): | ||
# type: (Text) -> bytes | ||
"""Get the contents of a file as bytes. | ||
|
||
|
@@ -568,7 +585,9 @@ def getbytes(self, path): | |
contents = read_file.read() | ||
return contents | ||
|
||
def getfile(self, path, file, chunk_size=None, **options): | ||
getbytes = _new_name(readbytes, "getbytes") | ||
|
||
def download(self, path, file, chunk_size=None, **options): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
From a network filesystem |
||
# type: (Text, BinaryIO, Optional[int], **Any) -> None | ||
"""Copies a file from the filesystem to a file-like object. | ||
|
||
|
@@ -591,14 +610,16 @@ def getfile(self, path, file, chunk_size=None, **options): | |
|
||
Example: | ||
>>> with open('starwars.mov', 'wb') as write_file: | ||
... my_fs.getfile('/movies/starwars.mov', write_file) | ||
... my_fs.download('/movies/starwars.mov', write_file) | ||
|
||
""" | ||
with self._lock: | ||
with self.openbin(path, **options) as read_file: | ||
tools.copy_file_data(read_file, file, chunk_size=chunk_size) | ||
|
||
def gettext( | ||
getfile = _new_name(download, "getfile") | ||
|
||
def readtext( | ||
self, | ||
path, # type: Text | ||
encoding=None, # type: Optional[Text] | ||
|
@@ -630,6 +651,8 @@ def gettext( | |
contents = read_file.read() | ||
return contents | ||
|
||
gettext = _new_name(readtext, "gettext") | ||
|
||
def getmeta(self, namespace="standard"): | ||
# type: (Text) -> Mapping[Text, object] | ||
"""Get meta information regarding a filesystem. | ||
|
@@ -1074,7 +1097,7 @@ def move(self, src_path, dst_path, overwrite=False): | |
with self._lock: | ||
with self.open(src_path, "rb") as read_file: | ||
# FIXME(@althonos): typing complains because open return IO | ||
self.setbinfile(dst_path, read_file) # type: ignore | ||
self.upload(dst_path, read_file) # type: ignore | ||
self.remove(src_path) | ||
|
||
def open( | ||
|
@@ -1226,7 +1249,7 @@ def scandir( | |
iter_info = itertools.islice(iter_info, start, end) | ||
return iter_info | ||
|
||
def setbytes(self, path, contents): | ||
def writebytes(self, path, contents): | ||
# type: (Text, bytes) -> None | ||
# FIXME(@althonos): accept bytearray and memoryview as well ? | ||
"""Copy binary data to a file. | ||
|
@@ -1244,7 +1267,9 @@ def setbytes(self, path, contents): | |
with closing(self.open(path, mode="wb")) as write_file: | ||
write_file.write(contents) | ||
|
||
def setbinfile(self, path, file): | ||
setbytes = _new_name(writebytes, "setbytes") | ||
|
||
def upload(self, path, file): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Like |
||
# type: (Text, BinaryIO) -> None | ||
"""Set a file to the contents of a binary file object. | ||
|
||
|
@@ -1263,14 +1288,16 @@ def setbinfile(self, path, file): | |
|
||
Example: | ||
>>> with open('myfile.bin') as read_file: | ||
... my_fs.setbinfile('myfile.bin', read_file) | ||
... my_fs.upload('myfile.bin', read_file) | ||
|
||
""" | ||
with self._lock: | ||
with self.open(path, "wb") as dst_file: | ||
tools.copy_file_data(file, dst_file) | ||
|
||
def setfile( | ||
setbinfile = _new_name(upload, "setbinfile") | ||
|
||
def writefile( | ||
self, | ||
path, # type: Text | ||
file, # type: IO | ||
|
@@ -1303,7 +1330,7 @@ def setfile( | |
|
||
Example: | ||
>>> with open('myfile.bin') as read_file: | ||
... my_fs.setfile('myfile.bin', read_file) | ||
... my_fs.writefile('myfile.bin', read_file) | ||
|
||
""" | ||
mode = "wb" if encoding is None else "wt" | ||
|
@@ -1340,7 +1367,7 @@ def settimes(self, path, accessed=None, modified=None): | |
|
||
self.setinfo(path, raw_info) | ||
|
||
def settext( | ||
def writetext( | ||
self, | ||
path, # type: Text | ||
contents, # type: Text | ||
|
@@ -1373,6 +1400,8 @@ def settext( | |
) as write_file: | ||
write_file.write(contents) | ||
|
||
settext = _new_name(writetext, "settext") | ||
|
||
def touch(self, path): | ||
# type: (Text) -> None | ||
"""Touch a file on the filesystem. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -552,9 +552,7 @@ def _parse_mlsx(cls, lines): | |
raw_info["basic"] = {"name": name, "is_dir": is_dir} | ||
raw_info["ftp"] = facts # type: ignore | ||
raw_info["details"] = { | ||
"type": ( | ||
int(ResourceType.directory if is_dir else ResourceType.file) | ||
) | ||
"type": (int(ResourceType.directory if is_dir else ResourceType.file)) | ||
} | ||
|
||
details = raw_info["details"] | ||
|
@@ -703,9 +701,7 @@ def removedir(self, path): | |
raise # pragma: no cover | ||
|
||
def _scandir( | ||
self, | ||
path, # type: Text | ||
namespaces=None # type: Optional[Container[Text]] | ||
self, path, namespaces=None # type: Text # type: Optional[Container[Text]] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Black broke mymy comments. Todo |
||
): | ||
# type: (...) -> Iterator[Info] | ||
_path = self.validatepath(path) | ||
|
@@ -745,7 +741,7 @@ def scandir( | |
iter_info = itertools.islice(iter_info, start, end) | ||
return iter_info | ||
|
||
def setbinfile(self, path, file): | ||
def upload(self, path, file): | ||
# type: (Text, BinaryIO) -> None | ||
_path = self.validatepath(path) | ||
with self._lock: | ||
|
@@ -755,18 +751,18 @@ def setbinfile(self, path, file): | |
str("STOR ") + _encode(_path, self.ftp.encoding), file | ||
) | ||
|
||
def setbytes(self, path, contents): | ||
def writebytes(self, path, contents): | ||
# type: (Text, ByteString) -> None | ||
if not isinstance(contents, bytes): | ||
raise TypeError("contents must be bytes") | ||
self.setbinfile(path, io.BytesIO(contents)) | ||
self.upload(path, io.BytesIO(contents)) | ||
|
||
def setinfo(self, path, info): | ||
# type: (Text, RawInfo) -> None | ||
if not self.exists(path): | ||
raise errors.ResourceNotFound(path) | ||
|
||
def getbytes(self, path): | ||
def readbytes(self, path): | ||
# type: (Text) -> bytes | ||
_path = self.validatepath(path) | ||
data = io.BytesIO() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think read/write is more intuitive that get/set in filesystem parlance. Although, writing to a file doesn't necessarily imply truncating it first. I'm hoping that the fact there is
appendbytes
and friends makes it clear what this does.