Skip to content

Commit f016533

Browse files
author
atollk
committed
Added fs.copy.copy_metadata.
All logic for the added `preserve_time` parameter is contained in that function, so other pieces of code just have to make a single call. It's still not implemented at this point.
1 parent ec39f9d commit f016533

File tree

8 files changed

+76
-43
lines changed

8 files changed

+76
-43
lines changed

fs/_bulk.py

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,30 @@ def __call__(self):
5656
class _CopyTask(_Task):
5757
"""A callable that copies from one file another."""
5858

59-
def __init__(self, src_file, dst_file):
60-
# type: (IO, IO) -> None
61-
self.src_file = src_file
62-
self.dst_file = dst_file
59+
def __init__(
60+
self,
61+
src_fs, # type: FS
62+
src_path, # type: Text
63+
dst_fs, # type: FS
64+
dst_path, # type: Text
65+
preserve_time, # type: bool
66+
):
67+
# type: (...) -> None
68+
self.src_fs = src_fs
69+
self.src_path = src_path
70+
self.dst_fs = dst_fs
71+
self.dst_path = dst_path
72+
self.preserve_time = preserve_time
6373

6474
def __call__(self):
6575
# type: () -> None
66-
try:
67-
copy_file_data(self.src_file, self.dst_file, chunk_size=1024 * 1024)
68-
finally:
69-
try:
70-
self.src_file.close()
71-
finally:
72-
self.dst_file.close()
76+
copy_file_internal(
77+
self.src_fs,
78+
self.src_path,
79+
self.dst_fs,
80+
self.dst_path,
81+
preserve_time=self.preserve_time,
82+
)
7383

7484

7585
class Copier(object):
@@ -88,7 +98,7 @@ def __init__(self, num_workers=4):
8898
def start(self):
8999
"""Start the workers."""
90100
if self.num_workers:
91-
self.queue = Queue(maxsize=self.num_workers)
101+
self.queue = Queue()
92102
self.workers = [_Worker(self) for _ in range(self.num_workers)]
93103
for worker in self.workers:
94104
worker.start()
@@ -133,12 +143,5 @@ def copy(self, src_fs, src_path, dst_fs, dst_path, preserve_time=False):
133143
src_fs, src_path, dst_fs, dst_path, preserve_time=preserve_time
134144
)
135145
else:
136-
# TODO(preserve_time)
137-
src_file = src_fs.openbin(src_path, "r")
138-
try:
139-
dst_file = dst_fs.openbin(dst_path, "w")
140-
except Exception:
141-
src_file.close()
142-
raise
143-
task = _CopyTask(src_file, dst_file)
146+
task = _CopyTask(src_fs, src_path, dst_fs, dst_path, preserve_time)
144147
self.queue.put(task)

fs/base.py

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

2424
from . import copy, errors, fsencode, iotools, move, tools, walk, wildcard
25+
from .copy import copy_metadata
2526
from .glob import BoundGlobber
2627
from .mode import validate_open_mode
2728
from .path import abspath, join, normpath
@@ -412,13 +413,13 @@ def copy(
412413
``dst_path`` does not exist.
413414
414415
"""
415-
# TODO(preserve_time)
416416
with self._lock:
417417
if not overwrite and self.exists(dst_path):
418418
raise errors.DestinationExists(dst_path)
419419
with closing(self.open(src_path, "rb")) as read_file:
420420
# FIXME(@althonos): typing complains because open return IO
421421
self.upload(dst_path, read_file) # type: ignore
422+
copy_metadata(self, src_path, self, dst_path)
422423

423424
def copydir(
424425
self,
@@ -1030,8 +1031,8 @@ def movedir(self, src_path, dst_path, create=False, preserve_time=False):
10301031
dst_path (str): Path to destination directory.
10311032
create (bool): If `True`, then ``dst_path`` will be created
10321033
if it doesn't exist already (defaults to `False`).
1033-
preserve_time (bool): If `True`, try to preserve atime, ctime,
1034-
and mtime of the resources (defaults to `False`).
1034+
preserve_time (bool): If `True`, try to preserve atime, ctime,
1035+
and mtime of the resources (defaults to `False`).
10351036
10361037
Raises:
10371038
fs.errors.ResourceNotFound: if ``dst_path`` does not exist,
@@ -1086,8 +1087,8 @@ def makedirs(
10861087
raise
10871088
return self.opendir(path)
10881089

1089-
def move(self, src_path, dst_path, overwrite=False):
1090-
# type: (Text, Text, bool) -> None
1090+
def move(self, src_path, dst_path, overwrite=False, preserve_time=False):
1091+
# type: (Text, Text, bool, bool) -> None
10911092
"""Move a file from ``src_path`` to ``dst_path``.
10921093
10931094
Arguments:
@@ -1096,6 +1097,8 @@ def move(self, src_path, dst_path, overwrite=False):
10961097
file will be written to.
10971098
overwrite (bool): If `True`, destination path will be
10981099
overwritten if it exists.
1100+
preserve_time (bool): If `True`, try to preserve atime, ctime,
1101+
and mtime of the resources (defaults to `False`).
10991102
11001103
Raises:
11011104
fs.errors.FileExpected: If ``src_path`` maps to a
@@ -1128,6 +1131,7 @@ def move(self, src_path, dst_path, overwrite=False):
11281131
# FIXME(@althonos): typing complains because open return IO
11291132
self.upload(dst_path, read_file) # type: ignore
11301133
self.remove(src_path)
1134+
copy_metadata(self, src_path, self, dst_path)
11311135

11321136
def open(
11331137
self,

fs/copy.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ def copy_file(
151151
src_path, dst_path, overwrite=True, preserve_time=preserve_time
152152
)
153153
else:
154-
# TODO(preserve_time)
155154
# Standard copy
156155
with _src_fs.lock(), _dst_fs.lock():
157156
if _dst_fs.hassyspath(dst_path):
@@ -160,6 +159,7 @@ def copy_file(
160159
else:
161160
with _src_fs.openbin(src_path) as read_file:
162161
_dst_fs.upload(dst_path, read_file)
162+
copy_metadata(_src_fs, src_path, _dst_fs, dst_path)
163163

164164

165165
def copy_file_internal(
@@ -190,14 +190,17 @@ def copy_file_internal(
190190
# Same filesystem, so we can do a potentially optimized
191191
# copy
192192
src_fs.copy(src_path, dst_path, overwrite=True, preserve_time=preserve_time)
193-
# TODO(preserve_time)
194-
elif dst_fs.hassyspath(dst_path):
193+
return
194+
195+
if dst_fs.hassyspath(dst_path):
195196
with dst_fs.openbin(dst_path, "w") as write_file:
196197
src_fs.download(src_path, write_file)
197198
else:
198199
with src_fs.openbin(src_path) as read_file:
199200
dst_fs.upload(dst_path, read_file)
200201

202+
copy_metadata(src_fs, src_path, dst_fs, dst_path)
203+
201204

202205
def copy_file_if_newer(
203206
src_fs, # type: Union[FS, Text]
@@ -326,9 +329,10 @@ def dst():
326329
from ._bulk import Copier
327330

328331
with src() as _src_fs, dst() as _dst_fs:
329-
with _src_fs.lock(), _dst_fs.lock():
330-
_thread_safe = is_thread_safe(_src_fs, _dst_fs)
331-
with Copier(num_workers=workers if _thread_safe else 0) as copier:
332+
_thread_safe = is_thread_safe(_src_fs, _dst_fs)
333+
copier = Copier(num_workers=workers if _thread_safe else 0)
334+
with copier:
335+
with _src_fs.lock(), _dst_fs.lock():
332336
_dst_fs.makedir(_dst_path, recreate=True)
333337
for dir_path, dirs, files in walker.walk(_src_fs, _src_path):
334338
copy_path = combine(_dst_path, frombase(_src_path, dir_path))
@@ -345,6 +349,7 @@ def dst():
345349
preserve_time=preserve_time,
346350
)
347351
on_copy(_src_fs, src_path, _dst_fs, dst_path)
352+
pass
348353

349354

350355
def copy_dir_if_newer(
@@ -438,3 +443,25 @@ def dst():
438443
preserve_time=preserve_time,
439444
)
440445
on_copy(_src_fs, dir_path, _dst_fs, copy_path)
446+
447+
448+
def copy_metadata(
449+
src_fs, # type: Union[FS, Text]
450+
src_path, # type: Text
451+
dst_fs, # type: Union[FS, Text]
452+
dst_path, # type: Text
453+
):
454+
# type: (...) -> None
455+
"""Copies metadata from one file to another.
456+
457+
Arguments:
458+
src_fs (FS or str): Source filesystem (instance or URL).
459+
src_path (str): Path to a directory on the source filesystem.
460+
dst_fs (FS or str): Destination filesystem (instance or URL).
461+
dst_path (str): Path to a directory on the destination filesystem.
462+
463+
"""
464+
# TODO(preserve_time)
465+
with manage_fs(src_fs, writeable=False) as _src_fs:
466+
with manage_fs(dst_fs, create=True) as _dst_fs:
467+
pass

fs/mirror.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ def dst():
8686
return manage_fs(dst_fs, create=True)
8787

8888
with src() as _src_fs, dst() as _dst_fs:
89-
with _src_fs.lock(), _dst_fs.lock():
90-
_thread_safe = is_thread_safe(_src_fs, _dst_fs)
91-
with Copier(num_workers=workers if _thread_safe else 0) as copier:
89+
_thread_safe = is_thread_safe(_src_fs, _dst_fs)
90+
with Copier(num_workers=workers if _thread_safe else 0) as copier:
91+
with _src_fs.lock(), _dst_fs.lock():
9292
_mirror(
9393
_src_fs,
9494
_dst_fs,

fs/move.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,13 @@ def move_file(
5555
and mtime of the resources (defaults to `False`).
5656
5757
"""
58-
# TODO(preserve_time)
5958
with manage_fs(src_fs) as _src_fs:
6059
with manage_fs(dst_fs, create=True) as _dst_fs:
6160
if _src_fs is _dst_fs:
6261
# Same filesystem, may be optimized
63-
_src_fs.move(src_path, dst_path, overwrite=True)
62+
_src_fs.move(
63+
src_path, dst_path, overwrite=True, preserve_time=preserve_time
64+
)
6465
else:
6566
# Standard copy and delete
6667
with _src_fs.lock(), _dst_fs.lock():

fs/osfs.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,6 @@ def _check_copy(self, src_path, dst_path, overwrite=False):
433433

434434
def copy(self, src_path, dst_path, overwrite=False, preserve_time=False):
435435
# type: (Text, Text, bool, bool) -> None
436-
# TODO(preserve_time)
437436
with self._lock:
438437
# validate and canonicalise paths
439438
_src_path, _dst_path = self._check_copy(src_path, dst_path, overwrite)
@@ -464,7 +463,6 @@ def copy(self, src_path, dst_path, overwrite=False, preserve_time=False):
464463

465464
def copy(self, src_path, dst_path, overwrite=False, preserve_time=False):
466465
# type: (Text, Text, bool, bool) -> None
467-
# TODO(preserve_time)
468466
with self._lock:
469467
_src_path, _dst_path = self._check_copy(src_path, dst_path, overwrite)
470468
shutil.copy2(self.getsyspath(_src_path), self.getsyspath(_dst_path))

fs/wrap.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ def makedir(
181181
self.check()
182182
raise ResourceReadOnly(path)
183183

184-
def move(self, src_path, dst_path, overwrite=False):
185-
# type: (Text, Text, bool) -> None
184+
def move(self, src_path, dst_path, overwrite=False, preserve_time=False):
185+
# type: (Text, Text, bool, bool) -> None
186186
self.check()
187187
raise ResourceReadOnly(dst_path)
188188

fs/wrapfs.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,15 @@ def makedir(
167167
with unwrap_errors(path):
168168
return _fs.makedir(_path, permissions=permissions, recreate=recreate)
169169

170-
def move(self, src_path, dst_path, overwrite=False):
171-
# type: (Text, Text, bool) -> None
170+
def move(self, src_path, dst_path, overwrite=False, preserve_time=False):
171+
# type: (Text, Text, bool, bool) -> None
172172
# A custom move permits a potentially optimized code path
173173
src_fs, _src_path = self.delegate_path(src_path)
174174
dst_fs, _dst_path = self.delegate_path(dst_path)
175175
with unwrap_errors({_src_path: src_path, _dst_path: dst_path}):
176176
if not overwrite and dst_fs.exists(_dst_path):
177177
raise errors.DestinationExists(_dst_path)
178-
move_file(src_fs, _src_path, dst_fs, _dst_path)
178+
move_file(src_fs, _src_path, dst_fs, _dst_path, preserve_time=preserve_time)
179179

180180
def movedir(self, src_path, dst_path, create=False):
181181
# type: (Text, Text, bool) -> None

0 commit comments

Comments
 (0)