fsspec-databricks 0.1.9__tar.gz → 0.2.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.
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/.github/workflows/check.yaml +1 -1
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/.github/workflows/on_push.yaml +0 -1
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/.github/workflows/on_release.yaml +1 -1
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/.github/workflows/publish.yaml +3 -3
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/.github/workflows/test.yaml +6 -6
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/.pre-commit-config.yaml +2 -2
- fsspec_databricks-0.2.0/AUTHENTICATION.md +81 -0
- fsspec_databricks-0.2.0/CLAUDE.md +108 -0
- fsspec_databricks-0.2.0/DEVELOPMENT.md +388 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/LICENSE +1 -1
- fsspec_databricks-0.2.0/PKG-INFO +128 -0
- fsspec_databricks-0.2.0/README.md +103 -0
- fsspec_databricks-0.2.0/USAGE.md +301 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/pyproject.toml +7 -3
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/src/fsspec_databricks/file.py +65 -53
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/src/fsspec_databricks/local.py +10 -5
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/src/fsspec_databricks/path.py +26 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/src/fsspec_databricks/spec.py +117 -42
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/src/fsspec_databricks/utils.py +4 -4
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/src/fsspec_databricks/volume.py +126 -63
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/tests/conftest.py +2 -1
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/tests/dummy_api.py +16 -4
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/tests/test_file.py +10 -2
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/tests/test_path.py +20 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/tests/test_spec_fs.py +81 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/tests/test_utils.py +2 -2
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/tests/test_volume.py +51 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/tests/test_volume_fs.py +47 -15
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/tests/test_workspace_fs.py +7 -7
- fsspec_databricks-0.1.9/DEVELOPMENT.md +0 -65
- fsspec_databricks-0.1.9/PKG-INFO +0 -277
- fsspec_databricks-0.1.9/README.md +0 -251
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/.github/dependabot.yml +0 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/.gitignore +0 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/src/fsspec_databricks/__init__.py +0 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/src/fsspec_databricks/base.py +0 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/src/fsspec_databricks/dbfs.py +0 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/src/fsspec_databricks/error.py +0 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/src/fsspec_databricks/py.typed +0 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/src/fsspec_databricks/workspace.py +0 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/tests/__init__.py +0 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/tests/test_base_fs.py +0 -0
- {fsspec_databricks-0.1.9 → fsspec_databricks-0.2.0}/tests/utils.py +0 -0
|
@@ -24,10 +24,10 @@ jobs:
|
|
|
24
24
|
name: ${{ inputs.environment }}
|
|
25
25
|
|
|
26
26
|
steps:
|
|
27
|
-
- uses: actions/checkout@
|
|
27
|
+
- uses: actions/checkout@v7
|
|
28
28
|
|
|
29
29
|
- name: Set up Python
|
|
30
|
-
uses: actions/setup-python@
|
|
30
|
+
uses: actions/setup-python@v7
|
|
31
31
|
with:
|
|
32
32
|
python-version: ${{ inputs.python-version }}
|
|
33
33
|
|
|
@@ -40,4 +40,4 @@ jobs:
|
|
|
40
40
|
run: uv build
|
|
41
41
|
|
|
42
42
|
- name: Publish Python package
|
|
43
|
-
run: uv publish
|
|
43
|
+
run: uv publish
|
|
@@ -61,10 +61,10 @@ jobs:
|
|
|
61
61
|
environment: ${{ inputs.environment }}
|
|
62
62
|
|
|
63
63
|
steps:
|
|
64
|
-
- uses: actions/checkout@
|
|
64
|
+
- uses: actions/checkout@v7
|
|
65
65
|
|
|
66
66
|
- name: Set up Python ${{ inputs.python-version }}
|
|
67
|
-
uses: actions/setup-python@
|
|
67
|
+
uses: actions/setup-python@v7
|
|
68
68
|
with:
|
|
69
69
|
python-version: ${{ inputs.python-version }}
|
|
70
70
|
|
|
@@ -81,7 +81,7 @@ jobs:
|
|
|
81
81
|
run: |
|
|
82
82
|
test_path="${{ github.ref_name }}/${{ inputs.python-version }}"
|
|
83
83
|
|
|
84
|
-
has_error=no
|
|
84
|
+
has_error=no
|
|
85
85
|
if [[ "${{ vars.FSSPEC_DATABRICKS_VOLUME_TEST_ROOT }}" == "" ]]; then
|
|
86
86
|
echo "GitHub Actions variable FSSPEC_DATABRICKS_VOLUME_TEST_ROOT must be set."
|
|
87
87
|
has_error=yes
|
|
@@ -126,14 +126,14 @@ jobs:
|
|
|
126
126
|
|
|
127
127
|
- name: Upload coverage to Codecov
|
|
128
128
|
if: ${{ inputs.coverage && !cancelled() }}
|
|
129
|
-
uses: codecov/codecov-action@
|
|
129
|
+
uses: codecov/codecov-action@v7
|
|
130
130
|
with:
|
|
131
131
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
132
132
|
report_type: coverage
|
|
133
133
|
|
|
134
134
|
- name: Upload test results to Codecov
|
|
135
135
|
if: ${{ inputs.coverage && !cancelled() }}
|
|
136
|
-
uses: codecov/codecov-action@
|
|
136
|
+
uses: codecov/codecov-action@v7
|
|
137
137
|
with:
|
|
138
138
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
139
|
-
report_type: test_results
|
|
139
|
+
report_type: test_results
|
|
@@ -5,14 +5,14 @@ exclude: >
|
|
|
5
5
|
repos:
|
|
6
6
|
|
|
7
7
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
8
|
-
rev:
|
|
8
|
+
rev: v6.0.0
|
|
9
9
|
hooks:
|
|
10
10
|
- id: trailing-whitespace
|
|
11
11
|
- id: end-of-file-fixer
|
|
12
12
|
- id: check-json
|
|
13
13
|
- id: check-yaml
|
|
14
14
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
15
|
-
rev: v0.
|
|
15
|
+
rev: v0.17.2
|
|
16
16
|
hooks:
|
|
17
17
|
- id: ruff-check
|
|
18
18
|
args: [ --fix, "--show-fixes"]
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Authentication
|
|
2
|
+
|
|
3
|
+
`fsspec-databricks` uses Databricks Unified Authentication, through the Databricks Python SDK. Its parameters and
|
|
4
|
+
environment variables are in the
|
|
5
|
+
[Databricks Python SDK documentation](https://databricks-sdk-py.readthedocs.io/en/latest/authentication.html).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Default
|
|
10
|
+
|
|
11
|
+
With Databricks Unified Authentication configured, e.g. a default profile, no parameter is needed:
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from fsspec_databricks import DatabricksFileSystem
|
|
15
|
+
|
|
16
|
+
fs = DatabricksFileSystem()
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Constructor parameters
|
|
22
|
+
|
|
23
|
+
`DatabricksFileSystem` takes the parameters of the SDK's `WorkspaceClient`:
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
# Personal access token
|
|
27
|
+
fs = DatabricksFileSystem(host=host_url, token=access_token)
|
|
28
|
+
|
|
29
|
+
# Another profile
|
|
30
|
+
fs = DatabricksFileSystem(profile="production")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Environment variables
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
export DATABRICKS_CONFIG_PROFILE=production
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
fs = DatabricksFileSystem() # uses the "production" profile
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## fsspec configuration
|
|
48
|
+
|
|
49
|
+
[fsspec's configuration](https://filesystem-spec.readthedocs.io/en/latest/features.html#configuration) sets default
|
|
50
|
+
parameters for the `dbfs` protocol:
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
import fsspec
|
|
54
|
+
|
|
55
|
+
fsspec.config.conf["dbfs"] = {"profile": "production"}
|
|
56
|
+
|
|
57
|
+
fs = DatabricksFileSystem() # uses the "production" profile
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Or with environment variables named `FSSPEC_DBFS_<PARAMETER>`, read when fsspec is imported:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
export FSSPEC_DBFS_PROFILE=production
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## `WorkspaceClient`
|
|
69
|
+
|
|
70
|
+
`DatabricksFileSystem` can use a `WorkspaceClient` of yours, with its authentication:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from databricks.sdk import WorkspaceClient
|
|
74
|
+
|
|
75
|
+
client = WorkspaceClient(...)
|
|
76
|
+
|
|
77
|
+
fs = DatabricksFileSystem(client=client)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
A file system created with a `WorkspaceClient` is generally not picklable, as `WorkspaceClient` objects are not. Use
|
|
81
|
+
another way to authenticate where file systems are pickled, e.g. with Dask.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
All Python goes through uv: never call `python` or `pip` directly.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
uv sync # the package, editable, with the dev dependencies
|
|
11
|
+
uv run pytest # all tests: most need a Databricks workspace (see below)
|
|
12
|
+
uv run pytest tests/test_path.py -k volume # one file / matching tests
|
|
13
|
+
uv run pytest --cov # with coverage of src/
|
|
14
|
+
uvx ruff check . # lint (ruff is not a dev dependency; config in pyproject.toml)
|
|
15
|
+
uvx ruff format . # format
|
|
16
|
+
uvx pre-commit run --all-files # the hooks: ruff, whitespace, end of files, YAML
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
CI, in `.github/workflows/on_push.yaml`, runs on pushes:
|
|
20
|
+
|
|
21
|
+
- ruff check and ruff format check, with the latest ruff;
|
|
22
|
+
- pytest on Python 3.14 against the default workspace, with coverage on `main`;
|
|
23
|
+
- on `main`, pytest on the other supported Python versions;
|
|
24
|
+
- pytest on Azure, AWS or GCP workspaces named in the `TEST_ENVIRONMENTS` variable.
|
|
25
|
+
|
|
26
|
+
Releases are published GitHub releases. DEVELOPMENT.md describes them.
|
|
27
|
+
|
|
28
|
+
## Tests and layout
|
|
29
|
+
|
|
30
|
+
DEVELOPMENT.md describes the layout, the tests and their setup. Read its Tests section before writing tests. The traps:
|
|
31
|
+
|
|
32
|
+
- Most tests run against a real workspace. They need credentials and the two test root variables, from `.env` or the
|
|
33
|
+
environment.
|
|
34
|
+
- The session fixtures `volume_test_root` and `workspace_test_root` delete everything in the test roots first. Never
|
|
35
|
+
point them at folders holding anything else.
|
|
36
|
+
- Without credentials, run `tests/test_file.py`, `tests/test_volume.py`, `tests/test_path.py` and `tests/test_utils.py`.
|
|
37
|
+
`test_volume.py` and `test_file.py` use the fake Files API in `tests/dummy_api.py`.
|
|
38
|
+
- A test of anything a workspace serves gets a check without one where possible, on the fake API or with mocks.
|
|
39
|
+
- Test helpers shared by files are in `tests/utils.py`.
|
|
40
|
+
- `tests/conftest.py` sets `cachable = False`, so each test gets new file system instances.
|
|
41
|
+
|
|
42
|
+
## Architecture
|
|
43
|
+
|
|
44
|
+
DEVELOPMENT.md's Architecture section describes each part: read it before changing one. The traps:
|
|
45
|
+
|
|
46
|
+
- `DatabricksFileSystem` routes each call to a backend by path. It holds no file system logic of its own, except for
|
|
47
|
+
the root folder and transfers between backends.
|
|
48
|
+
- Its methods get the backend and the path to pass with `_resolve(path)`. Inside a workspace, that path is a local
|
|
49
|
+
path, and names returned are mapped back with `from_local_path`.
|
|
50
|
+
- Base class methods in `base.py` only check preconditions. Subclasses call `super()` first, then the API.
|
|
51
|
+
- Wrap Databricks SDK calls in `error_mapping(path)`, so that callers get `OSError` subclasses.
|
|
52
|
+
- Parse paths with the helpers of `path.py`. Every method takes `dbfs:/` URLs and POSIX paths alike.
|
|
53
|
+
- aiohttp objects are created and used in the Volume backend's IO event loop. `TCPConnector` needs a running loop.
|
|
54
|
+
- Never block on the IO loop from code running in it. File objects' synchronous methods raise there.
|
|
55
|
+
- `DatabricksFileSystem.__init__` takes every parameter of the SDK's `WorkspaceClient`, in its order.
|
|
56
|
+
`test_dbx_fs_accepts_workspace_client_params` fails when the SDK adds one: add it to the signature, the docstring
|
|
57
|
+
and `config_params`.
|
|
58
|
+
- File systems must stay picklable. A new attribute holding a client, a loop, a thread or a session is dropped in
|
|
59
|
+
`__getstate__` and reset in `__setstate__`.
|
|
60
|
+
- Multipart upload uses an undocumented Databricks API. Keep its fallback to resumable upload working.
|
|
61
|
+
- Volume write block sizes are multiples of 256 KB.
|
|
62
|
+
- Workspace files are cached whole in memory, up to the API's 10 MB.
|
|
63
|
+
- Chatty debug logs go under `if self.verbose_debug_log:`.
|
|
64
|
+
|
|
65
|
+
## Conventions
|
|
66
|
+
|
|
67
|
+
### Code
|
|
68
|
+
|
|
69
|
+
- Comments are short, and say why the code does something not obvious. Keep that density and tone.
|
|
70
|
+
- Type hints use built-in generics and `X | None`.
|
|
71
|
+
- Each module ends with `__all__`.
|
|
72
|
+
|
|
73
|
+
### Docstrings
|
|
74
|
+
|
|
75
|
+
Docstrings of the public API are in numpy style: `Parameters`, `Returns`, `Raises`. The public API is what users
|
|
76
|
+
construct or call:
|
|
77
|
+
|
|
78
|
+
- `DatabricksFileSystem` and `use`;
|
|
79
|
+
- `VolumeFileSystem`, `WorkspaceFileSystem` and `DBFS`, with their constructors and `open`.
|
|
80
|
+
|
|
81
|
+
Internal docstrings stay one line or short prose: file objects, helpers and underscore names.
|
|
82
|
+
|
|
83
|
+
### Writing docs
|
|
84
|
+
|
|
85
|
+
Write docs so that people can review them. That covers this file, DEVELOPMENT.md and the user docs.
|
|
86
|
+
|
|
87
|
+
- One idea per sentence: about 30 words, never more than 50.
|
|
88
|
+
- At most one parenthesis per sentence, never nested.
|
|
89
|
+
- Three or more items make a list.
|
|
90
|
+
- Add a new fact as its own sentence or bullet where it belongs. Never append it to an existing sentence.
|
|
91
|
+
- Name an identifier only when the reader needs it to find the code. A function's details belong in its docstring.
|
|
92
|
+
- Describe what is, not what was: git keeps the history.
|
|
93
|
+
- When editing a passage that breaks these rules, rewrite it.
|
|
94
|
+
|
|
95
|
+
### Where docs go
|
|
96
|
+
|
|
97
|
+
- README.md is the quick start: features, installation, paths, compatibility, status and limitations.
|
|
98
|
+
- USAGE.md has the user-facing details: operations, each backend's behaviour, and the options.
|
|
99
|
+
- AUTHENTICATION.md covers the ways to configure authentication.
|
|
100
|
+
- DEVELOPMENT.md has setup, tests, CI, releasing, the design choices and the architecture.
|
|
101
|
+
|
|
102
|
+
Update the docs when behaviour, parameters or options change. Keep user docs short and compact: what users do, not how
|
|
103
|
+
it works or why.
|
|
104
|
+
|
|
105
|
+
### Links
|
|
106
|
+
|
|
107
|
+
README.md, USAGE.md and AUTHENTICATION.md are user docs. README.md uses absolute GitHub URLs for links to files, as
|
|
108
|
+
PyPI shows it but cannot resolve relative paths. The other docs are read on GitHub only, so they use relative paths.
|