fsspec-abfs 0.1.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 (62) hide show
  1. fsspec_abfs-0.1.0/.github/dependabot.yml +11 -0
  2. fsspec_abfs-0.1.0/.github/scripts/with-id-token-file.sh +29 -0
  3. fsspec_abfs-0.1.0/.github/workflows/ci.yaml +152 -0
  4. fsspec_abfs-0.1.0/.github/workflows/codeql.yaml +45 -0
  5. fsspec_abfs-0.1.0/.github/workflows/release.yaml +90 -0
  6. fsspec_abfs-0.1.0/.gitignore +56 -0
  7. fsspec_abfs-0.1.0/.pre-commit-config.yaml +20 -0
  8. fsspec_abfs-0.1.0/.python-version +1 -0
  9. fsspec_abfs-0.1.0/DEVELOPMENT.md +433 -0
  10. fsspec_abfs-0.1.0/LICENSE +202 -0
  11. fsspec_abfs-0.1.0/PKG-INFO +161 -0
  12. fsspec_abfs-0.1.0/README.md +129 -0
  13. fsspec_abfs-0.1.0/SECURITY.md +32 -0
  14. fsspec_abfs-0.1.0/USAGE.md +409 -0
  15. fsspec_abfs-0.1.0/codecov.yml +10 -0
  16. fsspec_abfs-0.1.0/pyproject.toml +136 -0
  17. fsspec_abfs-0.1.0/src/fsspec_abfs/__init__.py +62 -0
  18. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/__init__.py +0 -0
  19. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/LICENSE +202 -0
  20. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/_version.py +5 -0
  21. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/common/__init__.py +7 -0
  22. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/common/filesystem.py +638 -0
  23. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/common/jobs.py +669 -0
  24. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/common/operation.py +264 -0
  25. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/common/paths.py +40 -0
  26. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/common/patterns.py +226 -0
  27. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/files/__init__.py +27 -0
  28. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/files/_async_file.py +357 -0
  29. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/files/adaptive.py +942 -0
  30. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/files/fsspec_async.py +308 -0
  31. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/files/fsspec_transaction.py +657 -0
  32. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/py.typed +0 -0
  33. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/router.py +1220 -0
  34. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/tree/__init__.py +10 -0
  35. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/tree/_jobs.py +163 -0
  36. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/tree/cp.py +251 -0
  37. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/tree/du.py +102 -0
  38. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/tree/filesystem.py +533 -0
  39. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/tree/find.py +185 -0
  40. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/tree/glob.py +218 -0
  41. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/tree/mv.py +345 -0
  42. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/tree/rm.py +226 -0
  43. fsspec_abfs-0.1.0/src/fsspec_abfs/_contrib/strategy/tree/walk.py +724 -0
  44. fsspec_abfs-0.1.0/src/fsspec_abfs/_errors.py +110 -0
  45. fsspec_abfs-0.1.0/src/fsspec_abfs/_listing.py +154 -0
  46. fsspec_abfs-0.1.0/src/fsspec_abfs/_paths.py +184 -0
  47. fsspec_abfs-0.1.0/src/fsspec_abfs/_version.py +24 -0
  48. fsspec_abfs-0.1.0/src/fsspec_abfs/abfs.py +1369 -0
  49. fsspec_abfs-0.1.0/src/fsspec_abfs/credentials.py +176 -0
  50. fsspec_abfs-0.1.0/src/fsspec_abfs/py.typed +0 -0
  51. fsspec_abfs-0.1.0/src/fsspec_abfs/routing.py +328 -0
  52. fsspec_abfs-0.1.0/tests/conftest.py +272 -0
  53. fsspec_abfs-0.1.0/tests/dummy_api.py +916 -0
  54. fsspec_abfs-0.1.0/tests/test_abfs.py +512 -0
  55. fsspec_abfs-0.1.0/tests/test_credentials.py +138 -0
  56. fsspec_abfs-0.1.0/tests/test_errors.py +65 -0
  57. fsspec_abfs-0.1.0/tests/test_hns.py +167 -0
  58. fsspec_abfs-0.1.0/tests/test_listing.py +57 -0
  59. fsspec_abfs-0.1.0/tests/test_package.py +9 -0
  60. fsspec_abfs-0.1.0/tests/test_paths.py +240 -0
  61. fsspec_abfs-0.1.0/tests/test_routing.py +557 -0
  62. fsspec_abfs-0.1.0/uv.lock +1980 -0
@@ -0,0 +1,11 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "uv"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+
8
+ - package-ecosystem: "github-actions"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "weekly"
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env bash
2
+ # Runs a command with GitHub's ID token kept in a file, for Microsoft Entra ID's workload identity federation.
3
+ # DefaultAzureCredential's WorkloadIdentityCredential reads AZURE_FEDERATED_TOKEN_FILE whenever it exchanges it.
4
+ set -euo pipefail
5
+
6
+ : "${AZURE_CLIENT_ID:?AZURE_CLIENT_ID must be set}"
7
+ : "${AZURE_TENANT_ID:?AZURE_TENANT_ID must be set}"
8
+ token_file="$RUNNER_TEMP/github-id-token"
9
+
10
+ fetch_token() {
11
+ local token
12
+ token=$(curl -sSf -G \
13
+ -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
14
+ --data-urlencode "audience=api://AzureADTokenExchange" \
15
+ "$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -r .value) || return 1
16
+ [[ -n "$token" && "$token" != "null" ]] || return 1
17
+ echo "::add-mask::$token"
18
+ printf '%s' "$token" > "$token_file.tmp"
19
+ mv "$token_file.tmp" "$token_file"
20
+ }
21
+
22
+ fetch_token
23
+ # GitHub's ID tokens are short-lived, and each new exchange reads the one in the file.
24
+ (while sleep 60; do fetch_token || echo "Failed to refresh GitHub's ID token" >&2; done) &
25
+ refresher=$!
26
+ trap 'kill "$refresher"' EXIT
27
+
28
+ export AZURE_FEDERATED_TOKEN_FILE="$token_file"
29
+ "$@"
@@ -0,0 +1,152 @@
1
+ # Lint the code and the workflows, and test, on every push to main and pull
2
+ # request. The offline tests run on the dummy server, with no credentials, on
3
+ # every supported Python version. The coverage is uploaded to Codecov from one
4
+ # Python version: uploading needs the repository secret CODECOV_TOKEN.
5
+ #
6
+ # The live tests then run on Azure, in the GitHub environment `azure`, which
7
+ # DEVELOPMENT.md describes. An environment without AZURE_CLIENT_ID is skipped.
8
+ name: CI
9
+
10
+ on:
11
+ push:
12
+ branches: [main]
13
+ pull_request:
14
+ workflow_dispatch:
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ concurrency:
20
+ group: ci-${{ github.ref }}
21
+ cancel-in-progress: true
22
+
23
+ jobs:
24
+ lint:
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
28
+ with:
29
+ persist-credentials: false # no job pushes: the token is not left in .git/config
30
+
31
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
32
+ with:
33
+ version: "0.12.22" # not the latest uv: the same in every run
34
+
35
+ - name: Ruff check
36
+ run: uvx ruff check .
37
+
38
+ - name: Ruff format check
39
+ run: uvx ruff format --check .
40
+
41
+ # The workflows: their security (zizmor) and their syntax (actionlint).
42
+ - name: Workflow check
43
+ run: |
44
+ uvx zizmor --offline .github/workflows
45
+ uvx --from actionlint-py actionlint
46
+
47
+ test:
48
+ runs-on: ubuntu-latest
49
+ strategy:
50
+ fail-fast: false
51
+ matrix:
52
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
53
+ steps:
54
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
55
+ with:
56
+ persist-credentials: false # no job pushes: the token is not left in .git/config
57
+ fetch-depth: 0 # the version comes from the git tags (hatch-vcs)
58
+
59
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
60
+ with:
61
+ version: "0.12.22" # not the latest uv: the same in every run
62
+ python-version: ${{ matrix.python-version }}
63
+
64
+ - name: Install the project
65
+ run: uv sync --locked # fails if uv.lock is out of date
66
+
67
+ # The dummy server only, whatever a variable says: this job has no credentials.
68
+ - name: Test with coverage
69
+ run: uv run --no-sync pytest --api=dummy --cov --cov-report=term --cov-report=xml:coverage.xml
70
+
71
+ - name: Upload coverage to Codecov
72
+ if: ${{ !cancelled() && matrix.python-version == '3.14' }}
73
+ uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
74
+ with:
75
+ token: ${{ secrets.CODECOV_TOKEN }}
76
+ files: coverage.xml
77
+
78
+ live:
79
+ needs: test
80
+ # Pull requests from forks and Dependabot get neither the environment's
81
+ # variables nor an OIDC token trusted by Azure: they run offline only.
82
+ if: >-
83
+ github.event_name != 'pull_request'
84
+ || (github.event.pull_request.head.repo.full_name == github.repository
85
+ && github.actor != 'dependabot[bot]')
86
+ runs-on: ubuntu-latest
87
+ environment: azure
88
+ permissions:
89
+ contents: read
90
+ id-token: write # GitHub's OIDC token, for workload identity federation with Microsoft Entra ID
91
+ concurrency:
92
+ # One run at a time: each test works in a folder of its own, but the
93
+ # accounts' throughput is shared.
94
+ group: live-${{ github.ref }}
95
+ cancel-in-progress: false
96
+ env:
97
+ # DefaultAzureCredential takes these for its WorkloadIdentityCredential.
98
+ AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }}
99
+ AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }}
100
+ FSSPEC_ABFS_TEST_HNS_ACCOUNT_URL: ${{ vars.FSSPEC_ABFS_TEST_HNS_ACCOUNT_URL }}
101
+ FSSPEC_ABFS_TEST_FLAT_ACCOUNT_URL: ${{ vars.FSSPEC_ABFS_TEST_FLAT_ACCOUNT_URL }}
102
+ FSSPEC_ABFS_TEST_CONTAINER: ${{ vars.FSSPEC_ABFS_TEST_CONTAINER }}
103
+ steps:
104
+ # An environment not set up yet is skipped, not failed. The kinds of
105
+ # account tested are those whose endpoint is set.
106
+ - name: Check the environment
107
+ id: configured
108
+ run: |
109
+ if [[ -z "$AZURE_CLIENT_ID" ]]; then
110
+ echo "::notice::The environment azure has no AZURE_CLIENT_ID: skipped."
111
+ echo "ok=false" >> "$GITHUB_OUTPUT"
112
+ exit 0
113
+ fi
114
+ if [[ -z "$AZURE_TENANT_ID" || -z "$FSSPEC_ABFS_TEST_CONTAINER" ]]; then
115
+ echo "::error::AZURE_TENANT_ID and FSSPEC_ABFS_TEST_CONTAINER must be set."
116
+ exit 1
117
+ fi
118
+ if [[ -n "$FSSPEC_ABFS_TEST_HNS_ACCOUNT_URL" && -n "$FSSPEC_ABFS_TEST_FLAT_ACCOUNT_URL" ]]; then
119
+ hns=both
120
+ elif [[ -n "$FSSPEC_ABFS_TEST_HNS_ACCOUNT_URL" ]]; then
121
+ hns=true
122
+ elif [[ -n "$FSSPEC_ABFS_TEST_FLAT_ACCOUNT_URL" ]]; then
123
+ hns=false
124
+ else
125
+ echo "::error::FSSPEC_ABFS_TEST_HNS_ACCOUNT_URL or FSSPEC_ABFS_TEST_FLAT_ACCOUNT_URL must be set."
126
+ exit 1
127
+ fi
128
+ echo "hns=$hns" >> "$GITHUB_OUTPUT"
129
+ echo "ok=true" >> "$GITHUB_OUTPUT"
130
+
131
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
132
+ if: ${{ steps.configured.outputs.ok == 'true' }}
133
+ with:
134
+ persist-credentials: false # no job pushes: the token is not left in .git/config
135
+ fetch-depth: 0 # the version comes from the git tags (hatch-vcs)
136
+
137
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
138
+ if: ${{ steps.configured.outputs.ok == 'true' }}
139
+ with:
140
+ version: "0.12.22" # not the latest uv: the same in every run
141
+ python-version: "3.14"
142
+ enable-cache: false # this job holds credentials: nothing restored from a cache
143
+
144
+ - name: Install the project
145
+ if: ${{ steps.configured.outputs.ok == 'true' }}
146
+ run: uv sync --locked # fails if uv.lock is out of date
147
+
148
+ - name: Test on the live accounts
149
+ if: ${{ steps.configured.outputs.ok == 'true' }}
150
+ env:
151
+ HNS: ${{ steps.configured.outputs.hns }}
152
+ run: bash .github/scripts/with-id-token-file.sh uv run --no-sync pytest --api=live --hns="$HNS"
@@ -0,0 +1,45 @@
1
+ # Scan the code and the workflows for security issues with CodeQL, on pushes
2
+ # to main, pull requests and every week. The results go to the repository's
3
+ # Security tab, under Code scanning.
4
+ name: CodeQL
5
+
6
+ on:
7
+ push:
8
+ branches: [main]
9
+ pull_request:
10
+ schedule:
11
+ - cron: "17 4 * * 1" # Monday, 04:17 UTC: a scan of new queries on unchanged code
12
+ workflow_dispatch:
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ concurrency:
18
+ group: codeql-${{ github.ref }}
19
+ cancel-in-progress: true
20
+
21
+ jobs:
22
+ analyze:
23
+ runs-on: ubuntu-latest
24
+ permissions:
25
+ contents: read # the checkout: a job's permissions replace the workflow's
26
+ actions: read # the workflow runs, which CodeQL reads in a private repository
27
+ security-events: write # the results, to code scanning
28
+ strategy:
29
+ fail-fast: false
30
+ matrix:
31
+ language: [python, actions]
32
+ steps:
33
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
34
+ with:
35
+ persist-credentials: false # no job pushes: the token is not left in .git/config
36
+
37
+ - uses: github/codeql-action/init@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
38
+ with:
39
+ languages: ${{ matrix.language }}
40
+ # Neither is compiled: the source is analysed as it is.
41
+ build-mode: none
42
+
43
+ - uses: github/codeql-action/analyze@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
44
+ with:
45
+ category: /language:${{ matrix.language }}
@@ -0,0 +1,90 @@
1
+ # Release: on a version tag (e.g. `git push origin v0.1.0`), build the
2
+ # package, check its version is the tag's, create the GitHub release with it,
3
+ # and publish it to PyPI.
4
+ #
5
+ # PyPI publishing uses trusted publishing (no token): the PyPI project
6
+ # fsspec-abfs needs a trusted publisher for this repository, workflow
7
+ # `release.yaml` and environment `pypi` (see DEVELOPMENT.md).
8
+ name: Release
9
+
10
+ on:
11
+ push:
12
+ tags: ["v*"]
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ jobs:
18
+ build:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
22
+ with:
23
+ persist-credentials: false # no job pushes: the token is not left in .git/config
24
+ fetch-depth: 0 # the version comes from the git tags (hatch-vcs)
25
+
26
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
27
+ with:
28
+ version: "0.12.22" # not the latest uv: the same in every run
29
+ enable-cache: false # a release is built from nothing cached
30
+
31
+ - name: Build the package
32
+ run: uv build --out-dir dist
33
+
34
+ - name: Check the package
35
+ run: |
36
+ uv run --no-project python - <<'EOF'
37
+ import glob, os, sys
38
+
39
+ version = os.environ["GITHUB_REF_NAME"].removeprefix("v")
40
+ files = sorted(os.path.basename(f) for f in glob.glob("dist/*"))
41
+ print("\n".join(files))
42
+ expected = [
43
+ f"fsspec_abfs-{version}-py3-none-any.whl",
44
+ f"fsspec_abfs-{version}.tar.gz",
45
+ ]
46
+ if files != expected:
47
+ sys.exit(f"expected {expected} for tag {version}")
48
+ EOF
49
+
50
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
51
+ with:
52
+ name: dist
53
+ path: dist/
54
+ if-no-files-found: error
55
+
56
+ github-release:
57
+ needs: build
58
+ runs-on: ubuntu-latest
59
+ permissions:
60
+ contents: write
61
+ steps:
62
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
63
+ with:
64
+ name: dist
65
+ path: dist/
66
+
67
+ - name: Create the GitHub release
68
+ env:
69
+ GH_TOKEN: ${{ github.token }}
70
+ run: >
71
+ gh release create "$GITHUB_REF_NAME" dist/*
72
+ --repo "$GITHUB_REPOSITORY" --verify-tag
73
+ --title "$GITHUB_REF_NAME" --generate-notes
74
+
75
+ pypi:
76
+ needs: build
77
+ runs-on: ubuntu-latest
78
+ environment:
79
+ name: pypi
80
+ url: https://pypi.org/project/fsspec-abfs/
81
+ permissions:
82
+ id-token: write # trusted publishing
83
+ steps:
84
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
85
+ with:
86
+ name: dist
87
+ path: dist/
88
+
89
+ - name: Publish to PyPI
90
+ uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
@@ -0,0 +1,56 @@
1
+ # --- Python ---
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+
7
+ # Packaging
8
+ build/
9
+ dist/
10
+ *.egg-info/
11
+ *.egg
12
+ .eggs/
13
+ wheels/
14
+
15
+ # Written by hatch-vcs when the package is built
16
+ src/fsspec_abfs/_version.py
17
+
18
+ # Virtual environments
19
+ .venv/
20
+ venv/
21
+ env/
22
+
23
+ # Tests, coverage and type checkers
24
+ .pytest_cache/
25
+ .tox/
26
+ .nox/
27
+ .coverage
28
+ .coverage.*
29
+ htmlcov/
30
+ coverage.xml
31
+ .hypothesis/
32
+ .mypy_cache/
33
+ .ruff_cache/
34
+
35
+ # --- IPython / Jupyter ---
36
+ .ipynb_checkpoints/
37
+
38
+ # --- JetBrains IDEs (IntelliJ IDEA, PyCharm, ...) ---
39
+ .idea/
40
+ *.iml
41
+ *.ipr
42
+ *.iws
43
+ out/
44
+
45
+ # --- Claude Code ---
46
+ .claude/worktrees/
47
+ .claude/settings.local.json
48
+
49
+ # --- Environment and secrets ---
50
+ .env
51
+ .env.*
52
+
53
+ # --- OS files ---
54
+ .DS_Store
55
+ Thumbs.db
56
+ desktop.ini
@@ -0,0 +1,20 @@
1
+ exclude: >
2
+ (?x)^(
3
+ \.tox/.*
4
+ )$
5
+ repos:
6
+
7
+ - repo: https://github.com/pre-commit/pre-commit-hooks
8
+ rev: v6.0.0
9
+ hooks:
10
+ - id: trailing-whitespace
11
+ - id: end-of-file-fixer
12
+ - id: check-json
13
+ - id: check-yaml
14
+ - repo: https://github.com/astral-sh/ruff-pre-commit
15
+ rev: v0.17.2
16
+ hooks:
17
+ - id: ruff-check
18
+ args: [ --fix, "--show-fixes"]
19
+ - id: ruff-format
20
+ types_or: [python]
@@ -0,0 +1 @@
1
+ 3.14