Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 19 additions & 81 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,86 +1,24 @@
# template-python
[![Coverage Status](https://coveralls.io/repos/github/TUM-Aries-Lab/template-python/badge.svg?branch=main)](https://coveralls.io/github/TUM-Aries-Lab/template-python?branch=main)
![Docker Image CI](https://github.com/TUM-Aries-Lab/template-python/actions/workflows/ci.yml/badge.svg)
# Template-Python

Simple README.md for a Python project template.
Do ***NOT*** clone this repository. Please use it as a template instead—this README is meant to help you get started quickly.

Do ***NOT*** clone this repository. Please use it as a template instead. This readme is just here to serve as a template for you to get started faster.

## Install
To install the library run:
```bash
uv pip install change-me==latest
```
OR
```bash
uv add git+https://github.com/TUM-Aries-Lab/change-me.git@<specific-tag> # need credentials
```

## Development
0. Install [uv](https://docs.astral.sh/uv/getting-started/installation/) from Astral.
1. `git clone git@github.com:TUM-Aries-Lab/change-me.git`
2. `make init` to create the virtual environment and install dependencies
3. `make format` to format the code and check for errors
4. `make test` to run the test suite
5. `make clean` to delete the temporary files and directories


## Publishing
It's super easy to publish your own packages on PyPI. To build and publish this package run:

```bash
uv build
uv publish # make sure your version in pyproject.toml is updated
```
The package can then be found at: https://pypi.org/project/change-me

## Module Usage
```python
"""Basic docstring for my module."""

from loguru import logger

from change_me import definitions

def main() -> None:
"""Run a simple demonstration."""
logger.info("Hello World!")

if __name__ == "__main__":
main()
The file cookiecutter.json has the following contents:
```

## Program Usage
```bash
uv run python -m change_me
{
"repo_name": "temp-python",
"module_name": "new-repo",
"package_name": "new_repo",
"org_name": "TUM-Aries-Lab",
"description": "Basic description for the repo.",
"author_name": "Tony Smoragiewicz",
"author_email": "tony.smoragiewicz@tum.de",
"python_version": "3.12",
"version": "0.0.1"
}
```

## Structure
The following tree shows the important permanent files.
<!-- TREE-START -->
```
├── src
│ └── change_me
│ ├── __init__.py
│ ├── __main__.py
│ ├── definitions.py
│ └── utils.py
├── tests
│ ├── __init__.py
│ ├── conftest.py
│ ├── main_test.py
│ └── utils_test.py
├── .dockerignore
├── .gitignore
├── .pre-commit-config.yaml
├── .python-version
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── pyproject.toml
├── repo_tree.py
└── uv.lock
```
<!-- TREE-END -->
## Steps
1. Make the necessary names changes in `cookiecutter.json` and then run:
2. ` cookiecutter . # This will create a new repo with the correct names in place.`
3. You can then delete everything but the code in your newly generated folder.
4. Commit your new changes.
11 changes: 11 additions & 0 deletions cookiecutter.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"repo_name": "temp-python",
"module_name": "new-repo",
"package_name": "new_repo",
"org_name": "TUM-Aries-Lab",
"description": "Basic description for the repo.",
"author_name": "Tony Smoragiewicz",
"author_email": "tony.smoragiewicz@tum.de",
"python_version": "3.12",
"version": "0.0.1"
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% raw %}
name: CI

on:
Expand Down Expand Up @@ -119,3 +120,4 @@ jobs:
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ./coverage.xml
{% endraw %}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% raw %}
name: Docker Build & Publish

on:
Expand All @@ -17,8 +18,7 @@ permissions:

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }} # may include uppercase (we'll normalize)
# Flip this to "true" if you want multi-arch on all branches
IMAGE_NAME: ${{ github.repository }}
MULTIARCH_ON_BRANCHES: "false"

concurrency:
Expand All @@ -45,7 +45,6 @@ jobs:
- name: Set up Buildx
uses: docker/setup-buildx-action@v3

# Only set up QEMU when we actually need arm64 (main or tag builds)
- name: Set up QEMU (for arm64)
if: env.IS_MAIN == 'true' || env.IS_TAG == 'true' || env.MULTIARCH_ON_BRANCHES == 'true'
uses: docker/setup-qemu-action@v3
Expand All @@ -69,23 +68,21 @@ jobs:
echo "latest_tag=latest" >> "$GITHUB_OUTPUT"
fi

# Fast path for branches: single-arch build, cache, don't push
- name: Build (branch) — fast single-arch, no push
if: env.IS_MAIN != 'true' && env.IS_TAG != 'true' && env.MULTIARCH_ON_BRANCHES != 'true'
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: false
load: true # so we can run the smoke test
load: true
platforms: linux/amd64
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: false
tags: |
${{ env.REGISTRY }}/${{ steps.repo.outputs.image_name_lc }}:${{ steps.meta.outputs.sha_tag }}

# Publish path for main/tags: multi-arch build + push (with cache)
- name: Build & push (multi-arch)
if: env.IS_MAIN == 'true' || env.IS_TAG == 'true' || env.MULTIARCH_ON_BRANCHES == 'true'
uses: docker/build-push-action@v6
Expand All @@ -99,21 +96,33 @@ jobs:
provenance: false
tags: |
${{ env.REGISTRY }}/${{ steps.repo.outputs.image_name_lc }}:${{ steps.meta.outputs.sha_tag }}
${{ steps.meta.outputs.version_tag && format('{0}/{1}:{2}', env.REGISTRY, steps.repo.outputs.image_name_lc, steps.meta.outputs.version_tag) || '' }}
${{ steps.meta.outputs.latest_tag && format('{0}/{1}:{2}', env.REGISTRY, steps.repo.outputs.image_name_lc, steps.meta.outputs.latest_tag) || '' }}
{% endraw %}
{% raw %}${{ steps.meta.outputs.version_tag }}{% endraw %}{{ "" if not cookiecutter.module_name else "" }}
{% raw %}
{% endraw %}
{% raw %}${{ steps.meta.outputs.latest_tag }}{% endraw %}{{ "" if not cookiecutter.module_name else "" }}
{% raw %}

# Smoke test: use the local image for branch builds, or pull the pushed one for main/tags
- name: Smoke test (branch image)
if: env.IS_MAIN != 'true' && env.IS_TAG != 'true' && env.MULTIARCH_ON_BRANCHES != 'true'
run: |
IMAGE="${{ env.REGISTRY }}/${{ steps.repo.outputs.image_name_lc }}:${{ steps.meta.outputs.sha_tag }}"
echo "Smoke testing local image ${IMAGE}"
docker run --rm "$IMAGE" python -c "import change_me, sys; print('✅ import ok:', getattr(change_me,'__version__','?'), 'on', sys.version)"
{% endraw %}
python - << 'EOF'
import {{ cookiecutter.module_name }}, sys
print("✅ import ok:", getattr({{ cookiecutter.module_name }}, "__version__", "?"), "on", sys.version)
EOF
{% raw %}

- name: Smoke test (pushed image)
if: env.IS_MAIN == 'true' || env.IS_TAG == 'true' || env.MULTIARCH_ON_BRANCHES == 'true'
run: |
IMAGE="${{ env.REGISTRY }}/${{ steps.repo.outputs.image_name_lc }}:${{ steps.meta.outputs.sha_tag }}"
echo "Smoke testing pushed image ${IMAGE}"
docker pull "$IMAGE"
docker run --rm "$IMAGE" python -c "import change_me, sys; print('✅ import ok:', getattr(change_me,'__version__','?'), 'on', sys.version)"
{% endraw %}
python - << 'EOF'
import {{ cookiecutter.module_name }}, sys
print("✅ import ok:", getattr({{ cookiecutter.module_name }}, "__version__", "?"), "on", sys.version)
EOF
{% raw %}
{% endraw %}
172 changes: 172 additions & 0 deletions {{ cookiecutter.repo_name }}/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
../.coverage
.coveragerc
.coverage
coverage.xml
.cache
nosetests.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea
.idea?
.DS_Store
.DS_Store?

# pixi environments
.pixi
*.egg-info

/logs/log_*
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion Dockerfile → {{ cookiecutter.repo_name }}/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

# Select the package and version at build time
ARG PKG=change_me
ARG PKG={{ cookiecutter.module_name }}
ARG VER=latest
ENV PKG=${PKG} VER=${VER}

Expand Down
File renamed without changes.
Loading