fuse4dbricks 0.7.5__tar.gz → 0.7.7__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 (42) hide show
  1. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/.github/workflows/test.yml +80 -80
  2. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/CHANGELOG.md +9 -0
  3. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/PKG-INFO +2 -2
  4. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/fs/data_manager.py +10 -2
  5. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/main.py +13 -1
  6. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/pyproject.toml +1 -1
  7. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/.env.example +0 -0
  8. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/.gitignore +0 -0
  9. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/README.md +0 -0
  10. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/__init__.py +0 -0
  11. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/api/__init__.py +0 -0
  12. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/api/errors.py +0 -0
  13. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/api/uc_client.py +0 -0
  14. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/auth/__init__.py +0 -0
  15. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/auth/provider.py +0 -0
  16. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/fs/__init__.py +0 -0
  17. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/fs/auth_manager.py +0 -0
  18. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/fs/inode_manager.py +0 -0
  19. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/fs/metadata_manager.py +0 -0
  20. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/fs/operations.py +0 -0
  21. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/fs/ram_cache.py +0 -0
  22. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/fs/securable_filter.py +0 -0
  23. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/fs/utils.py +0 -0
  24. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/fs/write_buffer.py +0 -0
  25. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/storage/__init__.py +0 -0
  26. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/fuse4dbricks/storage/persistence.py +0 -0
  27. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_auth_manager.py +0 -0
  28. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_auth_provider.py +0 -0
  29. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_data_manager.py +0 -0
  30. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_e2e_mount.py +0 -0
  31. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_inode_manager.py +0 -0
  32. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_main.py +0 -0
  33. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_metadata_manager.py +0 -0
  34. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_operations.py +0 -0
  35. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_persistence.py +0 -0
  36. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_securable_filter.py +0 -0
  37. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_uc_client.py +0 -0
  38. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_uc_client_consistency.py +0 -0
  39. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_uc_client_live.py +0 -0
  40. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_utils.py +0 -0
  41. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/tests/test_write_buffer.py +0 -0
  42. {fuse4dbricks-0.7.5 → fuse4dbricks-0.7.7}/uv.lock +0 -0
@@ -1,80 +1,80 @@
1
- name: Test and lint
2
-
3
- on:
4
- push:
5
- branches: [ main ]
6
- tags: [ 'v*' ]
7
- pull_request:
8
- branches: [ main ]
9
-
10
- # Security hardening: restricts the GITHUB_TOKEN to read-only access
11
- permissions:
12
- contents: read
13
-
14
- jobs:
15
- build:
16
- runs-on: ubuntu-latest
17
-
18
- steps:
19
- - name: Checkout code
20
- uses: actions/checkout@v6
21
-
22
- - name: Set up Python 3.11
23
- uses: actions/setup-python@v6
24
- with:
25
- python-version: "3.11"
26
- # Caches pip packages to speed up subsequent runs
27
- cache: 'pip'
28
-
29
- - name: Install system dependencies for pyfuse3
30
- run: |
31
- sudo apt-get update
32
- sudo apt-get install -y libfuse3-dev fuse3 pkg-config
33
-
34
- - name: Install Python dependencies
35
- run: |
36
- python -m pip install --upgrade pip
37
- # wheel is required to build the pyfuse3 C-extension correctly
38
- pip install wheel flake8 pytest
39
- pip install --group dev .
40
-
41
- - name: Lint with flake8
42
- run: |
43
- # stop the build if there are Python syntax errors or undefined names
44
- flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
45
- # exit-zero treats all errors as warnings.
46
- flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
47
-
48
- - name: Run tests
49
- run: |
50
- pytest .
51
-
52
- - name: Install pypa/build
53
- run: python3 -m pip install uv
54
- - name: Build a binary wheel and a source tarball
55
- run: uv build
56
- - name: Store the distribution packages
57
- uses: actions/upload-artifact@v7
58
- with:
59
- name: python-package-distributions
60
- path: dist/
61
-
62
- publish-to-pypi:
63
- name: Publish package to PyPI
64
- if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
65
- needs:
66
- - build
67
- runs-on: ubuntu-latest
68
- environment:
69
- name: pypi
70
- url: https://pypi.org/p/fuse4dbricks
71
- permissions:
72
- id-token: write
73
- steps:
74
- - name: Download all the dists
75
- uses: actions/download-artifact@v6
76
- with:
77
- name: python-package-distributions
78
- path: dist/
79
- - name: Publish distribution to PyPI
80
- uses: pypa/gh-action-pypi-publish@release/v1
1
+ name: Test and lint
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ tags: [ 'v*' ]
7
+ pull_request:
8
+ branches: [ main ]
9
+
10
+ # Security hardening: restricts the GITHUB_TOKEN to read-only access
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ build:
16
+ runs-on: ubuntu-latest
17
+
18
+ steps:
19
+ - name: Checkout code
20
+ uses: actions/checkout@v6
21
+
22
+ - name: Set up Python 3.11
23
+ uses: actions/setup-python@v6
24
+ with:
25
+ python-version: "3.11"
26
+ # Caches pip packages to speed up subsequent runs
27
+ cache: 'pip'
28
+
29
+ - name: Install system dependencies for pyfuse3
30
+ run: |
31
+ sudo apt-get update
32
+ sudo apt-get install -y libfuse3-dev fuse3 pkg-config
33
+
34
+ - name: Install Python dependencies
35
+ run: |
36
+ python -m pip install --upgrade pip
37
+ # wheel is required to build the pyfuse3 C-extension correctly
38
+ pip install wheel flake8 pytest
39
+ pip install --group dev .
40
+
41
+ - name: Lint with flake8
42
+ run: |
43
+ # stop the build if there are Python syntax errors or undefined names
44
+ flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
45
+ # exit-zero treats all errors as warnings.
46
+ flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
47
+
48
+ - name: Run tests
49
+ run: |
50
+ pytest .
51
+
52
+ - name: Install pypa/build
53
+ run: python3 -m pip install uv
54
+ - name: Build a binary wheel and a source tarball
55
+ run: uv build
56
+ - name: Store the distribution packages
57
+ uses: actions/upload-artifact@v7
58
+ with:
59
+ name: python-package-distributions
60
+ path: dist/
61
+
62
+ publish-to-pypi:
63
+ name: Publish package to PyPI
64
+ if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
65
+ needs:
66
+ - build
67
+ runs-on: ubuntu-latest
68
+ environment:
69
+ name: pypi
70
+ url: https://pypi.org/p/fuse4dbricks
71
+ permissions:
72
+ id-token: write
73
+ steps:
74
+ - name: Download all the dists
75
+ uses: actions/download-artifact@v8
76
+ with:
77
+ name: python-package-distributions
78
+ path: dist/
79
+ - name: Publish distribution to PyPI
80
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -1,3 +1,12 @@
1
+ # 0.7.7 (2026-10-01)
2
+
3
+ - Add --num-download-workers and --prefetch-mb to control prefetching
4
+ and parallel downloads.
5
+
6
+ # 0.7.6 (2026-08-07)
7
+
8
+ - Force push. Bump for traceability.
9
+
1
10
  # 0.7.5 (2026-08-06)
2
11
 
3
12
  - Fix fatal startup/runtime errors exiting with status 0 instead of 1.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: fuse4dbricks
3
- Version: 0.7.5
3
+ Version: 0.7.7
4
4
  Summary: FUSE driver for Databricks Unity Catalog Volumes.
5
5
  Project-URL: Homepage, https://github.com/zeehio/fuse4dbricks
6
6
  Author-email: Sergio Oller <sergioller@gmail.com>
@@ -116,7 +116,7 @@ class DownloadScheduler:
116
116
 
117
117
 
118
118
  class DataManager:
119
- def __init__(self, uc_client: UnityCatalogClient, persistence: DiskPersistence, ram_cache_mb = 512, num_workers=10):
119
+ def __init__(self, uc_client: UnityCatalogClient, persistence: DiskPersistence, ram_cache_mb = 512, num_workers=10, prefecth_mb=80):
120
120
  """
121
121
  uc_client: client to download chunks from UC
122
122
  persistence: where to store downloaded chunks on disk
@@ -129,6 +129,9 @@ class DataManager:
129
129
  self._inflight_coalescer: InflightCoalescer[_CacheKey] = InflightCoalescer()
130
130
  "Inflight coalescer for downloads identified by (fs_path, chunk_id, mtime, gen)"
131
131
 
132
+ if num_workers < 1:
133
+ raise ValueError("num_workers must be >= 1")
134
+
132
135
  self._download_scheduler = DownloadScheduler(process_request=self._process_request, num_workers=num_workers)
133
136
 
134
137
  # Per-path cache generation. Bumped on a local write so previously cached
@@ -138,6 +141,11 @@ class DataManager:
138
141
  # max number of chunks to cache in memory
139
142
  max_ram_chunks = int(ram_cache_mb*1024*1024 / self.chunk_size)
140
143
  self._ram_cache: RamCache[_CacheKey] = RamCache(max_entries = max_ram_chunks)
144
+ prefetch_bytes = prefecth_mb * 1024 * 1024
145
+ chunks_to_prefetch = int(prefetch_bytes / self.chunk_size)
146
+ if chunks_to_prefetch < 0:
147
+ chunks_to_prefetch = 0
148
+ self._chunks_to_prefetch = chunks_to_prefetch
141
149
 
142
150
  def close(self) -> None:
143
151
  self._download_scheduler.close()
@@ -296,7 +304,7 @@ class DataManager:
296
304
  self._read_chunk, fs_path, chunk_id, mtime, gen, chunk_size, ctx, chunks
297
305
  )
298
306
  # fetch ahead next 10 chunks once we are beyond chunk 0 (avoid prefetching too much on `head *` command)
299
- num_chunks_to_prefetch = 10 if end_chunk > 0 else 1
307
+ num_chunks_to_prefetch = self._chunks_to_prefetch if end_chunk > 0 else min(1, self._chunks_to_prefetch)
300
308
  chunks_to_prefetch = []
301
309
  for i in range(num_chunks_to_prefetch):
302
310
  chunk_to_prefetch = end_chunk + 1 + i
@@ -95,6 +95,18 @@ def parse_args():
95
95
  default=30,
96
96
  help="Default TTL for metadata cache entries in seconds",
97
97
  )
98
+ parser.add_argument(
99
+ "--prefetch_mb",
100
+ type=int,
101
+ default=80,
102
+ help="Amount of data to prefetch in MB for each file",
103
+ )
104
+ parser.add_argument(
105
+ "--num-download-workers",
106
+ type=int,
107
+ default=10,
108
+ help="Number of concurrent download workers",
109
+ )
98
110
  parser.add_argument(
99
111
  "--metadata-cache-ttl-catalog-sec",
100
112
  type=int,
@@ -242,7 +254,7 @@ async def async_main():
242
254
  persistence = DiskPersistence(data_cache_dir, max_size_gb=args.disk_cache_gb, max_age_days=args.disk_cache_max_days)
243
255
 
244
256
  inode_manager = InodeManager()
245
- data_manager = DataManager(uc_client, persistence, ram_cache_mb=args.ram_cache_mb)
257
+ data_manager = DataManager(uc_client, persistence, ram_cache_mb=args.ram_cache_mb, num_workers=args.num_download_workers, prefetch_mb=args.prefetch_mb)
246
258
  metadata_manager = MetadataManager(uc_client, ttl=args.metadata_cache_ttl_sec, max_entries=args.metadata_cache_max_entries, ttl_catalog=args.metadata_cache_ttl_catalog_sec, ttl_negative=args.metadata_cache_ttl_negative_sec, inode_manager=inode_manager)
247
259
  # On a 401, the token is invalidated and re-resolved (possibly to a
248
260
  # different principal); drop the cached principal so authz re-derives it.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "fuse4dbricks"
7
- version = "0.7.5"
7
+ version = "0.7.7"
8
8
  description = "FUSE driver for Databricks Unity Catalog Volumes."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
File without changes
File without changes
File without changes
File without changes