translatarr-client 0.2.1__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.
- translatarr_client-0.2.1/.gitignore +208 -0
- translatarr_client-0.2.1/PKG-INFO +137 -0
- translatarr_client-0.2.1/README.md +123 -0
- translatarr_client-0.2.1/pyproject.toml +25 -0
- translatarr_client-0.2.1/scripts/model_header.txt +5 -0
- translatarr_client-0.2.1/scripts/regenerate.sh +46 -0
- translatarr_client-0.2.1/src/translatarr/__init__.py +76 -0
- translatarr_client-0.2.1/src/translatarr/_core.py +134 -0
- translatarr_client-0.2.1/src/translatarr/_errors.py +99 -0
- translatarr_client-0.2.1/src/translatarr/_models.py +335 -0
- translatarr_client-0.2.1/src/translatarr/aio.py +213 -0
- translatarr_client-0.2.1/src/translatarr/client.py +207 -0
- translatarr_client-0.2.1/src/translatarr/languages.py +35 -0
- translatarr_client-0.2.1/src/translatarr/py.typed +0 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
|
2
|
+
|
|
3
|
+
# Logs
|
|
4
|
+
|
|
5
|
+
logs
|
|
6
|
+
_.log
|
|
7
|
+
npm-debug.log_
|
|
8
|
+
yarn-debug.log*
|
|
9
|
+
yarn-error.log*
|
|
10
|
+
lerna-debug.log*
|
|
11
|
+
.pnpm-debug.log*
|
|
12
|
+
|
|
13
|
+
# Caches
|
|
14
|
+
|
|
15
|
+
.cache
|
|
16
|
+
|
|
17
|
+
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
18
|
+
|
|
19
|
+
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
|
20
|
+
|
|
21
|
+
# Runtime data
|
|
22
|
+
|
|
23
|
+
pids
|
|
24
|
+
_.pid
|
|
25
|
+
_.seed
|
|
26
|
+
*.pid.lock
|
|
27
|
+
|
|
28
|
+
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
29
|
+
|
|
30
|
+
lib-cov
|
|
31
|
+
|
|
32
|
+
# Coverage directory used by tools like istanbul
|
|
33
|
+
|
|
34
|
+
coverage
|
|
35
|
+
*.lcov
|
|
36
|
+
|
|
37
|
+
# nyc test coverage
|
|
38
|
+
|
|
39
|
+
.nyc_output
|
|
40
|
+
|
|
41
|
+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
42
|
+
|
|
43
|
+
.grunt
|
|
44
|
+
|
|
45
|
+
# Bower dependency directory (https://bower.io/)
|
|
46
|
+
|
|
47
|
+
bower_components
|
|
48
|
+
|
|
49
|
+
# node-waf configuration
|
|
50
|
+
|
|
51
|
+
.lock-wscript
|
|
52
|
+
|
|
53
|
+
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
54
|
+
|
|
55
|
+
build/Release
|
|
56
|
+
|
|
57
|
+
# Dependency directories
|
|
58
|
+
|
|
59
|
+
node_modules/
|
|
60
|
+
jspm_packages/
|
|
61
|
+
|
|
62
|
+
# Snowpack dependency directory (https://snowpack.dev/)
|
|
63
|
+
|
|
64
|
+
web_modules/
|
|
65
|
+
|
|
66
|
+
# TypeScript cache
|
|
67
|
+
|
|
68
|
+
*.tsbuildinfo
|
|
69
|
+
|
|
70
|
+
# Optional npm cache directory
|
|
71
|
+
|
|
72
|
+
.npm
|
|
73
|
+
|
|
74
|
+
# Optional eslint cache
|
|
75
|
+
|
|
76
|
+
.eslintcache
|
|
77
|
+
|
|
78
|
+
# Optional stylelint cache
|
|
79
|
+
|
|
80
|
+
.stylelintcache
|
|
81
|
+
|
|
82
|
+
# Microbundle cache
|
|
83
|
+
|
|
84
|
+
.rpt2_cache/
|
|
85
|
+
.rts2_cache_cjs/
|
|
86
|
+
.rts2_cache_es/
|
|
87
|
+
.rts2_cache_umd/
|
|
88
|
+
|
|
89
|
+
# Optional REPL history
|
|
90
|
+
|
|
91
|
+
.node_repl_history
|
|
92
|
+
|
|
93
|
+
# Output of 'npm pack'
|
|
94
|
+
|
|
95
|
+
*.tgz
|
|
96
|
+
|
|
97
|
+
# Yarn Integrity file
|
|
98
|
+
|
|
99
|
+
.yarn-integrity
|
|
100
|
+
|
|
101
|
+
# dotenv environment variable files
|
|
102
|
+
|
|
103
|
+
.env
|
|
104
|
+
.env.development.local
|
|
105
|
+
.env.test.local
|
|
106
|
+
.env.production.local
|
|
107
|
+
.env.local
|
|
108
|
+
|
|
109
|
+
# parcel-bundler cache (https://parceljs.org/)
|
|
110
|
+
|
|
111
|
+
.parcel-cache
|
|
112
|
+
|
|
113
|
+
# Next.js build output
|
|
114
|
+
|
|
115
|
+
.next
|
|
116
|
+
out
|
|
117
|
+
next-env.d.ts
|
|
118
|
+
|
|
119
|
+
# Nuxt.js build / generate output
|
|
120
|
+
|
|
121
|
+
.nuxt
|
|
122
|
+
dist
|
|
123
|
+
|
|
124
|
+
# Gatsby files
|
|
125
|
+
|
|
126
|
+
# Comment in the public line in if your project uses Gatsby and not Next.js
|
|
127
|
+
|
|
128
|
+
# https://nextjs.org/blog/next-9-1#public-directory-support
|
|
129
|
+
|
|
130
|
+
# public
|
|
131
|
+
|
|
132
|
+
# vuepress build output
|
|
133
|
+
|
|
134
|
+
.vuepress/dist
|
|
135
|
+
|
|
136
|
+
# vuepress v2.x temp and cache directory
|
|
137
|
+
|
|
138
|
+
.temp
|
|
139
|
+
|
|
140
|
+
# Docusaurus cache and generated files
|
|
141
|
+
|
|
142
|
+
.docusaurus
|
|
143
|
+
|
|
144
|
+
# Serverless directories
|
|
145
|
+
|
|
146
|
+
.serverless/
|
|
147
|
+
|
|
148
|
+
# FuseBox cache
|
|
149
|
+
|
|
150
|
+
.fusebox/
|
|
151
|
+
|
|
152
|
+
# DynamoDB Local files
|
|
153
|
+
|
|
154
|
+
.dynamodb/
|
|
155
|
+
|
|
156
|
+
# TernJS port file
|
|
157
|
+
|
|
158
|
+
.tern-port
|
|
159
|
+
|
|
160
|
+
# Stores VSCode versions used for testing VSCode extensions
|
|
161
|
+
|
|
162
|
+
.vscode-test
|
|
163
|
+
|
|
164
|
+
# yarn v2
|
|
165
|
+
|
|
166
|
+
.yarn/cache
|
|
167
|
+
.yarn/unplugged
|
|
168
|
+
.yarn/build-state.yml
|
|
169
|
+
.yarn/install-state.gz
|
|
170
|
+
.pnp.*
|
|
171
|
+
|
|
172
|
+
# IntelliJ based IDEs
|
|
173
|
+
.idea
|
|
174
|
+
|
|
175
|
+
# Finder (MacOS) folder config
|
|
176
|
+
.DS_Store
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
# app data
|
|
180
|
+
data
|
|
181
|
+
|
|
182
|
+
# generated Swagger UI assets (copied from swagger-ui-dist at dev/build time)
|
|
183
|
+
.swagger-ui
|
|
184
|
+
|
|
185
|
+
clients/python/.venv
|
|
186
|
+
clients/python/openapi.json
|
|
187
|
+
|
|
188
|
+
# TypeScript client: regenerated spec, build output, deps, packed tarballs
|
|
189
|
+
clients/typescript/openapi.json
|
|
190
|
+
clients/typescript/dist/
|
|
191
|
+
clients/typescript/node_modules/
|
|
192
|
+
clients/typescript/*.tgz
|
|
193
|
+
|
|
194
|
+
# Rust client: regenerated spec/schema, build output, lockfile (library crate)
|
|
195
|
+
clients/rust/openapi.json
|
|
196
|
+
clients/rust/schema.json
|
|
197
|
+
clients/rust/target/
|
|
198
|
+
clients/rust/Cargo.lock
|
|
199
|
+
__pycache__
|
|
200
|
+
.venv/
|
|
201
|
+
__pycache__/
|
|
202
|
+
*.pyc
|
|
203
|
+
*.egg-info/
|
|
204
|
+
build/
|
|
205
|
+
dist/
|
|
206
|
+
.mypy_cache/
|
|
207
|
+
.pytest_cache/
|
|
208
|
+
.ruff_cache/
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: translatarr-client
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Synchronous and asynchronous Python client for the Translatarr API.
|
|
5
|
+
Author: joshrmcdaniel
|
|
6
|
+
License: AGPL-3.0-or-later
|
|
7
|
+
Keywords: api,client,llm,translatarr,translation
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: httpx>=0.24
|
|
10
|
+
Requires-Dist: pydantic>=2.4
|
|
11
|
+
Provides-Extra: codegen
|
|
12
|
+
Requires-Dist: datamodel-code-generator>=0.65; extra == 'codegen'
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# translatarr-client
|
|
16
|
+
|
|
17
|
+
A typed Python client for the [Translatarr](../../README.md) API — synchronous
|
|
18
|
+
and asynchronous, with pydantic response models generated from the server's
|
|
19
|
+
OpenAPI spec.
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install translatarr-client
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Published to [PyPI](https://pypi.org/project/translatarr-client/) for each `v*`
|
|
28
|
+
tag (the version matches the app's tag). The same wheel + sdist are also
|
|
29
|
+
attached to the corresponding GitHub Release, and you can install straight from
|
|
30
|
+
this repo:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# from a published GitHub Release (version matches the app's v* tag)
|
|
34
|
+
pip install https://github.com/joshrmcdaniel/translatarr/releases/download/v1.2.3/translatarr_client-1.2.3-py3-none-any.whl
|
|
35
|
+
|
|
36
|
+
# or straight from this repo
|
|
37
|
+
pip install -e clients/python
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Requires Python 3.10+.
|
|
41
|
+
|
|
42
|
+
## Authentication
|
|
43
|
+
|
|
44
|
+
Mint a personal API key in the web UI under **Settings → API keys** (tokens are
|
|
45
|
+
prefixed `tra_` and shown only once). Pass it as `token`:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from translatarr import TranslatarrClient
|
|
49
|
+
|
|
50
|
+
with TranslatarrClient("https://translatarr.example", token="tra_…") as tra:
|
|
51
|
+
result = tra.translate("Good morning", source_lang="en", target_lang="ja")
|
|
52
|
+
best = result.translations[0]
|
|
53
|
+
print(best.text, best.romanization)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
A browser session cookie works too, via `session_cookie="…"` instead of `token`.
|
|
57
|
+
|
|
58
|
+
## Async
|
|
59
|
+
|
|
60
|
+
`AsyncTranslatarrClient` mirrors the sync client method-for-method:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
import asyncio
|
|
64
|
+
from translatarr import AsyncTranslatarrClient
|
|
65
|
+
|
|
66
|
+
async def main() -> None:
|
|
67
|
+
async with AsyncTranslatarrClient("https://translatarr.example", token="tra_…") as tra:
|
|
68
|
+
result = await tra.translate("Bonjour", source_lang="auto", target_lang="en")
|
|
69
|
+
print(result.detected_source_language, result.translations[0].text)
|
|
70
|
+
|
|
71
|
+
asyncio.run(main())
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## What you can do
|
|
75
|
+
|
|
76
|
+
| Area | Methods |
|
|
77
|
+
| --------- | ------- |
|
|
78
|
+
| Translate | `translate` |
|
|
79
|
+
| Chats | `list_chats`, `create_chat`, `get_chat`, `rename_chat`, `clear_chat`, `delete_chat` |
|
|
80
|
+
| Turns | `add_turn`, `select_option`, `retranslate_turn`, `switch_branch` |
|
|
81
|
+
| Speech | `transcribe`, `synthesize` |
|
|
82
|
+
| API keys | `list_keys`, `create_key`, `revoke_key` |
|
|
83
|
+
|
|
84
|
+
### Persisting a chat without paying for a second translation
|
|
85
|
+
|
|
86
|
+
`translate` does not store anything; `add_turn` translates *and* persists. To
|
|
87
|
+
avoid a duplicate LLM call, pass the `result` you already have:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
chat = tra.create_chat(source_lang="en", target_lang="ja")
|
|
91
|
+
preview = tra.translate("Let's ship it", source_lang="en", target_lang="ja", chat_id=chat.id)
|
|
92
|
+
chat = tra.add_turn(chat.id, "Let's ship it", source_lang="en", target_lang="ja", result=preview)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Errors
|
|
96
|
+
|
|
97
|
+
Failures raise a subclass of `translatarr.APIError`, each carrying `status_code`,
|
|
98
|
+
the server's `code` (when present), and the raw `response`:
|
|
99
|
+
|
|
100
|
+
| Exception | Status |
|
|
101
|
+
| --------- | ------ |
|
|
102
|
+
| `InvalidRequestError` | 400 |
|
|
103
|
+
| `AuthenticationError` | 401 |
|
|
104
|
+
| `ForbiddenError` | 403 |
|
|
105
|
+
| `NotFoundError` | 404 |
|
|
106
|
+
| `ConflictError` | 409 |
|
|
107
|
+
| `MalformedResponseError`| 422 |
|
|
108
|
+
| `ProviderError` | 502 |
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from translatarr import NotFoundError
|
|
112
|
+
|
|
113
|
+
try:
|
|
114
|
+
tra.get_chat("does-not-exist")
|
|
115
|
+
except NotFoundError:
|
|
116
|
+
...
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Development
|
|
120
|
+
|
|
121
|
+
The response models in `src/translatarr/_models.py` are **generated** from the
|
|
122
|
+
server's OpenAPI document — do not edit them by hand. To regenerate after the
|
|
123
|
+
API schema changes:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# one-time tooling install
|
|
127
|
+
python -m venv clients/python/.venv
|
|
128
|
+
clients/python/.venv/bin/pip install -e 'clients/python[codegen]'
|
|
129
|
+
|
|
130
|
+
# regenerate openapi.json + _models.py
|
|
131
|
+
clients/python/scripts/regenerate.sh
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The script dumps the spec via `bun scripts/dump-openapi.ts` (the same document
|
|
135
|
+
served at `/api/docs/openapi.json`) and runs `datamodel-codegen` over it. Only
|
|
136
|
+
`_models.py` is committed, so the client builds and installs without a running
|
|
137
|
+
server; `openapi.json` is a regenerated, gitignored artifact.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# translatarr-client
|
|
2
|
+
|
|
3
|
+
A typed Python client for the [Translatarr](../../README.md) API — synchronous
|
|
4
|
+
and asynchronous, with pydantic response models generated from the server's
|
|
5
|
+
OpenAPI spec.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install translatarr-client
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Published to [PyPI](https://pypi.org/project/translatarr-client/) for each `v*`
|
|
14
|
+
tag (the version matches the app's tag). The same wheel + sdist are also
|
|
15
|
+
attached to the corresponding GitHub Release, and you can install straight from
|
|
16
|
+
this repo:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# from a published GitHub Release (version matches the app's v* tag)
|
|
20
|
+
pip install https://github.com/joshrmcdaniel/translatarr/releases/download/v1.2.3/translatarr_client-1.2.3-py3-none-any.whl
|
|
21
|
+
|
|
22
|
+
# or straight from this repo
|
|
23
|
+
pip install -e clients/python
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Requires Python 3.10+.
|
|
27
|
+
|
|
28
|
+
## Authentication
|
|
29
|
+
|
|
30
|
+
Mint a personal API key in the web UI under **Settings → API keys** (tokens are
|
|
31
|
+
prefixed `tra_` and shown only once). Pass it as `token`:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from translatarr import TranslatarrClient
|
|
35
|
+
|
|
36
|
+
with TranslatarrClient("https://translatarr.example", token="tra_…") as tra:
|
|
37
|
+
result = tra.translate("Good morning", source_lang="en", target_lang="ja")
|
|
38
|
+
best = result.translations[0]
|
|
39
|
+
print(best.text, best.romanization)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
A browser session cookie works too, via `session_cookie="…"` instead of `token`.
|
|
43
|
+
|
|
44
|
+
## Async
|
|
45
|
+
|
|
46
|
+
`AsyncTranslatarrClient` mirrors the sync client method-for-method:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import asyncio
|
|
50
|
+
from translatarr import AsyncTranslatarrClient
|
|
51
|
+
|
|
52
|
+
async def main() -> None:
|
|
53
|
+
async with AsyncTranslatarrClient("https://translatarr.example", token="tra_…") as tra:
|
|
54
|
+
result = await tra.translate("Bonjour", source_lang="auto", target_lang="en")
|
|
55
|
+
print(result.detected_source_language, result.translations[0].text)
|
|
56
|
+
|
|
57
|
+
asyncio.run(main())
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## What you can do
|
|
61
|
+
|
|
62
|
+
| Area | Methods |
|
|
63
|
+
| --------- | ------- |
|
|
64
|
+
| Translate | `translate` |
|
|
65
|
+
| Chats | `list_chats`, `create_chat`, `get_chat`, `rename_chat`, `clear_chat`, `delete_chat` |
|
|
66
|
+
| Turns | `add_turn`, `select_option`, `retranslate_turn`, `switch_branch` |
|
|
67
|
+
| Speech | `transcribe`, `synthesize` |
|
|
68
|
+
| API keys | `list_keys`, `create_key`, `revoke_key` |
|
|
69
|
+
|
|
70
|
+
### Persisting a chat without paying for a second translation
|
|
71
|
+
|
|
72
|
+
`translate` does not store anything; `add_turn` translates *and* persists. To
|
|
73
|
+
avoid a duplicate LLM call, pass the `result` you already have:
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
chat = tra.create_chat(source_lang="en", target_lang="ja")
|
|
77
|
+
preview = tra.translate("Let's ship it", source_lang="en", target_lang="ja", chat_id=chat.id)
|
|
78
|
+
chat = tra.add_turn(chat.id, "Let's ship it", source_lang="en", target_lang="ja", result=preview)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Errors
|
|
82
|
+
|
|
83
|
+
Failures raise a subclass of `translatarr.APIError`, each carrying `status_code`,
|
|
84
|
+
the server's `code` (when present), and the raw `response`:
|
|
85
|
+
|
|
86
|
+
| Exception | Status |
|
|
87
|
+
| --------- | ------ |
|
|
88
|
+
| `InvalidRequestError` | 400 |
|
|
89
|
+
| `AuthenticationError` | 401 |
|
|
90
|
+
| `ForbiddenError` | 403 |
|
|
91
|
+
| `NotFoundError` | 404 |
|
|
92
|
+
| `ConflictError` | 409 |
|
|
93
|
+
| `MalformedResponseError`| 422 |
|
|
94
|
+
| `ProviderError` | 502 |
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from translatarr import NotFoundError
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
tra.get_chat("does-not-exist")
|
|
101
|
+
except NotFoundError:
|
|
102
|
+
...
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Development
|
|
106
|
+
|
|
107
|
+
The response models in `src/translatarr/_models.py` are **generated** from the
|
|
108
|
+
server's OpenAPI document — do not edit them by hand. To regenerate after the
|
|
109
|
+
API schema changes:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# one-time tooling install
|
|
113
|
+
python -m venv clients/python/.venv
|
|
114
|
+
clients/python/.venv/bin/pip install -e 'clients/python[codegen]'
|
|
115
|
+
|
|
116
|
+
# regenerate openapi.json + _models.py
|
|
117
|
+
clients/python/scripts/regenerate.sh
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The script dumps the spec via `bun scripts/dump-openapi.ts` (the same document
|
|
121
|
+
served at `/api/docs/openapi.json`) and runs `datamodel-codegen` over it. Only
|
|
122
|
+
`_models.py` is committed, so the client builds and installs without a running
|
|
123
|
+
server; `openapi.json` is a regenerated, gitignored artifact.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "translatarr-client"
|
|
7
|
+
version = "0.2.1"
|
|
8
|
+
description = "Synchronous and asynchronous Python client for the Translatarr API."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "AGPL-3.0-or-later" }
|
|
12
|
+
authors = [{ name = "joshrmcdaniel" }]
|
|
13
|
+
keywords = ["translatarr", "translation", "llm", "api", "client"]
|
|
14
|
+
dependencies = [
|
|
15
|
+
"httpx>=0.24",
|
|
16
|
+
"pydantic>=2.4",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[project.optional-dependencies]
|
|
20
|
+
# Tooling for regenerating the pydantic models from the OpenAPI spec
|
|
21
|
+
# (clients/python/scripts/regenerate.sh).
|
|
22
|
+
codegen = ["datamodel-code-generator>=0.65"]
|
|
23
|
+
|
|
24
|
+
[tool.hatch.build.targets.wheel]
|
|
25
|
+
packages = ["src/translatarr"]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Regenerate the Python client's pydantic models from the server's OpenAPI spec.
|
|
4
|
+
#
|
|
5
|
+
# Step 1 dumps the spec (built from the Zod schemas in app/lib) to
|
|
6
|
+
# clients/python/openapi.json; step 2 renders it to src/translatarr/_models.py.
|
|
7
|
+
# Both outputs are committed, so the client is usable without a running server.
|
|
8
|
+
#
|
|
9
|
+
# Requires: bun (to run the dump script) and datamodel-code-generator (installed
|
|
10
|
+
# in clients/python/.venv, or otherwise on PATH).
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
repo_root="$(cd "$script_dir/../../.." && pwd)"
|
|
16
|
+
client_dir="$repo_root/clients/python"
|
|
17
|
+
spec="$client_dir/openapi.json"
|
|
18
|
+
out="$client_dir/src/translatarr/_models.py"
|
|
19
|
+
|
|
20
|
+
echo "==> Dumping OpenAPI spec to $spec"
|
|
21
|
+
bun "$repo_root/scripts/dump-openapi.ts" "$spec"
|
|
22
|
+
|
|
23
|
+
codegen="$client_dir/.venv/bin/datamodel-codegen"
|
|
24
|
+
if [ ! -x "$codegen" ]; then
|
|
25
|
+
codegen="datamodel-codegen"
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
echo "==> Generating pydantic models with $codegen"
|
|
29
|
+
"$codegen" \
|
|
30
|
+
--input "$spec" \
|
|
31
|
+
--input-file-type openapi \
|
|
32
|
+
--output-model-type pydantic_v2.BaseModel \
|
|
33
|
+
--output-datetime-class datetime \
|
|
34
|
+
--enum-field-as-literal all \
|
|
35
|
+
--collapse-root-models \
|
|
36
|
+
--snake-case-field \
|
|
37
|
+
--use-union-operator \
|
|
38
|
+
--use-standard-collections \
|
|
39
|
+
--use-annotated \
|
|
40
|
+
--use-schema-description \
|
|
41
|
+
--disable-timestamp \
|
|
42
|
+
--custom-file-header-path "$script_dir/model_header.txt" \
|
|
43
|
+
--target-python-version 3.10 \
|
|
44
|
+
--output "$out"
|
|
45
|
+
|
|
46
|
+
echo "==> Wrote $out"
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Python client for the Translatarr API.
|
|
2
|
+
|
|
3
|
+
Synchronous and asynchronous clients over the documented REST endpoints, with
|
|
4
|
+
pydantic response models generated from the server's OpenAPI spec.
|
|
5
|
+
|
|
6
|
+
from translatarr import TranslatarrClient
|
|
7
|
+
|
|
8
|
+
with TranslatarrClient("https://translatarr.example", token="tra_…") as tra:
|
|
9
|
+
result = tra.translate("Good morning", source_lang="en", target_lang="ja")
|
|
10
|
+
print(result.translations[0].text)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from importlib.metadata import PackageNotFoundError, version as _package_version
|
|
16
|
+
|
|
17
|
+
from ._errors import (
|
|
18
|
+
APIError,
|
|
19
|
+
AuthenticationError,
|
|
20
|
+
ConflictError,
|
|
21
|
+
ForbiddenError,
|
|
22
|
+
InvalidRequestError,
|
|
23
|
+
MalformedResponseError,
|
|
24
|
+
NotFoundError,
|
|
25
|
+
ProviderError,
|
|
26
|
+
TranslatarrError,
|
|
27
|
+
)
|
|
28
|
+
from ._models import (
|
|
29
|
+
ApiKey,
|
|
30
|
+
ChatDetail,
|
|
31
|
+
ChatSummary,
|
|
32
|
+
ChatTurn,
|
|
33
|
+
CreatedApiKey,
|
|
34
|
+
KeyWord,
|
|
35
|
+
Translation,
|
|
36
|
+
TranslationResponse,
|
|
37
|
+
)
|
|
38
|
+
from .aio import AsyncTranslatarrClient
|
|
39
|
+
from .client import TranslatarrClient
|
|
40
|
+
from .languages import AUTO_DETECT, SUPPORTED_LANGUAGE_CODES, SourceLang, TargetLang
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
__version__ = _package_version("translatarr-client")
|
|
44
|
+
except PackageNotFoundError: # running from a source checkout without an install
|
|
45
|
+
__version__ = "0.0.0+unknown"
|
|
46
|
+
|
|
47
|
+
__all__ = [
|
|
48
|
+
"__version__",
|
|
49
|
+
# clients
|
|
50
|
+
"TranslatarrClient",
|
|
51
|
+
"AsyncTranslatarrClient",
|
|
52
|
+
# models
|
|
53
|
+
"ApiKey",
|
|
54
|
+
"ChatDetail",
|
|
55
|
+
"ChatSummary",
|
|
56
|
+
"ChatTurn",
|
|
57
|
+
"CreatedApiKey",
|
|
58
|
+
"KeyWord",
|
|
59
|
+
"Translation",
|
|
60
|
+
"TranslationResponse",
|
|
61
|
+
# languages
|
|
62
|
+
"AUTO_DETECT",
|
|
63
|
+
"SUPPORTED_LANGUAGE_CODES",
|
|
64
|
+
"SourceLang",
|
|
65
|
+
"TargetLang",
|
|
66
|
+
# errors
|
|
67
|
+
"TranslatarrError",
|
|
68
|
+
"APIError",
|
|
69
|
+
"InvalidRequestError",
|
|
70
|
+
"AuthenticationError",
|
|
71
|
+
"ForbiddenError",
|
|
72
|
+
"NotFoundError",
|
|
73
|
+
"ConflictError",
|
|
74
|
+
"MalformedResponseError",
|
|
75
|
+
"ProviderError",
|
|
76
|
+
]
|