diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ce78d16 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: "Continuous Integration" + +on: + pull_request: + +jobs: + test: + runs-on: "ubuntu-latest" + strategy: + matrix: + python-version: ["3.7", "3.8", "3.9", "3.10"] + steps: + - uses: actions/checkout@v2 + + - name: "Set up Python" + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: "Set up PDM" + run: pip install --user pdm + + - name: "Install Dependencies" + run: make install + + - name: "Test Cookiecutter" + run: make test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..da2ed12 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,26 @@ +name: "Create Release" + +on: + push: + tags: + - 'v*' + +jobs: + build: + name: "Create Release" + runs-on: ubuntu-latest + steps: + - name: "Checkout" + uses: actions/checkout@v2 + + - name: "Create Release" + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + body: Auto-generate release notes + draft: true + prerelease: false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cf89c48 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.idea/ +.mypy_cache/ +.pdm.toml +.pytest_cache/ +__pypackages__/ +**/__pycache__/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4f95cd3 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +install: + pdm install + pdm install --group dev + +test: + pdm run pytest -vv tests + +rm: + rm -rf .mypy_cache/ || true + rm -rf .pytest_cache/ || true + rm -rf __pypackages__/ || true + rm -rf tests/__pycache__/ || true diff --git a/README.md b/README.md new file mode 100644 index 0000000..24d7de5 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# cookiecutter-docker-python-pdm + +![CI Status](https://github.com/mnako/cookiecutter-docker-python-pdm/workflows/ci/badge.svg) + +A template for a Python project with a disposable, Docker-contained development +environment. + +This cookiecutter gives you a Python 3.10 development environment with nice +defaults: + +* Python 3.10 with PDM package manager +* Pytest tests with a required coverage; +* Mypy tests +* Black formatter +* Dev Docker image +* Production Docker image +* CI/CD using Github actions + +and depends on Docker and Makefile only. + +## Quickstart + +You can generate a new project by: + + pip install cookiecutter + cookiecutter gh:mnako/cookiecutter-docker-python-pdm diff --git a/cookiecutter.json b/cookiecutter.json new file mode 100644 index 0000000..84a77bf --- /dev/null +++ b/cookiecutter.json @@ -0,0 +1,4 @@ +{ + "github_username": "mnako", + "project_name": "projectname" +} diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py new file mode 100644 index 0000000..1974559 --- /dev/null +++ b/hooks/post_gen_project.py @@ -0,0 +1,8 @@ +import os + + +os.system("make build-dev") +os.system("make install-dev-deps") +os.system("make format") +os.system("make test") +os.system("cat README.md") diff --git a/pdm.lock b/pdm.lock new file mode 100644 index 0000000..4e3c7c1 --- /dev/null +++ b/pdm.lock @@ -0,0 +1,438 @@ +[[package]] +name = "arrow" +version = "1.2.1" +requires_python = ">=3.6" +summary = "Better dates & times for Python" +dependencies = [ + "python-dateutil>=2.7.0", + "typing-extensions; python_version < \"3.8\"", +] + +[[package]] +name = "atomicwrites" +version = "1.4.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +summary = "Atomic file writes." + +[[package]] +name = "attrs" +version = "21.4.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +summary = "Classes Without Boilerplate" + +[[package]] +name = "binaryornot" +version = "0.4.4" +summary = "Ultra-lightweight pure Python package to check if a file is binary or text." +dependencies = [ + "chardet>=3.0.2", +] + +[[package]] +name = "certifi" +version = "2021.10.8" +summary = "Python package for providing Mozilla's CA Bundle." + +[[package]] +name = "chardet" +version = "4.0.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +summary = "Universal encoding detector for Python 2 and 3" + +[[package]] +name = "charset-normalizer" +version = "2.0.10" +requires_python = ">=3.5.0" +summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." + +[[package]] +name = "click" +version = "8.0.3" +requires_python = ">=3.6" +summary = "Composable command line interface toolkit" +dependencies = [ + "colorama; platform_system == \"Windows\"", + "importlib-metadata; python_version < \"3.8\"", +] + +[[package]] +name = "colorama" +version = "0.4.4" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +summary = "Cross-platform colored terminal text." + +[[package]] +name = "cookiecutter" +version = "1.7.3" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +summary = "A command-line utility that creates projects from project templates, e.g. creating a Python package project from a Python package project template." +dependencies = [ + "Jinja2<4.0.0,>=2.7", + "binaryornot>=0.4.4", + "click>=7.0", + "jinja2-time>=0.2.0", + "poyo>=0.5.0", + "python-slugify>=4.0.0", + "requests>=2.23.0", + "six>=1.10", +] + +[[package]] +name = "idna" +version = "3.3" +requires_python = ">=3.5" +summary = "Internationalized Domain Names in Applications (IDNA)" + +[[package]] +name = "importlib-metadata" +version = "4.10.0" +requires_python = ">=3.7" +summary = "Read metadata from Python packages" +dependencies = [ + "typing-extensions>=3.6.4; python_version < \"3.8\"", + "zipp>=0.5", +] + +[[package]] +name = "iniconfig" +version = "1.1.1" +summary = "iniconfig: brain-dead simple config-ini parsing" + +[[package]] +name = "Jinja2" +version = "3.0.3" +requires_python = ">=3.6" +summary = "A very fast and expressive template engine." +dependencies = [ + "MarkupSafe>=2.0", +] + +[[package]] +name = "jinja2-time" +version = "0.2.0" +summary = "Jinja2 Extension for Dates and Times" +dependencies = [ + "arrow", + "jinja2", +] + +[[package]] +name = "MarkupSafe" +version = "2.0.1" +requires_python = ">=3.6" +summary = "Safely add untrusted strings to HTML/XML markup." + +[[package]] +name = "packaging" +version = "21.3" +requires_python = ">=3.6" +summary = "Core utilities for Python packages" +dependencies = [ + "pyparsing!=3.0.5,>=2.0.2", +] + +[[package]] +name = "pluggy" +version = "1.0.0" +requires_python = ">=3.6" +summary = "plugin and hook calling mechanisms for python" +dependencies = [ + "importlib-metadata>=0.12; python_version < \"3.8\"", +] + +[[package]] +name = "poyo" +version = "0.5.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +summary = "A lightweight YAML Parser for Python. 🐓" + +[[package]] +name = "py" +version = "1.11.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +summary = "library with cross-python path, ini-parsing, io, code, log facilities" + +[[package]] +name = "pyparsing" +version = "3.0.6" +requires_python = ">=3.6" +summary = "Python parsing module" + +[[package]] +name = "pytest" +version = "6.2.5" +requires_python = ">=3.6" +summary = "pytest: simple powerful testing with Python" +dependencies = [ + "atomicwrites>=1.0; sys_platform == \"win32\"", + "attrs>=19.2.0", + "colorama; sys_platform == \"win32\"", + "importlib-metadata>=0.12; python_version < \"3.8\"", + "iniconfig", + "packaging", + "pluggy<2.0,>=0.12", + "py>=1.8.2", + "toml", +] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +summary = "Extensions to the standard Python datetime module" +dependencies = [ + "six>=1.5", +] + +[[package]] +name = "python-slugify" +version = "5.0.2" +requires_python = ">=3.6" +summary = "A Python Slugify application that handles Unicode" +dependencies = [ + "text-unidecode>=1.3", +] + +[[package]] +name = "requests" +version = "2.27.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +summary = "Python HTTP for Humans." +dependencies = [ + "certifi>=2017.4.17", + "charset-normalizer~=2.0.0; python_version >= \"3\"", + "idna<4,>=2.5; python_version >= \"3\"", + "urllib3<1.27,>=1.21.1", +] + +[[package]] +name = "six" +version = "1.16.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +summary = "Python 2 and 3 compatibility utilities" + +[[package]] +name = "text-unidecode" +version = "1.3" +summary = "The most basic Text::Unidecode port" + +[[package]] +name = "toml" +version = "0.10.2" +requires_python = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +summary = "Python Library for Tom's Obvious, Minimal Language" + +[[package]] +name = "typing-extensions" +version = "4.0.1" +requires_python = ">=3.6" +summary = "Backported and Experimental Type Hints for Python 3.6+" + +[[package]] +name = "urllib3" +version = "1.26.7" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +summary = "HTTP library with thread-safe connection pooling, file post, and more." + +[[package]] +name = "zipp" +version = "3.7.0" +requires_python = ">=3.7" +summary = "Backport of pathlib-compatible object wrapper for zip files" + +[metadata] +lock_version = "3.1" +content_hash = "sha256:7728363864d87d3643926363265406b1158cb3df81aa8d19deb343e4edb5b24d" + +[metadata.files] +"arrow 1.2.1" = [ + {file = "arrow-1.2.1-py3-none-any.whl", hash = "sha256:6b2914ef3997d1fd7b37a71ce9dd61a6e329d09e1c7b44f4d3099ca4a5c0933e"}, + {file = "arrow-1.2.1.tar.gz", hash = "sha256:c2dde3c382d9f7e6922ce636bf0b318a7a853df40ecb383b29192e6c5cc82840"}, +] +"atomicwrites 1.4.0" = [ + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, +] +"attrs 21.4.0" = [ + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, +] +"binaryornot 0.4.4" = [ + {file = "binaryornot-0.4.4-py2.py3-none-any.whl", hash = "sha256:b8b71173c917bddcd2c16070412e369c3ed7f0528926f70cac18a6c97fd563e4"}, + {file = "binaryornot-0.4.4.tar.gz", hash = "sha256:359501dfc9d40632edc9fac890e19542db1a287bbcfa58175b66658392018061"}, +] +"certifi 2021.10.8" = [ + {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, + {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, +] +"chardet 4.0.0" = [ + {file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"}, + {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"}, +] +"charset-normalizer 2.0.10" = [ + {file = "charset_normalizer-2.0.10-py3-none-any.whl", hash = "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455"}, + {file = "charset-normalizer-2.0.10.tar.gz", hash = "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd"}, +] +"click 8.0.3" = [ + {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, + {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, +] +"colorama 0.4.4" = [ + {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, + {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, +] +"cookiecutter 1.7.3" = [ + {file = "cookiecutter-1.7.3-py2.py3-none-any.whl", hash = "sha256:f8671531fa96ab14339d0c59b4f662a4f12a2ecacd94a0f70a3500843da588e2"}, + {file = "cookiecutter-1.7.3.tar.gz", hash = "sha256:6b9a4d72882e243be077a7397d0f1f76fe66cf3df91f3115dbb5330e214fa457"}, +] +"idna 3.3" = [ + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, +] +"importlib-metadata 4.10.0" = [ + {file = "importlib_metadata-4.10.0-py3-none-any.whl", hash = "sha256:b7cf7d3fef75f1e4c80a96ca660efbd51473d7e8f39b5ab9210febc7809012a4"}, + {file = "importlib_metadata-4.10.0.tar.gz", hash = "sha256:92a8b58ce734b2a4494878e0ecf7d79ccd7a128b5fc6014c401e0b61f006f0f6"}, +] +"iniconfig 1.1.1" = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] +"jinja2 3.0.3" = [ + {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, + {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"}, +] +"jinja2-time 0.2.0" = [ + {file = "jinja2_time-0.2.0-py2.py3-none-any.whl", hash = "sha256:d3eab6605e3ec8b7a0863df09cc1d23714908fa61aa6986a845c20ba488b4efa"}, + {file = "jinja2-time-0.2.0.tar.gz", hash = "sha256:d14eaa4d315e7688daa4969f616f226614350c48730bfa1692d2caebd8c90d40"}, +] +"markupsafe 2.0.1" = [ + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, + {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, +] +"packaging 21.3" = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] +"pluggy 1.0.0" = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] +"poyo 0.5.0" = [ + {file = "poyo-0.5.0-py2.py3-none-any.whl", hash = "sha256:3e2ca8e33fdc3c411cd101ca395668395dd5dc7ac775b8e809e3def9f9fe041a"}, + {file = "poyo-0.5.0.tar.gz", hash = "sha256:e26956aa780c45f011ca9886f044590e2d8fd8b61db7b1c1cf4e0869f48ed4dd"}, +] +"py 1.11.0" = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] +"pyparsing 3.0.6" = [ + {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"}, + {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"}, +] +"pytest 6.2.5" = [ + {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, + {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, +] +"python-dateutil 2.8.2" = [ + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, +] +"python-slugify 5.0.2" = [ + {file = "python_slugify-5.0.2-py2.py3-none-any.whl", hash = "sha256:6d8c5df75cd4a7c3a2d21e257633de53f52ab0265cd2d1dc62a730e8194a7380"}, + {file = "python-slugify-5.0.2.tar.gz", hash = "sha256:f13383a0b9fcbe649a1892b9c8eb4f8eab1d6d84b84bb7a624317afa98159cab"}, +] +"requests 2.27.0" = [ + {file = "requests-2.27.0-py2.py3-none-any.whl", hash = "sha256:f71a09d7feba4a6b64ffd8e9d9bc60f9bf7d7e19fd0e04362acb1cfc2e3d98df"}, + {file = "requests-2.27.0.tar.gz", hash = "sha256:8e5643905bf20a308e25e4c1dd379117c09000bf8a82ebccc462cfb1b34a16b5"}, +] +"six 1.16.0" = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +"text-unidecode 1.3" = [ + {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, + {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, +] +"toml 0.10.2" = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] +"typing-extensions 4.0.1" = [ + {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, + {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"}, +] +"urllib3 1.26.7" = [ + {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"}, + {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"}, +] +"zipp 3.7.0" = [ + {file = "zipp-3.7.0-py3-none-any.whl", hash = "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"}, + {file = "zipp-3.7.0.tar.gz", hash = "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d"}, +] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..0cae16d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,38 @@ +[project] +name = "" +version = "" +description = "" +authors = [ + {name = "Michal Nakoneczny", email = "michal@nakoneczny.pl"}, +] +dependencies = [ + "cookiecutter==1.7.3", +] +requires-python = ">=3.7" +license = {text = "MIT"} + +[project.urls] +homepage = "" + +[project.optional-dependencies] +dev = [ + "pytest==6.2.5", +] +[tool] +[tool.pdm] +[tool.pdm.dev-dependencies] + +[build-system] +requires = ["pdm-pep517"] +build-backend = "pdm.pep517.api" + +[tool.mypy] +files = "{{ cookiecutter.project_name }}/**/*.py,tests/**/*.py" +exclude = "__pypackages__/" +ignore_missing_imports = true +disallow_untyped_calls = true +disallow_untyped_defs = true +disallow_incomplete_defs = true +warn_redundant_casts = true +warn_unused_ignores = true +warn_unreachable = true diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_cookiecutter.py b/tests/test_cookiecutter.py new file mode 100644 index 0000000..cb02c42 --- /dev/null +++ b/tests/test_cookiecutter.py @@ -0,0 +1,94 @@ +import os +import pytest +import subprocess +import time +import logging + +from cookiecutter import utils +from cookiecutter.main import cookiecutter + + +logging.basicConfig(level=logging.DEBUG) +logger = logging.getLogger("cookiecutter-docker-python-pdm") + +test_project_dir = "/tmp/testproject" + + +@pytest.fixture(scope="session", autouse=True) +def test_project(request): + """ + This fixture provides a test project to test cases. + It cookiecuts a project with the config below, runs the test and removes + the project directory. + """ + + def remove_generated_project(): + if os.path.isdir(test_project_dir): + try: + utils.rmtree(test_project_dir) + except PermissionError: + pass + + request.addfinalizer(remove_generated_project) + + cookiecutter( + ".", + output_dir="/tmp", + no_input=True, + extra_context={ + "github_username": "mnako", + "project_name": "testproject" + }, + ) + + +def test_project_renders_to_dir(caplog): + caplog.set_level(logging.INFO) + + assert os.path.isdir(test_project_dir) + assert "Lock file hash doesn't match pyproject.toml, packages may be outdated" not in caplog.text + + +def test_project_make_ci_succeeds(caplog): + caplog.set_level(logging.INFO) + + make_test_process = subprocess.Popen( + "make ci", + shell=True, + cwd=test_project_dir, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + for line in iter(make_test_process.stdout.readline, b""): + logger.info(line.decode().strip()) + + for line in iter(make_test_process.stderr.readline, b""): + logger.warning(line.decode().strip()) + + make_test_process_return_code = make_test_process.wait() + assert ( + make_test_process_return_code == 0 + ), "make test did not exit with code 0" + + +def test_project_make_build_production_succeeds(caplog): + caplog.set_level(logging.INFO) + + make_test_process = subprocess.Popen( + "make build-production VERSION=0.0.0", + shell=True, + cwd=test_project_dir, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + for line in iter(make_test_process.stdout.readline, b""): + logger.info(line.decode().strip()) + + for line in iter(make_test_process.stderr.readline, b""): + logger.warning(line.decode().strip()) + + make_test_process_return_code = make_test_process.wait() + assert ( + make_test_process_return_code == 0 + ), "make build-production VERSION=0.0.0 did not exit with code 0" + assert "Lock file hash doesn't match pyproject.toml, packages may be outdated" not in caplog.text diff --git a/{{ cookiecutter.project_name }}/.github/workflows/ci.yml b/{{ cookiecutter.project_name }}/.github/workflows/ci.yml new file mode 100644 index 0000000..84239c6 --- /dev/null +++ b/{{ cookiecutter.project_name }}/.github/workflows/ci.yml @@ -0,0 +1,20 @@ +name: "Continuous Integration Workflow" + +on: + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: "Checkout" + uses: actions/checkout@v2.3.4 + + - name: "Build Dev Image" + run: make build-dev + + - name: "Run Tests" + run: make ci + + - name: "Build Production Image" + run: make build-production VERSION=build-${GITHUB_SHA} diff --git a/{{ cookiecutter.project_name }}/.github/workflows/release.yml b/{{ cookiecutter.project_name }}/.github/workflows/release.yml new file mode 100644 index 0000000..c07821d --- /dev/null +++ b/{{ cookiecutter.project_name }}/.github/workflows/release.yml @@ -0,0 +1,40 @@ +name: "Create Release" + +on: + push: + tags: + - 'v*' + +jobs: + build: + name: Create Release + runs-on: ubuntu-latest + steps: + - name: "Checkout" + uses: actions/checkout@v2 + + - name: "Build Dev Image" + run: make build-dev + + - name: "Run Tests" + run: make ci + + - name: "Build Production Image" + run: make build-production VERSION={% raw %}${GITHUB_REF_NAME}{% endraw %} + + - name: "Push Production Image" + run: | + echo "${% raw %}{{ secrets.GITHUB_TOKEN }}{% endraw %}" | docker login ghcr.io -u ${% raw %}{{ github.actor }}{% endraw %} --password-stdin + make push-production VERSION={% raw %}${GITHUB_REF_NAME}{% endraw %} + + - name: "Create Release" + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %} + with: + tag_name: {% raw %}${{ github.ref }}{% endraw %} + release_name: Release {% raw %}${{ github.ref }}{% endraw %} + body: Auto-generate release notes + draft: true + prerelease: false diff --git a/{{ cookiecutter.project_name }}/.github/workflows/run.yml b/{{ cookiecutter.project_name }}/.github/workflows/run.yml new file mode 100644 index 0000000..6394bc0 --- /dev/null +++ b/{{ cookiecutter.project_name }}/.github/workflows/run.yml @@ -0,0 +1,17 @@ +name: "Scheduled Run" + +on: +# schedule: +# - cron: "0 */3 * * *" + + workflow_dispatch: + +jobs: + run: + runs-on: ubuntu-latest + steps: + - name: Run Tasks + run: | + echo "${% raw %}{{ secrets.GITHUB_TOKEN }}{% endraw %}" | docker login ghcr.io -u ${% raw %}{{ github.actor }}{% endraw %} --password-stdin + docker pull ghcr.io/{{ cookiecutter.github_username }}/{{ cookiecutter.project_name }}:latest + docker run ghcr.io/{{ cookiecutter.github_username }}/{{ cookiecutter.project_name }}:latest diff --git a/{{ cookiecutter.project_name }}/.idea/misc.xml b/{{ cookiecutter.project_name }}/.idea/misc.xml new file mode 100644 index 0000000..a0f56f8 --- /dev/null +++ b/{{ cookiecutter.project_name }}/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/{{ cookiecutter.project_name }}/.idea/modules.xml b/{{ cookiecutter.project_name }}/.idea/modules.xml new file mode 100644 index 0000000..a182ef0 --- /dev/null +++ b/{{ cookiecutter.project_name }}/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/{{ cookiecutter.project_name }}/.idea/workspace.xml b/{{ cookiecutter.project_name }}/.idea/workspace.xml new file mode 100644 index 0000000..537fd95 --- /dev/null +++ b/{{ cookiecutter.project_name }}/.idea/workspace.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1641359547876 + + + + + + diff --git a/{{ cookiecutter.project_name }}/.idea/{{ cookiecutter.project_name }}.iml b/{{ cookiecutter.project_name }}/.idea/{{ cookiecutter.project_name }}.iml new file mode 100644 index 0000000..292845c --- /dev/null +++ b/{{ cookiecutter.project_name }}/.idea/{{ cookiecutter.project_name }}.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + diff --git a/{{ cookiecutter.project_name }}/Dockerfile b/{{ cookiecutter.project_name }}/Dockerfile new file mode 100644 index 0000000..f11ce8f --- /dev/null +++ b/{{ cookiecutter.project_name }}/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.10.1-slim-buster + +LABEL org.opencontainers.image.source="https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.project_name }}" + +RUN useradd -m -r user && mkdir /app && chown user /app +USER user + +WORKDIR /app +RUN python -m pip install --upgrade pip==21.3.1 && pip install --user pdm==1.12.2 +ENV PATH="/app/__pypackages__/3.10/bin:/home/user/.local/bin:${PATH}" + +COPY main.py pdm.lock pyproject.toml /app/ +RUN pdm install +RUN pdm install --group dev --dev + +ADD {{ cookiecutter.project_name }} /app/{{ cookiecutter.project_name }} +ADD tests /app/tests + +CMD ["pdm", "run", "python", "main.py"] diff --git a/{{ cookiecutter.project_name }}/Dockerfile.production b/{{ cookiecutter.project_name }}/Dockerfile.production new file mode 100644 index 0000000..5ee6a8c --- /dev/null +++ b/{{ cookiecutter.project_name }}/Dockerfile.production @@ -0,0 +1,16 @@ +FROM python:3.10.1-alpine3.15 + +LABEL org.opencontainers.image.source="https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.project_name }}" + +RUN addgroup -S usergroup && adduser -S user -G usergroup && mkdir /app && chown user /app +USER user + +WORKDIR /app +RUN python -m pip install --upgrade pip==21.3.1 && pip install --user pdm==1.12.2 +ENV PATH="/app/__pypackages__/3.10/bin:/home/user/.local/bin:${PATH}" + +COPY main.py pdm.lock pyproject.toml /app/ +RUN pdm install && rm -f /app/pdm.lock +ADD {{ cookiecutter.project_name }} /app/{{ cookiecutter.project_name }} + +CMD ["pdm", "run", "python", "main.py"] diff --git a/{{ cookiecutter.project_name }}/Makefile b/{{ cookiecutter.project_name }}/Makefile new file mode 100644 index 0000000..f46aa96 --- /dev/null +++ b/{{ cookiecutter.project_name }}/Makefile @@ -0,0 +1,46 @@ +build-dev: + docker build --tag {{ cookiecutter.project_name }}:dev . + +install-dev-deps: + @docker run -it -v "$(PWD):/app" {{ cookiecutter.project_name }}:dev pdm install + @docker run -it -v "$(PWD):/app" {{ cookiecutter.project_name }}:dev pdm install --group dev + +run: + @docker run --rm -v "$(PWD):/app" {{ cookiecutter.project_name }}:dev + +bash: + docker run -it -v "$(PWD):/app" {{ cookiecutter.project_name }}:dev bash + +format: + @docker run -it -v "$(PWD):/app" {{ cookiecutter.project_name }}:dev pdm run black . + +test: + @docker run -t -v "$(PWD):/app" {{ cookiecutter.project_name }}:dev pdm run pytest --cov={{ cookiecutter.project_name }} tests + @docker run -t -v "$(PWD):/app" {{ cookiecutter.project_name }}:dev pdm run mypy + @docker run -t -v "$(PWD):/app" {{ cookiecutter.project_name }}:dev pdm run black --check . + +ci: + docker run --rm --name {{ cookiecutter.project_name }} -t {{ cookiecutter.project_name }}:dev pdm run pytest --cov={{ cookiecutter.project_name }} tests + docker run --rm --name {{ cookiecutter.project_name }} -t {{ cookiecutter.project_name }}:dev pdm run mypy + docker run --rm --name {{ cookiecutter.project_name }} -t {{ cookiecutter.project_name }}:dev pdm run black --check . + +build-production: + @if [ -z ${VERSION} ]; then echo Usage: make build-production VERSION=0.0.0 && exit 1; fi; + docker build --file Dockerfile.production --tag {{ cookiecutter.project_name }}:latest . + docker tag {{ cookiecutter.project_name }}:latest {{ cookiecutter.project_name }}:${VERSION} + +push-production: + @if [ -z ${VERSION} ]; then echo Usage: make push-production VERSION=0.0.0 && exit 1; fi; + docker tag {{ cookiecutter.project_name }}:latest ghcr.io/{{ cookiecutter.github_username }}/{{ cookiecutter.project_name }}:latest + docker tag {{ cookiecutter.project_name }}:latest ghcr.io/{{ cookiecutter.github_username }}/{{ cookiecutter.project_name }}:${VERSION} + docker push ghcr.io/{{ cookiecutter.github_username }}/{{ cookiecutter.project_name }}:latest + docker push ghcr.io/{{ cookiecutter.github_username }}/{{ cookiecutter.project_name }}:${VERSION} + +rm: + docker rm {{ cookiecutter.project_name }} || true + docker rmi --force {{ cookiecutter.project_name }}:dev || true + docker rmi --force {{ cookiecutter.project_name }}:latest || true + rm -rf .mypy_cache/ || true + rm -rf .pytest_cache/ || true + rm -rf __pypackages__/ || true + rm -rf tests/__pycache__/ || true diff --git a/{{ cookiecutter.project_name }}/README.md b/{{ cookiecutter.project_name }}/README.md new file mode 100644 index 0000000..663ff52 --- /dev/null +++ b/{{ cookiecutter.project_name }}/README.md @@ -0,0 +1,38 @@ +{{ cookiecutter.project_name }} +==== + +Welcome to {{ cookiecutter.project_name }} + +## Quickstart guide: + +1. Build dev Docker image: + + make build-dev + +2. Install dev dependencies: + + make install-dev-deps + +3. Run application: + + make run + +4. Run formatter: + + make format + +5. Test: + + make test + +6. Build production image: + + make build-production VERSION=0.0.1 + +7. Push production image: + + make push-production VERSION=0.0.1 + +8. Remove development environment: + + make rm diff --git a/{{ cookiecutter.project_name }}/main.py b/{{ cookiecutter.project_name }}/main.py new file mode 100644 index 0000000..3b28198 --- /dev/null +++ b/{{ cookiecutter.project_name }}/main.py @@ -0,0 +1,5 @@ +from {{ cookiecutter.project_name }}.functions import say_hi + + +if __name__ == "__main__": + print(say_hi("Docker")) diff --git a/{{ cookiecutter.project_name }}/pdm.lock b/{{ cookiecutter.project_name }}/pdm.lock new file mode 100644 index 0000000..4342682 --- /dev/null +++ b/{{ cookiecutter.project_name }}/pdm.lock @@ -0,0 +1,365 @@ +[[package]] +name = "atomicwrites" +version = "1.4.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +summary = "Atomic file writes." + +[[package]] +name = "attrs" +version = "21.2.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +summary = "Classes Without Boilerplate" + +[[package]] +name = "black" +version = "21.12b0" +requires_python = ">=3.6.2" +summary = "The uncompromising code formatter." +dependencies = [ + "click>=7.1.2", + "mypy-extensions>=0.4.3", + "pathspec<1,>=0.9.0", + "platformdirs>=2", + "tomli<2.0.0,>=0.2.6", + "typing-extensions!=3.10.0.1; python_version >= \"3.10\"", + "typing-extensions>=3.10.0.0", +] + +[[package]] +name = "certifi" +version = "2021.10.8" +summary = "Python package for providing Mozilla's CA Bundle." + +[[package]] +name = "charset-normalizer" +version = "2.0.9" +requires_python = ">=3.5.0" +summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." + +[[package]] +name = "click" +version = "8.0.3" +requires_python = ">=3.6" +summary = "Composable command line interface toolkit" +dependencies = [ + "colorama; platform_system == \"Windows\"", +] + +[[package]] +name = "colorama" +version = "0.4.4" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +summary = "Cross-platform colored terminal text." + +[[package]] +name = "coverage" +version = "6.2" +requires_python = ">=3.6" +summary = "Code coverage measurement for Python" + +[[package]] +name = "coverage" +version = "6.2" +extras = ["toml"] +requires_python = ">=3.6" +summary = "Code coverage measurement for Python" +dependencies = [ + "coverage==6.2", + "tomli", +] + +[[package]] +name = "idna" +version = "3.3" +requires_python = ">=3.5" +summary = "Internationalized Domain Names in Applications (IDNA)" + +[[package]] +name = "iniconfig" +version = "1.1.1" +summary = "iniconfig: brain-dead simple config-ini parsing" + +[[package]] +name = "mypy" +version = "0.930" +requires_python = ">=3.6" +summary = "Optional static typing for Python" +dependencies = [ + "mypy-extensions>=0.4.3", + "tomli>=1.1.0", + "typing-extensions>=3.10", +] + +[[package]] +name = "mypy-extensions" +version = "0.4.3" +summary = "Experimental type system extensions for programs checked with the mypy typechecker." + +[[package]] +name = "packaging" +version = "21.3" +requires_python = ">=3.6" +summary = "Core utilities for Python packages" +dependencies = [ + "pyparsing!=3.0.5,>=2.0.2", +] + +[[package]] +name = "pathspec" +version = "0.9.0" +summary = "Utility library for gitignore style pattern matching of file paths." + +[[package]] +name = "platformdirs" +version = "2.4.0" +requires_python = ">=3.6" +summary = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." + +[[package]] +name = "pluggy" +version = "1.0.0" +requires_python = ">=3.6" +summary = "plugin and hook calling mechanisms for python" + +[[package]] +name = "py" +version = "1.11.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +summary = "library with cross-python path, ini-parsing, io, code, log facilities" + +[[package]] +name = "pyparsing" +version = "3.0.6" +requires_python = ">=3.6" +summary = "Python parsing module" + +[[package]] +name = "pytest" +version = "6.2.5" +requires_python = ">=3.6" +summary = "pytest: simple powerful testing with Python" +dependencies = [ + "atomicwrites>=1.0; sys_platform == \"win32\"", + "attrs>=19.2.0", + "colorama; sys_platform == \"win32\"", + "iniconfig", + "packaging", + "pluggy<2.0,>=0.12", + "py>=1.8.2", + "toml", +] + +[[package]] +name = "pytest-cov" +version = "3.0.0" +requires_python = ">=3.6" +summary = "Pytest plugin for measuring coverage." +dependencies = [ + "coverage[toml]>=5.2.1", + "pytest>=4.6", +] + +[[package]] +name = "requests" +version = "2.27.1" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +summary = "Python HTTP for Humans." +dependencies = [ + "certifi>=2017.4.17", + "charset-normalizer~=2.0.0; python_version >= \"3\"", + "idna<4,>=2.5; python_version >= \"3\"", + "urllib3<1.27,>=1.21.1", +] + +[[package]] +name = "toml" +version = "0.10.2" +requires_python = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +summary = "Python Library for Tom's Obvious, Minimal Language" + +[[package]] +name = "tomli" +version = "1.2.3" +requires_python = ">=3.6" +summary = "A lil' TOML parser" + +[[package]] +name = "typing-extensions" +version = "4.0.1" +requires_python = ">=3.6" +summary = "Backported and Experimental Type Hints for Python 3.6+" + +[[package]] +name = "urllib3" +version = "1.26.7" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +summary = "HTTP library with thread-safe connection pooling, file post, and more." + +[metadata] +lock_version = "3.1" +content_hash = "sha256:113d3e5b6b67b32c2f02f8d003356079a5850433103911021c3ca68f54085355" + +[metadata.files] +"atomicwrites 1.4.0" = [ + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, +] +"attrs 21.2.0" = [ + {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, + {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, +] +"black 21.12b0" = [ + {file = "black-21.12b0-py3-none-any.whl", hash = "sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"}, + {file = "black-21.12b0.tar.gz", hash = "sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3"}, +] +"certifi 2021.10.8" = [ + {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, + {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, +] +"charset-normalizer 2.0.9" = [ + {file = "charset_normalizer-2.0.9-py3-none-any.whl", hash = "sha256:1eecaa09422db5be9e29d7fc65664e6c33bd06f9ced7838578ba40d58bdf3721"}, + {file = "charset-normalizer-2.0.9.tar.gz", hash = "sha256:b0b883e8e874edfdece9c28f314e3dd5badf067342e42fb162203335ae61aa2c"}, +] +"click 8.0.3" = [ + {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, + {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, +] +"colorama 0.4.4" = [ + {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, + {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, +] +"coverage 6.2" = [ + {file = "coverage-6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6dbc1536e105adda7a6312c778f15aaabe583b0e9a0b0a324990334fd458c94b"}, + {file = "coverage-6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:174cf9b4bef0db2e8244f82059a5a72bd47e1d40e71c68ab055425172b16b7d0"}, + {file = "coverage-6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92b8c845527eae547a2a6617d336adc56394050c3ed8a6918683646328fbb6da"}, + {file = "coverage-6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c7912d1526299cb04c88288e148c6c87c0df600eca76efd99d84396cfe00ef1d"}, + {file = "coverage-6.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d2033d5db1d58ae2d62f095e1aefb6988af65b4b12cb8987af409587cc0739"}, + {file = "coverage-6.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3feac4084291642165c3a0d9eaebedf19ffa505016c4d3db15bfe235718d4971"}, + {file = "coverage-6.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:276651978c94a8c5672ea60a2656e95a3cce2a3f31e9fb2d5ebd4c215d095840"}, + {file = "coverage-6.2-cp310-cp310-win32.whl", hash = "sha256:f506af4f27def639ba45789fa6fde45f9a217da0be05f8910458e4557eed020c"}, + {file = "coverage-6.2-cp310-cp310-win_amd64.whl", hash = "sha256:3f7c17209eef285c86f819ff04a6d4cbee9b33ef05cbcaae4c0b4e8e06b3ec8f"}, + {file = "coverage-6.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:13362889b2d46e8d9f97c421539c97c963e34031ab0cb89e8ca83a10cc71ac76"}, + {file = "coverage-6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22e60a3ca5acba37d1d4a2ee66e051f5b0e1b9ac950b5b0cf4aa5366eda41d47"}, + {file = "coverage-6.2-cp311-cp311-win_amd64.whl", hash = "sha256:b637c57fdb8be84e91fac60d9325a66a5981f8086c954ea2772efe28425eaf64"}, + {file = "coverage-6.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f467bbb837691ab5a8ca359199d3429a11a01e6dfb3d9dcc676dc035ca93c0a9"}, + {file = "coverage-6.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2641f803ee9f95b1f387f3e8f3bf28d83d9b69a39e9911e5bfee832bea75240d"}, + {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1219d760ccfafc03c0822ae2e06e3b1248a8e6d1a70928966bafc6838d3c9e48"}, + {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9a2b5b52be0a8626fcbffd7e689781bf8c2ac01613e77feda93d96184949a98e"}, + {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8e2c35a4c1f269704e90888e56f794e2d9c0262fb0c1b1c8c4ee44d9b9e77b5d"}, + {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:5d6b09c972ce9200264c35a1d53d43ca55ef61836d9ec60f0d44273a31aa9f17"}, + {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e3db840a4dee542e37e09f30859f1612da90e1c5239a6a2498c473183a50e781"}, + {file = "coverage-6.2-cp36-cp36m-win32.whl", hash = "sha256:4e547122ca2d244f7c090fe3f4b5a5861255ff66b7ab6d98f44a0222aaf8671a"}, + {file = "coverage-6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:01774a2c2c729619760320270e42cd9e797427ecfddd32c2a7b639cdc481f3c0"}, + {file = "coverage-6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb8b8ee99b3fffe4fd86f4c81b35a6bf7e4462cba019997af2fe679365db0c49"}, + {file = "coverage-6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:619346d57c7126ae49ac95b11b0dc8e36c1dd49d148477461bb66c8cf13bb521"}, + {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0a7726f74ff63f41e95ed3a89fef002916c828bb5fcae83b505b49d81a066884"}, + {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cfd9386c1d6f13b37e05a91a8583e802f8059bebfccde61a418c5808dea6bbfa"}, + {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:17e6c11038d4ed6e8af1407d9e89a2904d573be29d51515f14262d7f10ef0a64"}, + {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c254b03032d5a06de049ce8bca8338a5185f07fb76600afff3c161e053d88617"}, + {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dca38a21e4423f3edb821292e97cec7ad38086f84313462098568baedf4331f8"}, + {file = "coverage-6.2-cp37-cp37m-win32.whl", hash = "sha256:600617008aa82032ddeace2535626d1bc212dfff32b43989539deda63b3f36e4"}, + {file = "coverage-6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:bf154ba7ee2fd613eb541c2bc03d3d9ac667080a737449d1a3fb342740eb1a74"}, + {file = "coverage-6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f9afb5b746781fc2abce26193d1c817b7eb0e11459510fba65d2bd77fe161d9e"}, + {file = "coverage-6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edcada2e24ed68f019175c2b2af2a8b481d3d084798b8c20d15d34f5c733fa58"}, + {file = "coverage-6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9c8c4283e17690ff1a7427123ffb428ad6a52ed720d550e299e8291e33184dc"}, + {file = "coverage-6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f614fc9956d76d8a88a88bb41ddc12709caa755666f580af3a688899721efecd"}, + {file = "coverage-6.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9365ed5cce5d0cf2c10afc6add145c5037d3148585b8ae0e77cc1efdd6aa2953"}, + {file = "coverage-6.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8bdfe9ff3a4ea37d17f172ac0dff1e1c383aec17a636b9b35906babc9f0f5475"}, + {file = "coverage-6.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:63c424e6f5b4ab1cf1e23a43b12f542b0ec2e54f99ec9f11b75382152981df57"}, + {file = "coverage-6.2-cp38-cp38-win32.whl", hash = "sha256:49dbff64961bc9bdd2289a2bda6a3a5a331964ba5497f694e2cbd540d656dc1c"}, + {file = "coverage-6.2-cp38-cp38-win_amd64.whl", hash = "sha256:9a29311bd6429be317c1f3fe4bc06c4c5ee45e2fa61b2a19d4d1d6111cb94af2"}, + {file = "coverage-6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03b20e52b7d31be571c9c06b74746746d4eb82fc260e594dc662ed48145e9efd"}, + {file = "coverage-6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:215f8afcc02a24c2d9a10d3790b21054b58d71f4b3c6f055d4bb1b15cecce685"}, + {file = "coverage-6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a4bdeb0a52d1d04123b41d90a4390b096f3ef38eee35e11f0b22c2d031222c6c"}, + {file = "coverage-6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c332d8f8d448ded473b97fefe4a0983265af21917d8b0cdcb8bb06b2afe632c3"}, + {file = "coverage-6.2-cp39-cp39-win32.whl", hash = "sha256:6e1394d24d5938e561fbeaa0cd3d356207579c28bd1792f25a068743f2d5b282"}, + {file = "coverage-6.2-cp39-cp39-win_amd64.whl", hash = "sha256:86f2e78b1eff847609b1ca8050c9e1fa3bd44ce755b2ec30e70f2d3ba3844644"}, + {file = "coverage-6.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:5829192582c0ec8ca4a2532407bc14c2f338d9878a10442f5d03804a95fac9de"}, + {file = "coverage-6.2.tar.gz", hash = "sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8"}, +] +"idna 3.3" = [ + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, +] +"iniconfig 1.1.1" = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] +"mypy 0.930" = [ + {file = "mypy-0.930-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:221cc94dc6a801ccc2be7c0c9fd791c5e08d1fa2c5e1c12dec4eab15b2469871"}, + {file = "mypy-0.930-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db3a87376a1380f396d465bed462e76ea89f838f4c5e967d68ff6ee34b785c31"}, + {file = "mypy-0.930-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1d2296f35aae9802eeb1327058b550371ee382d71374b3e7d2804035ef0b830b"}, + {file = "mypy-0.930-cp310-cp310-win_amd64.whl", hash = "sha256:959319b9a3cafc33a8185f440a433ba520239c72e733bf91f9efd67b0a8e9b30"}, + {file = "mypy-0.930-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:45a4dc21c789cfd09b8ccafe114d6de66f0b341ad761338de717192f19397a8c"}, + {file = "mypy-0.930-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1e689e92cdebd87607a041585f1dc7339aa2e8a9f9bad9ba7e6ece619431b20c"}, + {file = "mypy-0.930-cp36-cp36m-win_amd64.whl", hash = "sha256:ed4e0ea066bb12f56b2812a15ff223c57c0a44eca817ceb96b214bb055c7051f"}, + {file = "mypy-0.930-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a9d8dffefba634b27d650e0de2564379a1a367e2e08d6617d8f89261a3bf63b2"}, + {file = "mypy-0.930-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b419e9721260161e70d054a15abbd50603c16f159860cfd0daeab647d828fc29"}, + {file = "mypy-0.930-cp37-cp37m-win_amd64.whl", hash = "sha256:601f46593f627f8a9b944f74fd387c9b5f4266b39abad77471947069c2fc7651"}, + {file = "mypy-0.930-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ea7199780c1d7940b82dbc0a4e37722b4e3851264dbba81e01abecc9052d8a7"}, + {file = "mypy-0.930-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:70b197dd8c78fc5d2daf84bd093e8466a2b2e007eedaa85e792e513a820adbf7"}, + {file = "mypy-0.930-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5feb56f8bb280468fe5fc8e6f56f48f99aa0df9eed3c507a11505ee4657b5380"}, + {file = "mypy-0.930-cp38-cp38-win_amd64.whl", hash = "sha256:2e9c5409e9cb81049bb03fa1009b573dea87976713e3898561567a86c4eaee01"}, + {file = "mypy-0.930-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:554873e45c1ca20f31ddf873deb67fa5d2e87b76b97db50669f0468ccded8fae"}, + {file = "mypy-0.930-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0feb82e9fa849affca7edd24713dbe809dce780ced9f3feca5ed3d80e40b777f"}, + {file = "mypy-0.930-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bc1a0607ea03c30225347334af66b0af12eefba018a89a88c209e02b7065ea95"}, + {file = "mypy-0.930-cp39-cp39-win_amd64.whl", hash = "sha256:f9f665d69034b1fcfdbcd4197480d26298bbfb5d2dfe206245b6498addb34999"}, + {file = "mypy-0.930-py3-none-any.whl", hash = "sha256:bf4a44e03040206f7c058d1f5ba02ef2d1820720c88bc4285c7d9a4269f54173"}, + {file = "mypy-0.930.tar.gz", hash = "sha256:51426262ae4714cc7dd5439814676e0992b55bcc0f6514eccb4cf8e0678962c2"}, +] +"mypy-extensions 0.4.3" = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] +"packaging 21.3" = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] +"pathspec 0.9.0" = [ + {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, + {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, +] +"platformdirs 2.4.0" = [ + {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"}, + {file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"}, +] +"pluggy 1.0.0" = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] +"py 1.11.0" = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] +"pyparsing 3.0.6" = [ + {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"}, + {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"}, +] +"pytest 6.2.5" = [ + {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, + {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, +] +"pytest-cov 3.0.0" = [ + {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, + {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, +] +"requests 2.27.1" = [ + {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, + {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, +] +"toml 0.10.2" = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] +"tomli 1.2.3" = [ + {file = "tomli-1.2.3-py3-none-any.whl", hash = "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"}, + {file = "tomli-1.2.3.tar.gz", hash = "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f"}, +] +"typing-extensions 4.0.1" = [ + {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, + {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"}, +] +"urllib3 1.26.7" = [ + {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"}, + {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"}, +] diff --git a/{{ cookiecutter.project_name }}/pyproject.toml b/{{ cookiecutter.project_name }}/pyproject.toml new file mode 100644 index 0000000..22ca8d5 --- /dev/null +++ b/{{ cookiecutter.project_name }}/pyproject.toml @@ -0,0 +1,49 @@ +[project] +name = "{{ cookiecutter.project_name }}" +version = "0.0.1" +description = "" +authors = [ + {name = "Michal Nakoneczny", email = "michal@nakoneczny.pl"}, +] +dependencies = [ + "requests==2.27.1", +] +requires-python = ">=3.10" +license = {text = "MIT"} + +[project.urls] +homepage = "" + +[project.optional-dependencies] +dev = [ + "black==21.12b0", + "mypy==0.930", + "pytest==6.2.5", + "pytest-cov==3.0.0", +] +[tool] +[tool.pdm] +[tool.pdm.dev-dependencies] + +[build-system] +requires = ["pdm-pep517"] +build-backend = "pdm.pep517.api" + +[tool.mypy] +files = "{{ cookiecutter.project_name }}/**/*.py,tests/**/*.py" +exclude = "__pypackages__/" +ignore_missing_imports = true +disallow_untyped_calls = true +disallow_untyped_defs = true +disallow_incomplete_defs = true +warn_redundant_casts = true +warn_unused_ignores = true +warn_unreachable = true + +[tool.coverage.run] +data_file = "/tmp/.{{ cookiecutter.project_name }}.coverage" +omit = ["tests/*"] + +[tool.coverage.report] +show_missing = true +fail_under = 92 diff --git a/{{ cookiecutter.project_name }}/tests/__init__.py b/{{ cookiecutter.project_name }}/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/{{ cookiecutter.project_name }}/tests/test_functions.py b/{{ cookiecutter.project_name }}/tests/test_functions.py new file mode 100644 index 0000000..dc735e6 --- /dev/null +++ b/{{ cookiecutter.project_name }}/tests/test_functions.py @@ -0,0 +1,11 @@ +import pytest + +from {{ cookiecutter.project_name }}.functions import say_hi + + +@pytest.mark.parametrize( + "name, expected_salutation", + [("Docker", "Hi, Docker"), ("Python", "Hi, Python"), ("PDM", "Hi, PDM")], +) +def test_say_hi(name: str, expected_salutation: str) -> None: + assert say_hi(name) == expected_salutation diff --git a/{{ cookiecutter.project_name }}/{{ '' }}.gitignore b/{{ cookiecutter.project_name }}/{{ '' }}.gitignore new file mode 100644 index 0000000..cf89c48 --- /dev/null +++ b/{{ cookiecutter.project_name }}/{{ '' }}.gitignore @@ -0,0 +1,6 @@ +.idea/ +.mypy_cache/ +.pdm.toml +.pytest_cache/ +__pypackages__/ +**/__pycache__/ diff --git a/{{ cookiecutter.project_name }}/{{ cookiecutter.project_name }}/__init__.py b/{{ cookiecutter.project_name }}/{{ cookiecutter.project_name }}/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/{{ cookiecutter.project_name }}/{{ cookiecutter.project_name }}/functions.py b/{{ cookiecutter.project_name }}/{{ cookiecutter.project_name }}/functions.py new file mode 100644 index 0000000..2ec6b27 --- /dev/null +++ b/{{ cookiecutter.project_name }}/{{ cookiecutter.project_name }}/functions.py @@ -0,0 +1,2 @@ +def say_hi(name: str) -> str: + return f"Hi, {name}"