voxelion 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.
- voxelion-0.1.0/.gitignore +7 -0
- voxelion-0.1.0/CHANGELOG.md +14 -0
- voxelion-0.1.0/LICENSE +21 -0
- voxelion-0.1.0/PKG-INFO +149 -0
- voxelion-0.1.0/README.md +117 -0
- voxelion-0.1.0/pyproject.toml +88 -0
- voxelion-0.1.0/scripts-generate.sh +30 -0
- voxelion-0.1.0/src/voxelion/__init__.py +64 -0
- voxelion-0.1.0/src/voxelion/_client.py +318 -0
- voxelion-0.1.0/src/voxelion/_transport.py +193 -0
- voxelion-0.1.0/src/voxelion/_version.py +1 -0
- voxelion-0.1.0/src/voxelion/errors.py +170 -0
- voxelion-0.1.0/src/voxelion/models.py +464 -0
- voxelion-0.1.0/src/voxelion/py.typed +0 -0
- voxelion-0.1.0/tests/__init__.py +0 -0
- voxelion-0.1.0/tests/test_credential.py +80 -0
- voxelion-0.1.0/tests/test_errors.py +76 -0
- voxelion-0.1.0/tests/test_live.py +110 -0
- voxelion-0.1.0/tests/test_retries.py +136 -0
- voxelion-0.1.0/tests/test_volumetric_models.py +82 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — unreleased
|
|
4
|
+
|
|
5
|
+
First release. Targets `/api/v1`.
|
|
6
|
+
|
|
7
|
+
- `dedup()` — synchronous batch deduplication
|
|
8
|
+
- `submit_job()` / `JobHandle.wait()` — the queued path, with polling backoff
|
|
9
|
+
- `list_reports()` / `get_report()` / `manifest()`
|
|
10
|
+
- `balance()`
|
|
11
|
+
- Typed exceptions per API error code
|
|
12
|
+
- Retries: `Retry-After` on 429, exponential backoff with full jitter on 5xx,
|
|
13
|
+
nothing else retried
|
|
14
|
+
- Streaming uploads — an archive is never read into memory
|
voxelion-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Voxelion
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
voxelion-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: voxelion
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Perceptual deduplication for image datasets — the official Python client for the Voxelion API.
|
|
5
|
+
Project-URL: Homepage, https://voxelion.ai
|
|
6
|
+
Project-URL: Documentation, https://voxelion.ai/docs/
|
|
7
|
+
Project-URL: Changelog, https://github.com/Asekun/bioHarmonix/blob/main/sdk/python/CHANGELOG.md
|
|
8
|
+
Author: Voxelion
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: data-quality,dataset,deduplication,dicom,machine-learning,perceptual-hash
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Image Processing
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Requires-Dist: httpx<1,>=0.24
|
|
25
|
+
Requires-Dist: pydantic<3,>=2
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: mypy>=1.8; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# voxelion
|
|
34
|
+
|
|
35
|
+
Perceptual deduplication for image datasets — the official Python client for the
|
|
36
|
+
[Voxelion API](https://voxelion.ai/docs/).
|
|
37
|
+
|
|
38
|
+
Voxelion finds the files in a dataset that are the *same image* — after
|
|
39
|
+
re-encoding, resizing, format conversion or a metadata rewrite — and tells you
|
|
40
|
+
which ones are redundant. It never deletes anything.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install voxelion
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quickstart
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from voxelion import Voxelion
|
|
50
|
+
|
|
51
|
+
vx = Voxelion() # reads VOXELION_API_KEY
|
|
52
|
+
report = vx.dedup(["a.png", "b.png", "c.png"], engine="curate")
|
|
53
|
+
|
|
54
|
+
print(f"{report.leakage:.1%} redundant across {report.count} images")
|
|
55
|
+
for cluster in report.clusters:
|
|
56
|
+
print("same image:", ", ".join(cluster))
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Create a key in the console under **API Keys**, then:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
export VOXELION_API_KEY=pk_live_...
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Large datasets
|
|
66
|
+
|
|
67
|
+
A batch that fits in one upload goes through `dedup()`. Anything larger is
|
|
68
|
+
queued, which survives a disconnect and reports progress:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
job = vx.submit_job("corpus.zip", engine="curate")
|
|
72
|
+
print(job.id, job.status)
|
|
73
|
+
|
|
74
|
+
report = job.wait() # polls with backoff
|
|
75
|
+
plan = vx.manifest(report.id)
|
|
76
|
+
print(f"keep {len(plan.keep)}, drop {len(plan.drop)}")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`plan.drop` is a list of filenames. **Voxelion does not delete them** — what
|
|
80
|
+
you do with the plan is yours to decide.
|
|
81
|
+
|
|
82
|
+
## Engines
|
|
83
|
+
|
|
84
|
+
| Engine | For |
|
|
85
|
+
|---|---|
|
|
86
|
+
| `health` | Medical imaging. DICOM-aware: a CT or MR series is deduplicated as a scan, not as loose slices. |
|
|
87
|
+
| `curate` | General image archives — product photography, scraped corpora, generated output. |
|
|
88
|
+
|
|
89
|
+
Omit `engine=` to use your account's default. The engine that actually ran is
|
|
90
|
+
on the report either way:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
report = vx.dedup(files)
|
|
94
|
+
print(report.engine) # "curate"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Errors
|
|
98
|
+
|
|
99
|
+
Exceptions are typed by what went wrong, not by status code:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from voxelion import InsufficientCreditError, ConsentRequiredError
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
report = vx.dedup(files)
|
|
106
|
+
except InsufficientCreditError as e:
|
|
107
|
+
print(f"needs {e.required_cents}c, have {e.available_cents}c")
|
|
108
|
+
except ConsentRequiredError:
|
|
109
|
+
print("Grant data-processing consent in the console first.")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`429` responses honour the server's `Retry-After` automatically, and `5xx`
|
|
113
|
+
retries with exponential backoff. Nothing else is retried: a `402` will not
|
|
114
|
+
become affordable by asking again.
|
|
115
|
+
|
|
116
|
+
## Sandbox
|
|
117
|
+
|
|
118
|
+
The sandbox is a separate deployment with its own database and accounts. It is
|
|
119
|
+
the same client with a different base URL:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from voxelion import Voxelion, SANDBOX_BASE_URL
|
|
123
|
+
|
|
124
|
+
vx = Voxelion(base_url=SANDBOX_BASE_URL)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Checking cost before spending
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
account = vx.balance()
|
|
131
|
+
print(account.spendable_cents) # not balance_cents — see below
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`spendable_cents` is the balance minus credit already held against runs in
|
|
135
|
+
flight. It is the number that decides whether the next call succeeds.
|
|
136
|
+
|
|
137
|
+
## Development
|
|
138
|
+
|
|
139
|
+
Models in `src/voxelion/models.py` are **generated** from the API's OpenAPI
|
|
140
|
+
document. Do not edit them by hand:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
./scripts-generate.sh
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
pytest # unit tests, no network
|
|
148
|
+
pytest -m live # against a real deployment; needs VOXELION_API_KEY
|
|
149
|
+
```
|
voxelion-0.1.0/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# voxelion
|
|
2
|
+
|
|
3
|
+
Perceptual deduplication for image datasets — the official Python client for the
|
|
4
|
+
[Voxelion API](https://voxelion.ai/docs/).
|
|
5
|
+
|
|
6
|
+
Voxelion finds the files in a dataset that are the *same image* — after
|
|
7
|
+
re-encoding, resizing, format conversion or a metadata rewrite — and tells you
|
|
8
|
+
which ones are redundant. It never deletes anything.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install voxelion
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Quickstart
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from voxelion import Voxelion
|
|
18
|
+
|
|
19
|
+
vx = Voxelion() # reads VOXELION_API_KEY
|
|
20
|
+
report = vx.dedup(["a.png", "b.png", "c.png"], engine="curate")
|
|
21
|
+
|
|
22
|
+
print(f"{report.leakage:.1%} redundant across {report.count} images")
|
|
23
|
+
for cluster in report.clusters:
|
|
24
|
+
print("same image:", ", ".join(cluster))
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Create a key in the console under **API Keys**, then:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
export VOXELION_API_KEY=pk_live_...
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Large datasets
|
|
34
|
+
|
|
35
|
+
A batch that fits in one upload goes through `dedup()`. Anything larger is
|
|
36
|
+
queued, which survives a disconnect and reports progress:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
job = vx.submit_job("corpus.zip", engine="curate")
|
|
40
|
+
print(job.id, job.status)
|
|
41
|
+
|
|
42
|
+
report = job.wait() # polls with backoff
|
|
43
|
+
plan = vx.manifest(report.id)
|
|
44
|
+
print(f"keep {len(plan.keep)}, drop {len(plan.drop)}")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`plan.drop` is a list of filenames. **Voxelion does not delete them** — what
|
|
48
|
+
you do with the plan is yours to decide.
|
|
49
|
+
|
|
50
|
+
## Engines
|
|
51
|
+
|
|
52
|
+
| Engine | For |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `health` | Medical imaging. DICOM-aware: a CT or MR series is deduplicated as a scan, not as loose slices. |
|
|
55
|
+
| `curate` | General image archives — product photography, scraped corpora, generated output. |
|
|
56
|
+
|
|
57
|
+
Omit `engine=` to use your account's default. The engine that actually ran is
|
|
58
|
+
on the report either way:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
report = vx.dedup(files)
|
|
62
|
+
print(report.engine) # "curate"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Errors
|
|
66
|
+
|
|
67
|
+
Exceptions are typed by what went wrong, not by status code:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from voxelion import InsufficientCreditError, ConsentRequiredError
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
report = vx.dedup(files)
|
|
74
|
+
except InsufficientCreditError as e:
|
|
75
|
+
print(f"needs {e.required_cents}c, have {e.available_cents}c")
|
|
76
|
+
except ConsentRequiredError:
|
|
77
|
+
print("Grant data-processing consent in the console first.")
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`429` responses honour the server's `Retry-After` automatically, and `5xx`
|
|
81
|
+
retries with exponential backoff. Nothing else is retried: a `402` will not
|
|
82
|
+
become affordable by asking again.
|
|
83
|
+
|
|
84
|
+
## Sandbox
|
|
85
|
+
|
|
86
|
+
The sandbox is a separate deployment with its own database and accounts. It is
|
|
87
|
+
the same client with a different base URL:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from voxelion import Voxelion, SANDBOX_BASE_URL
|
|
91
|
+
|
|
92
|
+
vx = Voxelion(base_url=SANDBOX_BASE_URL)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Checking cost before spending
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
account = vx.balance()
|
|
99
|
+
print(account.spendable_cents) # not balance_cents — see below
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`spendable_cents` is the balance minus credit already held against runs in
|
|
103
|
+
flight. It is the number that decides whether the next call succeeds.
|
|
104
|
+
|
|
105
|
+
## Development
|
|
106
|
+
|
|
107
|
+
Models in `src/voxelion/models.py` are **generated** from the API's OpenAPI
|
|
108
|
+
document. Do not edit them by hand:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
./scripts-generate.sh
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
pytest # unit tests, no network
|
|
116
|
+
pytest -m live # against a real deployment; needs VOXELION_API_KEY
|
|
117
|
+
```
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "voxelion"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Perceptual deduplication for image datasets — the official Python client for the Voxelion API."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Voxelion" }]
|
|
14
|
+
keywords = ["deduplication", "dataset", "perceptual-hash", "dicom", "machine-learning", "data-quality"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Intended Audience :: Science/Research",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.9",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Scientific/Engineering :: Image Processing",
|
|
26
|
+
"Typing :: Typed",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
# Two runtime dependencies and no more. Every dependency an SDK adds is one its
|
|
30
|
+
# users must resolve against their own pins, and a data-science environment is
|
|
31
|
+
# already the hardest place in Python to add a constraint.
|
|
32
|
+
dependencies = [
|
|
33
|
+
"httpx>=0.24,<1",
|
|
34
|
+
"pydantic>=2,<3",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://voxelion.ai"
|
|
39
|
+
Documentation = "https://voxelion.ai/docs/"
|
|
40
|
+
Changelog = "https://github.com/Asekun/bioHarmonix/blob/main/sdk/python/CHANGELOG.md"
|
|
41
|
+
|
|
42
|
+
[project.optional-dependencies]
|
|
43
|
+
dev = ["pytest>=7", "pytest-httpx>=0.30", "mypy>=1.8", "ruff>=0.4"]
|
|
44
|
+
|
|
45
|
+
[tool.hatch.version]
|
|
46
|
+
path = "src/voxelion/_version.py"
|
|
47
|
+
|
|
48
|
+
[tool.hatch.build.targets.wheel]
|
|
49
|
+
packages = ["src/voxelion"]
|
|
50
|
+
|
|
51
|
+
[tool.pytest.ini_options]
|
|
52
|
+
testpaths = ["tests"]
|
|
53
|
+
# Live tests need a sandbox key and are skipped without one.
|
|
54
|
+
markers = ["live: talks to a real deployment (needs VOXELION_API_KEY)"]
|
|
55
|
+
|
|
56
|
+
[tool.mypy]
|
|
57
|
+
python_version = "3.9"
|
|
58
|
+
strict = true
|
|
59
|
+
|
|
60
|
+
# The TESTS are type-checked too, but not at library strictness.
|
|
61
|
+
#
|
|
62
|
+
# They went unchecked entirely until the TypeScript side turned out to have the
|
|
63
|
+
# same blind spot — its tsconfig excluded `test/`, so every type assertion in
|
|
64
|
+
# every test there was inert. The same was true here.
|
|
65
|
+
#
|
|
66
|
+
# Annotating every pytest function and fixture buys noise, not safety, so the
|
|
67
|
+
# annotation REQUIREMENT is relaxed while real type errors — a wrong argument,
|
|
68
|
+
# a field that does not exist on a model — are still caught.
|
|
69
|
+
[[tool.mypy.overrides]]
|
|
70
|
+
module = "tests.*"
|
|
71
|
+
disallow_untyped_defs = false
|
|
72
|
+
disallow_incomplete_defs = false
|
|
73
|
+
disallow_untyped_calls = false
|
|
74
|
+
# Generated file: its style is the generator's business, not ours.
|
|
75
|
+
[[tool.mypy.overrides]]
|
|
76
|
+
module = "voxelion.models"
|
|
77
|
+
ignore_errors = true
|
|
78
|
+
|
|
79
|
+
[tool.ruff]
|
|
80
|
+
line-length = 100
|
|
81
|
+
target-version = "py39"
|
|
82
|
+
# models.py is generated from the OpenAPI document. Its formatting is the
|
|
83
|
+
# generator's business; linting it would mean either editing a generated file
|
|
84
|
+
# or carrying a permanent list of ignores.
|
|
85
|
+
extend-exclude = ["src/voxelion/models.py"]
|
|
86
|
+
|
|
87
|
+
[tool.ruff.lint]
|
|
88
|
+
select = ["E", "F", "I", "UP", "B", "SIM"]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Regenerate the models from the API's OpenAPI document.
|
|
3
|
+
#
|
|
4
|
+
# cd sdk/python && ./scripts-generate.sh
|
|
5
|
+
#
|
|
6
|
+
# Run this after any change to backend/src/schemas.js. The generated file is
|
|
7
|
+
# committed so that installing the SDK never requires the generator.
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
cd "$(dirname "$0")"
|
|
10
|
+
|
|
11
|
+
(cd ../../backend && npm run openapi >/dev/null)
|
|
12
|
+
|
|
13
|
+
.venv/bin/datamodel-codegen \
|
|
14
|
+
--input ../../backend/openapi.json --input-file-type openapi \
|
|
15
|
+
--output src/voxelion/models.py \
|
|
16
|
+
--output-model-type pydantic_v2.BaseModel \
|
|
17
|
+
--target-python-version 3.9 \
|
|
18
|
+
--use-schema-description --use-field-description \
|
|
19
|
+
--field-constraints --use-double-quotes --use-standard-collections \
|
|
20
|
+
--snake-case-field --allow-population-by-field-name --use-subclass-enum \
|
|
21
|
+
--custom-file-header "# GENERATED FROM backend/openapi.json — DO NOT EDIT BY HAND.
|
|
22
|
+
#
|
|
23
|
+
# Regenerate with: ./scripts-generate.sh
|
|
24
|
+
#
|
|
25
|
+
# Derived from the API's own OpenAPI document, which is generated from
|
|
26
|
+
# apiDocs(). Hand-editing here would create a third description of the API that
|
|
27
|
+
# drifts from the other two, and that drift surfaces as a wrong type in
|
|
28
|
+
# somebody else's program."
|
|
29
|
+
|
|
30
|
+
echo "models regenerated: $(grep -c '^class' src/voxelion/models.py) classes"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Voxelion — perceptual deduplication for image datasets.
|
|
2
|
+
|
|
3
|
+
from voxelion import Voxelion
|
|
4
|
+
|
|
5
|
+
vx = Voxelion() # reads VOXELION_API_KEY
|
|
6
|
+
report = vx.dedup(["a.png", "b.png"], engine="curate")
|
|
7
|
+
print(report.leakage, len(report.clusters))
|
|
8
|
+
|
|
9
|
+
Nothing here ever deletes a file. A report and its manifest tell you what is
|
|
10
|
+
redundant; acting on that stays your decision.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from ._client import (
|
|
14
|
+
DEFAULT_BASE_URL,
|
|
15
|
+
SANDBOX_BASE_URL,
|
|
16
|
+
JobHandle,
|
|
17
|
+
Voxelion,
|
|
18
|
+
)
|
|
19
|
+
from ._transport import ApiKeyProvider, ApiKeySource
|
|
20
|
+
from ._version import __version__
|
|
21
|
+
from .errors import (
|
|
22
|
+
AccountNotActiveError,
|
|
23
|
+
APIConnectionError,
|
|
24
|
+
AuthenticationError,
|
|
25
|
+
ConsentRequiredError,
|
|
26
|
+
InsufficientCreditError,
|
|
27
|
+
InvalidRequestError,
|
|
28
|
+
JobFailedError,
|
|
29
|
+
NotFoundError,
|
|
30
|
+
RateLimitError,
|
|
31
|
+
ServerError,
|
|
32
|
+
VoxelionError,
|
|
33
|
+
)
|
|
34
|
+
from .models import (
|
|
35
|
+
AutoTopUp,
|
|
36
|
+
BillingAccount,
|
|
37
|
+
Card,
|
|
38
|
+
DedupReport,
|
|
39
|
+
Engine,
|
|
40
|
+
Hash,
|
|
41
|
+
Job,
|
|
42
|
+
Manifest,
|
|
43
|
+
ManifestCluster,
|
|
44
|
+
Pair,
|
|
45
|
+
ReportSummary,
|
|
46
|
+
ReportVolume,
|
|
47
|
+
ReportVolumePair,
|
|
48
|
+
)
|
|
49
|
+
from .models import (
|
|
50
|
+
Report as StoredReport,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
__all__ = [
|
|
54
|
+
"ApiKeyProvider", "ApiKeySource",
|
|
55
|
+
"__version__",
|
|
56
|
+
"Voxelion", "JobHandle", "DEFAULT_BASE_URL", "SANDBOX_BASE_URL",
|
|
57
|
+
"VoxelionError", "AuthenticationError", "ConsentRequiredError",
|
|
58
|
+
"AccountNotActiveError", "InsufficientCreditError", "InvalidRequestError",
|
|
59
|
+
"NotFoundError", "RateLimitError", "ServerError", "APIConnectionError",
|
|
60
|
+
"JobFailedError",
|
|
61
|
+
"DedupReport", "StoredReport", "ReportSummary", "ReportVolume", "ReportVolumePair",
|
|
62
|
+
"Manifest", "ManifestCluster", "Job",
|
|
63
|
+
"BillingAccount", "Card", "AutoTopUp", "Hash", "Pair", "Engine",
|
|
64
|
+
]
|