scmrepo 3.3.5__tar.gz → 3.5.3__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.

Potentially problematic release.


This version of scmrepo might be problematic. Click here for more details.

Files changed (74) hide show
  1. {scmrepo-3.3.5 → scmrepo-3.5.3}/.github/workflows/release.yaml +4 -4
  2. {scmrepo-3.3.5 → scmrepo-3.5.3}/.github/workflows/tests.yaml +18 -9
  3. {scmrepo-3.3.5 → scmrepo-3.5.3}/.github/workflows/update-template.yaml +1 -1
  4. {scmrepo-3.3.5 → scmrepo-3.5.3}/.gitignore +1 -0
  5. {scmrepo-3.3.5 → scmrepo-3.5.3}/.pre-commit-config.yaml +4 -4
  6. {scmrepo-3.3.5/src/scmrepo.egg-info → scmrepo-3.5.3}/PKG-INFO +11 -7
  7. {scmrepo-3.3.5 → scmrepo-3.5.3}/noxfile.py +5 -9
  8. {scmrepo-3.3.5 → scmrepo-3.5.3}/pyproject.toml +24 -8
  9. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/asyn.py +1 -3
  10. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/base.py +4 -0
  11. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/fs.py +0 -31
  12. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/__init__.py +5 -3
  13. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/backend/base.py +1 -1
  14. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/backend/dulwich/__init__.py +97 -63
  15. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/backend/dulwich/asyncssh_vendor.py +30 -74
  16. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/backend/dulwich/client.py +11 -4
  17. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/backend/gitpython.py +21 -15
  18. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/backend/pygit2/__init__.py +101 -60
  19. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/backend/pygit2/callbacks.py +3 -1
  20. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/backend/pygit2/filter.py +16 -15
  21. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/credentials.py +48 -17
  22. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/lfs/client.py +2 -2
  23. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/lfs/fetch.py +3 -3
  24. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/lfs/progress.py +1 -1
  25. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/lfs/smudge.py +1 -1
  26. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/lfs/storage.py +2 -2
  27. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/objects.py +1 -1
  28. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/progress.py +13 -9
  29. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/utils.py +11 -7
  30. {scmrepo-3.3.5 → scmrepo-3.5.3/src/scmrepo.egg-info}/PKG-INFO +11 -7
  31. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo.egg-info/requires.txt +5 -4
  32. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/conftest.py +2 -1
  33. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/docker-compose.yml +2 -2
  34. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/test_credentials.py +40 -0
  35. scmrepo-3.5.3/tests/test_dulwich.py +287 -0
  36. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/test_git.py +255 -12
  37. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/test_lfs.py +1 -1
  38. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/test_pygit2.py +4 -3
  39. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/vendor/test_paramiko_vendor.py +6 -6
  40. scmrepo-3.3.5/tests/test_dulwich.py +0 -206
  41. {scmrepo-3.3.5 → scmrepo-3.5.3}/.coveragerc +0 -0
  42. {scmrepo-3.3.5 → scmrepo-3.5.3}/.cruft.json +0 -0
  43. {scmrepo-3.3.5 → scmrepo-3.5.3}/.gitattributes +0 -0
  44. {scmrepo-3.3.5 → scmrepo-3.5.3}/.github/dependabot.yml +0 -0
  45. {scmrepo-3.3.5 → scmrepo-3.5.3}/CODE_OF_CONDUCT.rst +0 -0
  46. {scmrepo-3.3.5 → scmrepo-3.5.3}/CONTRIBUTING.rst +0 -0
  47. {scmrepo-3.3.5 → scmrepo-3.5.3}/LICENSE +0 -0
  48. {scmrepo-3.3.5 → scmrepo-3.5.3}/README.rst +0 -0
  49. {scmrepo-3.3.5 → scmrepo-3.5.3}/setup.cfg +0 -0
  50. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/__init__.py +0 -0
  51. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/exceptions.py +0 -0
  52. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/backend/__init__.py +0 -0
  53. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/config.py +0 -0
  54. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/lfs/__init__.py +0 -0
  55. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/lfs/exceptions.py +0 -0
  56. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/lfs/object.py +0 -0
  57. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/lfs/pointer.py +0 -0
  58. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/git/stash.py +0 -0
  59. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/noscm.py +0 -0
  60. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/py.typed +0 -0
  61. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo/urls.py +0 -0
  62. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo.egg-info/SOURCES.txt +0 -0
  63. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo.egg-info/dependency_links.txt +0 -0
  64. {scmrepo-3.3.5 → scmrepo-3.5.3}/src/scmrepo.egg-info/top_level.txt +0 -0
  65. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/__init__.py +0 -0
  66. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/git-init/git.sh +0 -0
  67. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/test_fs.py +0 -0
  68. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/test_noscm.py +0 -0
  69. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/test_scmrepo.py +0 -0
  70. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/test_stash.py +0 -0
  71. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/test_urls.py +0 -0
  72. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/user.key +0 -0
  73. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/user.key.pub +0 -0
  74. {scmrepo-3.3.5 → scmrepo-3.5.3}/tests/vendor/__init__.py +0 -0
@@ -17,14 +17,14 @@ jobs:
17
17
  runs-on: ubuntu-latest
18
18
  steps:
19
19
  - name: Check out the repository
20
- uses: actions/checkout@v4
20
+ uses: actions/checkout@v5
21
21
  with:
22
22
  fetch-depth: 0
23
23
 
24
- - name: Set up Python 3.10
25
- uses: actions/setup-python@v5
24
+ - name: Set up Python 3.13
25
+ uses: actions/setup-python@v6
26
26
  with:
27
- python-version: '3.10'
27
+ python-version: '3.13'
28
28
 
29
29
  - name: Upgrade pip and nox
30
30
  run: |
@@ -20,19 +20,20 @@ jobs:
20
20
  strategy:
21
21
  fail-fast: false
22
22
  matrix:
23
- os: [ubuntu-20.04, windows-latest, macos-latest]
24
- pyv: ['3.9', '3.10', '3.11', '3.12']
23
+ os: [ubuntu-latest, windows-latest, macos-latest]
24
+ pyv: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
25
25
 
26
26
  steps:
27
27
  - name: Check out the repository
28
- uses: actions/checkout@v4
28
+ uses: actions/checkout@v5
29
29
  with:
30
30
  fetch-depth: 0
31
31
 
32
32
  - name: Set up Python ${{ matrix.pyv }}
33
- uses: actions/setup-python@v5
33
+ uses: actions/setup-python@v6
34
34
  with:
35
35
  python-version: ${{ matrix.pyv }}
36
+ allow-prereleases: true
36
37
 
37
38
  - name: Upgrade pip and nox
38
39
  run: |
@@ -40,15 +41,23 @@ jobs:
40
41
  pip --version
41
42
  nox --version
42
43
 
43
- - name: Lint code and check dependencies
44
- continue-on-error: ${{ matrix.nox_pyv == '3.11' }}
45
- run: nox -s lint safety --verbose
44
+ - name: Lint code
45
+ run: nox -s lint
46
46
 
47
47
  - name: Run tests
48
- run: nox -s tests-${{ matrix.nox_pyv || matrix.pyv }} -- --slow --cov-report=xml
48
+ run: nox -s tests-${{ matrix.pyv }} -- --slow --cov-report=xml
49
49
 
50
50
  - name: Upload coverage report
51
- uses: codecov/codecov-action@v3.1.0
51
+ uses: codecov/codecov-action@v5
52
52
 
53
53
  - name: Build package
54
54
  run: nox -s build
55
+
56
+ check:
57
+ if: always()
58
+ needs: [tests]
59
+ runs-on: ubuntu-latest
60
+ steps:
61
+ - uses: re-actors/alls-green@release/v1
62
+ with:
63
+ jobs: ${{ toJSON(needs) }}
@@ -10,7 +10,7 @@ jobs:
10
10
  runs-on: ubuntu-latest
11
11
  steps:
12
12
  - name: Check out the repository
13
- uses: actions/checkout@v4
13
+ uses: actions/checkout@v5
14
14
 
15
15
  - name: Update template via cruft
16
16
  uses: iterative/py-template@main
@@ -138,3 +138,4 @@ dmypy.json
138
138
  cython_debug/
139
139
 
140
140
  .DS_Store
141
+ .vscode/
@@ -2,7 +2,7 @@ default_language_version:
2
2
  python: python3
3
3
  repos:
4
4
  - repo: https://github.com/pre-commit/pre-commit-hooks
5
- rev: v4.6.0
5
+ rev: v6.0.0
6
6
  hooks:
7
7
  - id: check-added-large-files
8
8
  - id: check-case-conflict
@@ -20,13 +20,13 @@ repos:
20
20
  - id: sort-simple-yaml
21
21
  - id: trailing-whitespace
22
22
  - repo: https://github.com/astral-sh/ruff-pre-commit
23
- rev: 'v0.4.4'
23
+ rev: 'v0.14.3'
24
24
  hooks:
25
- - id: ruff
25
+ - id: ruff-check
26
26
  args: [--fix, --exit-non-zero-on-fix]
27
27
  - id: ruff-format
28
28
  - repo: https://github.com/codespell-project/codespell
29
- rev: v2.2.6
29
+ rev: v2.4.1
30
30
  hooks:
31
31
  - id: codespell
32
32
  additional_dependencies: ["tomli"]
@@ -1,9 +1,9 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: scmrepo
3
- Version: 3.3.5
3
+ Version: 3.5.3
4
4
  Summary: scmrepo
5
5
  Author-email: Iterative <support@dvc.org>
6
- License: Apache-2.0
6
+ License-Expression: Apache-2.0
7
7
  Project-URL: Issues, https://github.com/iterative/scmrepo/issues
8
8
  Project-URL: Source, https://github.com/iterative/scmrepo
9
9
  Classifier: Programming Language :: Python :: 3
@@ -11,12 +11,14 @@ Classifier: Programming Language :: Python :: 3.9
11
11
  Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
14
16
  Classifier: Development Status :: 4 - Beta
15
17
  Requires-Python: >=3.9
16
18
  Description-Content-Type: text/x-rst
17
19
  License-File: LICENSE
18
20
  Requires-Dist: gitpython>3
19
- Requires-Dist: dulwich>=0.22.1
21
+ Requires-Dist: dulwich>=0.24.0
20
22
  Requires-Dist: pygit2>=1.14.0
21
23
  Requires-Dist: pygtrie>=2.3.2
22
24
  Requires-Dist: fsspec[tqdm]>=2024.2.0
@@ -27,21 +29,23 @@ Requires-Dist: aiohttp-retry>=2.5.0
27
29
  Requires-Dist: tqdm
28
30
  Provides-Extra: tests
29
31
  Requires-Dist: aioresponses<0.8,>=0.7; extra == "tests"
30
- Requires-Dist: paramiko<4,>=3.4.0; extra == "tests"
32
+ Requires-Dist: paramiko<5,>=3.4.0; extra == "tests"
31
33
  Requires-Dist: pytest<9,>=7; extra == "tests"
32
- Requires-Dist: pytest-asyncio<1,>=0.23.2; extra == "tests"
34
+ Requires-Dist: pytest-asyncio<2,>=0.23.2; extra == "tests"
33
35
  Requires-Dist: pytest-cov>=4.1.0; extra == "tests"
34
36
  Requires-Dist: pytest-docker<4,>=1; extra == "tests"
35
37
  Requires-Dist: pytest-mock; extra == "tests"
36
38
  Requires-Dist: pytest-sugar; extra == "tests"
37
39
  Requires-Dist: pytest-test-utils<0.2,>=0.1.0; extra == "tests"
40
+ Requires-Dist: proxy.py; extra == "tests"
38
41
  Provides-Extra: dev
39
- Requires-Dist: mypy==1.10.0; extra == "dev"
42
+ Requires-Dist: mypy==1.18.2; extra == "dev"
40
43
  Requires-Dist: scmrepo[tests]; extra == "dev"
41
44
  Requires-Dist: types-certifi; extra == "dev"
42
45
  Requires-Dist: types-mock; extra == "dev"
43
46
  Requires-Dist: types-paramiko; extra == "dev"
44
47
  Requires-Dist: types-tqdm; extra == "dev"
48
+ Dynamic: license-file
45
49
 
46
50
  scmrepo
47
51
  =======
@@ -10,7 +10,11 @@ nox.options.sessions = "lint", "tests"
10
10
  locations = "src", "tests"
11
11
 
12
12
 
13
- @nox.session(python=["3.9", "3.10", "3.11", "3.12"])
13
+ project = nox.project.load_toml()
14
+ python_versions = nox.project.python_versions(project)
15
+
16
+
17
+ @nox.session(python=python_versions)
14
18
  def tests(session: nox.Session) -> None:
15
19
  session.install(".[tests]")
16
20
  session.run(
@@ -32,14 +36,6 @@ def lint(session: nox.Session) -> None:
32
36
  session.run("python", "-m", "mypy")
33
37
 
34
38
 
35
- @nox.session
36
- def safety(session: nox.Session) -> None:
37
- """Scan dependencies for insecure packages."""
38
- session.install(".[dev]")
39
- session.install("safety")
40
- session.run("safety", "check", "--full-report", "--ignore=67599")
41
-
42
-
43
39
  @nox.session
44
40
  def build(session: nox.Session) -> None:
45
41
  session.install("build", "setuptools", "twine")
@@ -1,5 +1,5 @@
1
1
  [build-system]
2
- requires = ["setuptools>=48", "setuptools_scm[toml]>=6.3.1"]
2
+ requires = ["setuptools>=77", "setuptools_scm[toml]>=8"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [tool.setuptools_scm]
@@ -8,7 +8,8 @@ build-backend = "setuptools.build_meta"
8
8
  name = "scmrepo"
9
9
  description = "scmrepo"
10
10
  readme = "README.rst"
11
- license = {text = "Apache-2.0"}
11
+ license = "Apache-2.0"
12
+ license-files = ["LICENSE"]
12
13
  authors = [{ name = "Iterative", email = "support@dvc.org" }]
13
14
  classifiers = [
14
15
  "Programming Language :: Python :: 3",
@@ -16,13 +17,15 @@ classifiers = [
16
17
  "Programming Language :: Python :: 3.10",
17
18
  "Programming Language :: Python :: 3.11",
18
19
  "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ "Programming Language :: Python :: 3.14",
19
22
  "Development Status :: 4 - Beta",
20
23
  ]
21
24
  requires-python = ">=3.9"
22
25
  dynamic = ["version"]
23
26
  dependencies = [
24
27
  "gitpython>3",
25
- "dulwich>=0.22.1",
28
+ "dulwich>=0.24.0",
26
29
  "pygit2>=1.14.0",
27
30
  "pygtrie>=2.3.2",
28
31
  "fsspec[tqdm]>=2024.2.0",
@@ -40,17 +43,18 @@ Source = "https://github.com/iterative/scmrepo"
40
43
  [project.optional-dependencies]
41
44
  tests = [
42
45
  "aioresponses>=0.7,<0.8",
43
- "paramiko>=3.4.0,<4",
46
+ "paramiko>=3.4.0,<5",
44
47
  "pytest>=7,<9",
45
- "pytest-asyncio>=0.23.2,<1",
48
+ "pytest-asyncio>=0.23.2,<2",
46
49
  "pytest-cov>=4.1.0",
47
50
  "pytest-docker>=1,<4",
48
51
  "pytest-mock",
49
52
  "pytest-sugar",
50
53
  "pytest-test-utils>=0.1.0,<0.2",
54
+ "proxy.py",
51
55
  ]
52
56
  dev = [
53
- "mypy==1.10.0",
57
+ "mypy==1.18.2",
54
58
  "scmrepo[tests]",
55
59
  "types-certifi",
56
60
  "types-mock",
@@ -73,6 +77,7 @@ markers = [
73
77
  ]
74
78
  asyncio_mode = "auto"
75
79
 
80
+
76
81
  [tool.coverage.run]
77
82
  branch = true
78
83
  source = ["scmrepo", "tests"]
@@ -99,7 +104,7 @@ show_error_codes = true
99
104
  show_error_context = true
100
105
  show_traceback = true
101
106
  pretty = true
102
- check_untyped_defs = false
107
+ check_untyped_defs = true
103
108
  # Warnings
104
109
  warn_no_return = true
105
110
  warn_redundant_casts = true
@@ -123,6 +128,7 @@ ignore_missing_imports = true
123
128
 
124
129
  [tool.codespell]
125
130
  ignore-words-list = "cachable, keypair"
131
+ skip = "CODE_OF_CONDUCT.rst"
126
132
 
127
133
  [tool.ruff]
128
134
  output-format = "full"
@@ -143,6 +149,7 @@ ignore = [
143
149
  "RET503", # implicit-return
144
150
  "SIM117", # multiple-with-statements
145
151
  "N818", # error-suffix-on-exception-name
152
+ "PLC0415", # import-outside-top-level
146
153
  ]
147
154
  select = [
148
155
  "A", # flake8-buitlins
@@ -187,8 +194,9 @@ select = [
187
194
 
188
195
  [tool.ruff.lint.per-file-ignores]
189
196
  "noxfile.py" = ["D", "PTH"]
190
- "tests/**" = ["S", "ARG001", "ARG002", "ANN"]
197
+ "tests/**" = ["S", "ARG001", "ARG002", "ANN", "TID251", "TID253"]
191
198
  "docs/**" = ["INP"]
199
+ "src/scmrepo/git/backend/gitpython.py" = ["TID251"]
192
200
 
193
201
  [tool.ruff.lint.flake8-pytest-style]
194
202
  fixture-parentheses = false
@@ -198,6 +206,14 @@ parametrize-names-type = "csv"
198
206
  [tool.ruff.lint.flake8-type-checking]
199
207
  strict = true
200
208
 
209
+ [tool.ruff.lint.flake8-tidy-imports.banned-api]
210
+ "git".msg = "importing from 'git' is not allowed except inside `gitpython` backend"
211
+
212
+ [tool.ruff.lint.flake8-tidy-imports]
213
+ # Ban certain modules from being imported at module level, instead requiring
214
+ # that they're imported lazily (e.g., within a function definition).
215
+ banned-module-level-imports = ["git"]
216
+
201
217
  [tool.ruff.lint.isort]
202
218
  known-first-party = ["scmrepo"]
203
219
 
@@ -6,7 +6,6 @@ import threading
6
6
  from typing import Any, Optional
7
7
 
8
8
  from fsspec.asyn import ( # noqa: F401, pylint:disable=unused-import
9
- _selector_policy,
10
9
  sync,
11
10
  sync_wrapper,
12
11
  )
@@ -23,8 +22,7 @@ def get_loop() -> asyncio.AbstractEventLoop:
23
22
  if default_loop[0] is None:
24
23
  with lock:
25
24
  if default_loop[0] is None:
26
- with _selector_policy():
27
- default_loop[0] = asyncio.new_event_loop()
25
+ default_loop[0] = asyncio.new_event_loop()
28
26
  loop = default_loop[0]
29
27
  th = threading.Thread(
30
28
  target=loop.run_forever, # type: ignore[attr-defined]
@@ -103,3 +103,7 @@ class Base(AbstractContextManager):
103
103
 
104
104
  def _reset(self) -> None:
105
105
  pass
106
+
107
+ def list_submodules(self) -> list[str]:
108
+ """Returns a list of submodules in the repo."""
109
+ return []
@@ -3,9 +3,7 @@ import os
3
3
  import posixpath
4
4
  from typing import TYPE_CHECKING, Any, BinaryIO, Callable, Optional
5
5
 
6
- from fsspec.callbacks import _DEFAULT_CALLBACK
7
6
  from fsspec.spec import AbstractFileSystem
8
- from fsspec.utils import isfilelike
9
7
 
10
8
  if TYPE_CHECKING:
11
9
  from io import BytesIO
@@ -242,32 +240,3 @@ class GitFileSystem(AbstractFileSystem):
242
240
  return paths
243
241
 
244
242
  return [self.info(_path) for _path in paths]
245
-
246
- def get_file(
247
- self, rpath, lpath, callback=_DEFAULT_CALLBACK, outfile=None, **kwargs
248
- ):
249
- # NOTE: temporary workaround while waiting for
250
- # https://github.com/fsspec/filesystem_spec/pull/1191
251
-
252
- if isfilelike(lpath):
253
- outfile = lpath
254
- elif self.isdir(rpath):
255
- os.makedirs(lpath, exist_ok=True)
256
- return None
257
-
258
- with self.open(rpath, "rb", **kwargs) as f1:
259
- if outfile is None:
260
- outfile = open(lpath, "wb") # noqa: SIM115
261
-
262
- try:
263
- callback.set_size(getattr(f1, "size", None))
264
- data = True
265
- while data:
266
- data = f1.read(self.blocksize)
267
- segment_len = outfile.write(data)
268
- if segment_len is None:
269
- segment_len = len(data)
270
- callback.relative_update(segment_len)
271
- finally:
272
- if not isfilelike(lpath):
273
- outfile.close()
@@ -10,6 +10,7 @@ from contextlib import contextmanager
10
10
  from functools import partialmethod
11
11
  from typing import (
12
12
  TYPE_CHECKING,
13
+ Any,
13
14
  Callable,
14
15
  ClassVar,
15
16
  Optional,
@@ -258,7 +259,7 @@ class Git(Base):
258
259
  self.hooks_dir.mkdir(exist_ok=True)
259
260
  hook = self.hooks_dir / name
260
261
 
261
- directive = f"#!{shutil.which(interpreter) or '/bin/sh' }"
262
+ directive = f"#!{shutil.which(interpreter) or '/bin/sh'}"
262
263
  hook.write_text(f"{directive}\n{script}\n", encoding="utf-8")
263
264
  hook.chmod(0o777)
264
265
 
@@ -287,7 +288,7 @@ class Git(Base):
287
288
  def no_commits(self):
288
289
  return not bool(self.get_ref("HEAD"))
289
290
 
290
- # Prefer re-using the most recently used backend when possible. When
291
+ # Prefer reusing the most recently used backend when possible. When
291
292
  # changing backends (due to unimplemented calls), we close the previous
292
293
  # backend to release any open git files/contexts that may cause conflicts
293
294
  # with the new backend.
@@ -295,7 +296,7 @@ class Git(Base):
295
296
  # See:
296
297
  # https://github.com/iterative/dvc/issues/5641
297
298
  # https://github.com/iterative/dvc/issues/7458
298
- def _backend_func(self, name, *args, **kwargs):
299
+ def _backend_func(self, name, *args, **kwargs) -> Any:
299
300
  backends: Iterable[str] = kwargs.pop("backends", self.backends)
300
301
  for key in backends:
301
302
  if self._last_backend is not None and key != self._last_backend:
@@ -411,6 +412,7 @@ class Git(Base):
411
412
  check_attr = partialmethod(_backend_func, "check_attr")
412
413
 
413
414
  get_tree_obj = partialmethod(_backend_func, "get_tree_obj")
415
+ list_submodules = partialmethod(_backend_func, "list_submodules")
414
416
 
415
417
  def branch_revs(self, branch: str, end_rev: Optional[str] = None) -> Iterable[str]:
416
418
  """Iterate over revisions in a given branch (from newest to oldest).
@@ -40,7 +40,7 @@ class BaseGitBackend(ABC):
40
40
 
41
41
  @property
42
42
  @abstractmethod
43
- def root_dir(self) -> str:
43
+ def root_dir(self) -> Optional[str]:
44
44
  pass
45
45
 
46
46
  @staticmethod