oe-python-template-example 0.3.5__tar.gz → 0.3.7__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.3.5 → oe_python_template_example-0.3.7}/PKG-INFO +78 -51
- {oe_python_template_example-0.3.5 → oe_python_template_example-0.3.7}/README.md +63 -48
- {oe_python_template_example-0.3.5 → oe_python_template_example-0.3.7}/pyproject.toml +23 -11
- oe_python_template_example-0.3.7/src/oe_python_template_example/__init__.py +6 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/api.py +75 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/cli.py +22 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/constants.py +7 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/hello/__init__.py +17 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/hello/_api.py +94 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/hello/_cli.py +47 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/hello/_constants.py +4 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/hello/_models.py +28 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/hello/_service.py +96 -0
- oe_python_template_example-0.3.5/src/oe_python_template_example/settings.py → oe_python_template_example-0.3.7/src/oe_python_template_example/hello/_settings.py +6 -4
- oe_python_template_example-0.3.7/src/oe_python_template_example/system/__init__.py +19 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/system/_api.py +116 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/system/_cli.py +165 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/system/_service.py +186 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/system/_settings.py +31 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/__init__.py +59 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/_api.py +18 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/_cli.py +68 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/_console.py +14 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/_constants.py +48 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/_di.py +70 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/_health.py +107 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/_log.py +122 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/_logfire.py +68 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/_process.py +41 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/_sentry.py +97 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/_service.py +39 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/_settings.py +80 -0
- oe_python_template_example-0.3.7/src/oe_python_template_example/utils/boot.py +86 -0
- oe_python_template_example-0.3.5/src/oe_python_template_example/__init__.py +0 -20
- oe_python_template_example-0.3.5/src/oe_python_template_example/api.py +0 -181
- oe_python_template_example-0.3.5/src/oe_python_template_example/cli.py +0 -150
- oe_python_template_example-0.3.5/src/oe_python_template_example/constants.py +0 -10
- oe_python_template_example-0.3.5/src/oe_python_template_example/models.py +0 -44
- oe_python_template_example-0.3.5/src/oe_python_template_example/service.py +0 -68
- {oe_python_template_example-0.3.5 → oe_python_template_example-0.3.7}/.gitignore +0 -0
- {oe_python_template_example-0.3.5 → oe_python_template_example-0.3.7}/LICENSE +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: oe-python-template-example
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.7
|
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/
|
@@ -49,13 +49,25 @@ Classifier: Programming Language :: Python :: 3.13
|
|
49
49
|
Classifier: Typing :: Typed
|
50
50
|
Requires-Python: <4.0,>=3.11
|
51
51
|
Requires-Dist: fastapi[all,standard]>=0.115.12
|
52
|
+
Requires-Dist: logfire[system-metrics]>=3.13.1
|
53
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.53b0
|
54
|
+
Requires-Dist: opentelemetry-instrumentation-httpx>=0.53b0
|
55
|
+
Requires-Dist: opentelemetry-instrumentation-jinja2>=0.53b0
|
56
|
+
Requires-Dist: opentelemetry-instrumentation-requests>=0.53b0
|
57
|
+
Requires-Dist: opentelemetry-instrumentation-sqlite3>=0.53b0
|
58
|
+
Requires-Dist: opentelemetry-instrumentation-tornado>=0.53b0
|
59
|
+
Requires-Dist: opentelemetry-instrumentation-urllib3>=0.53b0
|
60
|
+
Requires-Dist: opentelemetry-instrumentation-urllib>=0.53b0
|
61
|
+
Requires-Dist: psutil>=7.0.0
|
52
62
|
Requires-Dist: pydantic-settings>=2.8.1
|
53
|
-
Requires-Dist: pydantic>=2.11.
|
63
|
+
Requires-Dist: pydantic>=2.11.3
|
64
|
+
Requires-Dist: sentry-sdk>=2.25.1
|
54
65
|
Requires-Dist: typer>=0.15.1
|
66
|
+
Requires-Dist: uptime>=3.0.1
|
55
67
|
Provides-Extra: examples
|
56
68
|
Requires-Dist: jinja2>=3.1.6; extra == 'examples'
|
57
69
|
Requires-Dist: jupyter>=1.1.1; extra == 'examples'
|
58
|
-
Requires-Dist: marimo>=0.12.
|
70
|
+
Requires-Dist: marimo>=0.12.8; extra == 'examples'
|
59
71
|
Requires-Dist: streamlit>=1.44.1; extra == 'examples'
|
60
72
|
Description-Content-Type: text/markdown
|
61
73
|
|
@@ -89,6 +101,8 @@ Description-Content-Type: text/markdown
|
|
89
101
|
[](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template)
|
90
102
|
[](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example)
|
91
103
|
[](https://github.com/codespaces/new/helmut-hoffer-von-ankershoffen/oe-python-template-example)
|
104
|
+
[](https://oe-python-template-example.vercel.app/api/v1/hello/world)
|
105
|
+
[](https://helmut-hoffer-von-ankershoffen.betteruptime.com/)
|
92
106
|
|
93
107
|
<!---
|
94
108
|
[](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/pkgs/container/oe-python-template-example)
|
@@ -127,33 +141,40 @@ Projects generated with this template come with a comprehensive development tool
|
|
127
141
|
8. CI/CD pipeline can be run locally with [act](https://github.com/nektos/act)
|
128
142
|
9. Code quality and security checks with [SonarQube](https://www.sonarsource.com/products/sonarcloud) and [GitHub CodeQL](https://codeql.github.com/)
|
129
143
|
10. Dependency monitoring and vulnerability scanning with [pip-audit](https://pypi.org/project/pip-audit/), [trivy](https://trivy.dev/latest/), [Renovate](https://github.com/renovatebot/renovate), and [GitHub Dependabot](https://docs.github.com/en/code-security/getting-started/dependabot-quickstart-guide)
|
130
|
-
11.
|
131
|
-
12.
|
132
|
-
13.
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
144
|
+
11. Error monitoring and profiling with [Sentry](https://sentry.io/) (optional)
|
145
|
+
12. Logging and metrics with [Logfire](https://logfire.dev/) (optional)
|
146
|
+
13. Prepared for uptime monitoring with [betterstack](https://betterstack.com/) or alternatives
|
147
|
+
13. Licenses of dependencies extracted with [pip-licenses](https://pypi.org/project/pip-licenses/), matched with allow list, and published as release artifacts in CSV and JSON format for further compliance checks
|
148
|
+
14. Generation of attributions from extracted licenses
|
149
|
+
15. Software Bill of Materials (SBOM) generated in [CycloneDX](https://cyclonedx.org/) and [SPDX](https://spdx.dev/) formats with [cyclonedx-python](https://github.com/CycloneDX/cyclonedx-python) resp. [trivy](https://trivy.dev/latest/), published as release artifacts
|
150
|
+
16. Version and release management with [bump-my-version](https://callowayproject.github.io/bump-my-version/)
|
151
|
+
17. Changelog and release notes generated with [git-cliff](https://git-cliff.org/)
|
152
|
+
18. Documentation generated with [Sphinx](https://www.sphinx-doc.org/en/master/) including reference documentation for the library, CLI, and API
|
153
|
+
19. Documentation published to [Read The Docs](https://readthedocs.org/) including generation of PDF and single page HTML versions
|
154
|
+
20. Interactive OpenAPI specification with [Swagger](https://swagger.io/)
|
155
|
+
21. Python package published to [PyPI](https://pypi.org/)
|
156
|
+
22. Docker images published to [Docker.io](https://hub.docker.com/) and [GitHub Container Registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry) with [artifact attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds)
|
157
|
+
23. One-click development environments with [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) and [GitHub Codespaces](https://github.com/features/codespaces)
|
158
|
+
24. Settings for use with [VSCode](https://code.visualstudio.com/)
|
159
|
+
25. Settings and custom instructions for use with [GitHub Copilot](https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot)
|
160
|
+
26. API deployed as serverless function to [Vercel](https://vercel.com/) (optional)
|
143
161
|
|
144
162
|
### Application Features
|
145
163
|
|
146
|
-
Beyond development tooling, projects generated with this template include the code, documentation, and configuration of a fully functioning
|
147
|
-
|
148
|
-
1.
|
149
|
-
2.
|
150
|
-
3.
|
151
|
-
4.
|
152
|
-
5.
|
153
|
-
6.
|
154
|
-
7.
|
155
|
-
8.
|
156
|
-
9.
|
164
|
+
Beyond development tooling, projects generated with this template include the code, documentation, and configuration of a fully functioning application and service. This reference implementation serves as a starting point for your own business logic with modern patterns and enterprise practices already in place:
|
165
|
+
|
166
|
+
1. Usable as library with "Hello" module exposing a simple service
|
167
|
+
2. Command-line interface (CLI) with [Typer](https://typer.tiangolo.com/)
|
168
|
+
3. Versioned webservice API with [FastAPI](https://fastapi.tiangolo.com/)
|
169
|
+
4. [Interactive Jupyter notebook](https://jupyter.org/) and [reactive Marimo notebook](https://marimo.io/)
|
170
|
+
5. Simple Web UI with [Streamlit](https://streamlit.io/)
|
171
|
+
6. Configuration to run the CLI and API in a Docker container including setup for [Docker Compose](https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-docker-compose/)
|
172
|
+
7. Validation and settings management with [pydantic](https://docs.pydantic.dev/)
|
173
|
+
8. Info command enabling to inspect the runtime, compiled settings, and further info provided dynamically by modules
|
174
|
+
9. Health endpoint exposing system health dynamically aggregated from all modules and dependencies
|
175
|
+
10. Flexible logging and instrumentation, including support for [Sentry](https://sentry.io/) and [Logfire](https://logfire.dev/)
|
176
|
+
11. Modular architecture including auto-registration of services, CLI commands and API routes exposed by modules
|
177
|
+
12. Documentation including dynamic badges, setup instructions, contribution guide and security policy
|
157
178
|
|
158
179
|
Explore [here](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example) for what's generated out of the box.
|
159
180
|
|
@@ -276,7 +297,7 @@ The following examples run from source - clone this repository using
|
|
276
297
|
from dotenv import load_dotenv
|
277
298
|
from rich.console import Console
|
278
299
|
|
279
|
-
from oe_python_template_example import Service
|
300
|
+
from oe_python_template_example.hello import Service
|
280
301
|
|
281
302
|
console = Console()
|
282
303
|
|
@@ -362,13 +383,15 @@ uvx oe-python-template-example --help
|
|
362
383
|
Execute commands:
|
363
384
|
|
364
385
|
```shell
|
365
|
-
uvx oe-python-template-example hello
|
366
|
-
uvx oe-python-template-example echo --help
|
367
|
-
uvx oe-python-template-example echo "Lorem"
|
368
|
-
uvx oe-python-template-example echo "Lorem" --json
|
369
|
-
uvx oe-python-template-example
|
370
|
-
uvx oe-python-template-example
|
371
|
-
uvx oe-python-template-example
|
386
|
+
uvx oe-python-template-example hello world
|
387
|
+
uvx oe-python-template-example hello echo --help
|
388
|
+
uvx oe-python-template-example hello echo "Lorem"
|
389
|
+
uvx oe-python-template-example hello echo "Lorem" --json
|
390
|
+
uvx oe-python-template-example system info
|
391
|
+
uvx oe-python-template-example system health
|
392
|
+
uvx oe-python-template-example system openapi
|
393
|
+
uvx oe-python-template-example system openapi --output-format=json
|
394
|
+
uvx oe-python-template-example system serve
|
372
395
|
```
|
373
396
|
|
374
397
|
See the [reference documentation of the CLI](https://oe-python-template-example.readthedocs.io/en/latest/cli_reference.html) for detailed documentation of all CLI commands and options.
|
@@ -391,19 +414,21 @@ You can as well run the CLI within Docker.
|
|
391
414
|
|
392
415
|
```shell
|
393
416
|
docker run helmuthva/oe-python-template-example --help
|
394
|
-
docker run helmuthva/oe-python-template-example hello
|
395
|
-
docker run helmuthva/oe-python-template-example echo --help
|
396
|
-
docker run helmuthva/oe-python-template-example echo "Lorem"
|
397
|
-
docker run helmuthva/oe-python-template-example echo "Lorem" --json
|
398
|
-
docker run helmuthva/oe-python-template-example
|
399
|
-
docker run helmuthva/oe-python-template-example
|
400
|
-
docker run helmuthva/oe-python-template-example
|
417
|
+
docker run helmuthva/oe-python-template-example hello world
|
418
|
+
docker run helmuthva/oe-python-template-example hello echo --help
|
419
|
+
docker run helmuthva/oe-python-template-example hello echo "Lorem"
|
420
|
+
docker run helmuthva/oe-python-template-example hello echo "Lorem" --json
|
421
|
+
docker run helmuthva/oe-python-template-example system info
|
422
|
+
docker run helmuthva/oe-python-template-example system health
|
423
|
+
docker run helmuthva/oe-python-template-example system openapi
|
424
|
+
docker run helmuthva/oe-python-template-example system openapi --output-format=json
|
425
|
+
docker run helmuthva/oe-python-template-example system serve
|
401
426
|
```
|
402
427
|
|
403
428
|
Execute command:
|
404
429
|
|
405
430
|
```shell
|
406
|
-
docker run --env THE_VAR=MY_VALUE helmuthva/oe-python-template-example echo "Lorem Ipsum"
|
431
|
+
docker run --env THE_VAR=MY_VALUE helmuthva/oe-python-template-example hello echo "Lorem Ipsum"
|
407
432
|
```
|
408
433
|
|
409
434
|
Or use docker compose
|
@@ -412,12 +437,14 @@ The .env is passed through from the host to the Docker container.
|
|
412
437
|
|
413
438
|
```shell
|
414
439
|
docker compose run --remove-orphans oe-python-template-example --help
|
415
|
-
docker compose run --remove-orphans oe-python-template-example hello
|
416
|
-
docker compose run --remove-orphans oe-python-template-example echo --help
|
417
|
-
docker compose run --remove-orphans oe-python-template-example echo "Lorem"
|
418
|
-
docker compose run --remove-orphans oe-python-template-example echo "Lorem" --json
|
419
|
-
docker compose run --remove-orphans oe-python-template-example
|
420
|
-
docker compose run --remove-orphans oe-python-template-example
|
440
|
+
docker compose run --remove-orphans oe-python-template-example hello world
|
441
|
+
docker compose run --remove-orphans oe-python-template-example hello echo --help
|
442
|
+
docker compose run --remove-orphans oe-python-template-example hello echo "Lorem"
|
443
|
+
docker compose run --remove-orphans oe-python-template-example hello echo "Lorem" --json
|
444
|
+
docker compose run --remove-orphans oe-python-template-example system info
|
445
|
+
docker compose run --remove-orphans oe-python-template-example system health
|
446
|
+
docker compose run --remove-orphans oe-python-template-example system openapi
|
447
|
+
docker compose run --remove-orphans oe-python-template-example system openapi --output-format=json
|
421
448
|
echo "Running OE Python Template Example's API container as a daemon ..."
|
422
449
|
docker compose up -d
|
423
450
|
echo "Waiting for the API server to start ..."
|
@@ -426,7 +453,7 @@ echo "Checking health of v1 API ..."
|
|
426
453
|
curl http://127.0.0.1:8000/api/v1/healthz
|
427
454
|
echo ""
|
428
455
|
echo "Saying hello world with v1 API ..."
|
429
|
-
curl http://127.0.0.1:8000/api/v1/hello
|
456
|
+
curl http://127.0.0.1:8000/api/v1/hello/world
|
430
457
|
echo ""
|
431
458
|
echo "Swagger docs of v1 API ..."
|
432
459
|
curl http://127.0.0.1:8000/api/v1/docs
|
@@ -435,7 +462,7 @@ echo "Checking health of v2 API ..."
|
|
435
462
|
curl http://127.0.0.1:8000/api/v2/healthz
|
436
463
|
echo ""
|
437
464
|
echo "Saying hello world with v1 API ..."
|
438
|
-
curl http://127.0.0.1:8000/api/v2/hello
|
465
|
+
curl http://127.0.0.1:8000/api/v2/hello/world
|
439
466
|
echo ""
|
440
467
|
echo "Swagger docs of v2 API ..."
|
441
468
|
curl http://127.0.0.1:8000/api/v2/docs
|
@@ -28,6 +28,8 @@
|
|
28
28
|
[](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template)
|
29
29
|
[](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example)
|
30
30
|
[](https://github.com/codespaces/new/helmut-hoffer-von-ankershoffen/oe-python-template-example)
|
31
|
+
[](https://oe-python-template-example.vercel.app/api/v1/hello/world)
|
32
|
+
[](https://helmut-hoffer-von-ankershoffen.betteruptime.com/)
|
31
33
|
|
32
34
|
<!---
|
33
35
|
[](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/pkgs/container/oe-python-template-example)
|
@@ -66,33 +68,40 @@ Projects generated with this template come with a comprehensive development tool
|
|
66
68
|
8. CI/CD pipeline can be run locally with [act](https://github.com/nektos/act)
|
67
69
|
9. Code quality and security checks with [SonarQube](https://www.sonarsource.com/products/sonarcloud) and [GitHub CodeQL](https://codeql.github.com/)
|
68
70
|
10. Dependency monitoring and vulnerability scanning with [pip-audit](https://pypi.org/project/pip-audit/), [trivy](https://trivy.dev/latest/), [Renovate](https://github.com/renovatebot/renovate), and [GitHub Dependabot](https://docs.github.com/en/code-security/getting-started/dependabot-quickstart-guide)
|
69
|
-
11.
|
70
|
-
12.
|
71
|
-
13.
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
71
|
+
11. Error monitoring and profiling with [Sentry](https://sentry.io/) (optional)
|
72
|
+
12. Logging and metrics with [Logfire](https://logfire.dev/) (optional)
|
73
|
+
13. Prepared for uptime monitoring with [betterstack](https://betterstack.com/) or alternatives
|
74
|
+
13. Licenses of dependencies extracted with [pip-licenses](https://pypi.org/project/pip-licenses/), matched with allow list, and published as release artifacts in CSV and JSON format for further compliance checks
|
75
|
+
14. Generation of attributions from extracted licenses
|
76
|
+
15. Software Bill of Materials (SBOM) generated in [CycloneDX](https://cyclonedx.org/) and [SPDX](https://spdx.dev/) formats with [cyclonedx-python](https://github.com/CycloneDX/cyclonedx-python) resp. [trivy](https://trivy.dev/latest/), published as release artifacts
|
77
|
+
16. Version and release management with [bump-my-version](https://callowayproject.github.io/bump-my-version/)
|
78
|
+
17. Changelog and release notes generated with [git-cliff](https://git-cliff.org/)
|
79
|
+
18. Documentation generated with [Sphinx](https://www.sphinx-doc.org/en/master/) including reference documentation for the library, CLI, and API
|
80
|
+
19. Documentation published to [Read The Docs](https://readthedocs.org/) including generation of PDF and single page HTML versions
|
81
|
+
20. Interactive OpenAPI specification with [Swagger](https://swagger.io/)
|
82
|
+
21. Python package published to [PyPI](https://pypi.org/)
|
83
|
+
22. Docker images published to [Docker.io](https://hub.docker.com/) and [GitHub Container Registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry) with [artifact attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds)
|
84
|
+
23. One-click development environments with [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) and [GitHub Codespaces](https://github.com/features/codespaces)
|
85
|
+
24. Settings for use with [VSCode](https://code.visualstudio.com/)
|
86
|
+
25. Settings and custom instructions for use with [GitHub Copilot](https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot)
|
87
|
+
26. API deployed as serverless function to [Vercel](https://vercel.com/) (optional)
|
82
88
|
|
83
89
|
### Application Features
|
84
90
|
|
85
|
-
Beyond development tooling, projects generated with this template include the code, documentation, and configuration of a fully functioning
|
86
|
-
|
87
|
-
1.
|
88
|
-
2.
|
89
|
-
3.
|
90
|
-
4.
|
91
|
-
5.
|
92
|
-
6.
|
93
|
-
7.
|
94
|
-
8.
|
95
|
-
9.
|
91
|
+
Beyond development tooling, projects generated with this template include the code, documentation, and configuration of a fully functioning application and service. This reference implementation serves as a starting point for your own business logic with modern patterns and enterprise practices already in place:
|
92
|
+
|
93
|
+
1. Usable as library with "Hello" module exposing a simple service
|
94
|
+
2. Command-line interface (CLI) with [Typer](https://typer.tiangolo.com/)
|
95
|
+
3. Versioned webservice API with [FastAPI](https://fastapi.tiangolo.com/)
|
96
|
+
4. [Interactive Jupyter notebook](https://jupyter.org/) and [reactive Marimo notebook](https://marimo.io/)
|
97
|
+
5. Simple Web UI with [Streamlit](https://streamlit.io/)
|
98
|
+
6. Configuration to run the CLI and API in a Docker container including setup for [Docker Compose](https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-docker-compose/)
|
99
|
+
7. Validation and settings management with [pydantic](https://docs.pydantic.dev/)
|
100
|
+
8. Info command enabling to inspect the runtime, compiled settings, and further info provided dynamically by modules
|
101
|
+
9. Health endpoint exposing system health dynamically aggregated from all modules and dependencies
|
102
|
+
10. Flexible logging and instrumentation, including support for [Sentry](https://sentry.io/) and [Logfire](https://logfire.dev/)
|
103
|
+
11. Modular architecture including auto-registration of services, CLI commands and API routes exposed by modules
|
104
|
+
12. Documentation including dynamic badges, setup instructions, contribution guide and security policy
|
96
105
|
|
97
106
|
Explore [here](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example) for what's generated out of the box.
|
98
107
|
|
@@ -215,7 +224,7 @@ The following examples run from source - clone this repository using
|
|
215
224
|
from dotenv import load_dotenv
|
216
225
|
from rich.console import Console
|
217
226
|
|
218
|
-
from oe_python_template_example import Service
|
227
|
+
from oe_python_template_example.hello import Service
|
219
228
|
|
220
229
|
console = Console()
|
221
230
|
|
@@ -301,13 +310,15 @@ uvx oe-python-template-example --help
|
|
301
310
|
Execute commands:
|
302
311
|
|
303
312
|
```shell
|
304
|
-
uvx oe-python-template-example hello
|
305
|
-
uvx oe-python-template-example echo --help
|
306
|
-
uvx oe-python-template-example echo "Lorem"
|
307
|
-
uvx oe-python-template-example echo "Lorem" --json
|
308
|
-
uvx oe-python-template-example
|
309
|
-
uvx oe-python-template-example
|
310
|
-
uvx oe-python-template-example
|
313
|
+
uvx oe-python-template-example hello world
|
314
|
+
uvx oe-python-template-example hello echo --help
|
315
|
+
uvx oe-python-template-example hello echo "Lorem"
|
316
|
+
uvx oe-python-template-example hello echo "Lorem" --json
|
317
|
+
uvx oe-python-template-example system info
|
318
|
+
uvx oe-python-template-example system health
|
319
|
+
uvx oe-python-template-example system openapi
|
320
|
+
uvx oe-python-template-example system openapi --output-format=json
|
321
|
+
uvx oe-python-template-example system serve
|
311
322
|
```
|
312
323
|
|
313
324
|
See the [reference documentation of the CLI](https://oe-python-template-example.readthedocs.io/en/latest/cli_reference.html) for detailed documentation of all CLI commands and options.
|
@@ -330,19 +341,21 @@ You can as well run the CLI within Docker.
|
|
330
341
|
|
331
342
|
```shell
|
332
343
|
docker run helmuthva/oe-python-template-example --help
|
333
|
-
docker run helmuthva/oe-python-template-example hello
|
334
|
-
docker run helmuthva/oe-python-template-example echo --help
|
335
|
-
docker run helmuthva/oe-python-template-example echo "Lorem"
|
336
|
-
docker run helmuthva/oe-python-template-example echo "Lorem" --json
|
337
|
-
docker run helmuthva/oe-python-template-example
|
338
|
-
docker run helmuthva/oe-python-template-example
|
339
|
-
docker run helmuthva/oe-python-template-example
|
344
|
+
docker run helmuthva/oe-python-template-example hello world
|
345
|
+
docker run helmuthva/oe-python-template-example hello echo --help
|
346
|
+
docker run helmuthva/oe-python-template-example hello echo "Lorem"
|
347
|
+
docker run helmuthva/oe-python-template-example hello echo "Lorem" --json
|
348
|
+
docker run helmuthva/oe-python-template-example system info
|
349
|
+
docker run helmuthva/oe-python-template-example system health
|
350
|
+
docker run helmuthva/oe-python-template-example system openapi
|
351
|
+
docker run helmuthva/oe-python-template-example system openapi --output-format=json
|
352
|
+
docker run helmuthva/oe-python-template-example system serve
|
340
353
|
```
|
341
354
|
|
342
355
|
Execute command:
|
343
356
|
|
344
357
|
```shell
|
345
|
-
docker run --env THE_VAR=MY_VALUE helmuthva/oe-python-template-example echo "Lorem Ipsum"
|
358
|
+
docker run --env THE_VAR=MY_VALUE helmuthva/oe-python-template-example hello echo "Lorem Ipsum"
|
346
359
|
```
|
347
360
|
|
348
361
|
Or use docker compose
|
@@ -351,12 +364,14 @@ The .env is passed through from the host to the Docker container.
|
|
351
364
|
|
352
365
|
```shell
|
353
366
|
docker compose run --remove-orphans oe-python-template-example --help
|
354
|
-
docker compose run --remove-orphans oe-python-template-example hello
|
355
|
-
docker compose run --remove-orphans oe-python-template-example echo --help
|
356
|
-
docker compose run --remove-orphans oe-python-template-example echo "Lorem"
|
357
|
-
docker compose run --remove-orphans oe-python-template-example echo "Lorem" --json
|
358
|
-
docker compose run --remove-orphans oe-python-template-example
|
359
|
-
docker compose run --remove-orphans oe-python-template-example
|
367
|
+
docker compose run --remove-orphans oe-python-template-example hello world
|
368
|
+
docker compose run --remove-orphans oe-python-template-example hello echo --help
|
369
|
+
docker compose run --remove-orphans oe-python-template-example hello echo "Lorem"
|
370
|
+
docker compose run --remove-orphans oe-python-template-example hello echo "Lorem" --json
|
371
|
+
docker compose run --remove-orphans oe-python-template-example system info
|
372
|
+
docker compose run --remove-orphans oe-python-template-example system health
|
373
|
+
docker compose run --remove-orphans oe-python-template-example system openapi
|
374
|
+
docker compose run --remove-orphans oe-python-template-example system openapi --output-format=json
|
360
375
|
echo "Running OE Python Template Example's API container as a daemon ..."
|
361
376
|
docker compose up -d
|
362
377
|
echo "Waiting for the API server to start ..."
|
@@ -365,7 +380,7 @@ echo "Checking health of v1 API ..."
|
|
365
380
|
curl http://127.0.0.1:8000/api/v1/healthz
|
366
381
|
echo ""
|
367
382
|
echo "Saying hello world with v1 API ..."
|
368
|
-
curl http://127.0.0.1:8000/api/v1/hello
|
383
|
+
curl http://127.0.0.1:8000/api/v1/hello/world
|
369
384
|
echo ""
|
370
385
|
echo "Swagger docs of v1 API ..."
|
371
386
|
curl http://127.0.0.1:8000/api/v1/docs
|
@@ -374,7 +389,7 @@ echo "Checking health of v2 API ..."
|
|
374
389
|
curl http://127.0.0.1:8000/api/v2/healthz
|
375
390
|
echo ""
|
376
391
|
echo "Saying hello world with v1 API ..."
|
377
|
-
curl http://127.0.0.1:8000/api/v2/hello
|
392
|
+
curl http://127.0.0.1:8000/api/v2/hello/world
|
378
393
|
echo ""
|
379
394
|
echo "Swagger docs of v2 API ..."
|
380
395
|
curl http://127.0.0.1:8000/api/v2/docs
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "oe-python-template-example"
|
3
|
-
version = "0.3.
|
3
|
+
version = "0.3.7"
|
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 = [
|
@@ -64,9 +64,21 @@ requires-python = ">=3.11, <4.0"
|
|
64
64
|
dependencies = [
|
65
65
|
# From Template
|
66
66
|
"fastapi[standard,all]>=0.115.12",
|
67
|
-
"
|
67
|
+
"logfire[system-metrics]>=3.13.1",
|
68
|
+
"opentelemetry-instrumentation-fastapi>=0.53b0",
|
69
|
+
"opentelemetry-instrumentation-httpx>=0.53b0",
|
70
|
+
"opentelemetry-instrumentation-jinja2>=0.53b0",
|
71
|
+
"opentelemetry-instrumentation-requests>=0.53b0",
|
72
|
+
"opentelemetry-instrumentation-sqlite3>=0.53b0",
|
73
|
+
"opentelemetry-instrumentation-tornado>=0.53b0",
|
74
|
+
"opentelemetry-instrumentation-urllib>=0.53b0",
|
75
|
+
"opentelemetry-instrumentation-urllib3>=0.53b0",
|
76
|
+
"psutil>=7.0.0",
|
77
|
+
"pydantic>=2.11.3",
|
68
78
|
"pydantic-settings>=2.8.1",
|
79
|
+
"sentry-sdk>=2.25.1",
|
69
80
|
"typer>=0.15.1",
|
81
|
+
"uptime>=3.0.1",
|
70
82
|
# Custom
|
71
83
|
# Nothing yet
|
72
84
|
]
|
@@ -94,7 +106,7 @@ packages = ["src/oe_python_template_example"]
|
|
94
106
|
[project.optional-dependencies]
|
95
107
|
examples = [
|
96
108
|
"streamlit>=1.44.1",
|
97
|
-
"marimo>=0.12.
|
109
|
+
"marimo>=0.12.8",
|
98
110
|
"jupyter>=1.1.1",
|
99
111
|
"jinja2>=3.1.6",
|
100
112
|
]
|
@@ -111,20 +123,20 @@ dev = [
|
|
111
123
|
"matplotlib>=3.10.1",
|
112
124
|
"mypy>=1.5.0",
|
113
125
|
"nox[uv]>=2025.2.9",
|
114
|
-
"pip-audit>=2.
|
126
|
+
"pip-audit>=2.9.0",
|
115
127
|
"pip-licenses @ git+https://github.com/neXenio/pip-licenses.git@master", # https://github.com/raimon49/pip-licenses/pull/224
|
116
128
|
"pre-commit>=4.1.0",
|
117
|
-
"pyright>=1.1.
|
129
|
+
"pyright>=1.1.399",
|
118
130
|
"pytest>=8.3.5",
|
119
131
|
"pytest-asyncio>=0.26.0",
|
120
|
-
"pytest-cov>=6.1.
|
121
|
-
"pytest-docker>=3.2.
|
132
|
+
"pytest-cov>=6.1.1",
|
133
|
+
"pytest-docker>=3.2.1",
|
122
134
|
"pytest-env>=1.1.5",
|
123
135
|
"pytest-regressions>=2.7.0",
|
124
136
|
"pytest-subprocess>=1.5.3",
|
125
137
|
"pytest-timeout>=2.3.1",
|
126
138
|
"pytest-xdist[psutil]>=3.6.1",
|
127
|
-
"ruff>=0.11.
|
139
|
+
"ruff>=0.11.5",
|
128
140
|
"sphinx>=8.2.3",
|
129
141
|
"sphinx-autobuild>=2024.10.3",
|
130
142
|
"sphinx-copybutton>=0.5.2",
|
@@ -152,7 +164,7 @@ target-version = "py311"
|
|
152
164
|
preview = true
|
153
165
|
fix = true
|
154
166
|
line-length = 120
|
155
|
-
extend-exclude = [".fixme", "notebook.py"]
|
167
|
+
extend-exclude = [".fixme", "notebook.py", "template/*.py"]
|
156
168
|
|
157
169
|
[tool.ruff.lint]
|
158
170
|
select = ["ALL"]
|
@@ -178,7 +190,7 @@ ignore = [
|
|
178
190
|
]
|
179
191
|
|
180
192
|
[tool.ruff.lint.per-file-ignores]
|
181
|
-
"tests/**/*.py" = [
|
193
|
+
"**/tests/**/*.py" = [
|
182
194
|
# we are more relaxed in tests, while sill applying hundreds of rules
|
183
195
|
"S101", # asserts allowed in tests...
|
184
196
|
"ARG", # unused function args -> fixtures nevertheless are functionally relevant...
|
@@ -266,7 +278,7 @@ source = ["src/"]
|
|
266
278
|
|
267
279
|
|
268
280
|
[tool.bumpversion]
|
269
|
-
current_version = "0.3.
|
281
|
+
current_version = "0.3.7"
|
270
282
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
271
283
|
serialize = ["{major}.{minor}.{patch}"]
|
272
284
|
search = "{current_version}"
|
@@ -0,0 +1,75 @@
|
|
1
|
+
"""Webservice API of OE Python Template Example.
|
2
|
+
|
3
|
+
- Provides a versioned API
|
4
|
+
- Automatically registers APIs of modules and mounts them to the main API.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import os
|
8
|
+
|
9
|
+
from fastapi import FastAPI
|
10
|
+
|
11
|
+
from .constants import API_VERSIONS
|
12
|
+
from .utils import (
|
13
|
+
VersionedAPIRouter,
|
14
|
+
__author_email__,
|
15
|
+
__author_name__,
|
16
|
+
__documentation__url__,
|
17
|
+
__repository_url__,
|
18
|
+
locate_implementations,
|
19
|
+
)
|
20
|
+
|
21
|
+
TITLE = "OE Python Template Example"
|
22
|
+
UVICORN_HOST = os.environ.get("UVICORN_HOST", "127.0.0.1")
|
23
|
+
UVICORN_PORT = os.environ.get("UVICORN_PORT", "8000")
|
24
|
+
CONTACT_NAME = __author_name__
|
25
|
+
CONTACT_EMAIL = __author_email__
|
26
|
+
CONTACT_URL = __repository_url__
|
27
|
+
TERMS_OF_SERVICE_URL = __documentation__url__
|
28
|
+
|
29
|
+
|
30
|
+
app = FastAPI(
|
31
|
+
root_path="/api",
|
32
|
+
title=TITLE,
|
33
|
+
contact={
|
34
|
+
"name": CONTACT_NAME,
|
35
|
+
"email": CONTACT_EMAIL,
|
36
|
+
"url": CONTACT_URL,
|
37
|
+
},
|
38
|
+
terms_of_service=TERMS_OF_SERVICE_URL,
|
39
|
+
openapi_tags=[
|
40
|
+
{
|
41
|
+
"name": version,
|
42
|
+
"description": f"API version {version.lstrip('v')}, check link on the right",
|
43
|
+
"externalDocs": {
|
44
|
+
"description": "sub-docs",
|
45
|
+
"url": f"http://{UVICORN_HOST}:{UVICORN_PORT}/api/{version}/docs",
|
46
|
+
},
|
47
|
+
}
|
48
|
+
for version, _ in API_VERSIONS.items()
|
49
|
+
],
|
50
|
+
)
|
51
|
+
|
52
|
+
# Create API instances for each version
|
53
|
+
api_instances: dict["str", FastAPI] = {}
|
54
|
+
for version, semver in API_VERSIONS.items():
|
55
|
+
api_instances[version] = FastAPI(
|
56
|
+
version=semver,
|
57
|
+
title=TITLE,
|
58
|
+
contact={
|
59
|
+
"name": CONTACT_NAME,
|
60
|
+
"email": CONTACT_EMAIL,
|
61
|
+
"url": CONTACT_URL,
|
62
|
+
},
|
63
|
+
terms_of_service=TERMS_OF_SERVICE_URL,
|
64
|
+
)
|
65
|
+
|
66
|
+
# Register routers with appropriate API versions
|
67
|
+
for router in locate_implementations(VersionedAPIRouter):
|
68
|
+
router_instance: VersionedAPIRouter = router
|
69
|
+
version = router_instance.version
|
70
|
+
if version in API_VERSIONS:
|
71
|
+
api_instances[version].include_router(router_instance)
|
72
|
+
|
73
|
+
# Mount all API versions to the main app
|
74
|
+
for version in API_VERSIONS:
|
75
|
+
app.mount(f"/{version}", api_instances[version])
|
@@ -0,0 +1,22 @@
|
|
1
|
+
"""CLI (Command Line Interface) of OE Python Template Example."""
|
2
|
+
|
3
|
+
import sys
|
4
|
+
|
5
|
+
import typer
|
6
|
+
|
7
|
+
from .constants import MODULES_TO_INSTRUMENT
|
8
|
+
from .utils import __version__, boot, console, get_logger, prepare_cli
|
9
|
+
|
10
|
+
boot(MODULES_TO_INSTRUMENT)
|
11
|
+
logger = get_logger(__name__)
|
12
|
+
|
13
|
+
cli = typer.Typer(help="Command Line Interface of ")
|
14
|
+
prepare_cli(cli, f"🧠 OE Python Template Example v{__version__} - built with love in Berlin 🐻")
|
15
|
+
|
16
|
+
if __name__ == "__main__": # pragma: no cover
|
17
|
+
try:
|
18
|
+
cli()
|
19
|
+
except Exception as e: # noqa: BLE001
|
20
|
+
logger.critical("Fatal error occurred: %s", e)
|
21
|
+
console.print(f"Fatal error occurred: {e}", style="error")
|
22
|
+
sys.exit(1)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
"""Hello module."""
|
2
|
+
|
3
|
+
from ._api import api_v1, api_v2
|
4
|
+
from ._cli import cli
|
5
|
+
from ._models import Echo, Utterance
|
6
|
+
from ._service import Service
|
7
|
+
from ._settings import Settings
|
8
|
+
|
9
|
+
__all__ = [
|
10
|
+
"Echo",
|
11
|
+
"Service",
|
12
|
+
"Settings",
|
13
|
+
"Utterance",
|
14
|
+
"api_v1",
|
15
|
+
"api_v2",
|
16
|
+
"cli",
|
17
|
+
]
|