Skip to content

Commit 9fbc9bc

Browse files
committed
Add initial version of Python training project
Signed-off-by: Thomas Keller <[email protected]>
1 parent 974be22 commit 9fbc9bc

File tree

18 files changed

+1303
-0
lines changed

18 files changed

+1303
-0
lines changed

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
__pycache__
2+
.coverage
3+
.mypy_cache
4+
.pytest_cache
5+
.venv
6+
*.egg-info
7+
_build
8+
build
9+
dist
10+
coverage.xml
11+
report.xml
12+
version.py

README.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,94 @@
11
# Python Training Project by [devminds GmbH](https://devminds.ch)
2+
3+
This Python project is used for DevOps CI/CD trainings.
4+
5+
The project contains a Python package providing a CLI to calculate the sum of two numbers:
6+
7+
```bash
8+
Usage: python_training_project [OPTIONS] COMMAND [ARGS]...
9+
10+
Options:
11+
--version Show the version and exit.
12+
--help Show this message and exit.
13+
14+
Commands:
15+
sum
16+
```
17+
18+
19+
## Toolchain
20+
21+
The Python package is based on the following toolchain:
22+
23+
* [uv](https://docs.astral.sh/uv/) for dependencies, virtual environment, package build and deployment
24+
* [Sphinx](https://www.sphinx-doc.org/en/master/) for documentation
25+
* [Flake8](https://flake8.pycqa.org/en/latest/) for style guide enforcement
26+
* [mypy](https://mypy-lang.org/) for static type checking
27+
* [Pylint](https://www.pylint.org/) for static code analysis
28+
* [Ruff](https://docs.astral.sh/ruff/) for linting and code formatting
29+
* [pytest](https://docs.pytest.org/en/stable/) for test creation and execution
30+
31+
32+
## Directory structure
33+
34+
```
35+
├── build Reserved folder for build artifacts
36+
├── dist Reserved folder for build artifacts
37+
├── docs Sphinx documentation
38+
├── src Python package source code
39+
├── tests Python tests
40+
└── tools Scripts
41+
42+
```
43+
44+
## Build, test and deploy instructions
45+
46+
All steps required to build, test or deploy the Python package are wrapped in separate shell scripts.
47+
48+
Check the content of the corresponding scripts for details.
49+
50+
### Build documentation
51+
52+
Build the Sphinx documentation:
53+
54+
```bash
55+
./tools/build-docs.sh
56+
```
57+
58+
### Build Python package
59+
60+
Build the Python package:
61+
62+
```bash
63+
./tools/build-package.sh
64+
```
65+
66+
### Run Python linters
67+
68+
Run static code analysis:
69+
70+
```bash
71+
./tools/lint-package.sh
72+
```
73+
74+
### Run Python tests
75+
76+
Run Python tests:
77+
78+
```bash
79+
./tools/test-package.sh
80+
```
81+
82+
### Deploy Python package
83+
84+
Make sure the set the following environment variables before calling the deployment script:
85+
86+
* `UV_PUBLISH_URL`
87+
* `UV_PUBLISH_USERNAME`
88+
* `UV_PUBLISH_PASSWORD`
89+
90+
Deploy the Python package:
91+
92+
```bash
93+
./tools/deploy-package.sh
94+
```

docs/Makefile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Minimal makefile for Sphinx documentation
2+
#
3+
4+
# You can set these variables from the command line, and also
5+
# from the environment for the first two.
6+
SPHINXOPTS ?=
7+
SPHINXBUILD ?= sphinx-build
8+
SPHINXAPIDOC ?= sphinx-apidoc
9+
SOURCEDIR = .
10+
BUILDDIR = ../build
11+
PACKAGEDIR = ../src
12+
13+
# Put it first so that "make" without argument is like "make help".
14+
help:
15+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
16+
17+
# Generate API documentation
18+
apidoc:
19+
@$(SPHINXAPIDOC) -f -T -o "$(SOURCEDIR)" "$(PACKAGEDIR)"
20+
21+
# Generate API and HTML documentation
22+
doc: apidoc
23+
@$(SPHINXBUILD) -M html
24+
25+
.PHONY: help Makefile
26+
27+
# Catch-all target: route all unknown targets to Sphinx using the new
28+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
29+
%: Makefile
30+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

docs/conf.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Configuration file for the Sphinx documentation builder.
2+
#
3+
# For the full list of built-in configuration values, see the documentation:
4+
# https://www.sphinx-doc.org/en/master/usage/configuration.html
5+
6+
# -- Project information -----------------------------------------------------
7+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
8+
9+
project = 'Python Training Project by devminds GmbH'
10+
author = 'Andreas, Thomas'
11+
copyright = '2024, Andreas, Thomas'
12+
13+
# -- General configuration ---------------------------------------------------
14+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
15+
16+
extensions = [
17+
'myst_parser',
18+
'sphinx.ext.autodoc',
19+
'sphinx.ext.autosectionlabel',
20+
'sphinx.ext.napoleon',
21+
'sphinx_rtd_theme'
22+
]
23+
24+
templates_path = ['_templates']
25+
exclude_patterns = []
26+
27+
# -- Options for HTML output -------------------------------------------------
28+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
29+
30+
html_theme = 'sphinx_rtd_theme'
31+
html_static_path = ['_static']

docs/index.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Python Training Project Documentation
2+
=====================================
3+
4+
.. toctree::
5+
:maxdepth: 2
6+
:caption: Contents:
7+
8+
usage.md
9+
python_training_project.rst

docs/python_training_project.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
python\_training\_project package
2+
=================================
3+
4+
Submodules
5+
----------
6+
7+
python\_training\_project.calculate module
8+
------------------------------------------
9+
10+
.. automodule:: python_training_project.calculate
11+
:members:
12+
:undoc-members:
13+
:show-inheritance:
14+
15+
python\_training\_project.version module
16+
----------------------------------------
17+
18+
.. automodule:: python_training_project.version
19+
:members:
20+
:undoc-members:
21+
:show-inheritance:
22+
23+
Module contents
24+
---------------
25+
26+
.. automodule:: python_training_project
27+
:members:
28+
:undoc-members:
29+
:show-inheritance:

docs/usage.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# How to use the command line interface
2+
3+
Check the automatic help page for further information:
4+
5+
```bash
6+
python_training_project --help
7+
```

pyproject.toml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
[build-system]
2+
requires = [
3+
"setuptools",
4+
"setuptools_scm[toml]",
5+
"wheel"
6+
]
7+
build-backend = "setuptools.build_meta"
8+
9+
[project]
10+
name = "python_training_project"
11+
authors = [
12+
{name = "Andreas", email = "[email protected]"},
13+
{name = "Thomas", email = "[email protected]"},
14+
]
15+
description = "Python Training Project by devminds GmbH"
16+
readme = "README.md"
17+
requires-python = ">=3.10"
18+
classifiers = [
19+
"Programming Language :: Python :: 3",
20+
"License :: OSI Approved :: MIT License",
21+
"Operating System :: OS Independent",
22+
]
23+
dependencies = [
24+
"click",
25+
"flake8-gl-codeclimate>=0.2.1",
26+
]
27+
dynamic = ["version"]
28+
29+
[project.urls]
30+
"Homepage" = "https://github.com/devminds-ch/project-python"
31+
"Bug Tracker" = "https://github.com/devminds-ch/project-python/issues"
32+
33+
[project.scripts]
34+
python_training_project = "python_training_project.__main__:cli"
35+
36+
[tool.uv]
37+
dev-dependencies = [
38+
"coverage",
39+
"flake8",
40+
"mypy",
41+
"myst-parser",
42+
"pylint",
43+
"pytest",
44+
"pytest-cov",
45+
"pytest-mock",
46+
"ruff",
47+
"sphinx",
48+
"sphinx-rtd-theme",
49+
]
50+
51+
[tool.setuptools_scm]
52+
write_to = "src/python_training_project/version.py"
53+
54+
[tool.pytest.ini_options]
55+
minversion = "6.0"
56+
addopts = "--cov --cov-report term --cov-report xml --junitxml=build/test-report.xml"
57+
testpaths = [
58+
"tests",
59+
]
60+
61+
[tool.coverage.run]
62+
branch = true
63+
omit = [
64+
"*/__init__.py",
65+
"*/__main__.py",
66+
"*/version.py",
67+
"tests/*"
68+
]
69+
70+
[tool.coverage.xml]
71+
output = "build/test-coverage.xml"
72+
73+
source_pkgs = ["python_training_project"]
74+
75+
[tool.ruff]
76+
include = [
77+
"pyproject.toml",
78+
"src/**/*.py",
79+
"tests/**/*.py"
80+
]
81+
output-format = "pylint"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""
2+
Python Training Project by devminds GmbH.
3+
"""
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
The main entry point contains the command line interface.
3+
"""
4+
5+
import logging
6+
import sys
7+
8+
import click
9+
10+
from python_training_project.calculate import sum
11+
12+
log = logging.getLogger(__name__)
13+
14+
15+
@click.group()
16+
@click.version_option()
17+
def cli():
18+
"""Python Training Project by devminds GmbH."""
19+
logging.basicConfig(
20+
stream=sys.stdout,
21+
level=logging.INFO,
22+
format="%(asctime)s %(name)-16s %(levelname)-8s %(message)s",
23+
)
24+
25+
26+
@cli.command(name="sum")
27+
@click.argument("a", type=float)
28+
@click.argument("b", type=float)
29+
def cli_sum(a: float, b: float):
30+
"""Show the sum of two numbers on the console."""
31+
log.info("Sum of %f and %f is %f", a, b, sum(a, b))
32+
33+
34+
if __name__ == "__main__":
35+
cli()

0 commit comments

Comments
 (0)