dvc-objects 1.3.1__tar.gz → 1.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. {dvc-objects-1.3.1/src/dvc_objects.egg-info → dvc-objects-1.4.0}/PKG-INFO +3 -1
  2. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/noxfile.py +8 -4
  3. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/pyproject.toml +4 -0
  4. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/executors.py +6 -1
  5. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/fs/generic.py +1 -1
  6. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/fs/system.py +16 -6
  7. {dvc-objects-1.3.1 → dvc-objects-1.4.0/src/dvc_objects.egg-info}/PKG-INFO +3 -1
  8. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects.egg-info/SOURCES.txt +1 -0
  9. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects.egg-info/requires.txt +2 -0
  10. dvc-objects-1.4.0/tests/benchmarks/test_fs.py +42 -0
  11. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/.cruft.json +0 -0
  12. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/.gitattributes +0 -0
  13. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/.github/dependabot.yml +0 -0
  14. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/.github/workflows/release.yml +0 -0
  15. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/.github/workflows/tests.yml +0 -0
  16. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/.github/workflows/update-template.yaml +0 -0
  17. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/.gitignore +0 -0
  18. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/.pre-commit-config.yaml +0 -0
  19. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/CODE_OF_CONDUCT.rst +0 -0
  20. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/CONTRIBUTING.rst +0 -0
  21. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/LICENSE +0 -0
  22. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/README.rst +0 -0
  23. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/setup.cfg +0 -0
  24. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/__init__.py +0 -0
  25. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/_tqdm.py +0 -0
  26. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/db.py +0 -0
  27. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/errors.py +0 -0
  28. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/fs/__init__.py +0 -0
  29. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/fs/base.py +0 -0
  30. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/fs/callbacks.py +0 -0
  31. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/fs/errors.py +0 -0
  32. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/fs/local.py +0 -0
  33. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/fs/memory.py +0 -0
  34. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/fs/path.py +0 -0
  35. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/fs/scheme.py +0 -0
  36. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/fs/utils.py +0 -0
  37. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/obj.py +0 -0
  38. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/py.typed +0 -0
  39. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/transfer.py +0 -0
  40. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects/utils.py +0 -0
  41. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects.egg-info/dependency_links.txt +0 -0
  42. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/src/dvc_objects.egg-info/top_level.txt +0 -0
  43. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/tests/__init__.py +0 -0
  44. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/tests/conftest.py +0 -0
  45. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/tests/fs/__init__.py +0 -0
  46. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/tests/fs/test_callbacks.py +0 -0
  47. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/tests/fs/test_localfs.py +0 -0
  48. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/tests/fs/test_system.py +0 -0
  49. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/tests/fs/test_utils.py +0 -0
  50. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/tests/test_odb.py +0 -0
  51. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/tests/test_reflink.py +0 -0
  52. {dvc-objects-1.3.1 → dvc-objects-1.4.0}/tests/test_transfer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dvc-objects
3
- Version: 1.3.1
3
+ Version: 1.4.0
4
4
  Summary: dvc objects
5
5
  Author-email: Iterative <support@dvc.org>
6
6
  License: Apache-2.0
@@ -28,6 +28,8 @@ Requires-Dist: pytest-cov==4.0.0; extra == "tests"
28
28
  Requires-Dist: pytest-mock==3.8.2; extra == "tests"
29
29
  Requires-Dist: mypy==1.5.1; extra == "tests"
30
30
  Requires-Dist: pytest-servers[s3]==0.1.3; extra == "tests"
31
+ Requires-Dist: pytest-benchmark; extra == "tests"
32
+ Requires-Dist: reflink; extra == "tests"
31
33
  Provides-Extra: dev
32
34
  Requires-Dist: dvc-objects[tests]; extra == "dev"
33
35
  Requires-Dist: types-tqdm; extra == "dev"
@@ -8,10 +8,12 @@ nox.options.reuse_existing_virtualenvs = True
8
8
  nox.options.sessions = "lint", "tests"
9
9
  locations = "src", "tests"
10
10
 
11
+ pip_dev_flags = ["--use-pep517"] # reflink package is still missing wheels
12
+
11
13
 
12
14
  @nox.session(python=["3.8", "3.9", "3.10", "3.11", "pypy3.8", "pypy3.9"])
13
15
  def tests(session: nox.Session) -> None:
14
- session.install(".[tests]")
16
+ session.install(".[tests]", *pip_dev_flags)
15
17
  session.run(
16
18
  "pytest",
17
19
  "--cov",
@@ -24,7 +26,7 @@ def tests(session: nox.Session) -> None:
24
26
  @nox.session
25
27
  def lint(session: nox.Session) -> None:
26
28
  session.install("pre-commit")
27
- session.install("-e", ".[dev]")
29
+ session.install("-e", ".[dev]", *pip_dev_flags)
28
30
 
29
31
  args = *(session.posargs or ("--show-diff-on-failure",)), "--all-files"
30
32
  session.run("pre-commit", "run", *args)
@@ -34,7 +36,7 @@ def lint(session: nox.Session) -> None:
34
36
  @nox.session
35
37
  def safety(session: nox.Session) -> None:
36
38
  """Scan dependencies for insecure packages."""
37
- session.install(".[dev]")
39
+ session.install(".[dev]", *pip_dev_flags)
38
40
  session.install("safety")
39
41
  session.run("safety", "check", "--full-report")
40
42
 
@@ -58,4 +60,6 @@ def dev(session: nox.Session) -> None:
58
60
  session.run("virtualenv", venv_dir, silent=True)
59
61
 
60
62
  python = os.path.join(venv_dir, "bin/python")
61
- session.run(python, "-m", "pip", "install", "-e", ".[dev]", external=True)
63
+ session.run(
64
+ python, "-m", "pip", "install", "-e", ".[dev]", *pip_dev_flags, external=True
65
+ )
@@ -41,6 +41,8 @@ tests = [
41
41
  "pytest-mock==3.8.2",
42
42
  "mypy==1.5.1",
43
43
  "pytest-servers[s3]==0.1.3",
44
+ "pytest-benchmark",
45
+ "reflink",
44
46
  ]
45
47
  dev = [
46
48
  "dvc-objects[tests]",
@@ -98,6 +100,8 @@ ignore_missing_imports = true
98
100
  module = [
99
101
  "fsspec.*",
100
102
  "funcy",
103
+ "reflink.*",
104
+ "shortuuid",
101
105
  ]
102
106
 
103
107
  [tool.codespell]
@@ -45,10 +45,15 @@ class ThreadPoolExecutor(futures.ThreadPoolExecutor):
45
45
  It does not create all the futures at once to reduce memory usage.
46
46
  """
47
47
 
48
+ it = zip(*iterables)
49
+ if self.max_workers == 1:
50
+ for args in it:
51
+ yield fn(*args)
52
+ return
53
+
48
54
  def create_taskset(n: int) -> Set[futures.Future]:
49
55
  return {self.submit(fn, *args) for args in islice(it, n)}
50
56
 
51
- it = zip(*iterables)
52
57
  tasks = create_taskset(self.max_workers * 5)
53
58
  while tasks:
54
59
  done, tasks = futures.wait(tasks, return_when=futures.FIRST_COMPLETED)
@@ -86,7 +86,7 @@ def copy(
86
86
  to_fs,
87
87
  to_path,
88
88
  callback=callback,
89
- batch_size=batch_size,
89
+ batch_size=1 if isinstance(to_fs, LocalFileSystem) else batch_size,
90
90
  on_error=on_error,
91
91
  )
92
92
  if isinstance(to_fs, LocalFileSystem):
@@ -4,6 +4,7 @@ import os
4
4
  import platform
5
5
  import stat
6
6
  import sys
7
+ import functools
7
8
  from typing import TYPE_CHECKING
8
9
 
9
10
  if TYPE_CHECKING:
@@ -36,7 +37,8 @@ def symlink(source: "AnyFSPath", link_name: "AnyFSPath") -> None:
36
37
  os.symlink(source, link_name)
37
38
 
38
39
 
39
- def _reflink_darwin(src: "AnyFSPath", dst: "AnyFSPath") -> None:
40
+ @functools.lru_cache(maxsize=1)
41
+ def _clonefile():
40
42
  import ctypes
41
43
 
42
44
  def _cdll(name):
@@ -48,22 +50,30 @@ def _reflink_darwin(src: "AnyFSPath", dst: "AnyFSPath") -> None:
48
50
  clib = _cdll(LIBC)
49
51
  except OSError as exc:
50
52
  logger.debug(
51
- "unable to access '{}' (errno '{}'). " "Falling back to '{}'.".format(
52
- LIBC, exc.errno, LIBC_FALLBACK
53
- )
53
+ "unable to access '%s' (errno '%d'). Falling back to '%s'.",
54
+ LIBC,
55
+ exc.errno,
56
+ LIBC_FALLBACK,
54
57
  )
55
58
  if exc.errno != errno.ENOENT:
56
59
  raise
57
60
  # NOTE: trying to bypass System Integrity Protection (SIP)
58
61
  clib = _cdll(LIBC_FALLBACK)
59
62
 
60
- if not hasattr(clib, "clonefile"):
63
+ clonefile = getattr(clib, "clonefile", None)
64
+ if clonefile is None:
61
65
  raise OSError(
62
66
  errno.ENOTSUP,
63
67
  "'clonefile' not supported by the standard library",
64
68
  )
65
69
 
66
- clonefile = clib.clonefile
70
+ return clonefile
71
+
72
+
73
+ def _reflink_darwin(src: "AnyFSPath", dst: "AnyFSPath") -> None:
74
+ import ctypes
75
+
76
+ clonefile = _clonefile()
67
77
  clonefile.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_int]
68
78
  clonefile.restype = ctypes.c_int
69
79
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dvc-objects
3
- Version: 1.3.1
3
+ Version: 1.4.0
4
4
  Summary: dvc objects
5
5
  Author-email: Iterative <support@dvc.org>
6
6
  License: Apache-2.0
@@ -28,6 +28,8 @@ Requires-Dist: pytest-cov==4.0.0; extra == "tests"
28
28
  Requires-Dist: pytest-mock==3.8.2; extra == "tests"
29
29
  Requires-Dist: mypy==1.5.1; extra == "tests"
30
30
  Requires-Dist: pytest-servers[s3]==0.1.3; extra == "tests"
31
+ Requires-Dist: pytest-benchmark; extra == "tests"
32
+ Requires-Dist: reflink; extra == "tests"
31
33
  Provides-Extra: dev
32
34
  Requires-Dist: dvc-objects[tests]; extra == "dev"
33
35
  Requires-Dist: types-tqdm; extra == "dev"
@@ -42,6 +42,7 @@ tests/conftest.py
42
42
  tests/test_odb.py
43
43
  tests/test_reflink.py
44
44
  tests/test_transfer.py
45
+ tests/benchmarks/test_fs.py
45
46
  tests/fs/__init__.py
46
47
  tests/fs/test_callbacks.py
47
48
  tests/fs/test_localfs.py
@@ -16,3 +16,5 @@ pytest-cov==4.0.0
16
16
  pytest-mock==3.8.2
17
17
  mypy==1.5.1
18
18
  pytest-servers[s3]==0.1.3
19
+ pytest-benchmark
20
+ reflink
@@ -0,0 +1,42 @@
1
+ import errno
2
+ import pytest
3
+ import shutil
4
+ from reflink import reflink as pyreflink
5
+ from reflink.error import ReflinkImpossibleError
6
+ from dvc_objects.fs.system import reflink, hardlink, symlink
7
+
8
+ NLINKS = 10000
9
+
10
+
11
+ @pytest.mark.parametrize(
12
+ "link", [pytest.param(pyreflink, id="pyreflink"), reflink, hardlink, symlink]
13
+ )
14
+ def test_link(benchmark, tmp_path, link):
15
+ (tmp_path / "original").mkdir()
16
+
17
+ for idx in range(NLINKS):
18
+ (tmp_path / "original" / str(idx)).write_text(str(idx))
19
+
20
+ def _setup():
21
+ try:
22
+ shutil.rmtree(tmp_path / "links")
23
+ except FileNotFoundError:
24
+ pass
25
+
26
+ (tmp_path / "links").mkdir()
27
+
28
+ original = str(tmp_path / "original")
29
+ links = str(tmp_path / "links")
30
+
31
+ def _link():
32
+ for idx in range(NLINKS):
33
+ try:
34
+ link(f"{original}/{idx}", f"{links}/{idx}")
35
+ except Exception as exc:
36
+ if isinstance(exc, (ReflinkImpossibleError, NotImplementedError)) or (
37
+ isinstance(exc, OSError) and exc.errno == errno.ENOTSUP
38
+ ):
39
+ pytest.skip(str(exc))
40
+ raise
41
+
42
+ benchmark.pedantic(_link, setup=_setup)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes