Skip to content

Commit ebcd1a9

Browse files
author
atollk
committed
Optimization in FTPFS.setinfo.
Before, `setinfo` would always start by sending a MLST or LIST command to find whether the resources exists. This is actually not necessary if MFMT is sent anyway, so the command is now skipped in that case.
1 parent a200708 commit ebcd1a9

File tree

2 files changed

+39
-37
lines changed

2 files changed

+39
-37
lines changed

fs/ftpfs.py

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -836,27 +836,32 @@ def writebytes(self, path, contents):
836836

837837
def setinfo(self, path, info):
838838
# type: (Text, RawInfo) -> None
839-
current_info = self.getinfo(path)
840-
if current_info.is_file and "MFMT" in self.features:
841-
mtime = 0.0
839+
use_mfmt = False
840+
if "MFMT" in self.features:
841+
info_details = None
842842
if "modified" in info:
843-
mtime = float(cast(float, info["modified"]["modified"]))
844-
if "details" in info:
845-
mtime = float(cast(float, info["details"]["modified"]))
846-
if mtime:
847-
with ftp_errors(self, path):
848-
cmd = (
849-
"MFMT "
850-
+ datetime.datetime.fromtimestamp(mtime).strftime(
851-
"%Y%m%d%H%M%S"
852-
)
853-
+ " "
854-
+ _encode(path, self.ftp.encoding)
855-
)
856-
try:
857-
self.ftp.sendcmd(cmd)
858-
except error_perm:
859-
pass
843+
info_details = info["modified"]
844+
elif "details" in info:
845+
info_details = info["details"]
846+
if info_details and "modified" in info_details:
847+
use_mfmt = True
848+
mtime = cast(float, info_details["modified"])
849+
850+
if use_mfmt:
851+
with ftp_errors(self, path):
852+
cmd = (
853+
"MFMT "
854+
+ datetime.datetime.utcfromtimestamp(mtime).strftime("%Y%m%d%H%M%S")
855+
+ " "
856+
+ _encode(path, self.ftp.encoding)
857+
)
858+
try:
859+
self.ftp.sendcmd(cmd)
860+
except error_perm:
861+
pass
862+
else:
863+
if not self.exists(path):
864+
raise errors.ResourceNotFound(path)
860865

861866
def readbytes(self, path):
862867
# type: (Text) -> bytes

tests/test_ftpfs.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import print_function
44
from __future__ import unicode_literals
55

6+
import calendar
67
import os
78
import platform
89
import shutil
@@ -226,23 +227,19 @@ def test_geturl(self):
226227
def test_setinfo(self):
227228
# TODO: temporary test, since FSTestCases.test_setinfo is broken.
228229
self.fs.create("bar")
229-
time1 = time.mktime(datetime.datetime.now().timetuple())
230-
time2 = time1 + 60
231-
self.fs.setinfo("bar", {"details": {"modified": time1}})
232-
mtime1 = self.fs.getinfo("bar", ("details",)).modified
233-
self.fs.setinfo("bar", {"details": {"modified": time2}})
234-
mtime2 = self.fs.getinfo("bar", ("details",)).modified
235-
replacement = {}
236-
if mtime1.microsecond == 0 or mtime2.microsecond == 0:
237-
mtime1 = mtime1.replace(microsecond=0)
238-
mtime2 = mtime2.replace(microsecond=0)
239-
if mtime1.second == 0 or mtime2.second == 0:
240-
mtime1 = mtime1.replace(second=0)
241-
mtime2 = mtime2.replace(second=0)
242-
mtime2_modified = mtime2.replace(minute=mtime2.minute - 1)
243-
self.assertEqual(
244-
mtime1.replace(**replacement), mtime2_modified.replace(**replacement)
245-
)
230+
original_modified = self.fs.getinfo("bar", ("details",)).modified
231+
new_modified = original_modified - datetime.timedelta(hours=1)
232+
new_modified_stamp = calendar.timegm(new_modified.timetuple())
233+
self.fs.setinfo("bar", {"details": {"modified": new_modified_stamp}})
234+
new_modified_get = self.fs.getinfo("bar", ("details",)).modified
235+
if original_modified.microsecond == 0 or new_modified_get.microsecond == 0:
236+
original_modified = original_modified.replace(microsecond=0)
237+
new_modified_get = new_modified_get.replace(microsecond=0)
238+
if original_modified.second == 0 or new_modified_get.second == 0:
239+
original_modified = original_modified.replace(second=0)
240+
new_modified_get = new_modified_get.replace(second=0)
241+
new_modified_get = new_modified_get + datetime.timedelta(hours=1)
242+
self.assertEqual(original_modified, new_modified_get)
246243

247244
def test_host(self):
248245
self.assertEqual(self.fs.host, self.server.host)

0 commit comments

Comments
 (0)