oe-python-template-example 0.0.10__tar.gz → 0.1.1__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 (90) hide show
  1. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.copier-answers.yml +1 -1
  2. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.pre-commit-config.yaml +1 -0
  3. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/PKG-INFO +36 -17
  4. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/README.md +35 -16
  5. oe_python_template_example-0.1.1/VERSION +1 -0
  6. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/_readme_main.md +35 -16
  7. oe_python_template_example-0.1.1/docs/source/_static/openapi_v1.json +262 -0
  8. oe_python_template_example-0.1.1/docs/source/_static/openapi_v1.yaml +210 -0
  9. oe_python_template_example-0.1.1/docs/source/_static/openapi_v2.json +262 -0
  10. oe_python_template_example-0.1.1/docs/source/_static/openapi_v2.yaml +210 -0
  11. oe_python_template_example-0.1.1/docs/source/api_v1.rst +5 -0
  12. oe_python_template_example-0.1.1/docs/source/api_v2.rst +5 -0
  13. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/docs/source/conf.py +1 -1
  14. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/docs/source/index.rst +2 -1
  15. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/examples/notebook.py +1 -1
  16. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/noxfile.py +12 -4
  17. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/pyproject.toml +3 -2
  18. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/sonar-project.properties +1 -1
  19. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/src/oe_python_template_example/api.py +83 -5
  20. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/src/oe_python_template_example/cli.py +29 -3
  21. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/tests/api_test.py +54 -20
  22. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/tests/cli_test.py +12 -1
  23. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/uv.lock +12 -1
  24. oe_python_template_example-0.0.10/VERSION +0 -1
  25. oe_python_template_example-0.0.10/docs/source/api.rst +0 -5
  26. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.act-env-public +0 -0
  27. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.devcontainer/Dockerfile +0 -0
  28. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.devcontainer/devcontainer.json +0 -0
  29. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.devcontainer/onCreateCommand +0 -0
  30. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.devcontainer/postAttachCommand +0 -0
  31. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.devcontainer/postCreateCommand +0 -0
  32. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.env.example +0 -0
  33. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.github/workflows/docker-image-build-publish.yml +0 -0
  34. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.github/workflows/package-build-publish-release.yml +0 -0
  35. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.github/workflows/test-and-report.yml +0 -0
  36. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.gitignore +0 -0
  37. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.python-version +0 -0
  38. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.readthedocs.yml +0 -0
  39. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.secrets.baseline +0 -0
  40. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.vscode/extensions.json +0 -0
  41. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/.vscode/settings.json +0 -0
  42. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/CHANGELOG.md +0 -0
  43. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/CODEOWNERS +0 -0
  44. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/CONTRIBUTING.md +0 -0
  45. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/Dockerfile +0 -0
  46. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/LICENSE +0 -0
  47. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/RELEASE_NOTES.md +0 -0
  48. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/SERVICE_CONNECTIONS.md +0 -0
  49. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/_readme_footer.md +0 -0
  50. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/_readme_header.md +0 -0
  51. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/bin/git-cliff +0 -0
  52. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/bump +0 -0
  53. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/codecov.yml +0 -0
  54. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/compose.yaml +0 -0
  55. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/docs/Makefile +0 -0
  56. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/docs/make.bat +0 -0
  57. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/docs/source/_static/.keep +0 -0
  58. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/docs/source/_static/openapi.json +0 -0
  59. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/docs/source/_static/openapi.yaml +0 -0
  60. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/docs/source/contributing.rst +0 -0
  61. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/docs/source/latexmkrc +0 -0
  62. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/docs/source/main.rst +0 -0
  63. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/docs/source/reference.rst +0 -0
  64. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/docs/source/release-notes.rst +0 -0
  65. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/examples/__init__.py +0 -0
  66. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/examples/notebook.ipynb +0 -0
  67. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/examples/script.py +0 -0
  68. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/examples/streamlit.py +0 -0
  69. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0/CHANGELOG.md +0 -0
  70. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0/LICENSE-APACHE +0 -0
  71. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0/LICENSE-MIT +0 -0
  72. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0/README.md +0 -0
  73. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0/completions/_git-cliff +0 -0
  74. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0/completions/_git-cliff.ps1 +0 -0
  75. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0/completions/git-cliff.bash +0 -0
  76. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0/completions/git-cliff.elv +0 -0
  77. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0/completions/git-cliff.fish +0 -0
  78. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0/git-cliff-completions +0 -0
  79. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0/git-cliff-mangen +0 -0
  80. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0/man/git-cliff.1 +0 -0
  81. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/git-cliff-2.7.0-x86_64-unknown-linux-gnu.tar.gz +0 -0
  82. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/github-action-run +0 -0
  83. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/latexmkrc +0 -0
  84. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/logo.png +0 -0
  85. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/renovate.json +0 -0
  86. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/src/oe_python_template_example/__init__.py +0 -0
  87. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/src/oe_python_template_example/constants.py +0 -0
  88. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/src/oe_python_template_example/service.py +0 -0
  89. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/tests/__init__.py +0 -0
  90. {oe_python_template_example-0.0.10 → oe_python_template_example-0.1.1}/tests/fixtures/.keep +0 -0
@@ -1,4 +1,4 @@
1
- _commit: v0.3.9
1
+ _commit: v0.4.3
2
2
  _src_path: gh:helmut-hoffer-von-ankershoffen/oe-python-template
3
3
  author_email: helmuthva@gmail.com
4
4
  author_github_username: helmut-hoffer-von-ankershoffen
@@ -14,6 +14,7 @@ repos:
14
14
  hooks:
15
15
  - id: python-check-blanket-noqa
16
16
  - id: python-check-blanket-type-ignore
17
+ exclude: "^examples/notebook.py$"
17
18
  - id: python-check-mock-methods
18
19
  - id: python-no-eval
19
20
  - id: python-no-log-warn
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oe-python-template-example
3
- Version: 0.0.10
3
+ Version: 0.1.1
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/
@@ -101,9 +101,9 @@ Use Cases:
101
101
  2) Consistent update of already scaffolded projects to benefit from new and improved features.
102
102
  3) Dummy CLI application and service demonstrating example usage of the generated directory structure and build pipeline
103
103
 
104
- ## Scaffolding Instructions
104
+ ## Scaffolding
105
105
 
106
- Step 1: Install uv package manager and copier
106
+ **Step 1**: Install uv package manager and copier
107
107
  ```shell
108
108
  if [[ "$OSTYPE" == "darwin"* ]]; then # Install dependencies for macOS X
109
109
  if ! command -v brew &> /dev/null; then ## Install Homebrew if not present
@@ -119,31 +119,32 @@ fi
119
119
  uv tool install copier # Install copier as global tool
120
120
  ```
121
121
 
122
- Step 2: Now create an empty repo on GitHub and clone it to your local machine in a directory of your choice. Change to that directory.
122
+ **Step 2**: Now create an empty repository on GitHubm, clone to your local machine, and change into it's directory.
123
123
 
124
- Step 3: Scaffold the project
124
+ **Step 3**: Scaffold the project
125
125
  ```shell
126
126
  copier copy gh:helmut-hoffer-von-ankershoffen/oe-python-template .
127
127
  ```
128
- Step 4: Setup the local environment
128
+ **Step 4**: Setup the local environment
129
129
 
130
130
  ```shell
131
131
  uv run nox -s setup_dev
132
132
  ```
133
133
 
134
- Step 5: Perform inital commit and push
134
+ **Step 5**: Perform initial commit and push
135
135
  ```shell
136
136
  git add .
137
137
  git commit -m "feat: Initial commit"
138
+ git push
138
139
  ```
139
140
 
140
141
  Visit your GitHub repository and check the Actions tab. The CI workflow should fail at the SonarQube step,
141
142
  as this external service is not yet configured for our new repository.
142
143
 
143
- Step 6: Follow the instructions in SERVICE_CONNECTIONS.md to setup the connections to external services
144
- such as Cloudcov, SonarQube Cloud, Read The Docs, Docker.io, GHCR.io and Streamlit Community Cloud.
144
+ **Step 6**: Follow the [SERVICE_INSTRUCTIONS.md](instructions) to wire up
145
+ external services such as Cloudcov, SonarQube Cloud, Read The Docs, Docker.io, GHCR.io and Streamlit Community Cloud.
145
146
 
146
- Step 7: Release the first versions
147
+ **Step 7**: Release the first versions
147
148
  ```shell
148
149
  ./bump
149
150
  ```
@@ -166,24 +167,36 @@ If you don't have uv installed follow [these instructions](https://docs.astral.s
166
167
  pip install oe-python-template-example # add dependency to your project
167
168
  ```
168
169
 
169
- Executing the command line interface (CLI) is just as easy:
170
+ Executing the command line interface (CLI) in an isolated Python environment is just as easy:
170
171
 
171
172
  ```shell
172
- uvx oe-python-template-example
173
+ uvx oe-python-template-example hello-world # prints "Hello, world! [..]"
174
+ uvx oe-python-template-example serve # serves webservice API
175
+ uvx oe-python-template-example serve --port=4711 # serves webservice API on port 4711
173
176
  ```
174
177
 
178
+ Notes:
179
+ * The API is versioned, mounted at ```/api/v1``` resp. ```/api/v2```
180
+ * While serving the webservice API go to [http://127.0.0.1:8000/api/v1/hello-world](http://127.0.0.1:8000/api/v1/hello-world) to see the respons of the ```hello-world``` operation.
181
+ * Interactive documentation is provided at [http://127.0.0.1:8000/api/docs](http://127.0.0.1:8000/api/docs)
182
+
183
+
175
184
  The CLI provides extensive help:
176
185
 
177
186
  ```shell
178
187
  uvx oe-python-template-example --help # all CLI commands
179
188
  uvx oe-python-template-example hello-world --help # help for specific command
189
+ uvx oe-python-template-example echo --help
190
+ uvx oe-python-template-example openapi --help
191
+ uvx oe-python-template-example serve --help
180
192
  ```
181
193
 
182
194
 
183
- ## Highlights
195
+ ## Operational Excellence
184
196
 
185
- * Example project scaffolded and kept up to date with OE Python Template (oe-python-template).
186
- * Various Examples:
197
+ This project is designed with operational excellence in mind, using modern Python tooling and practices. It includes:
198
+
199
+ * Various examples demonstrating usage:
187
200
  - [Simple Python script](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/script.py)
188
201
  - [Streamlit web application](https://oe-python-template-example.streamlit.app/) deployed on [Streamlit Community Cloud](https://streamlit.io/cloud)
189
202
  - [Jupyter](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/notebook.ipynb) and [Marimo](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/notebook.py) notebook
@@ -199,6 +212,9 @@ uvx oe-python-template-example hello-world --help # help for specific command
199
212
 
200
213
  ## Usage Examples
201
214
 
215
+ The following examples run from source. Clone this repository first using
216
+ `git clone git@github.com:helmut-hoffer-von-ankershoffen/oe-python-template-example.git`.
217
+
202
218
  ### Minimal Python Script:
203
219
 
204
220
  ```python
@@ -240,7 +256,7 @@ uv run streamlit run examples/streamlit.py # Serve on localhost:8501, o
240
256
  ... or run within VSCode
241
257
 
242
258
  ```shell
243
- uv sync --all-extras # Install ipykernel dependency part of the examples extra, see pyproject.toml
259
+ uv sync --all-extras # Install dependencies required for examples such as Juypyter kernel, see pyproject.toml
244
260
  ```
245
261
  Install the [Jupyter extension for VSCode](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter)
246
262
 
@@ -337,7 +353,10 @@ docker compose run oe-python-template-example echo "Lorem" --json
337
353
  docker compose run oe-python-template-example openapi
338
354
  docker compose run oe-python-template-example openapi --output-format=json
339
355
  docker compose up
340
- curl http://127.0.0.1 8000
356
+ curl http://127.0.0.1:8000/api/v1/hello-world
357
+ curl http://127.0.0.1:8000/api/v1/docs
358
+ curl http://127.0.0.1:8000/api/v2/hello-world
359
+ curl http://127.0.0.1:8000/api/v2/docs
341
360
  ```
342
361
 
343
362
  ## Extra: Lorem Ipsum
@@ -40,9 +40,9 @@ Use Cases:
40
40
  2) Consistent update of already scaffolded projects to benefit from new and improved features.
41
41
  3) Dummy CLI application and service demonstrating example usage of the generated directory structure and build pipeline
42
42
 
43
- ## Scaffolding Instructions
43
+ ## Scaffolding
44
44
 
45
- Step 1: Install uv package manager and copier
45
+ **Step 1**: Install uv package manager and copier
46
46
  ```shell
47
47
  if [[ "$OSTYPE" == "darwin"* ]]; then # Install dependencies for macOS X
48
48
  if ! command -v brew &> /dev/null; then ## Install Homebrew if not present
@@ -58,31 +58,32 @@ fi
58
58
  uv tool install copier # Install copier as global tool
59
59
  ```
60
60
 
61
- Step 2: Now create an empty repo on GitHub and clone it to your local machine in a directory of your choice. Change to that directory.
61
+ **Step 2**: Now create an empty repository on GitHubm, clone to your local machine, and change into it's directory.
62
62
 
63
- Step 3: Scaffold the project
63
+ **Step 3**: Scaffold the project
64
64
  ```shell
65
65
  copier copy gh:helmut-hoffer-von-ankershoffen/oe-python-template .
66
66
  ```
67
- Step 4: Setup the local environment
67
+ **Step 4**: Setup the local environment
68
68
 
69
69
  ```shell
70
70
  uv run nox -s setup_dev
71
71
  ```
72
72
 
73
- Step 5: Perform inital commit and push
73
+ **Step 5**: Perform initial commit and push
74
74
  ```shell
75
75
  git add .
76
76
  git commit -m "feat: Initial commit"
77
+ git push
77
78
  ```
78
79
 
79
80
  Visit your GitHub repository and check the Actions tab. The CI workflow should fail at the SonarQube step,
80
81
  as this external service is not yet configured for our new repository.
81
82
 
82
- Step 6: Follow the instructions in SERVICE_CONNECTIONS.md to setup the connections to external services
83
- such as Cloudcov, SonarQube Cloud, Read The Docs, Docker.io, GHCR.io and Streamlit Community Cloud.
83
+ **Step 6**: Follow the [SERVICE_INSTRUCTIONS.md](instructions) to wire up
84
+ external services such as Cloudcov, SonarQube Cloud, Read The Docs, Docker.io, GHCR.io and Streamlit Community Cloud.
84
85
 
85
- Step 7: Release the first versions
86
+ **Step 7**: Release the first versions
86
87
  ```shell
87
88
  ./bump
88
89
  ```
@@ -105,24 +106,36 @@ If you don't have uv installed follow [these instructions](https://docs.astral.s
105
106
  pip install oe-python-template-example # add dependency to your project
106
107
  ```
107
108
 
108
- Executing the command line interface (CLI) is just as easy:
109
+ Executing the command line interface (CLI) in an isolated Python environment is just as easy:
109
110
 
110
111
  ```shell
111
- uvx oe-python-template-example
112
+ uvx oe-python-template-example hello-world # prints "Hello, world! [..]"
113
+ uvx oe-python-template-example serve # serves webservice API
114
+ uvx oe-python-template-example serve --port=4711 # serves webservice API on port 4711
112
115
  ```
113
116
 
117
+ Notes:
118
+ * The API is versioned, mounted at ```/api/v1``` resp. ```/api/v2```
119
+ * While serving the webservice API go to [http://127.0.0.1:8000/api/v1/hello-world](http://127.0.0.1:8000/api/v1/hello-world) to see the respons of the ```hello-world``` operation.
120
+ * Interactive documentation is provided at [http://127.0.0.1:8000/api/docs](http://127.0.0.1:8000/api/docs)
121
+
122
+
114
123
  The CLI provides extensive help:
115
124
 
116
125
  ```shell
117
126
  uvx oe-python-template-example --help # all CLI commands
118
127
  uvx oe-python-template-example hello-world --help # help for specific command
128
+ uvx oe-python-template-example echo --help
129
+ uvx oe-python-template-example openapi --help
130
+ uvx oe-python-template-example serve --help
119
131
  ```
120
132
 
121
133
 
122
- ## Highlights
134
+ ## Operational Excellence
123
135
 
124
- * Example project scaffolded and kept up to date with OE Python Template (oe-python-template).
125
- * Various Examples:
136
+ This project is designed with operational excellence in mind, using modern Python tooling and practices. It includes:
137
+
138
+ * Various examples demonstrating usage:
126
139
  - [Simple Python script](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/script.py)
127
140
  - [Streamlit web application](https://oe-python-template-example.streamlit.app/) deployed on [Streamlit Community Cloud](https://streamlit.io/cloud)
128
141
  - [Jupyter](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/notebook.ipynb) and [Marimo](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/notebook.py) notebook
@@ -138,6 +151,9 @@ uvx oe-python-template-example hello-world --help # help for specific command
138
151
 
139
152
  ## Usage Examples
140
153
 
154
+ The following examples run from source. Clone this repository first using
155
+ `git clone git@github.com:helmut-hoffer-von-ankershoffen/oe-python-template-example.git`.
156
+
141
157
  ### Minimal Python Script:
142
158
 
143
159
  ```python
@@ -179,7 +195,7 @@ uv run streamlit run examples/streamlit.py # Serve on localhost:8501, o
179
195
  ... or run within VSCode
180
196
 
181
197
  ```shell
182
- uv sync --all-extras # Install ipykernel dependency part of the examples extra, see pyproject.toml
198
+ uv sync --all-extras # Install dependencies required for examples such as Juypyter kernel, see pyproject.toml
183
199
  ```
184
200
  Install the [Jupyter extension for VSCode](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter)
185
201
 
@@ -276,7 +292,10 @@ docker compose run oe-python-template-example echo "Lorem" --json
276
292
  docker compose run oe-python-template-example openapi
277
293
  docker compose run oe-python-template-example openapi --output-format=json
278
294
  docker compose up
279
- curl http://127.0.0.1 8000
295
+ curl http://127.0.0.1:8000/api/v1/hello-world
296
+ curl http://127.0.0.1:8000/api/v1/docs
297
+ curl http://127.0.0.1:8000/api/v2/hello-world
298
+ curl http://127.0.0.1:8000/api/v2/docs
280
299
  ```
281
300
 
282
301
  ## Extra: Lorem Ipsum
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -5,9 +5,9 @@ Use Cases:
5
5
  2) Consistent update of already scaffolded projects to benefit from new and improved features.
6
6
  3) Dummy CLI application and service demonstrating example usage of the generated directory structure and build pipeline
7
7
 
8
- ## Scaffolding Instructions
8
+ ## Scaffolding
9
9
 
10
- Step 1: Install uv package manager and copier
10
+ **Step 1**: Install uv package manager and copier
11
11
  ```shell
12
12
  if [[ "$OSTYPE" == "darwin"* ]]; then # Install dependencies for macOS X
13
13
  if ! command -v brew &> /dev/null; then ## Install Homebrew if not present
@@ -23,31 +23,32 @@ fi
23
23
  uv tool install copier # Install copier as global tool
24
24
  ```
25
25
 
26
- Step 2: Now create an empty repo on GitHub and clone it to your local machine in a directory of your choice. Change to that directory.
26
+ **Step 2**: Now create an empty repository on GitHubm, clone to your local machine, and change into it's directory.
27
27
 
28
- Step 3: Scaffold the project
28
+ **Step 3**: Scaffold the project
29
29
  ```shell
30
30
  copier copy gh:helmut-hoffer-von-ankershoffen/oe-python-template .
31
31
  ```
32
- Step 4: Setup the local environment
32
+ **Step 4**: Setup the local environment
33
33
 
34
34
  ```shell
35
35
  uv run nox -s setup_dev
36
36
  ```
37
37
 
38
- Step 5: Perform inital commit and push
38
+ **Step 5**: Perform initial commit and push
39
39
  ```shell
40
40
  git add .
41
41
  git commit -m "feat: Initial commit"
42
+ git push
42
43
  ```
43
44
 
44
45
  Visit your GitHub repository and check the Actions tab. The CI workflow should fail at the SonarQube step,
45
46
  as this external service is not yet configured for our new repository.
46
47
 
47
- Step 6: Follow the instructions in SERVICE_CONNECTIONS.md to setup the connections to external services
48
- such as Cloudcov, SonarQube Cloud, Read The Docs, Docker.io, GHCR.io and Streamlit Community Cloud.
48
+ **Step 6**: Follow the [SERVICE_INSTRUCTIONS.md](instructions) to wire up
49
+ external services such as Cloudcov, SonarQube Cloud, Read The Docs, Docker.io, GHCR.io and Streamlit Community Cloud.
49
50
 
50
- Step 7: Release the first versions
51
+ **Step 7**: Release the first versions
51
52
  ```shell
52
53
  ./bump
53
54
  ```
@@ -70,24 +71,36 @@ If you don't have uv installed follow [these instructions](https://docs.astral.s
70
71
  pip install oe-python-template-example # add dependency to your project
71
72
  ```
72
73
 
73
- Executing the command line interface (CLI) is just as easy:
74
+ Executing the command line interface (CLI) in an isolated Python environment is just as easy:
74
75
 
75
76
  ```shell
76
- uvx oe-python-template-example
77
+ uvx oe-python-template-example hello-world # prints "Hello, world! [..]"
78
+ uvx oe-python-template-example serve # serves webservice API
79
+ uvx oe-python-template-example serve --port=4711 # serves webservice API on port 4711
77
80
  ```
78
81
 
82
+ Notes:
83
+ * The API is versioned, mounted at ```/api/v1``` resp. ```/api/v2```
84
+ * While serving the webservice API go to [http://127.0.0.1:8000/api/v1/hello-world](http://127.0.0.1:8000/api/v1/hello-world) to see the respons of the ```hello-world``` operation.
85
+ * Interactive documentation is provided at [http://127.0.0.1:8000/api/docs](http://127.0.0.1:8000/api/docs)
86
+
87
+
79
88
  The CLI provides extensive help:
80
89
 
81
90
  ```shell
82
91
  uvx oe-python-template-example --help # all CLI commands
83
92
  uvx oe-python-template-example hello-world --help # help for specific command
93
+ uvx oe-python-template-example echo --help
94
+ uvx oe-python-template-example openapi --help
95
+ uvx oe-python-template-example serve --help
84
96
  ```
85
97
 
86
98
 
87
- ## Highlights
99
+ ## Operational Excellence
88
100
 
89
- * Example project scaffolded and kept up to date with OE Python Template (oe-python-template).
90
- * Various Examples:
101
+ This project is designed with operational excellence in mind, using modern Python tooling and practices. It includes:
102
+
103
+ * Various examples demonstrating usage:
91
104
  - [Simple Python script](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/script.py)
92
105
  - [Streamlit web application](https://oe-python-template-example.streamlit.app/) deployed on [Streamlit Community Cloud](https://streamlit.io/cloud)
93
106
  - [Jupyter](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/notebook.ipynb) and [Marimo](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example/blob/main/examples/notebook.py) notebook
@@ -103,6 +116,9 @@ uvx oe-python-template-example hello-world --help # help for specific command
103
116
 
104
117
  ## Usage Examples
105
118
 
119
+ The following examples run from source. Clone this repository first using
120
+ `git clone git@github.com:helmut-hoffer-von-ankershoffen/oe-python-template-example.git`.
121
+
106
122
  ### Minimal Python Script:
107
123
 
108
124
  ```python
@@ -144,7 +160,7 @@ uv run streamlit run examples/streamlit.py # Serve on localhost:8501, o
144
160
  ... or run within VSCode
145
161
 
146
162
  ```shell
147
- uv sync --all-extras # Install ipykernel dependency part of the examples extra, see pyproject.toml
163
+ uv sync --all-extras # Install dependencies required for examples such as Juypyter kernel, see pyproject.toml
148
164
  ```
149
165
  Install the [Jupyter extension for VSCode](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter)
150
166
 
@@ -241,7 +257,10 @@ docker compose run oe-python-template-example echo "Lorem" --json
241
257
  docker compose run oe-python-template-example openapi
242
258
  docker compose run oe-python-template-example openapi --output-format=json
243
259
  docker compose up
244
- curl http://127.0.0.1 8000
260
+ curl http://127.0.0.1:8000/api/v1/hello-world
261
+ curl http://127.0.0.1:8000/api/v1/docs
262
+ curl http://127.0.0.1:8000/api/v2/hello-world
263
+ curl http://127.0.0.1:8000/api/v2/docs
245
264
  ```
246
265
 
247
266
  ## Extra: Lorem Ipsum
@@ -0,0 +1,262 @@
1
+ {
2
+ "openapi": "3.1.0",
3
+ "info": {
4
+ "title": "OE Python Template Example",
5
+ "termsOfService": "https://oe-python-template-example.readthedocs.io/en/latest/",
6
+ "contact": {
7
+ "name": "Helmut Hoffer von Ankershoffen",
8
+ "url": "https://github.com/helmut-hoffer-von-ankershoffen",
9
+ "email": "helmuthva@gmail.com"
10
+ },
11
+ "version": "1.0.0"
12
+ },
13
+ "paths": {
14
+ "/health": {
15
+ "get": {
16
+ "tags": [
17
+ "Observability"
18
+ ],
19
+ "summary": "Health",
20
+ "description": "Check the health of the service.\n\nThis endpoint returns the health status of the service.\nThe health status can be either UP or DOWN.\nIf the service is healthy, the status will be UP.\nIf the service is unhealthy, the status will be DOWN and a reason will be provided.\nThe response will have a 200 OK status code if the service is healthy,\nand a 500 Internal Server Error status code if the service is unhealthy.\n\nArgs:\n service (Annotated[Service, Depends): _description_\n response (Response): _description_\n\nReturns:\n Health: The health status of the service.",
21
+ "operationId": "health_health_get",
22
+ "responses": {
23
+ "200": {
24
+ "description": "Successful Response",
25
+ "content": {
26
+ "application/json": {
27
+ "schema": {
28
+ "$ref": "#/components/schemas/Health"
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
34
+ }
35
+ },
36
+ "/healthz": {
37
+ "get": {
38
+ "tags": [
39
+ "Observability"
40
+ ],
41
+ "summary": "Health",
42
+ "description": "Check the health of the service.\n\nThis endpoint returns the health status of the service.\nThe health status can be either UP or DOWN.\nIf the service is healthy, the status will be UP.\nIf the service is unhealthy, the status will be DOWN and a reason will be provided.\nThe response will have a 200 OK status code if the service is healthy,\nand a 500 Internal Server Error status code if the service is unhealthy.\n\nArgs:\n service (Annotated[Service, Depends): _description_\n response (Response): _description_\n\nReturns:\n Health: The health status of the service.",
43
+ "operationId": "health_healthz_get",
44
+ "responses": {
45
+ "200": {
46
+ "description": "Successful Response",
47
+ "content": {
48
+ "application/json": {
49
+ "schema": {
50
+ "$ref": "#/components/schemas/Health"
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+ },
58
+ "/hello-world": {
59
+ "get": {
60
+ "tags": [
61
+ "Basics"
62
+ ],
63
+ "summary": "Hello World",
64
+ "description": "Return a hello world message.\n\nReturns:\n HelloWorldResponse: A response containing the hello world message.",
65
+ "operationId": "hello_world_hello_world_get",
66
+ "responses": {
67
+ "200": {
68
+ "description": "Successful Response",
69
+ "content": {
70
+ "application/json": {
71
+ "schema": {
72
+ "$ref": "#/components/schemas/HelloWorldResponse"
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+ },
80
+ "/echo": {
81
+ "post": {
82
+ "tags": [
83
+ "Basics"
84
+ ],
85
+ "summary": "Echo",
86
+ "description": "Echo back the provided text.\n\nArgs:\n request (EchoRequest): The request containing the text to echo back.\n\nReturns:\n EchoResponse: A response containing the echoed text.\n\nRaises:\n 422 Unprocessable Entity: If text is not provided or empty.",
87
+ "operationId": "echo_echo_post",
88
+ "requestBody": {
89
+ "content": {
90
+ "application/json": {
91
+ "schema": {
92
+ "$ref": "#/components/schemas/EchoRequest"
93
+ }
94
+ }
95
+ },
96
+ "required": true
97
+ },
98
+ "responses": {
99
+ "200": {
100
+ "description": "Successful Response",
101
+ "content": {
102
+ "application/json": {
103
+ "schema": {
104
+ "$ref": "#/components/schemas/EchoResponse"
105
+ }
106
+ }
107
+ }
108
+ },
109
+ "422": {
110
+ "description": "Validation Error",
111
+ "content": {
112
+ "application/json": {
113
+ "schema": {
114
+ "$ref": "#/components/schemas/HTTPValidationError"
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ }
122
+ },
123
+ "components": {
124
+ "schemas": {
125
+ "EchoRequest": {
126
+ "properties": {
127
+ "text": {
128
+ "type": "string",
129
+ "minLength": 1,
130
+ "title": "Text",
131
+ "description": "The text to echo back",
132
+ "examples": [
133
+ "Hello, world!"
134
+ ]
135
+ }
136
+ },
137
+ "type": "object",
138
+ "required": [
139
+ "text"
140
+ ],
141
+ "title": "EchoRequest",
142
+ "description": "Request model for echo endpoint."
143
+ },
144
+ "EchoResponse": {
145
+ "properties": {
146
+ "message": {
147
+ "type": "string",
148
+ "minLength": 1,
149
+ "title": "Message",
150
+ "description": "The message content",
151
+ "examples": [
152
+ "Hello, world!"
153
+ ]
154
+ }
155
+ },
156
+ "type": "object",
157
+ "required": [
158
+ "message"
159
+ ],
160
+ "title": "EchoResponse",
161
+ "description": "Response model for echo endpoint."
162
+ },
163
+ "HTTPValidationError": {
164
+ "properties": {
165
+ "detail": {
166
+ "items": {
167
+ "$ref": "#/components/schemas/ValidationError"
168
+ },
169
+ "type": "array",
170
+ "title": "Detail"
171
+ }
172
+ },
173
+ "type": "object",
174
+ "title": "HTTPValidationError"
175
+ },
176
+ "Health": {
177
+ "properties": {
178
+ "status": {
179
+ "$ref": "#/components/schemas/_HealthStatus"
180
+ },
181
+ "reason": {
182
+ "anyOf": [
183
+ {
184
+ "type": "string"
185
+ },
186
+ {
187
+ "type": "null"
188
+ }
189
+ ],
190
+ "title": "Reason"
191
+ }
192
+ },
193
+ "type": "object",
194
+ "required": [
195
+ "status"
196
+ ],
197
+ "title": "Health",
198
+ "description": "Health status model.\n\nArgs:\n BaseModel (_type_): _description_"
199
+ },
200
+ "HelloWorldResponse": {
201
+ "properties": {
202
+ "message": {
203
+ "type": "string",
204
+ "title": "Message",
205
+ "description": "The hello world message",
206
+ "examples": [
207
+ "Hello, world!"
208
+ ]
209
+ }
210
+ },
211
+ "type": "object",
212
+ "required": [
213
+ "message"
214
+ ],
215
+ "title": "HelloWorldResponse",
216
+ "description": "Response model for hello-world endpoint."
217
+ },
218
+ "ValidationError": {
219
+ "properties": {
220
+ "loc": {
221
+ "items": {
222
+ "anyOf": [
223
+ {
224
+ "type": "string"
225
+ },
226
+ {
227
+ "type": "integer"
228
+ }
229
+ ]
230
+ },
231
+ "type": "array",
232
+ "title": "Location"
233
+ },
234
+ "msg": {
235
+ "type": "string",
236
+ "title": "Message"
237
+ },
238
+ "type": {
239
+ "type": "string",
240
+ "title": "Error Type"
241
+ }
242
+ },
243
+ "type": "object",
244
+ "required": [
245
+ "loc",
246
+ "msg",
247
+ "type"
248
+ ],
249
+ "title": "ValidationError"
250
+ },
251
+ "_HealthStatus": {
252
+ "type": "string",
253
+ "enum": [
254
+ "UP",
255
+ "DOWN"
256
+ ],
257
+ "title": "_HealthStatus",
258
+ "description": "Health status enumeration.\n\nArgs:\n StrEnum (_type_): _description_"
259
+ }
260
+ }
261
+ }
262
+ }