Skip to content

Commit a798169

Browse files
committed
Move copyfile to fs.py
1 parent eca5d2d commit a798169

File tree

7 files changed

+78
-78
lines changed

7 files changed

+78
-78
lines changed

dvc/remote/local.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from dvc.scheme import Schemes
2222
from dvc.scm.tree import is_working_tree
2323
from dvc.system import System
24-
from dvc.utils import copyfile
24+
from dvc.utils.fs import copyfile
2525
from dvc.utils import file_md5
2626
from dvc.utils import relpath
2727
from dvc.utils import tmp_fname

dvc/utils/__init__.py

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -105,36 +105,6 @@ def dict_md5(d, exclude=()):
105105
return bytes_md5(byts)
106106

107107

108-
def copyfile(src, dest, no_progress_bar=False, name=None):
109-
"""Copy file with progress bar"""
110-
from dvc.exceptions import DvcException
111-
from dvc.progress import Tqdm
112-
from dvc.system import System
113-
114-
src = fspath_py35(src)
115-
dest = fspath_py35(dest)
116-
117-
name = name if name else os.path.basename(dest)
118-
total = os.stat(src).st_size
119-
120-
if os.path.isdir(dest):
121-
dest = os.path.join(dest, os.path.basename(src))
122-
123-
try:
124-
System.reflink(src, dest)
125-
except DvcException:
126-
with Tqdm(
127-
desc=name, disable=no_progress_bar, total=total, bytes=True
128-
) as pbar:
129-
with open(src, "rb") as fsrc, open(dest, "wb+") as fdest:
130-
while True:
131-
buf = fsrc.read(LOCAL_CHUNK_SIZE)
132-
if not buf:
133-
break
134-
fdest.write(buf)
135-
pbar.update(len(buf))
136-
137-
138108
def _split(list_to_split, chunk_size):
139109
return [
140110
list_to_split[i : i + chunk_size]

dvc/utils/fs.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
logger = logging.getLogger(__name__)
2020

21+
LOCAL_CHUNK_SIZE = 2 ** 20 # 1 MB
22+
2123

2224
def fs_copy(src, dst):
2325
if os.path.isdir(src):
@@ -169,3 +171,33 @@ def makedirs(path, exist_ok=False, mode=None):
169171
os.makedirs(path, exist_ok=exist_ok)
170172
finally:
171173
os.umask(umask)
174+
175+
176+
def copyfile(src, dest, no_progress_bar=False, name=None):
177+
"""Copy file with progress bar"""
178+
from dvc.exceptions import DvcException
179+
from dvc.progress import Tqdm
180+
from dvc.system import System
181+
182+
src = fspath_py35(src)
183+
dest = fspath_py35(dest)
184+
185+
name = name if name else os.path.basename(dest)
186+
total = os.stat(src).st_size
187+
188+
if os.path.isdir(dest):
189+
dest = os.path.join(dest, os.path.basename(src))
190+
191+
try:
192+
System.reflink(src, dest)
193+
except DvcException:
194+
with Tqdm(
195+
desc=name, disable=no_progress_bar, total=total, bytes=True
196+
) as pbar:
197+
with open(src, "rb") as fsrc, open(dest, "wb+") as fdest:
198+
while True:
199+
buf = fsrc.read(LOCAL_CHUNK_SIZE)
200+
if not buf:
201+
break
202+
fdest.write(buf)
203+
pbar.update(len(buf))

tests/func/test_fs.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import pytest
55

6-
from dvc.utils.fs import makedirs
6+
from dvc.utils.fs import makedirs, copyfile
77

88

99
@pytest.mark.skipif(os.name == "nt", reason="Not supported for Windows.")
@@ -18,3 +18,19 @@ def test_makedirs_permissions(tmp_dir):
1818

1919
assert stat.S_IMODE(os.stat(test_dir).st_mode) == dir_mode
2020
assert stat.S_IMODE(os.stat(intermediate_dir).st_mode) == dir_mode
21+
22+
23+
def test_copyfile(tmp_dir):
24+
src = "file1"
25+
dest = "file2"
26+
dest_dir = "testdir"
27+
28+
tmp_dir.gen(src, "file1contents")
29+
30+
os.mkdir(dest_dir)
31+
32+
copyfile(src, dest)
33+
assert (tmp_dir / dest).read_text() == "file1contents"
34+
35+
copyfile(src, dest_dir)
36+
assert (tmp_dir / dest_dir / src).read_text() == "file1contents"

tests/func/test_utils.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,8 @@
11
# encoding: utf-8
2-
import os
32

43
from dvc import utils
54

65

7-
def test_copyfile(tmp_dir):
8-
src = "file1"
9-
dest = "file2"
10-
dest_dir = "testdir"
11-
12-
tmp_dir.gen(src, "file1contents")
13-
14-
os.mkdir(dest_dir)
15-
16-
utils.copyfile(src, dest)
17-
assert (tmp_dir / dest).read_text() == "file1contents"
18-
19-
utils.copyfile(src, dest_dir)
20-
assert (tmp_dir / dest_dir / src).read_text() == "file1contents"
21-
22-
236
def test_file_md5_crlf(tmp_dir):
247
tmp_dir.gen("cr", b"a\nb\nc")
258
tmp_dir.gen("crlf", b"a\r\nb\r\nc")

tests/unit/utils/test_fs.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import filecmp
12
import os
23
from unittest import TestCase
34

@@ -11,6 +12,7 @@
1112
from dvc.system import System
1213
from dvc.utils import relpath
1314
from dvc.utils.fs import BasePathNotInCheckedPathException
15+
from dvc.utils.fs import copyfile
1416
from dvc.utils.fs import contains_symlink_up_to
1517
from dvc.utils.fs import get_inode
1618
from dvc.utils.fs import get_mtime_and_size
@@ -216,3 +218,29 @@ def test_makedirs(repo_dir):
216218

217219
makedirs(path_info)
218220
assert os.path.isdir(path_info.fspath)
221+
222+
223+
@pytest.mark.parametrize("path", [TestDir.DATA, TestDir.DATA_DIR])
224+
def test_copyfile(path, repo_dir):
225+
src = repo_dir.FOO
226+
dest = path
227+
src_info = PathInfo(repo_dir.BAR)
228+
dest_info = PathInfo(path)
229+
230+
copyfile(src, dest)
231+
if os.path.isdir(dest):
232+
assert filecmp.cmp(
233+
src, os.path.join(dest, os.path.basename(src)), shallow=False
234+
)
235+
else:
236+
assert filecmp.cmp(src, dest, shallow=False)
237+
238+
copyfile(src_info, dest_info)
239+
if os.path.isdir(dest_info.fspath):
240+
assert filecmp.cmp(
241+
src_info.fspath,
242+
os.path.join(dest_info.fspath, os.path.basename(src_info.fspath)),
243+
shallow=False,
244+
)
245+
else:
246+
assert filecmp.cmp(src_info.fspath, dest_info.fspath, shallow=False)

tests/unit/utils/test_utils.py

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
import filecmp
21
import re
32
import os
43

54
import pytest
65

76
from dvc.path_info import PathInfo
8-
from dvc.utils import copyfile
97
from dvc.utils import file_md5
108
from dvc.utils import fix_env
119
from dvc.utils import relpath
1210
from dvc.utils import to_chunks
1311
from dvc.utils import tmp_fname
1412
from dvc.utils import walk_files
15-
from tests.basic_env import TestDir
1613

1714

1815
@pytest.mark.parametrize(
@@ -88,32 +85,6 @@ def test_file_md5(repo_dir):
8885
assert file_md5(fname) == file_md5(fname_object)
8986

9087

91-
@pytest.mark.parametrize("path", [TestDir.DATA, TestDir.DATA_DIR])
92-
def test_copyfile(path, repo_dir):
93-
src = repo_dir.FOO
94-
dest = path
95-
src_info = PathInfo(repo_dir.BAR)
96-
dest_info = PathInfo(path)
97-
98-
copyfile(src, dest)
99-
if os.path.isdir(dest):
100-
assert filecmp.cmp(
101-
src, os.path.join(dest, os.path.basename(src)), shallow=False
102-
)
103-
else:
104-
assert filecmp.cmp(src, dest, shallow=False)
105-
106-
copyfile(src_info, dest_info)
107-
if os.path.isdir(dest_info.fspath):
108-
assert filecmp.cmp(
109-
src_info.fspath,
110-
os.path.join(dest_info.fspath, os.path.basename(src_info.fspath)),
111-
shallow=False,
112-
)
113-
else:
114-
assert filecmp.cmp(src_info.fspath, dest_info.fspath, shallow=False)
115-
116-
11788
def test_tmp_fname():
11889
file_path = os.path.join("path", "to", "file")
11990
file_path_info = PathInfo(file_path)

0 commit comments

Comments
 (0)