plotwork 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,164 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ lerna-debug.log*
8
+
9
+ # Diagnostic reports (https://nodejs.org/api/report.html)
10
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11
+
12
+ # Runtime data
13
+ pids
14
+ *.pid
15
+ *.seed
16
+ *.pid.lock
17
+
18
+ # Directory for instrumented libs generated by jscoverage/JSCover
19
+ lib-cov
20
+
21
+ # Coverage directory used by tools like istanbul
22
+ coverage
23
+ *.lcov
24
+
25
+ # nyc test coverage
26
+ .nyc_output
27
+
28
+ # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29
+ .grunt
30
+
31
+ # Bower dependency directory (https://bower.io/)
32
+ bower_components
33
+
34
+ # node-waf configuration
35
+ .lock-wscript
36
+
37
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
38
+ build/Release
39
+
40
+ # Dependency directories
41
+ node_modules/
42
+ jspm_packages/
43
+
44
+ # Snowpack dependency directory (https://snowpack.dev/)
45
+ web_modules/
46
+
47
+ # TypeScript cache
48
+ *.tsbuildinfo
49
+
50
+ # Optional npm cache directory
51
+ .npm
52
+
53
+ # Optional eslint cache
54
+ .eslintcache
55
+
56
+ # Optional stylelint cache
57
+ .stylelintcache
58
+
59
+ # Optional REPL history
60
+ .node_repl_history
61
+
62
+ # Output of 'npm pack'
63
+ *.tgz
64
+
65
+ # Yarn Integrity file
66
+ .yarn-integrity
67
+
68
+ # dotenv environment variable files
69
+ .env
70
+ .env.*
71
+ !.env.example
72
+
73
+ # parcel-bundler cache (https://parceljs.org/)
74
+ .cache
75
+ .parcel-cache
76
+
77
+ # Next.js build output
78
+ .next
79
+ out
80
+
81
+ # Nuxt.js build / generate output
82
+ .nuxt
83
+ dist
84
+ .output
85
+
86
+ # Gatsby files
87
+ .cache/
88
+ # Comment in the public line in if your project uses Gatsby and not Next.js
89
+ # https://nextjs.org/blog/next-9-1#public-directory-support
90
+ # public
91
+
92
+ # vuepress build output
93
+ .vuepress/dist
94
+
95
+ # vuepress v2.x temp directory
96
+ .temp
97
+
98
+ # Sveltekit cache directory
99
+ .svelte-kit/
100
+
101
+ # vitepress build output
102
+ **/.vitepress/dist
103
+
104
+ # vitepress cache directory
105
+ **/.vitepress/cache
106
+
107
+ # Docusaurus cache and generated files
108
+ .docusaurus
109
+
110
+ # Serverless directories
111
+ .serverless/
112
+
113
+ # FuseBox cache
114
+ .fusebox/
115
+
116
+ # DynamoDB Local files
117
+ .dynamodb/
118
+
119
+ # Firebase cache directory
120
+ .firebase/
121
+
122
+ # TernJS port file
123
+ .tern-port
124
+
125
+ # Stores Visual Studio Code versions used for testing Visual Studio Code extensions
126
+ .vscode-test
127
+
128
+ # pnpm
129
+ .pnpm-store
130
+
131
+ # yarn v3
132
+ .pnp.*
133
+ .yarn/*
134
+ !.yarn/patches
135
+ !.yarn/plugins
136
+ !.yarn/releases
137
+ !.yarn/sdks
138
+ !.yarn/versions
139
+
140
+ # Vite files
141
+ vite.config.js.timestamp-*
142
+ vite.config.ts.timestamp-*
143
+ .vite/
144
+
145
+ # Astro generated types
146
+ .astro/
147
+
148
+ # Turbo Repo
149
+ .turbo
150
+
151
+ # SDK build output
152
+ dist/
153
+ dist-packs/
154
+ .claude/state/
155
+ .claude/settings.local.json
156
+ docs/film/out/
157
+
158
+ # Python
159
+ __pycache__/
160
+ *.py[cod]
161
+ .pytest_cache/
162
+ .mypy_cache/
163
+ .venv/
164
+ *.egg-info/
plotwork-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Plotwork
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.
@@ -0,0 +1,141 @@
1
+ Metadata-Version: 2.5
2
+ Name: plotwork
3
+ Version: 0.1.0
4
+ Summary: The Plotwork API from Python: validate, draw, render, import and publish diagrams, on the standard library alone.
5
+ Project-URL: Homepage, https://plotwork.dev
6
+ Project-URL: Documentation, https://docs.plotwork.dev/sdks
7
+ Project-URL: Source, https://github.com/plotwork-official/plotwork-sdk
8
+ Project-URL: Issues, https://github.com/plotwork-official/plotwork-sdk/issues
9
+ Author: Plotwork
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: api-client,architecture,diagrams,diagrams-as-code,plotwork,svg
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Documentation
24
+ Classifier: Topic :: Multimedia :: Graphics
25
+ Classifier: Topic :: Software Development :: Documentation
26
+ Classifier: Typing :: Typed
27
+ Requires-Python: >=3.10
28
+ Description-Content-Type: text/markdown
29
+
30
+ <p align="center">
31
+ <a href="https://plotwork.dev">
32
+ <picture>
33
+ <source media="(prefers-color-scheme: dark)" srcset="https://plotwork.dev/brand/logo/plotwork-lockup-on-dark.svg">
34
+ <img alt="Plotwork" src="https://plotwork.dev/brand/logo/plotwork-lockup-on-light.svg" width="240">
35
+ </picture>
36
+ </a>
37
+ </p>
38
+
39
+ # plotwork
40
+
41
+ <p>
42
+ <a href="https://pypi.org/project/plotwork/"><img alt="PyPI" src="https://img.shields.io/pypi/v/plotwork?logo=pypi&logoColor=white&color=0f766e"></a>
43
+ <img alt="Python" src="https://img.shields.io/pypi/pyversions/plotwork?logo=python&logoColor=white&color=0f766e">
44
+ <a href="https://pypi.org/project/plotwork/#provenance"><img alt="Provenance" src="https://img.shields.io/badge/provenance-attested-0f766e?logo=sigstore&logoColor=white"></a>
45
+ <img alt="Runtime dependencies" src="https://img.shields.io/badge/runtime%20dependencies-0-0f766e?logo=dependabot&logoColor=white">
46
+ <img alt="Typed" src="https://img.shields.io/badge/types-generated%20from%20OpenAPI-3776ab?logo=python&logoColor=white">
47
+ </p>
48
+
49
+ The hosted Plotwork API from Python. Every `/v1` operation (validate, draw, render, import a file, publish, patterns, icons) is a typed method generated from the API's OpenAPI document, sent with `urllib` from the standard library alone. It runs on Python 3.10 and later.
50
+
51
+ ## TL;DR
52
+
53
+ | Question | Answer |
54
+ |---|---|
55
+ | What does it install? | Nothing else. |
56
+ | Where do the types come from? | The API's OpenAPI document, kept in the SDK repository as [`spec/openapi.json`](https://github.com/plotwork-official/plotwork-sdk/blob/main/spec/openapi.json). Every request and answer is a `TypedDict`. |
57
+ | How do I sign in? | An API key from the Plotwork portal (`api_key`), or an OAuth access token (`access_token`). |
58
+ | Does a mistake in a diagram raise? | No. It is part of the answer, with a line, a column and a hint. Only a failed request raises, as `PlotworkApiError` with a stable `error_code`. |
59
+ | Does it retry? | A safe call is retried twice on 429 and 503, after the API's `Retry-After`. Publishing is never retried. |
60
+ | Is there a TypeScript client? | Yes, [`@plotwork.official/sdk`](https://www.npmjs.com/package/@plotwork.official/sdk), with the same calls in camelCase. |
61
+
62
+ ## Install
63
+
64
+ ```bash
65
+ pip install plotwork
66
+ ```
67
+
68
+ ## Use
69
+
70
+ ```python
71
+ import os
72
+
73
+ from plotwork import Plotwork
74
+
75
+ plotwork = Plotwork(api_key=os.environ["PLOTWORK_API_KEY"])
76
+
77
+ source = 'flow "Checkout"\nnode web service "Web tier"\nnode api service "Orders API"\nweb -> api : "places order"\n'
78
+
79
+ checked = plotwork.diagrams.validate(source=source)
80
+ if not checked["valid"]:
81
+ for error in checked["errors"]:
82
+ print(error["line"], error["column"], error["message"], error.get("hint"))
83
+
84
+ published = plotwork.diagrams.publish(source=source, embedSource=True)
85
+ # A diagram an organisation's policy keeps private has no public link.
86
+ if "url" in published:
87
+ print(published["url"])
88
+ ```
89
+
90
+ A method takes the request's fields as keyword arguments, named as the API names them (`embedSource`, `documentPath`), and returns the answer as a plain `dict` typed by a `TypedDict`. A body you already have as a `dict` is passed with `**body`. Keep the key in an environment variable or your CI's secret store, never in a file you commit.
91
+
92
+ | Group | Calls |
93
+ |---|---|
94
+ | `diagrams` | `validate`, `draw`, `render`, `outline`, `read`, `edit`, `compare`, `suggest`, `convert_mermaid`, `publish` |
95
+ | `import_source` | A diagram from Terraform, OpenAPI, SQL, Kubernetes, Compose and the other formats the API reads |
96
+ | `markdown` | `sync`, `plan` |
97
+ | `patterns` | `find`, `get`, `draw`, `check` |
98
+ | `icons` | `search`, `map` |
99
+ | `vocabulary` | The language's statements and limits, for a kind or a topic |
100
+
101
+ ## Errors
102
+
103
+ ```python
104
+ from plotwork import PlotworkApiError
105
+
106
+ try:
107
+ plotwork.diagrams.render(source=source)
108
+ except PlotworkApiError as error:
109
+ print(error.status, error.error_code, error.request_id)
110
+ ```
111
+
112
+ | `error_code` | Means |
113
+ |---|---|
114
+ | `auth.missing`, `auth.invalid_key` | No key, or one the API does not accept |
115
+ | `rate_limit.exceeded` | Too many calls; already retried for a safe call |
116
+ | `http.<status>` | An answer that was not the API's error envelope, such as a proxy's page |
117
+ | `request.timeout`, `request.failed` | No answer came; `status` is 0 |
118
+
119
+ ## Options
120
+
121
+ | Option | Default |
122
+ |---|---|
123
+ | `api_key` | none |
124
+ | `access_token` | none |
125
+ | `base_url` | `https://api.plotwork.dev` (`https://api-preview.plotwork.dev` for preview, or a self-hosted engine) |
126
+ | `timeout` | `60` seconds |
127
+ | `max_retries` | `2` |
128
+ | `opener` | `urllib.request.build_opener().open`; pass your own for a proxy or a test |
129
+ | `sleep` | `time.sleep`, the wait before a retry |
130
+
131
+ `plotwork.with_options(timeout=120)` gives a copy with another timeout or number of retries, for a slow call such as a large import.
132
+
133
+ ## See also
134
+
135
+ | Page | Why |
136
+ |---|---|
137
+ | [SDKs guide](https://docs.plotwork.dev/sdks) | Every Plotwork SDK, and which to choose |
138
+ | [API reference](https://docs.plotwork.dev) | What each operation does |
139
+ | [TypeScript client](https://www.npmjs.com/package/@plotwork.official/sdk) | The same API from TypeScript |
140
+ | [Viewer](https://www.npmjs.com/package/@plotwork.official/viewer) | Show what you publish, interactively, in a web page |
141
+ | [Source](https://github.com/plotwork-official/plotwork-sdk/tree/main/python) | This package, its tests and its generator |
@@ -0,0 +1,112 @@
1
+ <p align="center">
2
+ <a href="https://plotwork.dev">
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="https://plotwork.dev/brand/logo/plotwork-lockup-on-dark.svg">
5
+ <img alt="Plotwork" src="https://plotwork.dev/brand/logo/plotwork-lockup-on-light.svg" width="240">
6
+ </picture>
7
+ </a>
8
+ </p>
9
+
10
+ # plotwork
11
+
12
+ <p>
13
+ <a href="https://pypi.org/project/plotwork/"><img alt="PyPI" src="https://img.shields.io/pypi/v/plotwork?logo=pypi&logoColor=white&color=0f766e"></a>
14
+ <img alt="Python" src="https://img.shields.io/pypi/pyversions/plotwork?logo=python&logoColor=white&color=0f766e">
15
+ <a href="https://pypi.org/project/plotwork/#provenance"><img alt="Provenance" src="https://img.shields.io/badge/provenance-attested-0f766e?logo=sigstore&logoColor=white"></a>
16
+ <img alt="Runtime dependencies" src="https://img.shields.io/badge/runtime%20dependencies-0-0f766e?logo=dependabot&logoColor=white">
17
+ <img alt="Typed" src="https://img.shields.io/badge/types-generated%20from%20OpenAPI-3776ab?logo=python&logoColor=white">
18
+ </p>
19
+
20
+ The hosted Plotwork API from Python. Every `/v1` operation (validate, draw, render, import a file, publish, patterns, icons) is a typed method generated from the API's OpenAPI document, sent with `urllib` from the standard library alone. It runs on Python 3.10 and later.
21
+
22
+ ## TL;DR
23
+
24
+ | Question | Answer |
25
+ |---|---|
26
+ | What does it install? | Nothing else. |
27
+ | Where do the types come from? | The API's OpenAPI document, kept in the SDK repository as [`spec/openapi.json`](https://github.com/plotwork-official/plotwork-sdk/blob/main/spec/openapi.json). Every request and answer is a `TypedDict`. |
28
+ | How do I sign in? | An API key from the Plotwork portal (`api_key`), or an OAuth access token (`access_token`). |
29
+ | Does a mistake in a diagram raise? | No. It is part of the answer, with a line, a column and a hint. Only a failed request raises, as `PlotworkApiError` with a stable `error_code`. |
30
+ | Does it retry? | A safe call is retried twice on 429 and 503, after the API's `Retry-After`. Publishing is never retried. |
31
+ | Is there a TypeScript client? | Yes, [`@plotwork.official/sdk`](https://www.npmjs.com/package/@plotwork.official/sdk), with the same calls in camelCase. |
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ pip install plotwork
37
+ ```
38
+
39
+ ## Use
40
+
41
+ ```python
42
+ import os
43
+
44
+ from plotwork import Plotwork
45
+
46
+ plotwork = Plotwork(api_key=os.environ["PLOTWORK_API_KEY"])
47
+
48
+ source = 'flow "Checkout"\nnode web service "Web tier"\nnode api service "Orders API"\nweb -> api : "places order"\n'
49
+
50
+ checked = plotwork.diagrams.validate(source=source)
51
+ if not checked["valid"]:
52
+ for error in checked["errors"]:
53
+ print(error["line"], error["column"], error["message"], error.get("hint"))
54
+
55
+ published = plotwork.diagrams.publish(source=source, embedSource=True)
56
+ # A diagram an organisation's policy keeps private has no public link.
57
+ if "url" in published:
58
+ print(published["url"])
59
+ ```
60
+
61
+ A method takes the request's fields as keyword arguments, named as the API names them (`embedSource`, `documentPath`), and returns the answer as a plain `dict` typed by a `TypedDict`. A body you already have as a `dict` is passed with `**body`. Keep the key in an environment variable or your CI's secret store, never in a file you commit.
62
+
63
+ | Group | Calls |
64
+ |---|---|
65
+ | `diagrams` | `validate`, `draw`, `render`, `outline`, `read`, `edit`, `compare`, `suggest`, `convert_mermaid`, `publish` |
66
+ | `import_source` | A diagram from Terraform, OpenAPI, SQL, Kubernetes, Compose and the other formats the API reads |
67
+ | `markdown` | `sync`, `plan` |
68
+ | `patterns` | `find`, `get`, `draw`, `check` |
69
+ | `icons` | `search`, `map` |
70
+ | `vocabulary` | The language's statements and limits, for a kind or a topic |
71
+
72
+ ## Errors
73
+
74
+ ```python
75
+ from plotwork import PlotworkApiError
76
+
77
+ try:
78
+ plotwork.diagrams.render(source=source)
79
+ except PlotworkApiError as error:
80
+ print(error.status, error.error_code, error.request_id)
81
+ ```
82
+
83
+ | `error_code` | Means |
84
+ |---|---|
85
+ | `auth.missing`, `auth.invalid_key` | No key, or one the API does not accept |
86
+ | `rate_limit.exceeded` | Too many calls; already retried for a safe call |
87
+ | `http.<status>` | An answer that was not the API's error envelope, such as a proxy's page |
88
+ | `request.timeout`, `request.failed` | No answer came; `status` is 0 |
89
+
90
+ ## Options
91
+
92
+ | Option | Default |
93
+ |---|---|
94
+ | `api_key` | none |
95
+ | `access_token` | none |
96
+ | `base_url` | `https://api.plotwork.dev` (`https://api-preview.plotwork.dev` for preview, or a self-hosted engine) |
97
+ | `timeout` | `60` seconds |
98
+ | `max_retries` | `2` |
99
+ | `opener` | `urllib.request.build_opener().open`; pass your own for a proxy or a test |
100
+ | `sleep` | `time.sleep`, the wait before a retry |
101
+
102
+ `plotwork.with_options(timeout=120)` gives a copy with another timeout or number of retries, for a slow call such as a large import.
103
+
104
+ ## See also
105
+
106
+ | Page | Why |
107
+ |---|---|
108
+ | [SDKs guide](https://docs.plotwork.dev/sdks) | Every Plotwork SDK, and which to choose |
109
+ | [API reference](https://docs.plotwork.dev) | What each operation does |
110
+ | [TypeScript client](https://www.npmjs.com/package/@plotwork.official/sdk) | The same API from TypeScript |
111
+ | [Viewer](https://www.npmjs.com/package/@plotwork.official/viewer) | Show what you publish, interactively, in a web page |
112
+ | [Source](https://github.com/plotwork-official/plotwork-sdk/tree/main/python) | This package, its tests and its generator |
@@ -0,0 +1,55 @@
1
+ [build-system]
2
+ requires = ["hatchling==1.33.0"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "plotwork"
7
+ version = "0.1.0"
8
+ description = "The Plotwork API from Python: validate, draw, render, import and publish diagrams, on the standard library alone."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Plotwork" }]
14
+ keywords = ["plotwork", "diagrams", "diagrams-as-code", "architecture", "svg", "api-client"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3 :: Only",
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
+ "Programming Language :: Python :: 3.14",
26
+ "Topic :: Documentation",
27
+ "Topic :: Multimedia :: Graphics",
28
+ "Topic :: Software Development :: Documentation",
29
+ "Typing :: Typed",
30
+ ]
31
+ # No runtime dependencies: scripts/check-no-runtime-dependencies.mjs fails if this list gains a name.
32
+ dependencies = []
33
+
34
+ [project.urls]
35
+ Homepage = "https://plotwork.dev"
36
+ Documentation = "https://docs.plotwork.dev/sdks"
37
+ Source = "https://github.com/plotwork-official/plotwork-sdk"
38
+ Issues = "https://github.com/plotwork-official/plotwork-sdk/issues"
39
+
40
+ [dependency-groups]
41
+ # What CI installs: the tests, the build, and a strict type check of the generated types.
42
+ dev = ["pytest==9.2.0", "build==1.6.1", "mypy==2.4.1"]
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/plotwork"]
46
+ exclude = ["src/plotwork/README.md"]
47
+
48
+ [tool.hatch.build.targets.sdist]
49
+ include = ["src/plotwork", "tests", "README.md", "LICENSE", "pyproject.toml"]
50
+
51
+ [tool.pytest.ini_options]
52
+ testpaths = ["tests"]
53
+ pythonpath = ["src"]
54
+ addopts = "-ra"
55
+ filterwarnings = ["error"]
@@ -0,0 +1,21 @@
1
+ # Python client source
2
+
3
+ The typed client for the Plotwork API: one transport on `urllib.request`, and the operations generated from `spec/openapi.json`.
4
+
5
+ ## Standards
6
+
7
+ Code here follows:
8
+
9
+ - [API clients](../../../.standards/docs/standards/core/api-clients.md) - one transport, typed errors, a timeout, retries only for calls that are safe to send twice
10
+ - [Dependencies](../../../.standards/docs/standards/core/dependencies.md) - nothing is imported but the standard library
11
+ - [Error handling](../../../.standards/docs/standards/core/error-handling.md) - a diagram's mistakes are data in the answer; only a failed request raises
12
+
13
+ ## Contents
14
+
15
+ | Path | Purpose |
16
+ |---|---|
17
+ | `__init__.py` | `Plotwork`, the client: the key or token, the base address, `with_options`, and the generated operations on it. |
18
+ | `_request.py` | `Transport`: sends one request, reads the answer, retries 429 and 503 for safe calls, and turns the API's error envelope into `PlotworkApiError`. |
19
+ | `_generated.py` | Every schema as a `TypedDict` and every operation as a typed method, written by `pnpm gen:python`. Never edited by hand; `pnpm check` fails when it is stale. |
20
+ | `_version.py` | `__version__`; a test holds it equal to `pyproject.toml`. |
21
+ | `py.typed` | Tells type checkers the package carries its own types. |
@@ -0,0 +1,90 @@
1
+ """``plotwork``: the hosted Plotwork API from Python, on the standard library alone.
2
+
3
+ Every ``/v1`` operation is a typed method generated from ``spec/openapi.json``::
4
+
5
+ import os
6
+ from plotwork import Plotwork
7
+
8
+ plotwork = Plotwork(api_key=os.environ["PLOTWORK_API_KEY"])
9
+ checked = plotwork.diagrams.validate(source=source)
10
+ published = plotwork.diagrams.publish(source=source, alias="checkout-flow")
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from typing import Any, Callable, Dict, Optional
16
+
17
+ from ._generated import OPERATION_PATHS, Operations
18
+ from ._request import Opener, PlotworkApiError, Transport, retry_delay
19
+ from ._version import __version__
20
+
21
+ __all__ = ["DEFAULT_BASE_URL", "OPERATION_PATHS", "Plotwork", "PlotworkApiError", "Transport", "__version__", "retry_delay"]
22
+
23
+ #: The production API.
24
+ DEFAULT_BASE_URL = "https://api.plotwork.dev"
25
+
26
+ _UNSET: Any = object()
27
+
28
+
29
+ class Plotwork(Operations):
30
+ """The Plotwork API client.
31
+
32
+ :param api_key: An account or organisation API key, sent as ``X-API-Key``. Keep it in an environment variable or a secret store.
33
+ :param access_token: An OAuth access token, sent as ``Authorization: Bearer``, in place of a key.
34
+ :param base_url: The API's address: production by default, ``https://api-preview.plotwork.dev`` for preview, or a self-hosted engine.
35
+ :param timeout: Seconds before a call counts as failed: 60 by default.
36
+ :param max_retries: How many times a safe call is tried again on 429 or 503: 2 by default, 0 to never retry.
37
+ :param opener: Opens each request, called like ``urllib.request.urlopen``; a proxy or a test passes its own.
38
+ :param sleep: Waits the given seconds before a retry; ``time.sleep`` by default.
39
+ """
40
+
41
+ def __init__(
42
+ self,
43
+ *,
44
+ api_key: Optional[str] = None,
45
+ access_token: Optional[str] = None,
46
+ base_url: Optional[str] = None,
47
+ timeout: float = 60.0,
48
+ max_retries: int = 2,
49
+ opener: Optional[Opener] = None,
50
+ sleep: Optional[Callable[[float], Any]] = None,
51
+ ) -> None:
52
+ headers: Dict[str, str] = {}
53
+ if api_key:
54
+ headers["X-API-Key"] = api_key
55
+ if access_token:
56
+ headers["Authorization"] = f"Bearer {access_token}"
57
+ self._options: Dict[str, Any] = {
58
+ "api_key": api_key,
59
+ "access_token": access_token,
60
+ "base_url": base_url,
61
+ "timeout": timeout,
62
+ "max_retries": max_retries,
63
+ "opener": opener,
64
+ "sleep": sleep,
65
+ }
66
+ super().__init__(
67
+ Transport(
68
+ base_url=base_url or DEFAULT_BASE_URL,
69
+ headers=headers,
70
+ timeout=timeout,
71
+ max_retries=max_retries,
72
+ opener=opener,
73
+ sleep=sleep,
74
+ )
75
+ )
76
+
77
+ def with_options(self, *, timeout: float = _UNSET, max_retries: int = _UNSET) -> "Plotwork":
78
+ """A copy of this client with another timeout or number of retries, for one call or a few:
79
+
80
+ ``plotwork.with_options(timeout=120).import_source(format="terraform", text=text)``
81
+ """
82
+ options = dict(self._options)
83
+ if timeout is not _UNSET:
84
+ options["timeout"] = timeout
85
+ if max_retries is not _UNSET:
86
+ options["max_retries"] = max_retries
87
+ return Plotwork(**options)
88
+
89
+ def __repr__(self) -> str:
90
+ return f"Plotwork(base_url={self._transport.base_url!r})"