oe-python-template-example 0.3.5__tar.gz → 0.3.6__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.6}/PKG-INFO +77 -51
- {oe_python_template_example-0.3.5 → oe_python_template_example-0.3.6}/README.md +63 -48
- {oe_python_template_example-0.3.5 → oe_python_template_example-0.3.6}/pyproject.toml +22 -11
- oe_python_template_example-0.3.6/src/oe_python_template_example/__init__.py +6 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/api.py +75 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/cli.py +22 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/constants.py +7 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/hello/__init__.py +17 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/hello/_api.py +94 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/hello/_cli.py +47 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/hello/_constants.py +4 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/hello/_models.py +28 -0
- oe_python_template_example-0.3.6/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.6/src/oe_python_template_example/hello/_settings.py +6 -4
- oe_python_template_example-0.3.6/src/oe_python_template_example/system/__init__.py +19 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/system/_api.py +116 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/system/_cli.py +165 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/system/_service.py +182 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/system/_settings.py +31 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/__init__.py +59 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_api.py +18 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_cli.py +68 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_console.py +14 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_constants.py +48 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_di.py +70 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_health.py +107 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_log.py +122 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_logfire.py +68 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_process.py +41 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_sentry.py +97 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_service.py +39 -0
- oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_settings.py +80 -0
- oe_python_template_example-0.3.6/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.6}/.gitignore +0 -0
- {oe_python_template_example-0.3.5 → oe_python_template_example-0.3.6}/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.6
|
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,24 @@ 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
|
55
66
|
Provides-Extra: examples
|
56
67
|
Requires-Dist: jinja2>=3.1.6; extra == 'examples'
|
57
68
|
Requires-Dist: jupyter>=1.1.1; extra == 'examples'
|
58
|
-
Requires-Dist: marimo>=0.12.
|
69
|
+
Requires-Dist: marimo>=0.12.8; extra == 'examples'
|
59
70
|
Requires-Dist: streamlit>=1.44.1; extra == 'examples'
|
60
71
|
Description-Content-Type: text/markdown
|
61
72
|
|
@@ -89,6 +100,8 @@ Description-Content-Type: text/markdown
|
|
89
100
|
[](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template)
|
90
101
|
[](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
102
|
[](https://github.com/codespaces/new/helmut-hoffer-von-ankershoffen/oe-python-template-example)
|
103
|
+
[](https://oe-python-template-example.vercel.app/api/v1/hello/world)
|
104
|
+
[](https://helmut-hoffer-von-ankershoffen.betteruptime.com/)
|
92
105
|
|
93
106
|
<!---
|
94
107
|
[](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/pkgs/container/oe-python-template-example)
|
@@ -127,33 +140,40 @@ Projects generated with this template come with a comprehensive development tool
|
|
127
140
|
8. CI/CD pipeline can be run locally with [act](https://github.com/nektos/act)
|
128
141
|
9. Code quality and security checks with [SonarQube](https://www.sonarsource.com/products/sonarcloud) and [GitHub CodeQL](https://codeql.github.com/)
|
129
142
|
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
|
-
|
143
|
+
11. Error monitoring and profiling with [Sentry](https://sentry.io/) (optional)
|
144
|
+
12. Logging and metrics with [Logfire](https://logfire.dev/) (optional)
|
145
|
+
13. Prepared for uptime monitoring with [betterstack](https://betterstack.com/) or alternatives
|
146
|
+
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
|
147
|
+
14. Generation of attributions from extracted licenses
|
148
|
+
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
|
149
|
+
16. Version and release management with [bump-my-version](https://callowayproject.github.io/bump-my-version/)
|
150
|
+
17. Changelog and release notes generated with [git-cliff](https://git-cliff.org/)
|
151
|
+
18. Documentation generated with [Sphinx](https://www.sphinx-doc.org/en/master/) including reference documentation for the library, CLI, and API
|
152
|
+
19. Documentation published to [Read The Docs](https://readthedocs.org/) including generation of PDF and single page HTML versions
|
153
|
+
20. Interactive OpenAPI specification with [Swagger](https://swagger.io/)
|
154
|
+
21. Python package published to [PyPI](https://pypi.org/)
|
155
|
+
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)
|
156
|
+
23. One-click development environments with [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) and [GitHub Codespaces](https://github.com/features/codespaces)
|
157
|
+
24. Settings for use with [VSCode](https://code.visualstudio.com/)
|
158
|
+
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)
|
159
|
+
26. API deployed as serverless function to [Vercel](https://vercel.com/) (optional)
|
143
160
|
|
144
161
|
### Application Features
|
145
162
|
|
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.
|
163
|
+
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:
|
164
|
+
|
165
|
+
1. Usable as library with "Hello" module exposing a simple service
|
166
|
+
2. Command-line interface (CLI) with [Typer](https://typer.tiangolo.com/)
|
167
|
+
3. Versioned webservice API with [FastAPI](https://fastapi.tiangolo.com/)
|
168
|
+
4. [Interactive Jupyter notebook](https://jupyter.org/) and [reactive Marimo notebook](https://marimo.io/)
|
169
|
+
5. Simple Web UI with [Streamlit](https://streamlit.io/)
|
170
|
+
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/)
|
171
|
+
7. Validation and settings management with [pydantic](https://docs.pydantic.dev/)
|
172
|
+
8. Info command enabling to inspect the runtime, compiled settings, and further info provided dynamically by modules
|
173
|
+
9. Health endpoint exposing system health dynamically aggregated from all modules and dependencies
|
174
|
+
10. Flexible logging and instrumentation, including support for [Sentry](https://sentry.io/) and [Logfire](https://logfire.dev/)
|
175
|
+
11. Modular architecture including auto-registration of services, CLI commands and API routes exposed by modules
|
176
|
+
12. Documentation including dynamic badges, setup instructions, contribution guide and security policy
|
157
177
|
|
158
178
|
Explore [here](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example) for what's generated out of the box.
|
159
179
|
|
@@ -276,7 +296,7 @@ The following examples run from source - clone this repository using
|
|
276
296
|
from dotenv import load_dotenv
|
277
297
|
from rich.console import Console
|
278
298
|
|
279
|
-
from oe_python_template_example import Service
|
299
|
+
from oe_python_template_example.hello import Service
|
280
300
|
|
281
301
|
console = Console()
|
282
302
|
|
@@ -362,13 +382,15 @@ uvx oe-python-template-example --help
|
|
362
382
|
Execute commands:
|
363
383
|
|
364
384
|
```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
|
385
|
+
uvx oe-python-template-example hello world
|
386
|
+
uvx oe-python-template-example hello echo --help
|
387
|
+
uvx oe-python-template-example hello echo "Lorem"
|
388
|
+
uvx oe-python-template-example hello echo "Lorem" --json
|
389
|
+
uvx oe-python-template-example system info
|
390
|
+
uvx oe-python-template-example system health
|
391
|
+
uvx oe-python-template-example system openapi
|
392
|
+
uvx oe-python-template-example system openapi --output-format=json
|
393
|
+
uvx oe-python-template-example system serve
|
372
394
|
```
|
373
395
|
|
374
396
|
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 +413,21 @@ You can as well run the CLI within Docker.
|
|
391
413
|
|
392
414
|
```shell
|
393
415
|
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
|
416
|
+
docker run helmuthva/oe-python-template-example hello world
|
417
|
+
docker run helmuthva/oe-python-template-example hello echo --help
|
418
|
+
docker run helmuthva/oe-python-template-example hello echo "Lorem"
|
419
|
+
docker run helmuthva/oe-python-template-example hello echo "Lorem" --json
|
420
|
+
docker run helmuthva/oe-python-template-example system info
|
421
|
+
docker run helmuthva/oe-python-template-example system health
|
422
|
+
docker run helmuthva/oe-python-template-example system openapi
|
423
|
+
docker run helmuthva/oe-python-template-example system openapi --output-format=json
|
424
|
+
docker run helmuthva/oe-python-template-example system serve
|
401
425
|
```
|
402
426
|
|
403
427
|
Execute command:
|
404
428
|
|
405
429
|
```shell
|
406
|
-
docker run --env THE_VAR=MY_VALUE helmuthva/oe-python-template-example echo "Lorem Ipsum"
|
430
|
+
docker run --env THE_VAR=MY_VALUE helmuthva/oe-python-template-example hello echo "Lorem Ipsum"
|
407
431
|
```
|
408
432
|
|
409
433
|
Or use docker compose
|
@@ -412,12 +436,14 @@ The .env is passed through from the host to the Docker container.
|
|
412
436
|
|
413
437
|
```shell
|
414
438
|
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
|
439
|
+
docker compose run --remove-orphans oe-python-template-example hello world
|
440
|
+
docker compose run --remove-orphans oe-python-template-example hello echo --help
|
441
|
+
docker compose run --remove-orphans oe-python-template-example hello echo "Lorem"
|
442
|
+
docker compose run --remove-orphans oe-python-template-example hello echo "Lorem" --json
|
443
|
+
docker compose run --remove-orphans oe-python-template-example system info
|
444
|
+
docker compose run --remove-orphans oe-python-template-example system health
|
445
|
+
docker compose run --remove-orphans oe-python-template-example system openapi
|
446
|
+
docker compose run --remove-orphans oe-python-template-example system openapi --output-format=json
|
421
447
|
echo "Running OE Python Template Example's API container as a daemon ..."
|
422
448
|
docker compose up -d
|
423
449
|
echo "Waiting for the API server to start ..."
|
@@ -426,7 +452,7 @@ echo "Checking health of v1 API ..."
|
|
426
452
|
curl http://127.0.0.1:8000/api/v1/healthz
|
427
453
|
echo ""
|
428
454
|
echo "Saying hello world with v1 API ..."
|
429
|
-
curl http://127.0.0.1:8000/api/v1/hello
|
455
|
+
curl http://127.0.0.1:8000/api/v1/hello/world
|
430
456
|
echo ""
|
431
457
|
echo "Swagger docs of v1 API ..."
|
432
458
|
curl http://127.0.0.1:8000/api/v1/docs
|
@@ -435,7 +461,7 @@ echo "Checking health of v2 API ..."
|
|
435
461
|
curl http://127.0.0.1:8000/api/v2/healthz
|
436
462
|
echo ""
|
437
463
|
echo "Saying hello world with v1 API ..."
|
438
|
-
curl http://127.0.0.1:8000/api/v2/hello
|
464
|
+
curl http://127.0.0.1:8000/api/v2/hello/world
|
439
465
|
echo ""
|
440
466
|
echo "Swagger docs of v2 API ..."
|
441
467
|
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.6"
|
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,8 +64,19 @@ 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",
|
70
81
|
# Custom
|
71
82
|
# Nothing yet
|
@@ -94,7 +105,7 @@ packages = ["src/oe_python_template_example"]
|
|
94
105
|
[project.optional-dependencies]
|
95
106
|
examples = [
|
96
107
|
"streamlit>=1.44.1",
|
97
|
-
"marimo>=0.12.
|
108
|
+
"marimo>=0.12.8",
|
98
109
|
"jupyter>=1.1.1",
|
99
110
|
"jinja2>=3.1.6",
|
100
111
|
]
|
@@ -111,20 +122,20 @@ dev = [
|
|
111
122
|
"matplotlib>=3.10.1",
|
112
123
|
"mypy>=1.5.0",
|
113
124
|
"nox[uv]>=2025.2.9",
|
114
|
-
"pip-audit>=2.
|
125
|
+
"pip-audit>=2.9.0",
|
115
126
|
"pip-licenses @ git+https://github.com/neXenio/pip-licenses.git@master", # https://github.com/raimon49/pip-licenses/pull/224
|
116
127
|
"pre-commit>=4.1.0",
|
117
|
-
"pyright>=1.1.
|
128
|
+
"pyright>=1.1.399",
|
118
129
|
"pytest>=8.3.5",
|
119
130
|
"pytest-asyncio>=0.26.0",
|
120
|
-
"pytest-cov>=6.1.
|
121
|
-
"pytest-docker>=3.2.
|
131
|
+
"pytest-cov>=6.1.1",
|
132
|
+
"pytest-docker>=3.2.1",
|
122
133
|
"pytest-env>=1.1.5",
|
123
134
|
"pytest-regressions>=2.7.0",
|
124
135
|
"pytest-subprocess>=1.5.3",
|
125
136
|
"pytest-timeout>=2.3.1",
|
126
137
|
"pytest-xdist[psutil]>=3.6.1",
|
127
|
-
"ruff>=0.11.
|
138
|
+
"ruff>=0.11.5",
|
128
139
|
"sphinx>=8.2.3",
|
129
140
|
"sphinx-autobuild>=2024.10.3",
|
130
141
|
"sphinx-copybutton>=0.5.2",
|
@@ -152,7 +163,7 @@ target-version = "py311"
|
|
152
163
|
preview = true
|
153
164
|
fix = true
|
154
165
|
line-length = 120
|
155
|
-
extend-exclude = [".fixme", "notebook.py"]
|
166
|
+
extend-exclude = [".fixme", "notebook.py", "template/*.py"]
|
156
167
|
|
157
168
|
[tool.ruff.lint]
|
158
169
|
select = ["ALL"]
|
@@ -178,7 +189,7 @@ ignore = [
|
|
178
189
|
]
|
179
190
|
|
180
191
|
[tool.ruff.lint.per-file-ignores]
|
181
|
-
"tests/**/*.py" = [
|
192
|
+
"**/tests/**/*.py" = [
|
182
193
|
# we are more relaxed in tests, while sill applying hundreds of rules
|
183
194
|
"S101", # asserts allowed in tests...
|
184
195
|
"ARG", # unused function args -> fixtures nevertheless are functionally relevant...
|
@@ -266,7 +277,7 @@ source = ["src/"]
|
|
266
277
|
|
267
278
|
|
268
279
|
[tool.bumpversion]
|
269
|
-
current_version = "0.3.
|
280
|
+
current_version = "0.3.6"
|
270
281
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
271
282
|
serialize = ["{major}.{minor}.{patch}"]
|
272
283
|
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
|
+
]
|