vbase-api 0.1.3__tar.gz → 0.1.4__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.
- vbase_api-0.1.4/CHANGELOG.md +17 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4}/MANIFEST.in +1 -0
- {vbase_api-0.1.3/src/vbase_api.egg-info → vbase_api-0.1.4}/PKG-INFO +7 -2
- {vbase_api-0.1.3 → vbase_api-0.1.4}/README.md +2 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4}/pyproject.toml +5 -2
- vbase_api-0.1.4/src/vbase_api/_version.py +1 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4/src/vbase_api.egg-info}/PKG-INFO +7 -2
- {vbase_api-0.1.3 → vbase_api-0.1.4}/src/vbase_api.egg-info/SOURCES.txt +2 -0
- vbase_api-0.1.4/tests/test_api_client.py +107 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4}/tests/test_file_integrity_e2e.py +45 -0
- vbase_api-0.1.3/src/vbase_api/_version.py +0 -1
- {vbase_api-0.1.3 → vbase_api-0.1.4}/LICENSE.txt +0 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4}/NOTICE.txt +0 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4}/requirements.in +0 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4}/setup.cfg +0 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4}/src/vbase_api/__init__.py +0 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4}/src/vbase_api/vbase_api_client.py +0 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4}/src/vbase_api/vbase_api_models.py +0 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4}/src/vbase_api.egg-info/dependency_links.txt +0 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4}/src/vbase_api.egg-info/requires.txt +0 -0
- {vbase_api-0.1.3 → vbase_api-0.1.4}/src/vbase_api.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes are documented here, following
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
|
+
Versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
Earlier releases were not tracked in this file; see the
|
|
8
|
+
[commit history](https://github.com/validityBase/vbase-api-py/commits/main/)
|
|
9
|
+
for prior changes.
|
|
10
|
+
|
|
11
|
+
## [Unreleased]
|
|
12
|
+
|
|
13
|
+
## [0.1.4] - 2026-10-26
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Compatibility test matrix for Python 3.8, 3.11, and 3.12.
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vbase-api
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: vBase REST API Python Client
|
|
5
5
|
Author-email: vBase <tech@vbase.com>
|
|
6
|
-
License
|
|
6
|
+
License: Apache-2.0
|
|
7
7
|
Project-URL: Homepage, https://github.com/validityBase/vbase-api-py
|
|
8
8
|
Project-URL: Documentation, https://docs.vbase.com/
|
|
9
9
|
Keywords: vbase,stamping,web3,blockchain,validation
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
14
|
Classifier: Operating System :: OS Independent
|
|
12
15
|
Requires-Python: >=3.8
|
|
13
16
|
Description-Content-Type: text/markdown
|
|
@@ -20,6 +23,8 @@ Dynamic: license-file
|
|
|
20
23
|
|
|
21
24
|
vBase REST API Python Client
|
|
22
25
|
|
|
26
|
+
Requires Python 3.11 or newer.
|
|
27
|
+
|
|
23
28
|
See [documentation](https://docs.vbase.com/) and the [Swagger UI](https://app.vbase.com/swagger/) for more details.
|
|
24
29
|
|
|
25
30
|
---
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["setuptools >=
|
|
2
|
+
requires = ["setuptools >= 62.6"]
|
|
3
3
|
build-backend = "setuptools.build_meta"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
@@ -8,7 +8,7 @@ dynamic = ["version", "dependencies"]
|
|
|
8
8
|
description = "vBase REST API Python Client"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
11
|
-
license = "Apache-2.0"
|
|
11
|
+
license = {text = "Apache-2.0"}
|
|
12
12
|
authors = [
|
|
13
13
|
{ name = "vBase", email = "tech@vbase.com" }
|
|
14
14
|
]
|
|
@@ -16,6 +16,9 @@ authors = [
|
|
|
16
16
|
keywords = ["vbase", "stamping", "web3", "blockchain", "validation"]
|
|
17
17
|
classifiers = [
|
|
18
18
|
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
19
22
|
"Operating System :: OS Independent",
|
|
20
23
|
]
|
|
21
24
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.4"
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vbase-api
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: vBase REST API Python Client
|
|
5
5
|
Author-email: vBase <tech@vbase.com>
|
|
6
|
-
License
|
|
6
|
+
License: Apache-2.0
|
|
7
7
|
Project-URL: Homepage, https://github.com/validityBase/vbase-api-py
|
|
8
8
|
Project-URL: Documentation, https://docs.vbase.com/
|
|
9
9
|
Keywords: vbase,stamping,web3,blockchain,validation
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
14
|
Classifier: Operating System :: OS Independent
|
|
12
15
|
Requires-Python: >=3.8
|
|
13
16
|
Description-Content-Type: text/markdown
|
|
@@ -20,6 +23,8 @@ Dynamic: license-file
|
|
|
20
23
|
|
|
21
24
|
vBase REST API Python Client
|
|
22
25
|
|
|
26
|
+
Requires Python 3.11 or newer.
|
|
27
|
+
|
|
23
28
|
See [documentation](https://docs.vbase.com/) and the [Swagger UI](https://app.vbase.com/swagger/) for more details.
|
|
24
29
|
|
|
25
30
|
---
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
CHANGELOG.md
|
|
1
2
|
LICENSE.txt
|
|
2
3
|
MANIFEST.in
|
|
3
4
|
NOTICE.txt
|
|
@@ -13,4 +14,5 @@ src/vbase_api.egg-info/SOURCES.txt
|
|
|
13
14
|
src/vbase_api.egg-info/dependency_links.txt
|
|
14
15
|
src/vbase_api.egg-info/requires.txt
|
|
15
16
|
src/vbase_api.egg-info/top_level.txt
|
|
17
|
+
tests/test_api_client.py
|
|
16
18
|
tests/test_file_integrity_e2e.py
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Client request/response contracts that run without live services."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import tempfile
|
|
5
|
+
import unittest
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from unittest.mock import patch
|
|
8
|
+
|
|
9
|
+
import requests
|
|
10
|
+
|
|
11
|
+
import vbase_api
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class APIClientTests(unittest.TestCase):
|
|
15
|
+
def setUp(self):
|
|
16
|
+
self.client = vbase_api.VBaseAPIClient(
|
|
17
|
+
api_key="test-only-key", base_url="https://example.invalid", timeout=7
|
|
18
|
+
)
|
|
19
|
+
self.addCleanup(self.client.close)
|
|
20
|
+
self.receipt = {
|
|
21
|
+
"transaction_hash": "0xtransaction",
|
|
22
|
+
"user_address": "0xuser",
|
|
23
|
+
"set_cid": "0xset",
|
|
24
|
+
"object_cid": "0xobject",
|
|
25
|
+
"timestamp": "2026-10-26T00:00:00Z",
|
|
26
|
+
"chain_id": 1,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@staticmethod
|
|
30
|
+
def response(status, payload):
|
|
31
|
+
response = requests.Response()
|
|
32
|
+
response.status_code = status
|
|
33
|
+
response._content = json.dumps(payload).encode("utf-8")
|
|
34
|
+
return response
|
|
35
|
+
|
|
36
|
+
def test_collection_request_and_response(self):
|
|
37
|
+
payload = {
|
|
38
|
+
"id": 1,
|
|
39
|
+
"name": "Example",
|
|
40
|
+
"cid": "0xset",
|
|
41
|
+
"is_pinned": True,
|
|
42
|
+
"is_public": False,
|
|
43
|
+
"created_at": "2026-10-26T00:00:00Z",
|
|
44
|
+
"description": "Example collection",
|
|
45
|
+
}
|
|
46
|
+
with patch.object(
|
|
47
|
+
self.client.session, "post", return_value=self.response(201, payload)
|
|
48
|
+
) as post:
|
|
49
|
+
collection = self.client.create_collection("Example", "Example collection")
|
|
50
|
+
self.assertEqual(collection.cid, "0xset")
|
|
51
|
+
self.assertEqual(collection.name, "Example")
|
|
52
|
+
post.assert_called_once_with(
|
|
53
|
+
"https://example.invalid/api/v1/collections",
|
|
54
|
+
json={
|
|
55
|
+
"name": "Example",
|
|
56
|
+
"cid": None,
|
|
57
|
+
"description": "Example collection",
|
|
58
|
+
"is_pinned": True,
|
|
59
|
+
},
|
|
60
|
+
timeout=7,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def test_stamp_response_types(self):
|
|
64
|
+
for status, expected in [
|
|
65
|
+
(200, vbase_api.IdempotentStampResponse),
|
|
66
|
+
(201, vbase_api.StampCreatedResponse),
|
|
67
|
+
]:
|
|
68
|
+
with self.subTest(status=status):
|
|
69
|
+
with patch.object(
|
|
70
|
+
self.client.session,
|
|
71
|
+
"post",
|
|
72
|
+
return_value=self.response(
|
|
73
|
+
status, {"commitment_receipt": self.receipt}
|
|
74
|
+
),
|
|
75
|
+
):
|
|
76
|
+
stamp = self.client.create_stamp(data_cid="0xobject")
|
|
77
|
+
self.assertIsInstance(stamp, expected)
|
|
78
|
+
self.assertEqual(stamp.commitment_receipt.object_cid, "0xobject")
|
|
79
|
+
|
|
80
|
+
def test_upload_closes_file_after_request(self):
|
|
81
|
+
with tempfile.TemporaryDirectory() as directory:
|
|
82
|
+
path = Path(directory) / "example.bin"
|
|
83
|
+
path.write_bytes(b"example")
|
|
84
|
+
with patch.object(
|
|
85
|
+
self.client.session,
|
|
86
|
+
"post",
|
|
87
|
+
return_value=self.response(201, {"commitment_receipt": self.receipt}),
|
|
88
|
+
) as post:
|
|
89
|
+
result = self.client.upload_stamped_file("Example", path)
|
|
90
|
+
uploaded = post.call_args.kwargs["files"]["file"][1]
|
|
91
|
+
self.assertTrue(uploaded.closed)
|
|
92
|
+
self.assertEqual(result.commitment_receipt.object_cid, "0xobject")
|
|
93
|
+
|
|
94
|
+
def test_api_error_preserves_status_and_message(self):
|
|
95
|
+
with patch.object(
|
|
96
|
+
self.client.session,
|
|
97
|
+
"get",
|
|
98
|
+
return_value=self.response(403, {"error": "Access denied"}),
|
|
99
|
+
):
|
|
100
|
+
with self.assertRaises(vbase_api.VBaseAPIError) as raised:
|
|
101
|
+
self.client.get_collections()
|
|
102
|
+
self.assertEqual(raised.exception.status_code, 403)
|
|
103
|
+
self.assertEqual(str(raised.exception), "[403] Access denied")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
if __name__ == "__main__":
|
|
107
|
+
unittest.main()
|
|
@@ -9,6 +9,7 @@ environment variables.
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
11
|
import hashlib
|
|
12
|
+
import importlib.metadata as metadata
|
|
12
13
|
import os
|
|
13
14
|
import tempfile
|
|
14
15
|
import time
|
|
@@ -26,6 +27,7 @@ except ImportError as exc: # pragma: no cover
|
|
|
26
27
|
"Install requirements/e2e.txt to run live file-integrity E2E tests."
|
|
27
28
|
) from exc
|
|
28
29
|
|
|
30
|
+
import vbase_api
|
|
29
31
|
from vbase_api import VBaseAPIClient, VBaseAPIError
|
|
30
32
|
|
|
31
33
|
|
|
@@ -54,6 +56,48 @@ def _int_env(name: str, default: int) -> int:
|
|
|
54
56
|
) from None
|
|
55
57
|
|
|
56
58
|
|
|
59
|
+
def _log_and_assert_package_source() -> None:
|
|
60
|
+
install_source = _first_env("VBASE_API_PACKAGE_SOURCE")
|
|
61
|
+
if not install_source:
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
package_path = Path(vbase_api.__file__).resolve()
|
|
65
|
+
package_version = getattr(vbase_api, "__version__", "unknown")
|
|
66
|
+
try:
|
|
67
|
+
distribution_version = metadata.version("vbase-api")
|
|
68
|
+
except metadata.PackageNotFoundError:
|
|
69
|
+
distribution_version = "not installed"
|
|
70
|
+
print(
|
|
71
|
+
"vbase-api "
|
|
72
|
+
f"package_version={package_version} "
|
|
73
|
+
f"distribution_version={distribution_version} "
|
|
74
|
+
f"imported from {package_path}"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
repo_root_raw = _first_env("GITHUB_WORKSPACE")
|
|
78
|
+
if not repo_root_raw:
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
repo_root = Path(repo_root_raw).resolve()
|
|
82
|
+
try:
|
|
83
|
+
package_path.relative_to(repo_root)
|
|
84
|
+
package_in_repo = True
|
|
85
|
+
except ValueError:
|
|
86
|
+
package_in_repo = False
|
|
87
|
+
|
|
88
|
+
if install_source == "source":
|
|
89
|
+
if not package_in_repo:
|
|
90
|
+
raise AssertionError(
|
|
91
|
+
"Source-install E2E run imported vbase_api outside the checkout: "
|
|
92
|
+
f"{package_path}"
|
|
93
|
+
)
|
|
94
|
+
elif install_source == "pypi" and package_in_repo:
|
|
95
|
+
raise AssertionError(
|
|
96
|
+
"PyPI-install E2E run imported vbase_api from the checkout instead of "
|
|
97
|
+
f"site-packages: {package_path}"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
|
|
57
101
|
@dataclass(frozen=True)
|
|
58
102
|
class LiveE2EConfig:
|
|
59
103
|
"""Configuration needed for live app/API file-integrity tests."""
|
|
@@ -119,6 +163,7 @@ class VBaseAPIClientFileIntegrityE2ETests(unittest.TestCase):
|
|
|
119
163
|
|
|
120
164
|
@classmethod
|
|
121
165
|
def setUpClass(cls) -> None:
|
|
166
|
+
_log_and_assert_package_source()
|
|
122
167
|
cls.config = LiveE2EConfig.from_env()
|
|
123
168
|
cls.client = VBaseAPIClient(
|
|
124
169
|
api_key=cls.config.api_key,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.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
|