Skip to content

Commit 3d56a46

Browse files
author
atollk
committed
Implemented changes proposed by code review.
1 parent 59627bd commit 3d56a46

File tree

7 files changed

+41
-36
lines changed

7 files changed

+41
-36
lines changed

fs/base.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import six
2323

2424
from . import copy, errors, fsencode, iotools, move, tools, walk, wildcard
25-
from .errors import Unsupported
2625
from .glob import BoundGlobber
2726
from .mode import validate_open_mode
2827
from .path import abspath, join, normpath
@@ -680,7 +679,7 @@ def readtext(
680679
gettext = _new_name(readtext, "gettext")
681680

682681
def getmodified(self, path):
683-
# type: (Text) -> datetime
682+
# type: (Text) -> Optional[datetime]
684683
"""Get the timestamp of the last modifying access of a resource.
685684
686685
Arguments:
@@ -694,15 +693,9 @@ def getmodified(self, path):
694693
it might only have limited accuracy.
695694
696695
"""
697-
timestamp = self.getinfo(path, ("details", "modified")).modified
698-
if timestamp is None:
699-
raise Unsupported(
700-
"Last modified time is not supported by the filesystem"
701-
+ "for the requested resource: "
702-
+ path
703-
)
704-
else:
705-
return timestamp
696+
if self.getmeta().get("supports_mtime", False):
697+
return self.getinfo(path, namespaces=["modified"]).modified
698+
return self.getinfo(path, namespaces=["details"]).modified
706699

707700
def getmeta(self, namespace="standard"):
708701
# type: (Text) -> Mapping[Text, object]

fs/ftpfs.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@
1313
import typing
1414
from collections import OrderedDict
1515
from contextlib import contextmanager
16-
from datetime import datetime
1716
from ftplib import FTP
1817

19-
from .time import epoch_to_datetime
2018

2119
try:
2220
from ftplib import FTP_TLS
@@ -587,18 +585,6 @@ def create(self, path, wipe=False):
587585
return True
588586
return False
589587

590-
def getmodified(self, path):
591-
# type: (Text) -> datetime
592-
if "MDTM" in self.features:
593-
with self._lock:
594-
with ftp_errors(self, path=path):
595-
cmd = "MDTM " + _encode(self.validatepath(path), self.ftp.encoding)
596-
response = self.ftp.sendcmd(cmd)
597-
time_num = self._parse_ftp_time(response.split()[1])
598-
if time_num is not None:
599-
return epoch_to_datetime(time_num)
600-
return super(FTPFS, self).getmodified(path)
601-
602588
@classmethod
603589
def _parse_ftp_time(cls, time_text):
604590
# type: (Text) -> Optional[int]
@@ -682,6 +668,18 @@ def getinfo(self, path, namespaces=None):
682668
}
683669
)
684670

671+
if "modified" in namespaces:
672+
if "basic" in namespaces or "details" in namespaces:
673+
raise ValueError(
674+
'Cannot use the "modified" namespace in combination with others.'
675+
)
676+
with self._lock:
677+
with ftp_errors(self, path=path):
678+
cmd = "MDTM " + _encode(self.validatepath(path), self.ftp.encoding)
679+
response = self.ftp.sendcmd(cmd)
680+
modified_info = {"modified": self._parse_ftp_time(response.split()[1])}
681+
return Info({"modified": modified_info})
682+
685683
if self.supports_mlst:
686684
with self._lock:
687685
with ftp_errors(self, path=path):

fs/info.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,12 @@ def modified(self):
317317
namespace is not in the Info.
318318
319319
"""
320-
self._require_namespace("details")
321-
_time = self._make_datetime(self.get("details", "modified"))
322-
return _time
320+
try:
321+
self._require_namespace("details")
322+
return self._make_datetime(self.get("details", "modified"))
323+
except MissingInfoNamespace:
324+
self._require_namespace("modified")
325+
return self._make_datetime(self.get("modified", "modified"))
323326

324327
@property
325328
def created(self):

fs/osfs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ def __init__(
144144
"network": False,
145145
"read_only": False,
146146
"supports_rename": True,
147-
"supports_mtime": True,
147+
"supports_mtime": False,
148148
"thread_safe": True,
149149
"unicode_paths": os.path.supports_unicode_filenames,
150150
"virtual": False,

tests/test_memoryfs.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ def test_close_mem_free(self):
6969

7070

7171
class TestMemoryFile(unittest.TestCase):
72-
7372
def setUp(self):
7473
self.fs = memoryfs.MemoryFS()
7574

tests/test_opener.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,14 +300,26 @@ def test_user_data_opener(self, app_dir):
300300
def test_open_ftp(self, mock_FTPFS):
301301
open_fs("ftp://foo:[email protected]")
302302
mock_FTPFS.assert_called_once_with(
303-
"ftp.example.org", passwd="bar", port=21, user="foo", proxy=None, timeout=10, tls=False
303+
"ftp.example.org",
304+
passwd="bar",
305+
port=21,
306+
user="foo",
307+
proxy=None,
308+
timeout=10,
309+
tls=False,
304310
)
305311

306312
@mock.patch("fs.ftpfs.FTPFS")
307313
def test_open_ftps(self, mock_FTPFS):
308314
open_fs("ftps://foo:[email protected]")
309315
mock_FTPFS.assert_called_once_with(
310-
"ftp.example.org", passwd="bar", port=21, user="foo", proxy=None, timeout=10, tls=True
316+
"ftp.example.org",
317+
passwd="bar",
318+
port=21,
319+
user="foo",
320+
proxy=None,
321+
timeout=10,
322+
tls=True,
311323
)
312324

313325
@mock.patch("fs.ftpfs.FTPFS")

tests/test_wrap.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def test_scandir(self):
177177
]
178178
with mock.patch.object(self.fs, "scandir", wraps=self.fs.scandir) as scandir:
179179
self.assertEqual(sorted(self.cached.scandir("/"), key=key), expected)
180-
scandir.assert_has_calls([mock.call('/', namespaces=None, page=None)])
180+
scandir.assert_has_calls([mock.call("/", namespaces=None, page=None)])
181181
with mock.patch.object(self.fs, "scandir", wraps=self.fs.scandir) as scandir:
182182
self.assertEqual(sorted(self.cached.scandir("/"), key=key), expected)
183183
scandir.assert_not_called()
@@ -187,7 +187,7 @@ def test_isdir(self):
187187
self.assertTrue(self.cached.isdir("foo"))
188188
self.assertFalse(self.cached.isdir("egg")) # is file
189189
self.assertFalse(self.cached.isdir("spam")) # doesn't exist
190-
scandir.assert_has_calls([mock.call('/', namespaces=None, page=None)])
190+
scandir.assert_has_calls([mock.call("/", namespaces=None, page=None)])
191191
with mock.patch.object(self.fs, "scandir", wraps=self.fs.scandir) as scandir:
192192
self.assertTrue(self.cached.isdir("foo"))
193193
self.assertFalse(self.cached.isdir("egg"))
@@ -199,7 +199,7 @@ def test_isfile(self):
199199
self.assertTrue(self.cached.isfile("egg"))
200200
self.assertFalse(self.cached.isfile("foo")) # is dir
201201
self.assertFalse(self.cached.isfile("spam")) # doesn't exist
202-
scandir.assert_has_calls([mock.call('/', namespaces=None, page=None)])
202+
scandir.assert_has_calls([mock.call("/", namespaces=None, page=None)])
203203
with mock.patch.object(self.fs, "scandir", wraps=self.fs.scandir) as scandir:
204204
self.assertTrue(self.cached.isfile("egg"))
205205
self.assertFalse(self.cached.isfile("foo"))
@@ -211,7 +211,7 @@ def test_getinfo(self):
211211
self.assertEqual(self.cached.getinfo("foo"), self.fs.getinfo("foo"))
212212
self.assertEqual(self.cached.getinfo("/"), self.fs.getinfo("/"))
213213
self.assertNotFound(self.cached.getinfo, "spam")
214-
scandir.assert_has_calls([mock.call('/', namespaces=None, page=None)])
214+
scandir.assert_has_calls([mock.call("/", namespaces=None, page=None)])
215215
with mock.patch.object(self.fs, "scandir", wraps=self.fs.scandir) as scandir:
216216
self.assertEqual(self.cached.getinfo("foo"), self.fs.getinfo("foo"))
217217
self.assertEqual(self.cached.getinfo("/"), self.fs.getinfo("/"))

0 commit comments

Comments
 (0)