riffsdk 0.4.2__tar.gz → 0.4.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.
Files changed (47) hide show
  1. {riffsdk-0.4.2 → riffsdk-0.4.3}/.github/workflows/release.yml +16 -0
  2. {riffsdk-0.4.2 → riffsdk-0.4.3}/CHANGELOG.md +24 -0
  3. riffsdk-0.4.3/PKG-INFO +127 -0
  4. {riffsdk-0.4.2 → riffsdk-0.4.3}/pyproject.toml +8 -1
  5. riffsdk-0.4.2/PKG-INFO +0 -9
  6. {riffsdk-0.4.2 → riffsdk-0.4.3}/.github/workflows/ci.yml +0 -0
  7. {riffsdk-0.4.2 → riffsdk-0.4.3}/.github/workflows/pr-comment.yml +0 -0
  8. {riffsdk-0.4.2 → riffsdk-0.4.3}/.gitignore +0 -0
  9. {riffsdk-0.4.2 → riffsdk-0.4.3}/.python-version +0 -0
  10. {riffsdk-0.4.2 → riffsdk-0.4.3}/AGENTS.md +0 -0
  11. {riffsdk-0.4.2 → riffsdk-0.4.3}/CLAUDE.md +0 -0
  12. {riffsdk-0.4.2 → riffsdk-0.4.3}/LICENCE +0 -0
  13. {riffsdk-0.4.2 → riffsdk-0.4.3}/README.md +0 -0
  14. {riffsdk-0.4.2 → riffsdk-0.4.3}/examples/async_client.py +0 -0
  15. {riffsdk-0.4.2 → riffsdk-0.4.3}/examples/basic_crud.py +0 -0
  16. {riffsdk-0.4.2 → riffsdk-0.4.3}/examples/file_upload_download.py +0 -0
  17. {riffsdk-0.4.2 → riffsdk-0.4.3}/examples/optimistic_concurrency.py +0 -0
  18. {riffsdk-0.4.2 → riffsdk-0.4.3}/mise.toml +0 -0
  19. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/__init__.py +0 -0
  20. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/__main__.py +0 -0
  21. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/_cli.py +0 -0
  22. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/_internal/__init__.py +0 -0
  23. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/_internal/auth.py +0 -0
  24. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/_internal/config.py +0 -0
  25. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/storage/__init__.py +0 -0
  26. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/storage/_async_client.py +0 -0
  27. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/storage/_client.py +0 -0
  28. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/storage/_http.py +0 -0
  29. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/storage/_models.py +0 -0
  30. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/storage/_session.py +0 -0
  31. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/storage/_streaming.py +0 -0
  32. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/storage/_upload.py +0 -0
  33. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/storage/exceptions.py +0 -0
  34. {riffsdk-0.4.2 → riffsdk-0.4.3}/src/riffsdk/storage/py.typed +0 -0
  35. {riffsdk-0.4.2 → riffsdk-0.4.3}/tests/__init__.py +0 -0
  36. {riffsdk-0.4.2 → riffsdk-0.4.3}/tests/test_async_client.py +0 -0
  37. {riffsdk-0.4.2 → riffsdk-0.4.3}/tests/test_cli.py +0 -0
  38. {riffsdk-0.4.2 → riffsdk-0.4.3}/tests/test_client.py +0 -0
  39. {riffsdk-0.4.2 → riffsdk-0.4.3}/tests/test_exceptions.py +0 -0
  40. {riffsdk-0.4.2 → riffsdk-0.4.3}/tests/test_http.py +0 -0
  41. {riffsdk-0.4.2 → riffsdk-0.4.3}/tests/test_imports.py +0 -0
  42. {riffsdk-0.4.2 → riffsdk-0.4.3}/tests/test_integration.py +0 -0
  43. {riffsdk-0.4.2 → riffsdk-0.4.3}/tests/test_models.py +0 -0
  44. {riffsdk-0.4.2 → riffsdk-0.4.3}/tests/test_session.py +0 -0
  45. {riffsdk-0.4.2 → riffsdk-0.4.3}/tests/test_streaming.py +0 -0
  46. {riffsdk-0.4.2 → riffsdk-0.4.3}/tests/test_upload.py +0 -0
  47. {riffsdk-0.4.2 → riffsdk-0.4.3}/uv.lock +0 -0
@@ -86,3 +86,19 @@ jobs:
86
86
  path: dist/
87
87
  - name: Publish to PyPI
88
88
  uses: pypa/gh-action-pypi-publish@release/v1
89
+ - name: Verify release landed on PyPI
90
+ env:
91
+ TAG: ${{ needs.release.outputs.tag }}
92
+ run: |
93
+ VER="${TAG#v}"
94
+ echo "Verifying riffsdk ${VER} is available on PyPI..."
95
+ for i in $(seq 1 12); do
96
+ if curl -sf "https://pypi.org/pypi/riffsdk/${VER}/json" >/dev/null; then
97
+ echo "riffsdk ${VER} is live on PyPI"
98
+ exit 0
99
+ fi
100
+ echo "not yet on PyPI, retry ${i}/12..."
101
+ sleep 10
102
+ done
103
+ echo "::error::riffsdk ${VER} never appeared on PyPI despite a successful upload step (likely a silent edge 200 — see https://upload.pypi.org/legacy/ response in the publish step)"
104
+ exit 1
@@ -2,6 +2,30 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v0.4.3 (2026-06-11)
6
+
7
+ ### Bug Fixes
8
+
9
+ - Add project homepage URL ([#12](https://github.com/databutton/riff-sdk-python/pull/12),
10
+ [`7333ba9`](https://github.com/databutton/riff-sdk-python/commit/7333ba9badb64eef3b111b74ee060fb5a6538c5b))
11
+
12
+ - Declare MIT license and package author
13
+ ([#12](https://github.com/databutton/riff-sdk-python/pull/12),
14
+ [`7333ba9`](https://github.com/databutton/riff-sdk-python/commit/7333ba9badb64eef3b111b74ee060fb5a6538c5b))
15
+
16
+ - Include README as package long description
17
+ ([#12](https://github.com/databutton/riff-sdk-python/pull/12),
18
+ [`7333ba9`](https://github.com/databutton/riff-sdk-python/commit/7333ba9badb64eef3b111b74ee060fb5a6538c5b))
19
+
20
+ - Populate pypi release details and check publishing in CI job
21
+ ([#12](https://github.com/databutton/riff-sdk-python/pull/12),
22
+ [`7333ba9`](https://github.com/databutton/riff-sdk-python/commit/7333ba9badb64eef3b111b74ee060fb5a6538c5b))
23
+
24
+ - Verify PyPI publish actually landed before passing release
25
+ ([#12](https://github.com/databutton/riff-sdk-python/pull/12),
26
+ [`7333ba9`](https://github.com/databutton/riff-sdk-python/commit/7333ba9badb64eef3b111b74ee060fb5a6538c5b))
27
+
28
+
5
29
  ## v0.4.2 (2026-06-11)
6
30
 
7
31
  ### Bug Fixes
riffsdk-0.4.3/PKG-INFO ADDED
@@ -0,0 +1,127 @@
1
+ Metadata-Version: 2.4
2
+ Name: riffsdk
3
+ Version: 0.4.3
4
+ Summary: Python SDK for the Riff Storage API
5
+ Project-URL: Homepage, https://riff.ai
6
+ Author-email: Martin Sandve Alnæs <msa@databutton.io>
7
+ License-Expression: MIT
8
+ License-File: LICENCE
9
+ Requires-Python: >=3.11
10
+ Requires-Dist: httpx>=0.27
11
+ Requires-Dist: pydantic>=2.6
12
+ Requires-Dist: tenacity>=8.3
13
+ Description-Content-Type: text/markdown
14
+
15
+ # riffsdk
16
+
17
+ Python SDK for the Riff Storage API. Provides sync and async clients for storing, retrieving, and managing objects.
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ uv add riffsdk
23
+ # or
24
+ pip install riffsdk
25
+ ```
26
+
27
+ Or install from a branch (for pre-release testing):
28
+
29
+ ```bash
30
+ uv add git+https://github.com/databutton/riff-sdk-python.git@main
31
+ # or
32
+ pip install git+https://github.com/databutton/riff-sdk-python.git@main
33
+ ```
34
+
35
+ ## Quick start
36
+
37
+ ```python
38
+ from riffsdk.storage import StorageClient
39
+
40
+ client = StorageClient()
41
+
42
+ # Upload
43
+ meta = client.put("hello.txt", "Hello, world!")
44
+
45
+ # Download
46
+ data = client.get("hello.txt")
47
+
48
+ # List
49
+ for obj in client.list("hello"):
50
+ print(f"{obj.key} ({obj.size} bytes)")
51
+
52
+ # Delete
53
+ client.delete("hello.txt")
54
+
55
+ client.close()
56
+ ```
57
+
58
+ ### Async
59
+
60
+ ```python
61
+ from riffsdk.storage import AsyncStorageClient
62
+
63
+ async with AsyncStorageClient() as client:
64
+ await client.put("key", b"data", content_type="application/octet-stream")
65
+ data = await client.get("key")
66
+ ```
67
+
68
+ ## Authentication
69
+
70
+ Set the `RIFF_TOKEN` environment variable. The SDK picks it up automatically.
71
+
72
+ ## API
73
+
74
+ ### Clients
75
+
76
+ - `StorageClient` -- sync client
77
+ - `AsyncStorageClient` -- async client
78
+
79
+ Both support: `put`, `get`, `stat`, `exists`, `list`, `delete`, `close`, and context manager usage.
80
+
81
+ ### Models
82
+
83
+ - `ObjectMeta` -- metadata for a stored object (key, version, size, content_type, timestamps)
84
+ - `UploadResult`, `DownloadResult` -- operation results
85
+ - `ListPage` -- paginated listing
86
+ - `Scope` -- access scope (use `account_scope()`, `project_scope()`, `session_scope()`)
87
+
88
+ ### Uploads
89
+
90
+ - `ResumableUpload` / `AsyncResumableUpload` -- multipart resumable uploads for large files
91
+ - `StorageReader` / `StorageWriter` -- streaming read/write
92
+
93
+ ### Exceptions
94
+
95
+ All exceptions inherit from `StorageError`:
96
+
97
+ - `AuthorisationError`
98
+ - `ObjectNotFoundError`
99
+ - `VersionConflictError`
100
+ - `AlreadyExistsError`
101
+ - `LeaseConflictError`
102
+ - `UploadNotFoundError`
103
+ - `QuotaExceededError`
104
+ - `PartMismatchError`
105
+ - `StorageTransportError`
106
+
107
+ ## Examples
108
+
109
+ See the `examples/` directory for complete working examples:
110
+
111
+ - `basic_crud.py` -- put, get, list, delete
112
+ - `async_client.py` -- async usage with asyncio
113
+ - `file_upload_download.py` -- file uploads with progress
114
+ - `optimistic_concurrency.py` -- version-based conflict handling
115
+
116
+ ## Development
117
+
118
+ Requires Python 3.11+ and [uv](https://docs.astral.sh/uv/).
119
+
120
+ ```bash
121
+ uv sync --dev # Install dependencies
122
+ mise run test # Run tests
123
+ mise run lint # Lint
124
+ mise run format # Format code
125
+ ```
126
+
127
+ See `AGENTS.md` for full development workflow details.
@@ -4,11 +4,18 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "riffsdk"
7
- version = "0.4.2"
7
+ version = "0.4.3"
8
8
  description = "Python SDK for the Riff Storage API"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENCE"]
12
+ authors = [{ name = "Martin Sandve Alnæs", email = "msa@databutton.io" }]
9
13
  requires-python = ">=3.11"
10
14
  dependencies = ["httpx>=0.27", "pydantic>=2.6", "tenacity>=8.3"]
11
15
 
16
+ [project.urls]
17
+ Homepage = "https://riff.ai"
18
+
12
19
  [project.scripts]
13
20
  riffsdk = "riffsdk._cli:main"
14
21
 
riffsdk-0.4.2/PKG-INFO DELETED
@@ -1,9 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: riffsdk
3
- Version: 0.4.2
4
- Summary: Python SDK for the Riff Storage API
5
- License-File: LICENCE
6
- Requires-Python: >=3.11
7
- Requires-Dist: httpx>=0.27
8
- Requires-Dist: pydantic>=2.6
9
- Requires-Dist: tenacity>=8.3
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes