├── .github ├── actions │ └── validation │ │ └── action.yaml └── workflows │ ├── main-validate.yaml │ └── publish.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── .python-version ├── Dockerfile ├── Justfile ├── LICENSE ├── README.md ├── main.py ├── pyproject.toml ├── python_repo_template ├── __init__.py └── func.py ├── ruff.toml └── tests ├── __init__.py └── test_func.py /.github/actions/validation/action.yaml: -------------------------------------------------------------------------------- 1 | name: Validation 2 | description: format, lint, test code 3 | runs: 4 | using: "composite" 5 | steps: 6 | 7 | - name: 📦 Install uv 8 | uses: astral-sh/setup-uv@v6 9 | 10 | - name: 🐍 Set up Python ${{ env.PY_VERSION }} 11 | uses: actions/setup-python@v5 12 | with: 13 | python-version: ${{ env.PY_VERSION }} 14 | 15 | - name: 🚀 Install just 16 | uses: extractions/setup-just@v2 17 | 18 | - name: 🦾 Install dependencies 19 | run: just dev-sync 20 | shell: bash 21 | 22 | - name: 💅 🧪 Validate! 23 | run: just validate 24 | shell: bash 25 | -------------------------------------------------------------------------------- /.github/workflows/main-validate.yaml: -------------------------------------------------------------------------------- 1 | name: Main Lint Test on Main 2 | on: 3 | push: 4 | branches: 5 | - main 6 | - dev 7 | 8 | defaults: 9 | run: 10 | shell: bash 11 | 12 | jobs: 13 | format-lint-test: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | python-version: ["3.10", "3.11", "3.12", "3.13"] 18 | 19 | steps: 20 | 21 | - name: 🛎️ Checkout 22 | uses: actions/checkout@v4 23 | 24 | - name: ✅ validate code 25 | env: 26 | PY_VERSION: ${{ matrix.python-version }} 27 | 28 | uses: ./.github/actions/validation 29 | -------------------------------------------------------------------------------- /.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | # This workflow is triggered on every tag push and can also be triggered manually. 4 | # The tags should follow the semantic versioning format (e.g., v1.0.0). 5 | on: 6 | push: 7 | tags: 8 | - "v[0-9]+.[0-9]+.[0-9]+*" 9 | workflow_dispatch: 10 | 11 | # First, checks out repository, installs dependencies, and runs tests. 12 | # Then, builds the package and publishes it to PyPI. 13 | 14 | jobs: 15 | format-lint-test: 16 | runs-on: ubuntu-latest 17 | strategy: 18 | matrix: 19 | python-version: ["3.10", "3.11", "3.12", "3.13"] 20 | 21 | steps: 22 | - name: 🛎️ Checkout 23 | uses: actions/checkout@v4 24 | 25 | - name: ✅ validate code 26 | env: 27 | PY_VERSION: ${{ matrix.python-version }} 28 | 29 | uses: ./.github/actions/validation 30 | 31 | publish: 32 | runs-on: ubuntu-latest 33 | needs: format-lint-test 34 | # Uncomment to run this job on a custom environment. 35 | # environment: pypi 36 | 37 | steps: 38 | - name: 🛎️ Checkout 39 | uses: actions/checkout@v4 40 | 41 | - name: 📦 Install uv 42 | uses: astral-sh/setup-uv@v6 43 | 44 | - name: 🏗️ Build distribution 45 | run: uv build 46 | 47 | # REMEMBER TO SET THE PYPI_TOKEN SECRET IN YOUR REPO SETTINGS!! 48 | - name: 📩 Set PYPI token as env variable for UV 49 | run: echo "UV_PUBLISH_TOKEN=${{ secrets.PYPI_TOKEN }}" >> $GITHUB_ENV 50 | 51 | - name: 📢 Publish to PyPI 52 | run: uv publish 53 | 54 | - name: 👌 Check upload 55 | run: | 56 | TAG=${GITHUB_REF#refs/tags/} 57 | VERSION=${TAG:1} 58 | echo "Version: $VERSION" 59 | uv run --with python-repo-template==$VERSION --no-project -- python -c "import python_repo_template" 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.env 2 | 3 | # Created by .ignore support plugin (hsz.mobi) 4 | ### Diff template 5 | *.patch 6 | *.diff 7 | 8 | ### Windows template 9 | # Windows thumbnail cache files 10 | Thumbs.db 11 | Thumbs.db:encryptable 12 | ehthumbs.db 13 | ehthumbs_vista.db 14 | 15 | # Dump file 16 | *.stackdump 17 | 18 | # Folder config file 19 | [Dd]esktop.ini 20 | 21 | # Recycle Bin used on file shares 22 | $RECYCLE.BIN/ 23 | 24 | # Windows Installer files 25 | *.cab 26 | *.msi 27 | *.msix 28 | *.msm 29 | *.msp 30 | 31 | # Windows shortcuts 32 | *.lnk 33 | 34 | ### Python template 35 | # Byte-compiled / optimized / DLL files 36 | __pycache__/ 37 | *.py[cod] 38 | *$py.class 39 | 40 | # C extensions 41 | *.so 42 | 43 | # Distribution / packaging 44 | .Python 45 | build/ 46 | develop-eggs/ 47 | dist/ 48 | downloads/ 49 | eggs/ 50 | .eggs/ 51 | lib/ 52 | lib64/ 53 | parts/ 54 | sdist/ 55 | var/ 56 | wheels/ 57 | share/python-wheels/ 58 | *.egg-info/ 59 | .installed.cfg 60 | *.egg 61 | MANIFEST 62 | 63 | # PyInstaller 64 | # Usually these files are written by a python script from a template 65 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 66 | *.manifest 67 | *.spec 68 | 69 | # Installer logs 70 | pip-log.txt 71 | pip-delete-this-directory.txt 72 | 73 | # Unit test / coverage reports 74 | htmlcov/ 75 | .tox/ 76 | .nox/ 77 | .coverage 78 | .coverage.* 79 | .cache 80 | nosetests.xml 81 | coverage.xml 82 | *.cover 83 | *.py,cover 84 | .hypothesis/ 85 | .pytest_cache/ 86 | cover/ 87 | 88 | # Translations 89 | *.mo 90 | *.pot 91 | 92 | # Django stuff: 93 | *.log 94 | local_settings.py 95 | db.sqlite3 96 | db.sqlite3-journal 97 | 98 | # Flask stuff: 99 | instance/ 100 | .webassets-cache 101 | 102 | # Scrapy stuff: 103 | .scrapy 104 | 105 | # Sphinx documentation 106 | docs/_build/ 107 | 108 | # PyBuilder 109 | .pybuilder/ 110 | target/ 111 | 112 | # Jupyter Notebook 113 | .ipynb_checkpoints 114 | 115 | # IPython 116 | profile_default/ 117 | ipython_config.py 118 | 119 | # pyenv 120 | # For a library or package, you might want to ignore these files since the code is 121 | # intended to run in multiple environments; otherwise, check them in: 122 | .python-version 123 | 124 | # pipenv 125 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 126 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 127 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 128 | # install all needed dependencies. 129 | Pipfile.lock 130 | 131 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 132 | __pypackages__/ 133 | 134 | # Celery stuff 135 | celerybeat-schedule 136 | celerybeat.pid 137 | 138 | # SageMath parsed files 139 | *.sage.py 140 | 141 | # Environments 142 | .env 143 | .venv 144 | env/ 145 | venv/ 146 | ENV/ 147 | env.bak/ 148 | venv.bak/ 149 | 150 | # Spyder project settings 151 | .spyderproject 152 | .spyproject 153 | 154 | # Rope project settings 155 | .ropeproject 156 | 157 | # mkdocs documentation 158 | /site 159 | 160 | # mypy 161 | .mypy_cache/ 162 | .dmypy.json 163 | dmypy.json 164 | 165 | # Pyre type checker 166 | .pyre/ 167 | 168 | # pytype static type analyzer 169 | .pytype/ 170 | 171 | # Cython debug symbols 172 | cython_debug/ 173 | 174 | ### JetBrains template 175 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 176 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 177 | 178 | .idea 179 | 180 | # CMake 181 | cmake-build-*/ 182 | 183 | # File-based project format 184 | *.iws 185 | 186 | # IntelliJ 187 | out/ 188 | 189 | # mpeltonen/sbt-idea plugin 190 | .idea_modules/ 191 | 192 | # JIRA plugin 193 | atlassian-ide-plugin.xml 194 | 195 | # Crashlytics plugin (for Android Studio and IntelliJ) 196 | com_crashlytics_export_strings.xml 197 | crashlytics.properties 198 | crashlytics-build.properties 199 | fabric.properties 200 | 201 | ### Vim template 202 | # Swap 203 | [._]*.s[a-v][a-z] 204 | !*.svg # comment out if you don't need vector files 205 | [._]*.sw[a-p] 206 | [._]s[a-rt-v][a-z] 207 | [._]ss[a-gi-z] 208 | [._]sw[a-p] 209 | 210 | # Session 211 | Session.vim 212 | Sessionx.vim 213 | 214 | # Temporary 215 | .netrwhist 216 | *~ 217 | # Auto-generated tag files 218 | tags 219 | # Persistent undo 220 | [._]*.un~ 221 | 222 | ### Redis template 223 | # Ignore redis binary dump (dump.rdb) files 224 | 225 | *.rdb 226 | 227 | ### macOS template 228 | # General 229 | .DS_Store 230 | .AppleDouble 231 | .LSOverride 232 | 233 | # Icon must end with two \r 234 | Icon 235 | 236 | # Thumbnails 237 | ._* 238 | 239 | # Files that might appear in the root of a volume 240 | .DocumentRevisions-V100 241 | .fseventsd 242 | .Spotlight-V100 243 | .TemporaryItems 244 | .Trashes 245 | .VolumeIcon.icns 246 | .com.apple.timemachine.donotpresent 247 | 248 | # Directories potentially created on remote AFP share 249 | .AppleDB 250 | .AppleDesktop 251 | Network Trash Folder 252 | Temporary Items 253 | .apdisk 254 | 255 | ### Linux template 256 | 257 | # temporary files which can be created if a process still has a handle open of a deleted file 258 | .fuse_hidden* 259 | 260 | # KDE directory preferences 261 | .directory 262 | 263 | # Linux trash folder which might appear on any partition or disk 264 | .Trash-* 265 | 266 | # .nfs files are created when an open file is removed but is still being accessed 267 | .nfs* 268 | 269 | ### VirtualEnv template 270 | # Virtualenv 271 | # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ 272 | [Bb]in 273 | [Ii]nclude 274 | [Ll]ib 275 | [Ll]ib64 276 | [Ll]ocal 277 | [Ss]cripts 278 | pyvenv.cfg 279 | pip-selfcheck.json 280 | 281 | # Virtual environments 282 | .venv 283 | .mypy_cache 284 | .ruff_cache 285 | .pytest_cache 286 | .uv_cache 287 | 288 | # This should be removed when the template is actually being used 289 | uv.lock 290 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v5.0.0 4 | hooks: 5 | - id: trailing-whitespace 6 | - id: end-of-file-fixer 7 | - id: check-yaml 8 | - id: check-added-large-files 9 | - id: check-docstring-first 10 | 11 | - repo: https://github.com/astral-sh/ruff-pre-commit 12 | rev: v0.11.11 13 | hooks: 14 | - id: ruff-check 15 | - id: ruff-format 16 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.12 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Example taken from https://github.com/astral-sh/uv-docker-example/blob/main/multistage.Dockerfile 2 | 3 | FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder 4 | 5 | # Bytecode compilation, copy from the cache instead of linking, since it is 6 | # a mounted volume 7 | ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy 8 | 9 | # Disable Python downloads, because we want to use the system interpreter 10 | # across both images. 11 | ENV UV_PYTHON_DOWNLOADS=0 12 | 13 | WORKDIR /app 14 | RUN --mount=type=cache,target=/root/.cache/uv \ 15 | --mount=type=bind,source=uv.lock,target=uv.lock \ 16 | --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ 17 | uv sync --frozen --no-install-project --no-dev --no-editable --all-extras 18 | 19 | ADD python_repo_template /app/python_repo_template 20 | ADD main.py /app/main.py 21 | ADD pyproject.toml /app/pyproject.toml 22 | 23 | # Copy the lock file to make sure the Docker environment has the same 24 | # dependencies as the development environment 25 | ADD uv.lock /app/uv.lock 26 | 27 | RUN --mount=type=cache,target=/root/.cache/uv \ 28 | uv sync --frozen --no-dev --no-editable --all-extras 29 | 30 | 31 | # Then, use a final image without uv 32 | # It is important to use the image that matches the builder, as the path to the 33 | # Python executable must be the same 34 | FROM python:3.12-slim-bookworm 35 | 36 | WORKDIR /app 37 | 38 | # Copy the application from the builder 39 | COPY --from=builder --chown=app:app /app /app 40 | 41 | # Place executables in the environment at the front of the path 42 | ENV PATH="/app/.venv/bin:$PATH" 43 | 44 | CMD ["python", "main.py", "--number", "10"] 45 | -------------------------------------------------------------------------------- /Justfile: -------------------------------------------------------------------------------- 1 | # https://github.com/casey/just 2 | 3 | # Don't show the recipe name when running 4 | set quiet 5 | 6 | # Default recipe, it's run when just is invoked without a recipe 7 | default: 8 | just --list --unsorted 9 | 10 | # Sync dev dependencies 11 | dev-sync: 12 | uv sync --all-extras --cache-dir .uv_cache 13 | 14 | # Sync production dependencies (excludes dev dependencies) 15 | prod-sync: 16 | uv sync --all-extras --no-dev --cache-dir .uv_cache 17 | 18 | # Install pre commit hooks 19 | install-hooks: 20 | uv run pre-commit install 21 | 22 | # Run ruff formatting 23 | format: 24 | uv run ruff format 25 | 26 | # Run ruff linting and mypy type checking 27 | lint: 28 | uv run ruff check --fix 29 | uv run mypy --ignore-missing-imports --install-types --non-interactive --package python_repo_template 30 | 31 | # Run tests using pytest 32 | test: 33 | uv run pytest --verbose --color=yes tests 34 | 35 | # Run all checks: format, lint, and test 36 | validate: format lint test 37 | 38 | # Build docker image 39 | dockerize: 40 | docker build -t python-repo-template . 41 | 42 | # Use it like: just run 10 43 | run number: 44 | uv run main.py --number {{number}} 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Giovanni Giacometti 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python Repository Template 2 | 3 | The ultimate 2025 Python repository template. Simple, fast, customizable, and ready to use. 4 | 5 | --- 6 | I wrote a blog post about this template! Check it out [here](https://giovannigiacometti.github.io/posts/python-template/) 7 | 8 | ## 🎯 Core Features 9 | 10 | ### Development Tools 11 | 12 | - 📦 UV - Ultra-fast Python package manager 13 | - 🚀 Just - Modern command runner with powerful features 14 | - 💅 Ruff - Lightning-fast linter and formatter 15 | - 🔍 Mypy - Static type checker 16 | - 🧪 Pytest - Testing framework with fixtures and plugins 17 | - 🧾 Loguru - Python logging made simple 18 | 19 | ### Infrastructure 20 | 21 | - 🛫 Pre-commit hooks 22 | - 🐳 Docker support with multi-stage builds and distroless images 23 | - 🔄 GitHub Actions CI/CD pipeline 24 | 25 | 26 | ## Usage 27 | 28 | The template is based on [UV](https://docs.astral.sh/) as package manager and [Just](https://github.com/casey/just) as command runner. You need to have both installed in your system to use this template. 29 | 30 | Once you have those, you can just run 31 | 32 | ```bash 33 | just dev-sync 34 | ``` 35 | 36 | to create a virtual environment and install all the dependencies, including the development ones. If instead you want to build a "production-like" environment, you can run 37 | 38 | ```bash 39 | just prod-sync 40 | ``` 41 | 42 | In both cases, all extra dependencies will be installed (notice that the current pyproject.toml file has no extra dependencies). 43 | 44 | You also need to install the pre-commit hooks with: 45 | 46 | ```bash 47 | just install-hooks 48 | ``` 49 | 50 | ### Formatting, Linting and Testing 51 | 52 | You can configure Ruff by editing the `.ruff.toml` file. It is currently set to the default configuration. 53 | 54 | Format your code: 55 | 56 | ```bash 57 | just format 58 | ``` 59 | 60 | Run linters (ruff and mypy): 61 | 62 | ```bash 63 | just lint 64 | ``` 65 | 66 | Run tests: 67 | 68 | ```bash 69 | just test 70 | ``` 71 | 72 | Do all of the above: 73 | 74 | ```bash 75 | just validate 76 | ``` 77 | 78 | ### Executing 79 | 80 | The code is a simple hello world example, which just requires a number as input. It will output the sum of the provided number with a random number. 81 | You can run the code with: 82 | 83 | ```bash 84 | just run 5 85 | ``` 86 | 87 | ### Docker 88 | 89 | The template includes a multi stage Dockerfile, which produces an image with the code and the dependencies installed. You can build the image with: 90 | 91 | ```bash 92 | just dockerize 93 | ``` 94 | 95 | ### Github Actions 96 | 97 | The template includes two Github Actions workflows. 98 | 99 | The first one runs tests and linters on every push on the main and dev branches. You can find the workflow file in `.github/workflows/main-list-test.yml`. 100 | 101 | The second one is triggered on every tag push and can also be triggered manually. It builds the distribution and uploads it to PyPI. You can find the workflow file in `.github/workflows/publish.yaml`. 102 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import sys 3 | from python_repo_template.func import random_sum 4 | import loguru 5 | 6 | if __name__ == "__main__": 7 | logger = loguru.logger 8 | logger.remove() 9 | logger.add( 10 | sys.stdout, 11 | level="INFO", 12 | format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {message}", 13 | ) 14 | 15 | arg_parser = argparse.ArgumentParser() 16 | arg_parser.add_argument("--number", type=int, help="Input number") 17 | args = arg_parser.parse_args() 18 | number = args.number 19 | 20 | logger.info("-" * 50) 21 | logger.info(f"Input number: {number}") 22 | logger.info(f"Output number: {random_sum(number)}") 23 | logger.info("-" * 50) 24 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "python-repo-template" 3 | version = "0.0.1" 4 | description = "A template for Python projects" 5 | readme = "README.md" 6 | license = { text = "MIT" } 7 | authors = [ { name = "Giovanni Giacometti", email = "giovanni.giacometti5@gmail.com" } ] 8 | requires-python = ">=3.12" 9 | dependencies = [ 10 | "loguru>=0.7.3", 11 | ] 12 | 13 | [dependency-groups] 14 | dev = [ 15 | "mypy>=1.15.0", 16 | "pre-commit>=4.1.0", 17 | "pytest>=8.3.4", 18 | "ruff>=0.9.5", 19 | ] 20 | -------------------------------------------------------------------------------- /python_repo_template/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiovanniGiacometti/python-repo-template/0225b227968437dd2fbccaab246ce48b48d26448/python_repo_template/__init__.py -------------------------------------------------------------------------------- /python_repo_template/func.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | 4 | def random_sum(num: int) -> int: 5 | """ 6 | Add a random number between 0 and 100 to the input number. 7 | """ 8 | return num + random.randint(0, 100) 9 | -------------------------------------------------------------------------------- /ruff.toml: -------------------------------------------------------------------------------- 1 | # Exclude a variety of commonly ignored directories. 2 | exclude = [ 3 | ".bzr", 4 | ".direnv", 5 | ".eggs", 6 | ".git", 7 | ".git-rewrite", 8 | ".hg", 9 | ".ipynb_checkpoints", 10 | ".mypy_cache", 11 | ".nox", 12 | ".pants.d", 13 | ".pyenv", 14 | ".pytest_cache", 15 | ".pytype", 16 | ".ruff_cache", 17 | ".svn", 18 | ".tox", 19 | ".venv", 20 | ".vscode", 21 | "__pypackages__", 22 | "_build", 23 | "buck-out", 24 | "build", 25 | "dist", 26 | "node_modules", 27 | "site-packages", 28 | "venv", 29 | ] 30 | 31 | # Same as Black. 32 | line-length = 88 33 | indent-width = 4 34 | 35 | # Assume Python 3.9 36 | target-version = "py39" 37 | 38 | [lint] 39 | # Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. 40 | # Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or 41 | # McCabe complexity (`C901`) by default. 42 | select = ["E4", "E7", "E9", "F"] 43 | ignore = [] 44 | 45 | # Allow fix for all enabled rules (when `--fix`) is provided. 46 | fixable = ["ALL"] 47 | unfixable = [] 48 | 49 | # Allow unused variables when underscore-prefixed. 50 | dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" 51 | 52 | [format] 53 | # Like Black, use double quotes for strings. 54 | quote-style = "double" 55 | 56 | # Like Black, indent with spaces, rather than tabs. 57 | indent-style = "space" 58 | 59 | # Like Black, respect magic trailing commas. 60 | skip-magic-trailing-comma = false 61 | 62 | # Like Black, automatically detect the appropriate line ending. 63 | line-ending = "auto" 64 | 65 | # Enable auto-formatting of code examples in docstrings. Markdown, 66 | # reStructuredText code/literal blocks and doctests are all supported. 67 | # 68 | # This is currently disabled by default, but it is planned for this 69 | # to be opt-out in the future. 70 | docstring-code-format = false 71 | 72 | # Set the line length limit used when formatting code snippets in 73 | # docstrings. 74 | # 75 | # This only has an effect when the `docstring-code-format` setting is 76 | # enabled. 77 | docstring-code-line-length = "dynamic" -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiovanniGiacometti/python-repo-template/0225b227968437dd2fbccaab246ce48b48d26448/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_func.py: -------------------------------------------------------------------------------- 1 | from python_repo_template.func import random_sum 2 | 3 | 4 | def test_random_sum(): 5 | assert random_sum(1) < 101 6 | assert random_sum(100) < 200 7 | --------------------------------------------------------------------------------