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.
@@ -0,0 +1,4 @@
1
+ node_modules/
2
+ .wrangler/
3
+ .dev.vars
4
+ dist/
@@ -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
+ ]