diff --git a/.github/workflows/test-cookiecutters.yml b/.github/workflows/test-cookiecutters.yml index 166380d..2485094 100644 --- a/.github/workflows/test-cookiecutters.yml +++ b/.github/workflows/test-cookiecutters.yml @@ -12,20 +12,21 @@ on: jobs: build-cli: runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.9', '3.10'] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python-version }} + python-version: | + 3.8 + 3.9 + 3.10 + 3.11 - name: Install dependencies run: | - pip install cookiecutter tox tox-gh-actions + pip install cookiecutter tox - run: mkdir -p .tmp/ @@ -39,20 +40,21 @@ jobs: build-lib: runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.7', '3.8', '3.9', '3.10'] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python-version }} + python-version: | + 3.8 + 3.9 + 3.10 + 3.11 - name: Install dependencies run: | - pip install cookiecutter tox tox-gh-actions build twine + pip install cookiecutter tox build twine - run: mkdir -p .tmp/ @@ -72,27 +74,32 @@ jobs: build-service: 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 ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version-loop }} + uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python-version }} + python-version: | + 3.8 + 3.9 + 3.10 + 3.11 - name: Install dependencies run: | - pip install cookiecutter tox tox-gh-actions + pip install cookiecutter tox - run: mkdir -p .tmp/ - - name: Build cli + - name: Build service working-directory: .tmp run: cookiecutter --config-file ../tests/service.yaml --no-input ../ + - name: Generate requirements + working-directory: .tmp/python_service + run: tox run -m requirements + - name: Run tox working-directory: .tmp/python_service run: tox diff --git a/README.md b/README.md index ce32ee8..e73ed7b 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,8 @@ A generated example can be found at https://github.com/vikahl/python-example - Always package the Python code as a library, even if is a service that will not be distributed through PyPI. Doing this makes it easy to write tests or extend functionality in various directions. -- Use [Setuptools] as the build system. It is a proven build system that has - gotten much better with the static configuration files (`setup.cfg`) and PEP - 517 compliant builds. I do not see a reason to use another system. +- Use [Setuptools] as the build system. It is a proven build system that + supports the latest standards. I do not see a reason to use another system. - Use Github Actions to run tests configured in tox and build and upload to PyPI for libraries. - Selection for library, cli and/or service support. @@ -28,12 +27,13 @@ A generated example can be found at https://github.com/vikahl/python-example package. - __module_name__: Project name, following specification in [PEP 508]. Will be suggested based on the project name. -- __author__: Name of the project author. Added in package metadata (setup.cfg) +- __author__: Name of the project author. Added in package metadata + (pyproject.toml) and in some cases the license. -- __email__: Email for the project author. Added in package metadata (setup.cfg). -- __homepage__: Homepage for the project. Added in package metadata (setup.cfg). +- __email__: Email for the project author. Added in package metadata (pyproject.toml). +- __homepage__: Homepage for the project. Added in package metadata (pyproject.toml). - __license__: Select a license for the project. Will add a trove classifier - (in setup.cfg) and a license file. If another license is needed they can be + (in pyproject.toml) and a license file. If another license is needed they can be replaced later. - __version__: Initial version. - __min_python__: Minimum Python version that is supported. Tox will generate @@ -42,20 +42,20 @@ A generated example can be found at https://github.com/vikahl/python-example - __library__: Toggle library functions, adds a Github workflow for uploading to PyPi. - __cli__: Toggle cli functions, adds a basic cli (based on Typer) with - entrypoint defined in setup.cfg. + entrypoint defined in pyproject.toml. - __service__: Toggle service functions, adds a dockerfile and instructions on compiled requirements. ## Linters and tools _A note about configs_: This template aims to collect all configuration in -`pyproject.toml`, except for Setuptools which uses `setup.cfg` and tox which -uses `tox.ini` (until tox better supports pyproject.toml). +`pyproject.toml`, except for tox which uses `tox.ini` until tox better supports +pyproject.toml. The linters and formatters are configured in tox and can be invoked by running `tox`. Github Actions ensures the same linters and formatters are run in CI. -- [Setuptools]: Packaging tool. Uses `setup.cfg` for package configuration. +- [Setuptools]: Packaging tool. Uses `pyproject.toml` for package configuration. - [tox](https://tox.wiki/en/latest/): Test automation framework. Run in Github actions and can be run locally. - [Black](https://github.com/psf/black): Code formatter, formats the code in a diff --git a/cookiecutter.json b/cookiecutter.json index 8442816..4953b23 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -1,5 +1,5 @@ { - "h": "]\nA reasonable modern Python project template.\n\n- __project_name__: Human friendly name for the project.\n- __description__: Short description of the project. Added to the README and\n package.\n- __module_name__: Project name, following specification in [PEP 508]. Will be\n suggested based on the project name.\n- __author__: Name of the project author. Added in package metadata (setup.cfg)\n and in some cases the license.\n- __email__: Email for the project author. Added in package metadata (setup.cfg).\n- __homepage__: Homepage for the project. Added in package metadata (setup.cfg).\n- __license__: Select a license for the project. Will add a trove classifier\n (in setup.cfg) and a license file. If another license is needed they can be\n replaced later.\n- __version__: Initial version.\n- __min_python__: Minimum Python version that is supported. Tox will generate\n test environments for all newer versions. Backported modules might be used\n for older Python versions.\n- __library__: Toggle library functions, adds a Github workflow for uploading\n to PyPi.\n- __cli__: Toggle cli functions, adds a basic cli (based on Typer) with\n entrypoint defined in setup.cfg.\n- __service__: Toggle service functions, adds a dockerfile and instructions on\n compiled requirements.\n\n [Press enter to continue", + "h": "]\nA reasonable modern Python project template.\n\n- __project_name__: Human friendly name for the project.\n- __description__: Short description of the project. Added to the README and\n package.\n- __module_name__: Project name, following specification in [PEP 508]. Will be\n suggested based on the project name.\n- __author__: Name of the project author. Added in package metadata (pyproject.toml)\n and in some cases the license.\n- __email__: Email for the project author. Added in package metadata (pyproject.toml).\n- __homepage__: Homepage for the project. Added in package metadata (pyproject.toml).\n- __license__: Select a license for the project. Will add a trove classifier\n (in pyproject.toml) and a license file. If another license is needed they can be\n replaced later.\n- __version__: Initial version.\n- __min_python__: Minimum Python version that is supported. Tox will generate\n test environments for all newer versions. Backported modules might be used\n for older Python versions.\n- __library__: Toggle library functions, adds a Github workflow for uploading\n to PyPi.\n- __cli__: Toggle cli functions, adds a basic cli (based on Typer) with\n entrypoint defined in pyproject.toml.\n- __service__: Toggle service functions, adds a dockerfile and instructions on\n compiled requirements.\n\n [Press enter to continue", "project_name": "Python project template", "description": "", @@ -11,7 +11,7 @@ "Apache - explicitly grants patent rights", "GPL - ensures that code based on this is shared with the same terms"], "version": "0.0.1", - "min_python": "3.7", + "min_python": "3.8", "library": ["y", "n"], "cli": ["n", "y"], diff --git a/tests/lib.yaml b/tests/lib.yaml index 4b5f6cd..ab98295 100644 --- a/tests/lib.yaml +++ b/tests/lib.yaml @@ -8,7 +8,7 @@ default_context: homepage: "example.com" license: "MIT - simple and permissive" version: "1.0.0" - min_python: "3.7" + min_python: "3.8" library: "y" cli: "n" service: "n" diff --git a/tests/service.yaml b/tests/service.yaml index 409f5d9..41cfd2b 100644 --- a/tests/service.yaml +++ b/tests/service.yaml @@ -8,7 +8,7 @@ default_context: homepage: "" license: "GPL - ensures that code based on this is shared with the same terms" version: "0.0.1" - min_python: "3.7" + min_python: "3.8" library: "n" cli: "n" service: "y" diff --git a/{{cookiecutter.module_name}}/.github/workflows/test.yml b/{{cookiecutter.module_name}}/.github/workflows/test.yml index e529076..76a27f3 100644 --- a/{{cookiecutter.module_name}}/.github/workflows/test.yml +++ b/{{cookiecutter.module_name}}/.github/workflows/test.yml @@ -1,9 +1,5 @@ # This workflow runs the test suite defined in tox. # -# Note the python-version matrix, if new Python versions are wanted they need -# to be added in this matrix AS WELL as in the tox.ini file for -# "tox-gh-actions". Read more about tox-gh-actions on -# https://github.com/ymyzk/tox-gh-actions name: Test package on: @@ -15,26 +11,23 @@ on: jobs: run-tests: runs-on: ubuntu-latest - strategy: - matrix: - python-version: [{%- for version in (range(cookiecutter.min_python | replace('3.', '') | int, 11)) -%}'3.{{ version }}'{{ ", " if not loop.last else ""}}{%- endfor %}] - {% raw -%} steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python-version }} + python-version: | +{% for version in (range(cookiecutter.min_python | replace('3.', '') | int, 11)) -%} + {{10 * " "}}3.{{ version }}{{ "\n" if not loop.last else ""}} +{%- endfor %} # To get completely reproducible builds these dependencies should be # pinned. For most smaller projects it should be ok to leave them - # unpinend as they are stable projects. + # unpinned as they are stable projects. - name: Install dependencies run: | - python -m pip install --upgrade pip - pip install tox tox-gh-actions + pip install tox - name: Run tox run: tox - {%- endraw %} diff --git a/{{cookiecutter.module_name}}/.github/workflows/{% if cookiecutter.library == 'y' -%} publish.yml {%- endif %} b/{{cookiecutter.module_name}}/.github/workflows/{% if cookiecutter.library == 'y' -%} publish.yml {%- endif %} index 5e1b687..fe42712 100644 --- a/{{cookiecutter.module_name}}/.github/workflows/{% if cookiecutter.library == 'y' -%} publish.yml {%- endif %} +++ b/{{cookiecutter.module_name}}/.github/workflows/{% if cookiecutter.library == 'y' -%} publish.yml {%- endif %} @@ -16,9 +16,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: '3.x' @@ -27,14 +27,13 @@ jobs: # unpinend as they are stable projects. - name: Install dependencies run: | - python -m pip install --upgrade pip pip install build - name: Build package run: python -m build - name: Publish package - uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 + uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/{{cookiecutter.module_name}}/.github/workflows/{% if cookiecutter.library == 'y' -%} test-build.yml {%- endif %} b/{{cookiecutter.module_name}}/.github/workflows/{% if cookiecutter.library == 'y' -%} test-build.yml {%- endif %} index 4a3ff9b..3e196b8 100644 --- a/{{cookiecutter.module_name}}/.github/workflows/{% if cookiecutter.library == 'y' -%} test-build.yml {%- endif %} +++ b/{{cookiecutter.module_name}}/.github/workflows/{% if cookiecutter.library == 'y' -%} test-build.yml {%- endif %} @@ -12,9 +12,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: '3.x' @@ -23,7 +23,6 @@ jobs: # unpinend as they are stable projects. - name: Install dependencies run: | - python -m pip install --upgrade pip pip install build twine - name: Build package diff --git a/{{cookiecutter.module_name}}/pyproject.toml b/{{cookiecutter.module_name}}/pyproject.toml index 56c82f0..a4ed58a 100644 --- a/{{cookiecutter.module_name}}/pyproject.toml +++ b/{{cookiecutter.module_name}}/pyproject.toml @@ -1,9 +1,92 @@ [build-system] -# >= 51 is required since "entry_points" in setup.cfg was added in this -# version. -requires = ["setuptools>=51.0", "wheel"] +requires = ["setuptools>=61.0", "wheel"] build-backend = "setuptools.build_meta" +[project] +name = "{{ cookiecutter.module_name }}" +description = "{{ cookiecutter.description }}" +{% if cookiecutter.author or cookiecutter.email -%} +authors = [ + { {% if cookiecutter.author -%} name = "{{ cookiecutter.author }}",{% endif -%}{% if cookiecutter.email -%} email = "{{ cookiecutter.email }}" {% endif -%} } +] +{% endif -%} +{%- if cookiecutter.homepage %} +urls = { homepage = "{{ cookiecutter.homepage }}" } +{% endif -%} + +classifiers = [ + "Development Status :: 4 - Beta", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + {%- for version in (range(cookiecutter.min_python | replace('3.', '') | int, 11) | list) %} + "Programming Language :: Python :: 3.{{ version }}", + {%- endfor %} + {%- if cookiecutter.license == "MIT - simple and permissive" %} + "License :: OSI Approved :: MIT License" + {%- elif cookiecutter.license == "Apache - explicitly grants patent rights" %} + "License :: OSI Approved :: Apache Software License" + {%- elif cookiecutter.license == "GPL - ensures that code based on this is shared with the same terms" %} + "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)" + {%- endif %} +] +dynamic = ["version", "readme"] + +requires-python = ">={{ cookiecutter.min_python }}" + +# Specify the packages required by the project. For libraries, the constraints +# should be loosely defined as too narrow constraints will make it hard to +# install the package together with other libraries and will prevent users from +# getting security updates. +{% if cookiecutter.service == "y" %} +# For services, the dependencies (including transitive) should be compiled with +# pip-tools. See requirements.txt for details. +{% elif cookiecutter.cli == "y" -%} +dependencies = [ + "typer" +] +{% else %} +# dependencies = [ +# "some_package" +# ] +{%- endif %} + +[project.optional-dependencies] +# pip-compile doesn't work well with extras referencing the package itself when +# hashes are required, as the package itself will be added to the list. +# Therefore the dependency groups "dev" is just for developer convenience and +# should not list dependencies itself. The compilation in tox lists all extras +# explicitly (i.e., --extra format,lint,types,test +dev = [ # All dev dependencies + "{{ cookiecutter.module_name }}[format]", + "{{ cookiecutter.module_name }}[lint]", + "{{ cookiecutter.module_name }}[test]", +] +format = [ + "black", + "isort" +] +lint = [ + "black", + "isort", + "pylint" +] +types = [ + "mypy" +] +test = [ + "pytest", + "pytest-cov" +] + +{%- if cookiecutter.cli == "y" %} +[project.scripts] +{{ cookiecutter.module_name }} = "{{ cookiecutter.module_name }}:app" +{%- endif %} + +[tool.setuptools.dynamic] +version = {attr = "{{ cookiecutter.module_name }}.__version__"} +readme = {file = "README.md", content-type = "text/markdown"} + [tool.isort] # For compatibility with Black profile = "black" @@ -36,7 +119,7 @@ source = ["src", ".tox/*/site-packages/"] show_missing = true [tool.pylint.'FORMAT'] -# Black defaults to 88 character line length, +# Black defaults to 88 character line length, max-line-length = 88 [tool.pylint.'MESSAGES_CONTROL'] diff --git a/{{cookiecutter.module_name}}/requirements-dev.txt b/{{cookiecutter.module_name}}/requirements-dev.txt deleted file mode 100644 index 94b82c8..0000000 --- a/{{cookiecutter.module_name}}/requirements-dev.txt +++ /dev/null @@ -1,14 +0,0 @@ --e . - -black==21.12b0 -isort==5.10.1 - -pylint==2.12.2 -mypy==0.930 - -pytest==6.2.5 -pytest-cov==3.0.0 - -{% if cookiecutter.service == "y" -%} -pip-tools==6.4.0 -{% endif %} diff --git a/{{cookiecutter.module_name}}/setup.cfg b/{{cookiecutter.module_name}}/setup.cfg deleted file mode 100644 index 48e13c1..0000000 --- a/{{cookiecutter.module_name}}/setup.cfg +++ /dev/null @@ -1,64 +0,0 @@ -[metadata] -name = {{ cookiecutter.module_name }} -version = attr: {{ cookiecutter.module_name }}.__version__ -description = {{ cookiecutter.description }} -long_description = file:README.md -long_description_content_type = text/markdown -{% if cookiecutter.author -%} -author = {{ cookiecutter.author }} -{% endif -%} -{% if cookiecutter.email -%} -author_email = {{ cookiecutter.email }} -{% endif -%} -{% if cookiecutter.homepage -%} -url = {{ cookiecutter.homepage }} -{% endif -%} -classifiers = - Development Status :: 4 - Beta - Programming Language :: Python - Programming Language :: Python :: 3 - {%- for version in (range(cookiecutter.min_python | replace('3.', '') | int, 11) | list) %} - Programming Language :: Python :: 3.{{ version }} - {%- endfor %} - {%- if cookiecutter.license == "MIT - simple and permissive" %} - License :: OSI Approved :: MIT License - {%- elif cookiecutter.license == "Apache - explicitly grants patent rights" %} - License :: OSI Approved :: Apache Software License - {%- elif cookiecutter.license == "GPL - ensures that code based on this is shared with the same terms" %} - License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) - {%- endif %} - -[options] -python_requires = >= {{ cookiecutter.min_python }} - -# Specify the packages required by the project. For libraries, the constraints -# should be loosely defined as too narrow constraints will make it hard to -# install the package together with other libraries and will prevent users from -# getting security updates. -{% if cookiecutter.service == "y" -%} -# For services, the dependencies (including transitive) should be compiled with -# pip-tools. See requirements.txt for details. -{%- endif %} -{% if cookiecutter.cli == "y" -%} -install_requires = - typer<1 -{% else -%} -# install_requires = -# some_package>1,<2 -{%- endif %} - -# Find the packages in the src folder. -packages = find: -package_dir = - =src - -[options.packages.find] -where = src - -{% if cookiecutter.cli == "y" %} -# Define the entrypoints/cli command for the project. Multiple entrypoints can -# be defined. -[options.entry_points] -console_scripts = - {{ cookiecutter.module_name }} = {{ cookiecutter.module_name }}:app -{%- endif %} diff --git a/{{cookiecutter.module_name}}/tox.ini b/{{cookiecutter.module_name}}/tox.ini index 085dc2a..58784b7 100644 --- a/{{cookiecutter.module_name}}/tox.ini +++ b/{{cookiecutter.module_name}}/tox.ini @@ -4,45 +4,46 @@ envlist = lint, lint-format, - types, + types, {%- if cookiecutter.library == "y" %} # It is good practice to test the library for all supported versions. -{%- for version in range(cookiecutter.min_python | replace('3.', '') | int, 11) %} +{%- for version in range(cookiecutter.min_python | replace('3.', '') | int, 12) %} py3{{ version }}{{ "," if not loop.last else "" }} {%- endfor %} {%- else %} py3{{ cookiecutter.min_python | replace('3.', '') }} {%- endif %} -isolated_build = true - -[gh-actions] -# Config for mapping gh-actions to environment. See tox-gh-actions for details -# https://github.com/ymyzk/tox-gh-actions -python = -{%- for version in range(cookiecutter.min_python | replace('3.', '') | int, 11) %} - 3.{{ version }}: py3{{ version }} - {%- if version == (cookiecutter.min_python | replace('3.', '') | int) -%} - , lint, lint-format, types - {%- endif -%} -{%- endfor %} +min_version = 4.0 [testenv] # Run pytest and measure coverage. -deps = -r{toxinidir}/requirements-dev.txt -commands = +{% if cookiecutter.service == "y" %} +deps = -r{toxinidir}/requirements/requirements-{envname}-dev.txt +{%- else %} +extras = test +{% endif %} +commands = pytest --cov={{ cookiecutter.module_name }} --cov-report=xml [testenv:lint] # Run the linter for both src and tests folders. basepython = python{{ cookiecutter.min_python }} -deps = -r{toxinidir}/requirements-dev.txt +{%- if cookiecutter.service == "y" %} +deps = -r{toxinidir}/requirements/requirements-py{{ cookiecutter.min_python | replace ('.', '') }}-dev.txt +{%- else %} +extras = lint, test +{%- endif %} commands = pylint {toxinidir}/src/{{ cookiecutter.module_name }} {toxinidir}/tests -[testenv:list-format] +[testenv:lint-format] # Check the code format by running black and isort in check mode. basepython = python{{ cookiecutter.min_python }} -deps = -r{toxinidir}/requirements-dev.txt +{%- if cookiecutter.service == "y" %} +deps = -r{toxinidir}/requirements/requirements-py{{ cookiecutter.min_python | replace ('.', '') }}-dev.txt +{%- else %} +extras = format, test +{%- endif %} commands = black --diff --check {toxinidir} isort --diff --check-only {toxinidir} @@ -51,7 +52,11 @@ commands = # Run mypy linter. Mypy needs to be run in src and tests separately to not # cause errors with imports. basepython = python{{ cookiecutter.min_python }} -deps = -r{toxinidir}/requirements-dev.txt +{%- if cookiecutter.service == "y" %} +deps = -r{toxinidir}/requirements/requirements-py{{ cookiecutter.min_python | replace ('.', '') }}-dev.txt +{%- else %} +extras = types, test +{%- endif %} commands = mypy {toxinidir}/src mypy {toxinidir}/tests @@ -60,7 +65,40 @@ commands = # Applies the formatting from black and isort. Not run by default when invoking # tox but provides an easy way to fix format errors. Run with tox -e format basepython = python{{ cookiecutter.min_python }} -deps = -r{toxinidir}/requirements-dev.txt +{%- if cookiecutter.service == "y" %} +deps = -r{toxinidir}/requirements/requirements-py{{ cookiecutter.min_python | replace ('.', '') }}-dev.txt +{%- else %} +extras = format, test +{%- endif %} commands = black {toxinidir} isort {toxinidir} + +{% if cookiecutter.service == "y" -%} +[testenv:requirements-py{38,39,310,311}] +; Generate new requirements files +; only run this on linux as compiled requirements are platform dependent and +; this code is deployed in linux containers. +; Would be better to only run this on a specific processor architecture, but +; this is not supported in tox at the moment. +labels = requirements +platform = linux +deps = pip-tools +skip_install = true +setenv = + ; will show `tox run -m requirements` in the top of the generated files. + CUSTOM_COMPILE_COMMAND='tox run -m requirements' +commands = +; ensure that the requirements-folder exists + python3 -c 'import pathlib;pathlib.Path("requirements").mkdir(exist_ok=True)' +; explanation of flags used +; --upgrade: upgrade all dependencies to latest version. normally pip-compile +; change as little as possible, but without constraints it means that +; it will never update transitive dependencies. +; --resolver backtracking: use the "new" improved backtracking resolver from +; pip. this will be default in pip-tools 7. +; --allow-unsafe: allow the "unsafe" packages, which will be default behaviour +; in upcoming pip-tools version. + pip-compile --upgrade --generate-hashes --resolver backtracking --allow-unsafe pyproject.toml --output-file requirements/{envname}.txt + pip-compile --extra format,lint,types,test --upgrade --generate-hashes --resolver backtracking --allow-unsafe pyproject.toml --output-file requirements/{envname}-dev.txt +{% endif -%} diff --git a/{{cookiecutter.module_name}}/{% if cookiecutter.service == 'y' -%} Dockerfile {%- endif %} b/{{cookiecutter.module_name}}/{% if cookiecutter.service == 'y' -%} Dockerfile {%- endif %} index da69db3..0cb8dd2 100644 --- a/{{cookiecutter.module_name}}/{% if cookiecutter.service == 'y' -%} Dockerfile {%- endif %} +++ b/{{cookiecutter.module_name}}/{% if cookiecutter.service == 'y' -%} Dockerfile {%- endif %} @@ -55,21 +55,25 @@ COPY --chown=1000:1000 requirements.txt . # RUN apt-get update \ # && apt-get install -y --no-install-recommends build-essential \ # && rm -rf /var/lib/apt/lists/* \ -# && pip3 install --no-cache-dir -r requirements.txt \ +# Use --no-deps as the requirements-file already contains all dependencies (as it is a compiled file). +# Require hashes to ensure no meddling occurs. +# && pip3 install --no-deps --require-hashes --no-cache-dir -r requirements.txt \ # && rm requirements.txt \ # && apt-get purge -y build-essential # ALTERNATIVE 2: Just install them -RUN pip3 install --no-cache-dir -r requirements.txt \ +# Use --no-deps as the requirements-file already contains all dependencies (as it is a compiled file). +# Require hashes to ensure no meddling occurs. +RUN pip3 install --no-deps --require-hashes --no-cache-dir -r requirements.txt \ && rm requirements.txt # Set the user USER {{ cookiecutter.module_name }} # Copy the run.py entrypoint. -# One alternative solution is to specify an entrpoint in setup.cfg and run the -# service as a cli command. This needs to be modified if the service is started -# with another command (e.g., gunicorn). +# One alternative solution is to specify an entrpoint in pyproject.toml and run +# the service as a cli command. This needs to be modified if the service is +# started with another command (e.g., gunicorn). COPY --chown=1000:1000 src/run.py . # Run the service. This needs to be modified if the service is started with diff --git a/{{cookiecutter.module_name}}/{% if cookiecutter.service == 'y' -%} requirements.txt {%- endif %} b/{{cookiecutter.module_name}}/{% if cookiecutter.service == 'y' -%} requirements.txt {%- endif %} deleted file mode 100644 index 80ef643..0000000 --- a/{{cookiecutter.module_name}}/{% if cookiecutter.service == 'y' -%} requirements.txt {%- endif %} +++ /dev/null @@ -1,8 +0,0 @@ -# This file is generated with pip-tools and contains pinned versions of all -# dependencies, either directly specified in setup.cfg or transitive. This -# makes the installation reproducible by ensuring that all dependencies matches -# version. -# -# The file can updated by running: -# -# pip-compile setup.cfg