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.
Files changed (41) hide show
  1. {oe_python_template_example-0.3.5 → oe_python_template_example-0.3.6}/PKG-INFO +77 -51
  2. {oe_python_template_example-0.3.5 → oe_python_template_example-0.3.6}/README.md +63 -48
  3. {oe_python_template_example-0.3.5 → oe_python_template_example-0.3.6}/pyproject.toml +22 -11
  4. oe_python_template_example-0.3.6/src/oe_python_template_example/__init__.py +6 -0
  5. oe_python_template_example-0.3.6/src/oe_python_template_example/api.py +75 -0
  6. oe_python_template_example-0.3.6/src/oe_python_template_example/cli.py +22 -0
  7. oe_python_template_example-0.3.6/src/oe_python_template_example/constants.py +7 -0
  8. oe_python_template_example-0.3.6/src/oe_python_template_example/hello/__init__.py +17 -0
  9. oe_python_template_example-0.3.6/src/oe_python_template_example/hello/_api.py +94 -0
  10. oe_python_template_example-0.3.6/src/oe_python_template_example/hello/_cli.py +47 -0
  11. oe_python_template_example-0.3.6/src/oe_python_template_example/hello/_constants.py +4 -0
  12. oe_python_template_example-0.3.6/src/oe_python_template_example/hello/_models.py +28 -0
  13. oe_python_template_example-0.3.6/src/oe_python_template_example/hello/_service.py +96 -0
  14. 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
  15. oe_python_template_example-0.3.6/src/oe_python_template_example/system/__init__.py +19 -0
  16. oe_python_template_example-0.3.6/src/oe_python_template_example/system/_api.py +116 -0
  17. oe_python_template_example-0.3.6/src/oe_python_template_example/system/_cli.py +165 -0
  18. oe_python_template_example-0.3.6/src/oe_python_template_example/system/_service.py +182 -0
  19. oe_python_template_example-0.3.6/src/oe_python_template_example/system/_settings.py +31 -0
  20. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/__init__.py +59 -0
  21. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_api.py +18 -0
  22. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_cli.py +68 -0
  23. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_console.py +14 -0
  24. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_constants.py +48 -0
  25. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_di.py +70 -0
  26. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_health.py +107 -0
  27. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_log.py +122 -0
  28. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_logfire.py +68 -0
  29. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_process.py +41 -0
  30. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_sentry.py +97 -0
  31. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_service.py +39 -0
  32. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/_settings.py +80 -0
  33. oe_python_template_example-0.3.6/src/oe_python_template_example/utils/boot.py +86 -0
  34. oe_python_template_example-0.3.5/src/oe_python_template_example/__init__.py +0 -20
  35. oe_python_template_example-0.3.5/src/oe_python_template_example/api.py +0 -181
  36. oe_python_template_example-0.3.5/src/oe_python_template_example/cli.py +0 -150
  37. oe_python_template_example-0.3.5/src/oe_python_template_example/constants.py +0 -10
  38. oe_python_template_example-0.3.5/src/oe_python_template_example/models.py +0 -44
  39. oe_python_template_example-0.3.5/src/oe_python_template_example/service.py +0 -68
  40. {oe_python_template_example-0.3.5 → oe_python_template_example-0.3.6}/.gitignore +0 -0
  41. {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.5
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.1
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.2; extra == 'examples'
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
  [![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-orange.json)](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template)
90
101
  [![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE3IDE2VjdsLTYgNU0yIDlWOGwxLTFoMWw0IDMgOC04aDFsNCAyIDEgMXYxNGwtMSAxLTQgMmgtMWwtOC04LTQgM0gzbC0xLTF2LTFsMy0zIi8+PC9zdmc+)](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
  [![Open in GitHub Codespaces](https://img.shields.io/static/v1?label=GitHub%20Codespaces&message=Open&color=blue&logo=github)](https://github.com/codespaces/new/helmut-hoffer-von-ankershoffen/oe-python-template-example)
103
+ [![Vercel Deploy](https://deploy-badge.vercel.app/vercel/oe-python-template-example?root=api%2Fv1%2Fhealthz)](https://oe-python-template-example.vercel.app/api/v1/hello/world)
104
+ [![Better Stack Badge](https://uptime.betterstack.com/status-badges/v1/monitor/1vzoq.svg)](https://helmut-hoffer-von-ankershoffen.betteruptime.com/)
92
105
 
93
106
  <!---
94
107
  [![ghcr.io - Version](https://ghcr-badge.egpl.dev/helmut-hoffer-von-ankershoffen/oe-python-template-example/tags?color=%2344cc11&ignore=0.0%2C0%2Clatest&n=3&label=ghcr.io&trim=)](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. 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
131
- 12. Generation of attributions from extracted licenses
132
- 13. 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
133
- 14. Version and release management with [bump-my-version](https://callowayproject.github.io/bump-my-version/)
134
- 15. Changelog and release notes generated with [git-cliff](https://git-cliff.org/)
135
- 16. Documentation generated with [Sphinx](https://www.sphinx-doc.org/en/master/) including reference documentation for the library, CLI, and API
136
- 17. Documentation published to [Read The Docs](https://readthedocs.org/) including generation of PDF and single page HTML versions
137
- 18. Interactive OpenAPI specification with [Swagger](https://swagger.io/)
138
- 19. Python package published to [PyPI](https://pypi.org/)
139
- 20. 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)
140
- 21. One-click development environments with [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) and [GitHub Codespaces](https://github.com/features/codespaces)
141
- 22. Settings for use with [VSCode](https://code.visualstudio.com/)
142
- 23. Settings and custom instructions for use with [GitHub Copilot](https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot)
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 demo application and service. This reference implementation serves as a starting point for your own business logic with modern patterns and practices already in place:
147
-
148
- 1. Service architecture suitable for use as shared library
149
- 2. Validation with [pydantic](https://docs.pydantic.dev/)
150
- 3. Command-line interface (CLI) with [Typer](https://typer.tiangolo.com/)
151
- 4. Versioned Web API with [FastAPI](https://fastapi.tiangolo.com/)
152
- 5. [Interactive Jupyter notebook](https://jupyter.org/) and [reactive Marimo notebook](https://marimo.io/)
153
- 6. Simple Web UI with [Streamlit](https://streamlit.io/)
154
- 7. 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/)
155
- 8. Documentation including badges, setup instructions, contribution guide and security policy
156
- 9. Preparation to deploy API as serverless function to Vercel
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-world
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 openapi
370
- uvx oe-python-template-example openapi --output-format=json
371
- uvx oe-python-template-example serve
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-world
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 openapi
399
- docker run helmuthva/oe-python-template-example openapi --output-format=json
400
- docker run helmuthva/oe-python-template-example serve
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-world
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 openapi
420
- docker compose run --remove-orphans oe-python-template-example openapi --output-format=json
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-world
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-world
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
  [![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-orange.json)](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template)
29
29
  [![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE3IDE2VjdsLTYgNU0yIDlWOGwxLTFoMWw0IDMgOC04aDFsNCAyIDEgMXYxNGwtMSAxLTQgMmgtMWwtOC04LTQgM0gzbC0xLTF2LTFsMy0zIi8+PC9zdmc+)](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
  [![Open in GitHub Codespaces](https://img.shields.io/static/v1?label=GitHub%20Codespaces&message=Open&color=blue&logo=github)](https://github.com/codespaces/new/helmut-hoffer-von-ankershoffen/oe-python-template-example)
31
+ [![Vercel Deploy](https://deploy-badge.vercel.app/vercel/oe-python-template-example?root=api%2Fv1%2Fhealthz)](https://oe-python-template-example.vercel.app/api/v1/hello/world)
32
+ [![Better Stack Badge](https://uptime.betterstack.com/status-badges/v1/monitor/1vzoq.svg)](https://helmut-hoffer-von-ankershoffen.betteruptime.com/)
31
33
 
32
34
  <!---
33
35
  [![ghcr.io - Version](https://ghcr-badge.egpl.dev/helmut-hoffer-von-ankershoffen/oe-python-template-example/tags?color=%2344cc11&ignore=0.0%2C0%2Clatest&n=3&label=ghcr.io&trim=)](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. 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
70
- 12. Generation of attributions from extracted licenses
71
- 13. 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
72
- 14. Version and release management with [bump-my-version](https://callowayproject.github.io/bump-my-version/)
73
- 15. Changelog and release notes generated with [git-cliff](https://git-cliff.org/)
74
- 16. Documentation generated with [Sphinx](https://www.sphinx-doc.org/en/master/) including reference documentation for the library, CLI, and API
75
- 17. Documentation published to [Read The Docs](https://readthedocs.org/) including generation of PDF and single page HTML versions
76
- 18. Interactive OpenAPI specification with [Swagger](https://swagger.io/)
77
- 19. Python package published to [PyPI](https://pypi.org/)
78
- 20. 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)
79
- 21. One-click development environments with [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) and [GitHub Codespaces](https://github.com/features/codespaces)
80
- 22. Settings for use with [VSCode](https://code.visualstudio.com/)
81
- 23. Settings and custom instructions for use with [GitHub Copilot](https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot)
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 demo application and service. This reference implementation serves as a starting point for your own business logic with modern patterns and practices already in place:
86
-
87
- 1. Service architecture suitable for use as shared library
88
- 2. Validation with [pydantic](https://docs.pydantic.dev/)
89
- 3. Command-line interface (CLI) with [Typer](https://typer.tiangolo.com/)
90
- 4. Versioned Web API with [FastAPI](https://fastapi.tiangolo.com/)
91
- 5. [Interactive Jupyter notebook](https://jupyter.org/) and [reactive Marimo notebook](https://marimo.io/)
92
- 6. Simple Web UI with [Streamlit](https://streamlit.io/)
93
- 7. 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/)
94
- 8. Documentation including badges, setup instructions, contribution guide and security policy
95
- 9. Preparation to deploy API as serverless function to Vercel
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-world
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 openapi
309
- uvx oe-python-template-example openapi --output-format=json
310
- uvx oe-python-template-example serve
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-world
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 openapi
338
- docker run helmuthva/oe-python-template-example openapi --output-format=json
339
- docker run helmuthva/oe-python-template-example serve
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-world
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 openapi
359
- docker compose run --remove-orphans oe-python-template-example openapi --output-format=json
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-world
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-world
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.5"
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
- "pydantic>=2.11.1",
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.2",
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.8.0",
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.398",
128
+ "pyright>=1.1.399",
118
129
  "pytest>=8.3.5",
119
130
  "pytest-asyncio>=0.26.0",
120
- "pytest-cov>=6.1.0",
121
- "pytest-docker>=3.2.0",
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.2",
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.5"
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,6 @@
1
+ """Copier template to scaffold Python projects compliant with best practices and modern tooling."""
2
+
3
+ from .constants import MODULES_TO_INSTRUMENT
4
+ from .utils.boot import boot
5
+
6
+ boot(modules_to_instrument=MODULES_TO_INSTRUMENT)
@@ -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,7 @@
1
+ """Constants for the OE Python Template Example."""
2
+
3
+ API_VERSIONS = {
4
+ "v1": "1.0.0",
5
+ "v2": "2.0.0",
6
+ }
7
+ MODULES_TO_INSTRUMENT = ["oe_python_template_example.hello"]
@@ -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
+ ]