oe-python-template-example 0.0.9__tar.gz → 0.0.10__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.
- oe_python_template_example-0.0.9/.act-env → oe_python_template_example-0.0.10/.act-env-public +0 -1
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.copier-answers.yml +1 -1
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.gitignore +9 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/Dockerfile +3 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/PKG-INFO +21 -6
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/README.md +20 -5
- oe_python_template_example-0.0.10/VERSION +1 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/_readme_main.md +20 -5
- oe_python_template_example-0.0.10/compose.yaml +35 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/source/_static/openapi.json +77 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/source/_static/openapi.yaml +79 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/source/conf.py +1 -1
- oe_python_template_example-0.0.10/github-action-run +5 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/noxfile.py +2 -1
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/pyproject.toml +2 -2
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/sonar-project.properties +1 -1
- oe_python_template_example-0.0.10/src/oe_python_template_example/api.py +168 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/src/oe_python_template_example/cli.py +28 -9
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/src/oe_python_template_example/service.py +10 -0
- oe_python_template_example-0.0.10/tests/api_test.py +92 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/tests/cli_test.py +1 -1
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/uv.lock +1 -1
- oe_python_template_example-0.0.9/.act-secret +0 -1
- oe_python_template_example-0.0.9/VERSION +0 -1
- oe_python_template_example-0.0.9/compose.yaml +0 -13
- oe_python_template_example-0.0.9/github-action-run +0 -4
- oe_python_template_example-0.0.9/src/oe_python_template_example/api.py +0 -87
- oe_python_template_example-0.0.9/tests/api_test.py +0 -48
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.devcontainer/Dockerfile +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.devcontainer/devcontainer.json +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.devcontainer/onCreateCommand +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.devcontainer/postAttachCommand +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.devcontainer/postCreateCommand +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.env.example +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.github/workflows/docker-image-build-publish.yml +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.github/workflows/package-build-publish-release.yml +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.github/workflows/test-and-report.yml +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.pre-commit-config.yaml +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.python-version +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.readthedocs.yml +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.secrets.baseline +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.vscode/extensions.json +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/.vscode/settings.json +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/CHANGELOG.md +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/CODEOWNERS +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/CONTRIBUTING.md +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/LICENSE +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/RELEASE_NOTES.md +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/SERVICE_CONNECTIONS.md +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/_readme_footer.md +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/_readme_header.md +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/bin/git-cliff +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/bump +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/codecov.yml +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/Makefile +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/make.bat +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/source/_static/.keep +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/source/api.rst +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/source/contributing.rst +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/source/index.rst +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/source/latexmkrc +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/source/main.rst +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/source/reference.rst +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/docs/source/release-notes.rst +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/examples/__init__.py +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/examples/notebook.ipynb +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/examples/notebook.py +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/examples/script.py +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/examples/streamlit.py +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0/CHANGELOG.md +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0/LICENSE-APACHE +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0/LICENSE-MIT +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0/README.md +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0/completions/_git-cliff +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0/completions/_git-cliff.ps1 +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0/completions/git-cliff.bash +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0/completions/git-cliff.elv +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0/completions/git-cliff.fish +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0/git-cliff-completions +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0/git-cliff-mangen +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0/man/git-cliff.1 +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/git-cliff-2.7.0-x86_64-unknown-linux-gnu.tar.gz +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/latexmkrc +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/logo.png +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/renovate.json +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/src/oe_python_template_example/__init__.py +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/src/oe_python_template_example/constants.py +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/tests/__init__.py +0 -0
- {oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/tests/fixtures/.keep +0 -0
@@ -35,5 +35,8 @@ RUN --mount=type=cache,target=/root/.cache/uv \
|
|
35
35
|
|
36
36
|
ENV OE_PYTHON_TEMPLATE_EXAMPLE_RUNNING_IN_CONTAINER=1
|
37
37
|
|
38
|
+
# API will run on port 8000 by default
|
39
|
+
EXPOSE 8000/tcp
|
40
|
+
|
38
41
|
# But feel free to add arguments and options as needed when doing a docker run
|
39
42
|
ENTRYPOINT ["uv", "run", "--no-dev", "oe-python-template-example"]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: oe-python-template-example
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.10
|
4
4
|
Summary: 🧠 Example project scaffolded and kept up to date with OE Python Template (oe-python-template).
|
5
5
|
Project-URL: Homepage, https://oe-python-template-example.readthedocs.io/en/latest/
|
6
6
|
Project-URL: Documentation, https://oe-python-template-example.readthedocs.io/en/latest/
|
@@ -184,7 +184,7 @@ uvx oe-python-template-example hello-world --help # help for specific command
|
|
184
184
|
|
185
185
|
* Example project scaffolded and kept up to date with OE Python Template (oe-python-template).
|
186
186
|
* Various Examples:
|
187
|
-
- [Simple Python script]https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/script.py)
|
187
|
+
- [Simple Python script](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/script.py)
|
188
188
|
- [Streamlit web application](https://oe-python-template-example.streamlit.app/) deployed on [Streamlit Community Cloud](https://streamlit.io/cloud)
|
189
189
|
- [Jupyter](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/notebook.ipynb) and [Marimo](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/notebook.py) notebook
|
190
190
|
* [Complete reference documenation](https://oe-python-template-example.readthedocs.io/en/latest/reference.html) on Read the Docs
|
@@ -284,8 +284,12 @@ Execute commands:
|
|
284
284
|
|
285
285
|
```shell
|
286
286
|
uvx oe-python-template-example hello-world
|
287
|
-
uvx oe-python-template-example
|
288
|
-
uvx oe-python-template-example echo "Lorem
|
287
|
+
uvx oe-python-template-example echo --help
|
288
|
+
uvx oe-python-template-example echo "Lorem"
|
289
|
+
uvx oe-python-template-example echo "Lorem" --json
|
290
|
+
uvx oe-python-template-example openapi
|
291
|
+
uvx oe-python-template-example openapi --output-format=json
|
292
|
+
uvx oe-python-template-example serve
|
289
293
|
```
|
290
294
|
|
291
295
|
### Environment
|
@@ -306,8 +310,12 @@ You can as well run the CLI within Docker.
|
|
306
310
|
```shell
|
307
311
|
docker run helmuthva/oe-python-template-example --help
|
308
312
|
docker run helmuthva/oe-python-template-example hello-world
|
309
|
-
docker run helmuthva/oe-python-template-example
|
313
|
+
docker run helmuthva/oe-python-template-example echo --help
|
310
314
|
docker run helmuthva/oe-python-template-example echo "Lorem"
|
315
|
+
docker run helmuthva/oe-python-template-example echo "Lorem" --json
|
316
|
+
docker run helmuthva/oe-python-template-example openapi
|
317
|
+
docker run helmuthva/oe-python-template-example openapi --output-format=json
|
318
|
+
docker run helmuthva/oe-python-template-example serve
|
311
319
|
```
|
312
320
|
|
313
321
|
Execute command:
|
@@ -321,8 +329,15 @@ Or use docker compose
|
|
321
329
|
The .env is passed through from the host to the Docker container.
|
322
330
|
|
323
331
|
```shell
|
324
|
-
docker compose up
|
325
332
|
docker compose run oe-python-template-example --help
|
333
|
+
docker compose run oe-python-template-example hello-world
|
334
|
+
docker compose run oe-python-template-example echo --help
|
335
|
+
docker compose run oe-python-template-example echo "Lorem"
|
336
|
+
docker compose run oe-python-template-example echo "Lorem" --json
|
337
|
+
docker compose run oe-python-template-example openapi
|
338
|
+
docker compose run oe-python-template-example openapi --output-format=json
|
339
|
+
docker compose up
|
340
|
+
curl http://127.0.0.1 8000
|
326
341
|
```
|
327
342
|
|
328
343
|
## Extra: Lorem Ipsum
|
@@ -123,7 +123,7 @@ uvx oe-python-template-example hello-world --help # help for specific command
|
|
123
123
|
|
124
124
|
* Example project scaffolded and kept up to date with OE Python Template (oe-python-template).
|
125
125
|
* Various Examples:
|
126
|
-
- [Simple Python script]https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/script.py)
|
126
|
+
- [Simple Python script](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/script.py)
|
127
127
|
- [Streamlit web application](https://oe-python-template-example.streamlit.app/) deployed on [Streamlit Community Cloud](https://streamlit.io/cloud)
|
128
128
|
- [Jupyter](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/notebook.ipynb) and [Marimo](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/notebook.py) notebook
|
129
129
|
* [Complete reference documenation](https://oe-python-template-example.readthedocs.io/en/latest/reference.html) on Read the Docs
|
@@ -223,8 +223,12 @@ Execute commands:
|
|
223
223
|
|
224
224
|
```shell
|
225
225
|
uvx oe-python-template-example hello-world
|
226
|
-
uvx oe-python-template-example
|
227
|
-
uvx oe-python-template-example echo "Lorem
|
226
|
+
uvx oe-python-template-example echo --help
|
227
|
+
uvx oe-python-template-example echo "Lorem"
|
228
|
+
uvx oe-python-template-example echo "Lorem" --json
|
229
|
+
uvx oe-python-template-example openapi
|
230
|
+
uvx oe-python-template-example openapi --output-format=json
|
231
|
+
uvx oe-python-template-example serve
|
228
232
|
```
|
229
233
|
|
230
234
|
### Environment
|
@@ -245,8 +249,12 @@ You can as well run the CLI within Docker.
|
|
245
249
|
```shell
|
246
250
|
docker run helmuthva/oe-python-template-example --help
|
247
251
|
docker run helmuthva/oe-python-template-example hello-world
|
248
|
-
docker run helmuthva/oe-python-template-example
|
252
|
+
docker run helmuthva/oe-python-template-example echo --help
|
249
253
|
docker run helmuthva/oe-python-template-example echo "Lorem"
|
254
|
+
docker run helmuthva/oe-python-template-example echo "Lorem" --json
|
255
|
+
docker run helmuthva/oe-python-template-example openapi
|
256
|
+
docker run helmuthva/oe-python-template-example openapi --output-format=json
|
257
|
+
docker run helmuthva/oe-python-template-example serve
|
250
258
|
```
|
251
259
|
|
252
260
|
Execute command:
|
@@ -260,8 +268,15 @@ Or use docker compose
|
|
260
268
|
The .env is passed through from the host to the Docker container.
|
261
269
|
|
262
270
|
```shell
|
263
|
-
docker compose up
|
264
271
|
docker compose run oe-python-template-example --help
|
272
|
+
docker compose run oe-python-template-example hello-world
|
273
|
+
docker compose run oe-python-template-example echo --help
|
274
|
+
docker compose run oe-python-template-example echo "Lorem"
|
275
|
+
docker compose run oe-python-template-example echo "Lorem" --json
|
276
|
+
docker compose run oe-python-template-example openapi
|
277
|
+
docker compose run oe-python-template-example openapi --output-format=json
|
278
|
+
docker compose up
|
279
|
+
curl http://127.0.0.1 8000
|
265
280
|
```
|
266
281
|
|
267
282
|
## Extra: Lorem Ipsum
|
@@ -0,0 +1 @@
|
|
1
|
+
0.0.10
|
@@ -88,7 +88,7 @@ uvx oe-python-template-example hello-world --help # help for specific command
|
|
88
88
|
|
89
89
|
* Example project scaffolded and kept up to date with OE Python Template (oe-python-template).
|
90
90
|
* Various Examples:
|
91
|
-
- [Simple Python script]https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/script.py)
|
91
|
+
- [Simple Python script](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/script.py)
|
92
92
|
- [Streamlit web application](https://oe-python-template-example.streamlit.app/) deployed on [Streamlit Community Cloud](https://streamlit.io/cloud)
|
93
93
|
- [Jupyter](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/notebook.ipynb) and [Marimo](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/notebook.py) notebook
|
94
94
|
* [Complete reference documenation](https://oe-python-template-example.readthedocs.io/en/latest/reference.html) on Read the Docs
|
@@ -188,8 +188,12 @@ Execute commands:
|
|
188
188
|
|
189
189
|
```shell
|
190
190
|
uvx oe-python-template-example hello-world
|
191
|
-
uvx oe-python-template-example
|
192
|
-
uvx oe-python-template-example echo "Lorem
|
191
|
+
uvx oe-python-template-example echo --help
|
192
|
+
uvx oe-python-template-example echo "Lorem"
|
193
|
+
uvx oe-python-template-example echo "Lorem" --json
|
194
|
+
uvx oe-python-template-example openapi
|
195
|
+
uvx oe-python-template-example openapi --output-format=json
|
196
|
+
uvx oe-python-template-example serve
|
193
197
|
```
|
194
198
|
|
195
199
|
### Environment
|
@@ -210,8 +214,12 @@ You can as well run the CLI within Docker.
|
|
210
214
|
```shell
|
211
215
|
docker run helmuthva/oe-python-template-example --help
|
212
216
|
docker run helmuthva/oe-python-template-example hello-world
|
213
|
-
docker run helmuthva/oe-python-template-example
|
217
|
+
docker run helmuthva/oe-python-template-example echo --help
|
214
218
|
docker run helmuthva/oe-python-template-example echo "Lorem"
|
219
|
+
docker run helmuthva/oe-python-template-example echo "Lorem" --json
|
220
|
+
docker run helmuthva/oe-python-template-example openapi
|
221
|
+
docker run helmuthva/oe-python-template-example openapi --output-format=json
|
222
|
+
docker run helmuthva/oe-python-template-example serve
|
215
223
|
```
|
216
224
|
|
217
225
|
Execute command:
|
@@ -225,8 +233,15 @@ Or use docker compose
|
|
225
233
|
The .env is passed through from the host to the Docker container.
|
226
234
|
|
227
235
|
```shell
|
228
|
-
docker compose up
|
229
236
|
docker compose run oe-python-template-example --help
|
237
|
+
docker compose run oe-python-template-example hello-world
|
238
|
+
docker compose run oe-python-template-example echo --help
|
239
|
+
docker compose run oe-python-template-example echo "Lorem"
|
240
|
+
docker compose run oe-python-template-example echo "Lorem" --json
|
241
|
+
docker compose run oe-python-template-example openapi
|
242
|
+
docker compose run oe-python-template-example openapi --output-format=json
|
243
|
+
docker compose up
|
244
|
+
curl http://127.0.0.1 8000
|
230
245
|
```
|
231
246
|
|
232
247
|
## Extra: Lorem Ipsum
|
@@ -0,0 +1,35 @@
|
|
1
|
+
services:
|
2
|
+
oe-python-template-example:
|
3
|
+
build: .
|
4
|
+
env_file:
|
5
|
+
- path: .env
|
6
|
+
required: true
|
7
|
+
develop:
|
8
|
+
watch:
|
9
|
+
- path: src
|
10
|
+
action: rebuild
|
11
|
+
restart: no
|
12
|
+
profiles:
|
13
|
+
- manual
|
14
|
+
tty: true
|
15
|
+
stdin_open: true
|
16
|
+
oe-python-template-example-api:
|
17
|
+
build: .
|
18
|
+
env_file:
|
19
|
+
- path: .env
|
20
|
+
required: true
|
21
|
+
develop:
|
22
|
+
watch:
|
23
|
+
- path: src
|
24
|
+
action: rebuild
|
25
|
+
command: serve --host=0.0.0.0 --port=8000 --no-reload
|
26
|
+
restart: always
|
27
|
+
ports:
|
28
|
+
- "8000:8000"
|
29
|
+
healthcheck:
|
30
|
+
test: [ "CMD", "curl", "-f", "http://127.0.0.1:8000/healthz" ]
|
31
|
+
interval: 5s
|
32
|
+
timeout: 2s
|
33
|
+
retries: 3
|
34
|
+
start_period: 5s
|
35
|
+
start_interval: 1s
|
@@ -11,6 +11,50 @@
|
|
11
11
|
"version": "1.0.0"
|
12
12
|
},
|
13
13
|
"paths": {
|
14
|
+
"/health": {
|
15
|
+
"get": {
|
16
|
+
"tags": [
|
17
|
+
"Observability"
|
18
|
+
],
|
19
|
+
"summary": "Health",
|
20
|
+
"description": "Check the health of the service.\n\nThis endpoint returns the health status of the service.\nThe health status can be either UP or DOWN.\nIf the service is healthy, the status will be UP.\nIf the service is unhealthy, the status will be DOWN and a reason will be provided.\nThe response will have a 200 OK status code if the service is healthy,\nand a 500 Internal Server Error status code if the service is unhealthy.\n\nArgs:\n service (Annotated[Service, Depends): _description_\n response (Response): _description_\n\nReturns:\n Health: The health status of the service.",
|
21
|
+
"operationId": "health_health_get",
|
22
|
+
"responses": {
|
23
|
+
"200": {
|
24
|
+
"description": "Successful Response",
|
25
|
+
"content": {
|
26
|
+
"application/json": {
|
27
|
+
"schema": {
|
28
|
+
"$ref": "#/components/schemas/Health"
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
},
|
36
|
+
"/healthz": {
|
37
|
+
"get": {
|
38
|
+
"tags": [
|
39
|
+
"Observability"
|
40
|
+
],
|
41
|
+
"summary": "Health",
|
42
|
+
"description": "Check the health of the service.\n\nThis endpoint returns the health status of the service.\nThe health status can be either UP or DOWN.\nIf the service is healthy, the status will be UP.\nIf the service is unhealthy, the status will be DOWN and a reason will be provided.\nThe response will have a 200 OK status code if the service is healthy,\nand a 500 Internal Server Error status code if the service is unhealthy.\n\nArgs:\n service (Annotated[Service, Depends): _description_\n response (Response): _description_\n\nReturns:\n Health: The health status of the service.",
|
43
|
+
"operationId": "health_healthz_get",
|
44
|
+
"responses": {
|
45
|
+
"200": {
|
46
|
+
"description": "Successful Response",
|
47
|
+
"content": {
|
48
|
+
"application/json": {
|
49
|
+
"schema": {
|
50
|
+
"$ref": "#/components/schemas/Health"
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
},
|
14
58
|
"/hello-world": {
|
15
59
|
"get": {
|
16
60
|
"tags": [
|
@@ -129,6 +173,30 @@
|
|
129
173
|
"type": "object",
|
130
174
|
"title": "HTTPValidationError"
|
131
175
|
},
|
176
|
+
"Health": {
|
177
|
+
"properties": {
|
178
|
+
"status": {
|
179
|
+
"$ref": "#/components/schemas/_HealthStatus"
|
180
|
+
},
|
181
|
+
"reason": {
|
182
|
+
"anyOf": [
|
183
|
+
{
|
184
|
+
"type": "string"
|
185
|
+
},
|
186
|
+
{
|
187
|
+
"type": "null"
|
188
|
+
}
|
189
|
+
],
|
190
|
+
"title": "Reason"
|
191
|
+
}
|
192
|
+
},
|
193
|
+
"type": "object",
|
194
|
+
"required": [
|
195
|
+
"status"
|
196
|
+
],
|
197
|
+
"title": "Health",
|
198
|
+
"description": "Health status model.\n\nArgs:\n BaseModel (_type_): _description_"
|
199
|
+
},
|
132
200
|
"HelloWorldResponse": {
|
133
201
|
"properties": {
|
134
202
|
"message": {
|
@@ -179,6 +247,15 @@
|
|
179
247
|
"type"
|
180
248
|
],
|
181
249
|
"title": "ValidationError"
|
250
|
+
},
|
251
|
+
"_HealthStatus": {
|
252
|
+
"type": "string",
|
253
|
+
"enum": [
|
254
|
+
"UP",
|
255
|
+
"DOWN"
|
256
|
+
],
|
257
|
+
"title": "_HealthStatus",
|
258
|
+
"description": "Health status enumeration.\n\nArgs:\n StrEnum (_type_): _description_"
|
182
259
|
}
|
183
260
|
}
|
184
261
|
}
|
@@ -37,6 +37,21 @@ components:
|
|
37
37
|
type: array
|
38
38
|
title: HTTPValidationError
|
39
39
|
type: object
|
40
|
+
Health:
|
41
|
+
description: "Health status model.\n\nArgs:\n BaseModel (_type_):
|
42
|
+
_description_"
|
43
|
+
properties:
|
44
|
+
reason:
|
45
|
+
anyOf:
|
46
|
+
- type: string
|
47
|
+
- type: 'null'
|
48
|
+
title: Reason
|
49
|
+
status:
|
50
|
+
$ref: '#/components/schemas/_HealthStatus'
|
51
|
+
required:
|
52
|
+
- status
|
53
|
+
title: Health
|
54
|
+
type: object
|
40
55
|
HelloWorldResponse:
|
41
56
|
description: Response model for hello-world endpoint.
|
42
57
|
properties:
|
@@ -71,6 +86,14 @@ components:
|
|
71
86
|
- type
|
72
87
|
title: ValidationError
|
73
88
|
type: object
|
89
|
+
_HealthStatus:
|
90
|
+
description: "Health status enumeration.\n\nArgs:\n StrEnum (_type_):
|
91
|
+
_description_"
|
92
|
+
enum:
|
93
|
+
- UP
|
94
|
+
- DOWN
|
95
|
+
title: _HealthStatus
|
96
|
+
type: string
|
74
97
|
info:
|
75
98
|
contact:
|
76
99
|
email: helmuthva@gmail.com
|
@@ -113,6 +136,62 @@ Unprocessable\
|
|
113
136
|
summary: Echo
|
114
137
|
tags:
|
115
138
|
- Basics
|
139
|
+
/health:
|
140
|
+
get:
|
141
|
+
description: "Check the health of the service.\n\nThis endpoint returns
|
142
|
+
the\
|
143
|
+
\ health status of the service.\nThe health status can be either UP or
|
144
|
+
DOWN.\n\
|
145
|
+
If the service is healthy, the status will be UP.\nIf the service is
|
146
|
+
unhealthy,\
|
147
|
+
\ the status will be DOWN and a reason will be provided.\nThe response
|
148
|
+
will\
|
149
|
+
\ have a 200 OK status code if the service is healthy,\nand a 500
|
150
|
+
Internal\
|
151
|
+
\ Server Error status code if the service is unhealthy.\n\nArgs:\n
|
152
|
+
service\
|
153
|
+
\ (Annotated[Service, Depends): _description_\n response (Response):
|
154
|
+
_description_\n\
|
155
|
+
\nReturns:\n Health: The health status of the service."
|
156
|
+
operationId: health_health_get
|
157
|
+
responses:
|
158
|
+
'200':
|
159
|
+
content:
|
160
|
+
application/json:
|
161
|
+
schema:
|
162
|
+
$ref: '#/components/schemas/Health'
|
163
|
+
description: Successful Response
|
164
|
+
summary: Health
|
165
|
+
tags:
|
166
|
+
- Observability
|
167
|
+
/healthz:
|
168
|
+
get:
|
169
|
+
description: "Check the health of the service.\n\nThis endpoint returns
|
170
|
+
the\
|
171
|
+
\ health status of the service.\nThe health status can be either UP or
|
172
|
+
DOWN.\n\
|
173
|
+
If the service is healthy, the status will be UP.\nIf the service is
|
174
|
+
unhealthy,\
|
175
|
+
\ the status will be DOWN and a reason will be provided.\nThe response
|
176
|
+
will\
|
177
|
+
\ have a 200 OK status code if the service is healthy,\nand a 500
|
178
|
+
Internal\
|
179
|
+
\ Server Error status code if the service is unhealthy.\n\nArgs:\n
|
180
|
+
service\
|
181
|
+
\ (Annotated[Service, Depends): _description_\n response (Response):
|
182
|
+
_description_\n\
|
183
|
+
\nReturns:\n Health: The health status of the service."
|
184
|
+
operationId: health_healthz_get
|
185
|
+
responses:
|
186
|
+
'200':
|
187
|
+
content:
|
188
|
+
application/json:
|
189
|
+
schema:
|
190
|
+
$ref: '#/components/schemas/Health'
|
191
|
+
description: Successful Response
|
192
|
+
summary: Health
|
193
|
+
tags:
|
194
|
+
- Observability
|
116
195
|
/hello-world:
|
117
196
|
get:
|
118
197
|
description: "Return a hello world message.\n\nReturns:\n
|
@@ -26,7 +26,7 @@ extensions = [
|
|
26
26
|
project = "oe-python-template-example"
|
27
27
|
author = "Helmut Hoffer von Ankershoffen"
|
28
28
|
copyright = f" (c) 2025-{datetime.now(UTC).year}, {author}" # noqa: A001
|
29
|
-
version = "0.0.
|
29
|
+
version = "0.0.10"
|
30
30
|
release = version
|
31
31
|
github_username = "helmut-hoffer-von-ankershoffen"
|
32
32
|
github_repository = "oe-python-template-example"
|
@@ -0,0 +1,5 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# Locally run job test of CI workflow in .github/workflows/test-and-report.yml. Helpful for debugging.
|
4
|
+
act -j test --env-file .act-env-public --secret-file .act-env-secret --container-architecture linux/amd64 -P
|
5
|
+
ubuntu-latest=catthehacker/ubuntu:act-latest --action-offline-mode --container-daemon-socket -
|
@@ -117,7 +117,8 @@ def setup_dev(session: nox.Session) -> None:
|
|
117
117
|
session.run("ruff", "format", ".", external=True)
|
118
118
|
git_dir = Path(".git")
|
119
119
|
if git_dir.is_dir():
|
120
|
-
session.run("echo", "found .git directory
|
120
|
+
session.run("echo", "found .git directory", external=True)
|
121
|
+
session.run("touch", ".act-env-secret", external=True)
|
121
122
|
session.run("pre-commit", "install", external=True)
|
122
123
|
with Path(".secrets.baseline").open("w", encoding="utf-8") as out:
|
123
124
|
session.run("detect-secrets", "scan", stdout=out, external=True)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "oe-python-template-example"
|
3
|
-
version = "0.0.
|
3
|
+
version = "0.0.10"
|
4
4
|
description = "🧠 Example project scaffolded and kept up to date with OE Python Template (oe-python-template)."
|
5
5
|
readme = "README.md"
|
6
6
|
authors = [
|
@@ -244,7 +244,7 @@ source = ["src/"]
|
|
244
244
|
|
245
245
|
|
246
246
|
[tool.bumpversion]
|
247
|
-
current_version = "0.0.
|
247
|
+
current_version = "0.0.10"
|
248
248
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
249
249
|
serialize = ["{major}.{minor}.{patch}"]
|
250
250
|
search = "{current_version}"
|
{oe_python_template_example-0.0.9 → oe_python_template_example-0.0.10}/sonar-project.properties
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
sonar.projectKey=helmut-hoffer-von-ankershoffen_oe-python-template-example
|
2
2
|
sonar.organization=helmut-hoffer-von-ankershoffen
|
3
|
-
sonar.projectVersion=0.0.
|
3
|
+
sonar.projectVersion=0.0.10
|
4
4
|
sonar.projectDescription=🧠 Example project scaffolded and kept up to date with OE Python Template (oe-python-template).
|
5
5
|
sonar.links.homepage=https://oe-python-template-example.readthedocs.io/en/latest/
|
6
6
|
sonar.links.scm=https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example
|
@@ -0,0 +1,168 @@
|
|
1
|
+
"""Webservice API of OE Python Template Example.
|
2
|
+
|
3
|
+
This module provides a webservice API with several endpoints:
|
4
|
+
- A health/healthz endpoint that returns the health status of the service
|
5
|
+
- A hello-world endpoint that returns a greeting message
|
6
|
+
- An echo endpoint that echoes back the provided text
|
7
|
+
|
8
|
+
The endpoints use Pydantic models for request and response validation.
|
9
|
+
"""
|
10
|
+
|
11
|
+
from collections.abc import Generator
|
12
|
+
from enum import StrEnum
|
13
|
+
from typing import Annotated
|
14
|
+
|
15
|
+
from fastapi import Depends, FastAPI, Response, status
|
16
|
+
from pydantic import BaseModel, Field
|
17
|
+
|
18
|
+
from oe_python_template_example import Service
|
19
|
+
|
20
|
+
HELLO_WORLD_EXAMPLE = "Hello, world!"
|
21
|
+
|
22
|
+
|
23
|
+
def get_service() -> Generator[Service, None, None]:
|
24
|
+
"""Get the service instance.
|
25
|
+
|
26
|
+
Yields:
|
27
|
+
Service: The service instance.
|
28
|
+
"""
|
29
|
+
service = Service()
|
30
|
+
try:
|
31
|
+
yield service
|
32
|
+
finally:
|
33
|
+
# Cleanup code if needed
|
34
|
+
pass
|
35
|
+
|
36
|
+
|
37
|
+
app = FastAPI(
|
38
|
+
version="1.0.0",
|
39
|
+
title="OE Python Template Example",
|
40
|
+
contact={
|
41
|
+
"name": "Helmut Hoffer von Ankershoffen",
|
42
|
+
"email": "helmuthva@gmail.com",
|
43
|
+
"url": "https://github.com/helmut-hoffer-von-ankershoffen",
|
44
|
+
},
|
45
|
+
terms_of_service="https://oe-python-template-example.readthedocs.io/en/latest/",
|
46
|
+
)
|
47
|
+
|
48
|
+
|
49
|
+
class _HealthStatus(StrEnum):
|
50
|
+
"""Health status enumeration.
|
51
|
+
|
52
|
+
Args:
|
53
|
+
StrEnum (_type_): _description_
|
54
|
+
"""
|
55
|
+
|
56
|
+
UP = "UP"
|
57
|
+
DOWN = "DOWN"
|
58
|
+
|
59
|
+
|
60
|
+
class Health(BaseModel):
|
61
|
+
"""Health status model.
|
62
|
+
|
63
|
+
Args:
|
64
|
+
BaseModel (_type_): _description_
|
65
|
+
"""
|
66
|
+
|
67
|
+
status: _HealthStatus
|
68
|
+
reason: str | None = None
|
69
|
+
|
70
|
+
|
71
|
+
class HealthResponse(BaseModel):
|
72
|
+
"""Response model for health endpoint."""
|
73
|
+
|
74
|
+
health: str = Field(
|
75
|
+
...,
|
76
|
+
description="The hello world message",
|
77
|
+
examples=[HELLO_WORLD_EXAMPLE],
|
78
|
+
)
|
79
|
+
|
80
|
+
|
81
|
+
@app.get("/healthz", tags=["Observability"])
|
82
|
+
@app.get("/health", tags=["Observability"])
|
83
|
+
async def health(service: Annotated[Service, Depends(get_service)], response: Response) -> Health:
|
84
|
+
"""Check the health of the service.
|
85
|
+
|
86
|
+
This endpoint returns the health status of the service.
|
87
|
+
The health status can be either UP or DOWN.
|
88
|
+
If the service is healthy, the status will be UP.
|
89
|
+
If the service is unhealthy, the status will be DOWN and a reason will be provided.
|
90
|
+
The response will have a 200 OK status code if the service is healthy,
|
91
|
+
and a 500 Internal Server Error status code if the service is unhealthy.
|
92
|
+
|
93
|
+
Args:
|
94
|
+
service (Annotated[Service, Depends): _description_
|
95
|
+
response (Response): _description_
|
96
|
+
|
97
|
+
Returns:
|
98
|
+
Health: The health status of the service.
|
99
|
+
"""
|
100
|
+
if service.healthy():
|
101
|
+
health_result = Health(status=_HealthStatus.UP)
|
102
|
+
else:
|
103
|
+
health_result = Health(status=_HealthStatus.DOWN, reason="Service is unhealthy")
|
104
|
+
|
105
|
+
if health_result.status == _HealthStatus.DOWN:
|
106
|
+
response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
|
107
|
+
|
108
|
+
return health_result
|
109
|
+
|
110
|
+
|
111
|
+
class HelloWorldResponse(BaseModel):
|
112
|
+
"""Response model for hello-world endpoint."""
|
113
|
+
|
114
|
+
message: str = Field(
|
115
|
+
...,
|
116
|
+
description="The hello world message",
|
117
|
+
examples=[HELLO_WORLD_EXAMPLE],
|
118
|
+
)
|
119
|
+
|
120
|
+
|
121
|
+
@app.get("/hello-world", tags=["Basics"])
|
122
|
+
async def hello_world() -> HelloWorldResponse:
|
123
|
+
"""
|
124
|
+
Return a hello world message.
|
125
|
+
|
126
|
+
Returns:
|
127
|
+
HelloWorldResponse: A response containing the hello world message.
|
128
|
+
"""
|
129
|
+
return HelloWorldResponse(message=Service.get_hello_world())
|
130
|
+
|
131
|
+
|
132
|
+
class EchoResponse(BaseModel):
|
133
|
+
"""Response model for echo endpoint."""
|
134
|
+
|
135
|
+
message: str = Field(
|
136
|
+
...,
|
137
|
+
min_length=1,
|
138
|
+
description="The message content",
|
139
|
+
examples=[HELLO_WORLD_EXAMPLE],
|
140
|
+
)
|
141
|
+
|
142
|
+
|
143
|
+
class EchoRequest(BaseModel):
|
144
|
+
"""Request model for echo endpoint."""
|
145
|
+
|
146
|
+
text: str = Field(
|
147
|
+
...,
|
148
|
+
min_length=1,
|
149
|
+
description="The text to echo back",
|
150
|
+
examples=[HELLO_WORLD_EXAMPLE],
|
151
|
+
)
|
152
|
+
|
153
|
+
|
154
|
+
@app.post("/echo", tags=["Basics"])
|
155
|
+
async def echo(request: EchoRequest) -> EchoResponse:
|
156
|
+
"""
|
157
|
+
Echo back the provided text.
|
158
|
+
|
159
|
+
Args:
|
160
|
+
request (EchoRequest): The request containing the text to echo back.
|
161
|
+
|
162
|
+
Returns:
|
163
|
+
EchoResponse: A response containing the echoed text.
|
164
|
+
|
165
|
+
Raises:
|
166
|
+
422 Unprocessable Entity: If text is not provided or empty.
|
167
|
+
"""
|
168
|
+
return EchoResponse(message=request.text)
|