elaunira-r2index 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.
- elaunira_r2index-0.1.0/.gitignore +4 -0
- elaunira_r2index-0.1.0/PKG-INFO +101 -0
- elaunira_r2index-0.1.0/README.md +69 -0
- elaunira_r2index-0.1.0/pyproject.toml +83 -0
- elaunira_r2index-0.1.0/scripts/publish.sh +34 -0
- elaunira_r2index-0.1.0/src/elaunira/__init__.py +1 -0
- elaunira_r2index-0.1.0/src/elaunira/r2index/__init__.py +118 -0
- elaunira_r2index-0.1.0/src/elaunira/r2index/async_client.py +503 -0
- elaunira_r2index-0.1.0/src/elaunira/r2index/async_uploader.py +149 -0
- elaunira_r2index-0.1.0/src/elaunira/r2index/checksums.py +127 -0
- elaunira_r2index-0.1.0/src/elaunira/r2index/client.py +502 -0
- elaunira_r2index-0.1.0/src/elaunira/r2index/exceptions.py +40 -0
- elaunira_r2index-0.1.0/src/elaunira/r2index/models.py +204 -0
- elaunira_r2index-0.1.0/src/elaunira/r2index/uploader.py +147 -0
- elaunira_r2index-0.1.0/tests/__init__.py +1 -0
- elaunira_r2index-0.1.0/tests/test_async_client.py +118 -0
- elaunira_r2index-0.1.0/tests/test_checksums.py +83 -0
- elaunira_r2index-0.1.0/tests/test_client.py +220 -0
- elaunira_r2index-0.1.0/tests/test_models.py +110 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: elaunira-r2index
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python library for uploading files to R2 and registering them with the r2index API
|
|
5
|
+
Project-URL: Homepage, https://github.com/elaunira/elaunira-r2-index
|
|
6
|
+
Project-URL: Repository, https://github.com/elaunira/elaunira-r2-index
|
|
7
|
+
Author: Elaunira
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Keywords: cloudflare,index,r2,storage,upload
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Typing :: Typed
|
|
17
|
+
Requires-Python: >=3.12
|
|
18
|
+
Requires-Dist: aioboto3>=12.0.0
|
|
19
|
+
Requires-Dist: boto3>=1.34.0
|
|
20
|
+
Requires-Dist: httpx>=0.25.0
|
|
21
|
+
Requires-Dist: pydantic>=2.0.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: boto3-stubs[s3]>=1.34.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: build>=1.0.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: mypy>=1.8.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-httpx>=0.30.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.3.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: twine>=5.0.0; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# elaunira-r2index
|
|
34
|
+
|
|
35
|
+
Python library for uploading files to Cloudflare R2 and registering them with the r2index API.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install elaunira-r2index
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
### Sync Client
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from elaunira.r2index import R2IndexClient, R2Config
|
|
49
|
+
|
|
50
|
+
client = R2IndexClient(
|
|
51
|
+
api_url="https://r2index.example.com",
|
|
52
|
+
api_token="your-bearer-token",
|
|
53
|
+
r2_config=R2Config(
|
|
54
|
+
access_key_id="your-r2-access-key-id",
|
|
55
|
+
secret_access_key="your-r2-secret-access-key",
|
|
56
|
+
endpoint_url="https://your-account-id.r2.cloudflarestorage.com",
|
|
57
|
+
bucket="your-bucket-name",
|
|
58
|
+
),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Upload and register a file
|
|
62
|
+
record = client.upload_and_register(
|
|
63
|
+
file_path="./myfile.zip",
|
|
64
|
+
category="software",
|
|
65
|
+
entity="myapp",
|
|
66
|
+
remote_path="/releases",
|
|
67
|
+
remote_filename="myapp-1.0.0.zip",
|
|
68
|
+
remote_version="1.0.0",
|
|
69
|
+
tags=["release", "stable"],
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Async Client
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from elaunira.r2index import AsyncR2IndexClient, R2Config
|
|
77
|
+
|
|
78
|
+
async with AsyncR2IndexClient(
|
|
79
|
+
api_url="https://r2index.example.com",
|
|
80
|
+
api_token="your-bearer-token",
|
|
81
|
+
r2_config=R2Config(
|
|
82
|
+
access_key_id="your-r2-access-key-id",
|
|
83
|
+
secret_access_key="your-r2-secret-access-key",
|
|
84
|
+
endpoint_url="https://your-account-id.r2.cloudflarestorage.com",
|
|
85
|
+
bucket="your-bucket-name",
|
|
86
|
+
),
|
|
87
|
+
) as client:
|
|
88
|
+
record = await client.upload_and_register(
|
|
89
|
+
file_path="./myfile.zip",
|
|
90
|
+
category="software",
|
|
91
|
+
entity="myapp",
|
|
92
|
+
remote_path="/releases",
|
|
93
|
+
remote_filename="myapp-1.0.0.zip",
|
|
94
|
+
remote_version="1.0.0",
|
|
95
|
+
tags=["release", "stable"],
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## License
|
|
100
|
+
|
|
101
|
+
MIT
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# elaunira-r2index
|
|
2
|
+
|
|
3
|
+
Python library for uploading files to Cloudflare R2 and registering them with the r2index API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install elaunira-r2index
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Sync Client
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from elaunira.r2index import R2IndexClient, R2Config
|
|
17
|
+
|
|
18
|
+
client = R2IndexClient(
|
|
19
|
+
api_url="https://r2index.example.com",
|
|
20
|
+
api_token="your-bearer-token",
|
|
21
|
+
r2_config=R2Config(
|
|
22
|
+
access_key_id="your-r2-access-key-id",
|
|
23
|
+
secret_access_key="your-r2-secret-access-key",
|
|
24
|
+
endpoint_url="https://your-account-id.r2.cloudflarestorage.com",
|
|
25
|
+
bucket="your-bucket-name",
|
|
26
|
+
),
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# Upload and register a file
|
|
30
|
+
record = client.upload_and_register(
|
|
31
|
+
file_path="./myfile.zip",
|
|
32
|
+
category="software",
|
|
33
|
+
entity="myapp",
|
|
34
|
+
remote_path="/releases",
|
|
35
|
+
remote_filename="myapp-1.0.0.zip",
|
|
36
|
+
remote_version="1.0.0",
|
|
37
|
+
tags=["release", "stable"],
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Async Client
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from elaunira.r2index import AsyncR2IndexClient, R2Config
|
|
45
|
+
|
|
46
|
+
async with AsyncR2IndexClient(
|
|
47
|
+
api_url="https://r2index.example.com",
|
|
48
|
+
api_token="your-bearer-token",
|
|
49
|
+
r2_config=R2Config(
|
|
50
|
+
access_key_id="your-r2-access-key-id",
|
|
51
|
+
secret_access_key="your-r2-secret-access-key",
|
|
52
|
+
endpoint_url="https://your-account-id.r2.cloudflarestorage.com",
|
|
53
|
+
bucket="your-bucket-name",
|
|
54
|
+
),
|
|
55
|
+
) as client:
|
|
56
|
+
record = await client.upload_and_register(
|
|
57
|
+
file_path="./myfile.zip",
|
|
58
|
+
category="software",
|
|
59
|
+
entity="myapp",
|
|
60
|
+
remote_path="/releases",
|
|
61
|
+
remote_filename="myapp-1.0.0.zip",
|
|
62
|
+
remote_version="1.0.0",
|
|
63
|
+
tags=["release", "stable"],
|
|
64
|
+
)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## License
|
|
68
|
+
|
|
69
|
+
MIT
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "elaunira-r2index"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python library for uploading files to R2 and registering them with the r2index API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.12"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Elaunira" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["r2", "cloudflare", "storage", "upload", "index"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Typing :: Typed",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"httpx>=0.25.0",
|
|
27
|
+
"boto3>=1.34.0",
|
|
28
|
+
"aioboto3>=12.0.0",
|
|
29
|
+
"pydantic>=2.0.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest>=8.0.0",
|
|
35
|
+
"pytest-asyncio>=0.23.0",
|
|
36
|
+
"pytest-httpx>=0.30.0",
|
|
37
|
+
"ruff>=0.3.0",
|
|
38
|
+
"mypy>=1.8.0",
|
|
39
|
+
"boto3-stubs[s3]>=1.34.0",
|
|
40
|
+
"build>=1.0.0",
|
|
41
|
+
"twine>=5.0.0",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[project.urls]
|
|
45
|
+
Homepage = "https://github.com/elaunira/elaunira-r2-index"
|
|
46
|
+
Repository = "https://github.com/elaunira/elaunira-r2-index"
|
|
47
|
+
|
|
48
|
+
[tool.hatch.build.targets.wheel]
|
|
49
|
+
packages = ["src/elaunira"]
|
|
50
|
+
|
|
51
|
+
[tool.ruff]
|
|
52
|
+
target-version = "py312"
|
|
53
|
+
line-length = 100
|
|
54
|
+
|
|
55
|
+
[tool.ruff.lint]
|
|
56
|
+
select = [
|
|
57
|
+
"E", # pycodestyle errors
|
|
58
|
+
"W", # pycodestyle warnings
|
|
59
|
+
"F", # Pyflakes
|
|
60
|
+
"I", # isort
|
|
61
|
+
"B", # flake8-bugbear
|
|
62
|
+
"C4", # flake8-comprehensions
|
|
63
|
+
"UP", # pyupgrade
|
|
64
|
+
"ARG", # flake8-unused-arguments
|
|
65
|
+
"SIM", # flake8-simplify
|
|
66
|
+
]
|
|
67
|
+
ignore = [
|
|
68
|
+
"E501", # line too long (handled by formatter)
|
|
69
|
+
"B008", # do not perform function calls in argument defaults
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[tool.ruff.lint.isort]
|
|
73
|
+
known-first-party = ["elaunira"]
|
|
74
|
+
|
|
75
|
+
[tool.mypy]
|
|
76
|
+
python_version = "3.12"
|
|
77
|
+
strict = true
|
|
78
|
+
warn_return_any = true
|
|
79
|
+
warn_unused_ignores = true
|
|
80
|
+
|
|
81
|
+
[tool.pytest.ini_options]
|
|
82
|
+
asyncio_mode = "auto"
|
|
83
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Build package and publish to PyPI
|
|
5
|
+
#
|
|
6
|
+
# Requirements:
|
|
7
|
+
# - ~/.pypirc configured, OR
|
|
8
|
+
# - PYPI_TOKEN environment variable (API token from pypi.org)
|
|
9
|
+
#
|
|
10
|
+
# Usage:
|
|
11
|
+
# ./scripts/publish.sh
|
|
12
|
+
|
|
13
|
+
cd "$(dirname "$0")/.."
|
|
14
|
+
|
|
15
|
+
echo "Installing build dependencies..."
|
|
16
|
+
pip install --quiet build twine
|
|
17
|
+
|
|
18
|
+
echo "Cleaning previous builds..."
|
|
19
|
+
rm -rf dist/ build/ *.egg-info src/*.egg-info
|
|
20
|
+
|
|
21
|
+
echo "Building package..."
|
|
22
|
+
python -m build
|
|
23
|
+
|
|
24
|
+
echo "Publishing to PyPI..."
|
|
25
|
+
if [[ -n "${PYPI_TOKEN:-}" ]]; then
|
|
26
|
+
twine upload \
|
|
27
|
+
--username __token__ \
|
|
28
|
+
--password "${PYPI_TOKEN}" \
|
|
29
|
+
dist/*
|
|
30
|
+
else
|
|
31
|
+
twine upload dist/*
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
echo "Done!"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Elaunira namespace package."""
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""
|
|
2
|
+
R2 Index Python Library.
|
|
3
|
+
|
|
4
|
+
A Python library for uploading files to Cloudflare R2 and registering them
|
|
5
|
+
with the r2index API. Supports both sync and async operations with streaming
|
|
6
|
+
checksums for memory-efficient handling of large files.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
from elaunira.r2index import R2IndexClient, R2Config
|
|
10
|
+
|
|
11
|
+
client = R2IndexClient(
|
|
12
|
+
api_url="https://r2index.example.com",
|
|
13
|
+
api_token="your-bearer-token",
|
|
14
|
+
r2_config=R2Config(
|
|
15
|
+
access_key_id="...",
|
|
16
|
+
secret_access_key="...",
|
|
17
|
+
endpoint_url="https://xxx.r2.cloudflarestorage.com",
|
|
18
|
+
bucket="your-bucket",
|
|
19
|
+
),
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Upload and register a file
|
|
23
|
+
record = client.upload_and_register(
|
|
24
|
+
file_path="./myfile.zip",
|
|
25
|
+
category="software",
|
|
26
|
+
entity="myapp",
|
|
27
|
+
remote_path="/releases",
|
|
28
|
+
remote_filename="myapp-1.0.0.zip",
|
|
29
|
+
remote_version="1.0.0",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
Async usage:
|
|
33
|
+
from elaunira.r2index import AsyncR2IndexClient, R2Config
|
|
34
|
+
|
|
35
|
+
async with AsyncR2IndexClient(...) as client:
|
|
36
|
+
record = await client.upload_and_register(...)
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
from .async_client import AsyncR2IndexClient
|
|
40
|
+
from .async_uploader import AsyncR2Uploader
|
|
41
|
+
from .checksums import (
|
|
42
|
+
ChecksumResult,
|
|
43
|
+
compute_checksums,
|
|
44
|
+
compute_checksums_async,
|
|
45
|
+
compute_checksums_from_file_object,
|
|
46
|
+
)
|
|
47
|
+
from .client import R2IndexClient
|
|
48
|
+
from .exceptions import (
|
|
49
|
+
AuthenticationError,
|
|
50
|
+
ConflictError,
|
|
51
|
+
NotFoundError,
|
|
52
|
+
R2IndexError,
|
|
53
|
+
UploadError,
|
|
54
|
+
ValidationError,
|
|
55
|
+
)
|
|
56
|
+
from .models import (
|
|
57
|
+
CleanupResponse,
|
|
58
|
+
DownloadByIpEntry,
|
|
59
|
+
DownloadRecord,
|
|
60
|
+
DownloadRecordRequest,
|
|
61
|
+
DownloadsByIpResponse,
|
|
62
|
+
FileCreateRequest,
|
|
63
|
+
FileListResponse,
|
|
64
|
+
FileRecord,
|
|
65
|
+
FileUpdateRequest,
|
|
66
|
+
HealthResponse,
|
|
67
|
+
IndexEntry,
|
|
68
|
+
RemoteTuple,
|
|
69
|
+
SummaryResponse,
|
|
70
|
+
TimeseriesDataPoint,
|
|
71
|
+
TimeseriesResponse,
|
|
72
|
+
UserAgentEntry,
|
|
73
|
+
UserAgentsResponse,
|
|
74
|
+
)
|
|
75
|
+
from .uploader import R2Config, R2Uploader
|
|
76
|
+
|
|
77
|
+
__all__ = [
|
|
78
|
+
# Clients
|
|
79
|
+
"R2IndexClient",
|
|
80
|
+
"AsyncR2IndexClient",
|
|
81
|
+
# Uploaders
|
|
82
|
+
"R2Uploader",
|
|
83
|
+
"AsyncR2Uploader",
|
|
84
|
+
"R2Config",
|
|
85
|
+
# Checksums
|
|
86
|
+
"ChecksumResult",
|
|
87
|
+
"compute_checksums",
|
|
88
|
+
"compute_checksums_async",
|
|
89
|
+
"compute_checksums_from_file_object",
|
|
90
|
+
# Exceptions
|
|
91
|
+
"R2IndexError",
|
|
92
|
+
"AuthenticationError",
|
|
93
|
+
"NotFoundError",
|
|
94
|
+
"ValidationError",
|
|
95
|
+
"ConflictError",
|
|
96
|
+
"UploadError",
|
|
97
|
+
# Models - File operations
|
|
98
|
+
"FileRecord",
|
|
99
|
+
"FileCreateRequest",
|
|
100
|
+
"FileUpdateRequest",
|
|
101
|
+
"FileListResponse",
|
|
102
|
+
"IndexEntry",
|
|
103
|
+
"RemoteTuple",
|
|
104
|
+
# Models - Downloads
|
|
105
|
+
"DownloadRecord",
|
|
106
|
+
"DownloadRecordRequest",
|
|
107
|
+
# Models - Analytics
|
|
108
|
+
"TimeseriesDataPoint",
|
|
109
|
+
"TimeseriesResponse",
|
|
110
|
+
"SummaryResponse",
|
|
111
|
+
"DownloadByIpEntry",
|
|
112
|
+
"DownloadsByIpResponse",
|
|
113
|
+
"UserAgentEntry",
|
|
114
|
+
"UserAgentsResponse",
|
|
115
|
+
# Models - Other
|
|
116
|
+
"CleanupResponse",
|
|
117
|
+
"HealthResponse",
|
|
118
|
+
]
|