diff --git a/python-project-template/.github/workflows/pre-commit-ci.yml.jinja b/python-project-template/.github/workflows/pre-commit-ci.yml.jinja index a57e2219..752b5126 100644 --- a/python-project-template/.github/workflows/pre-commit-ci.yml.jinja +++ b/python-project-template/.github/workflows/pre-commit-ci.yml.jinja @@ -1,3 +1,4 @@ +{%- import 'python-versions.jinja' as py %} # This workflow runs pre-commit hooks on pushes and pull requests to main # to enforce coding style. To ensure correct configuration, please refer to: # https://lincc-ppt.readthedocs.io/en/latest/practices/ci_precommit.html @@ -19,7 +20,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '{{ py.pref(python_versions) }}' - name: Install dependencies run: | sudo apt-get update diff --git a/python-project-template/.github/workflows/publish-to-pypi.yml b/python-project-template/.github/workflows/publish-to-pypi.yml.jinja similarity index 90% rename from python-project-template/.github/workflows/publish-to-pypi.yml rename to python-project-template/.github/workflows/publish-to-pypi.yml.jinja index f7cecc2e..fec3125d 100644 --- a/python-project-template/.github/workflows/publish-to-pypi.yml +++ b/python-project-template/.github/workflows/publish-to-pypi.yml.jinja @@ -1,3 +1,4 @@ +{%- import 'python-versions.jinja' as py %} # This workflow will upload a Python Package using Twine when a release is created # For more information see: https://github.com/pypa/gh-action-pypi-publish#trusted-publishing @@ -26,7 +27,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '{{ py.pref(python_versions) }}' - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/python-project-template/.github/workflows/{% if include_benchmarks %}asv-main.yml{% endif %}.jinja b/python-project-template/.github/workflows/{% if include_benchmarks %}asv-main.yml{% endif %}.jinja index ff836b9d..2c537ffd 100644 --- a/python-project-template/.github/workflows/{% if include_benchmarks %}asv-main.yml{% endif %}.jinja +++ b/python-project-template/.github/workflows/{% if include_benchmarks %}asv-main.yml{% endif %}.jinja @@ -9,7 +9,10 @@ on: branches: [ main ] env: - PYTHON_VERSION: "3.10" +{%- endraw %} +{%- import 'python-versions.jinja' as py%} + PYTHON_VERSION: "{{ py.pref(python_versions) }}" +{%- raw %} ASV_VERSION: "0.6.4" WORKING_DIR: ${{github.workspace}}/benchmarks diff --git a/python-project-template/.github/workflows/{% if include_benchmarks %}asv-nightly.yml{% endif %}.jinja b/python-project-template/.github/workflows/{% if include_benchmarks %}asv-nightly.yml{% endif %}.jinja index 583d988d..a3358e52 100644 --- a/python-project-template/.github/workflows/{% if include_benchmarks %}asv-nightly.yml{% endif %}.jinja +++ b/python-project-template/.github/workflows/{% if include_benchmarks %}asv-nightly.yml{% endif %}.jinja @@ -10,7 +10,10 @@ on: workflow_dispatch: env: - PYTHON_VERSION: "3.10" +{%- endraw %} +{%- import 'python-versions.jinja' as py%} + PYTHON_VERSION: "{{ py.pref(python_versions) }}" +{%- raw %} ASV_VERSION: "0.6.4" WORKING_DIR: ${{github.workspace}}/benchmarks NIGHTLY_HASH_FILE: nightly-hash diff --git a/python-project-template/.github/workflows/{% if include_benchmarks %}asv-pr.yml{% endif %}.jinja b/python-project-template/.github/workflows/{% if include_benchmarks %}asv-pr.yml{% endif %}.jinja index be577f26..328ea864 100644 --- a/python-project-template/.github/workflows/{% if include_benchmarks %}asv-pr.yml{% endif %}.jinja +++ b/python-project-template/.github/workflows/{% if include_benchmarks %}asv-pr.yml{% endif %}.jinja @@ -16,7 +16,10 @@ concurrency: cancel-in-progress: true env: - PYTHON_VERSION: "3.10" +{%- endraw %} +{%- import 'python-versions.jinja' as py%} + PYTHON_VERSION: "{{ py.pref(python_versions) }}" +{%- raw %} ASV_VERSION: "0.6.4" WORKING_DIR: ${{github.workspace}}/benchmarks ARTIFACTS_DIR: ${{github.workspace}}/artifacts diff --git a/python-project-template/.github/workflows/{% if include_docs %}build-documentation.yml{% endif %}.jinja b/python-project-template/.github/workflows/{% if include_docs %}build-documentation.yml{% endif %}.jinja index 6df816d9..17102b48 100644 --- a/python-project-template/.github/workflows/{% if include_docs %}build-documentation.yml{% endif %}.jinja +++ b/python-project-template/.github/workflows/{% if include_docs %}build-documentation.yml{% endif %}.jinja @@ -1,3 +1,4 @@ +{%- import 'python-versions.jinja' as py %} # This workflow will install Python dependencies, build the package and then build the documentation. name: Build documentation @@ -20,10 +21,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python 3.10 + - name: Set up Python {{ py.pref(python_versions) }} uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '{{ py.pref(python_versions) }}' - name: Install dependencies run: | sudo apt-get update diff --git a/python-project-template/.pre-commit-config.yaml.jinja b/python-project-template/.pre-commit-config.yaml.jinja index b16574ca..1fd949b0 100644 --- a/python-project-template/.pre-commit-config.yaml.jinja +++ b/python-project-template/.pre-commit-config.yaml.jinja @@ -1,3 +1,4 @@ +{%- import 'python-versions.jinja' as py %} repos: # Compare the local template version to the latest remote template version # This hook should always pass. It will print a message if the local version @@ -98,7 +99,7 @@ repos: # supported by your project here, or alternatively use # pre-commit's default_language_version, see # https://pre-commit.com/#top_level-default_language_version - language_version: python3.10 + language_version: python{{ py.pref(python_versions) }} {%- endif %} {%- if 'ruff_lint' in enforce_style %} - repo: https://github.com/astral-sh/ruff-pre-commit diff --git a/python-project-template/README.md.jinja b/python-project-template/README.md.jinja index b39d9f63..5702f658 100644 --- a/python-project-template/README.md.jinja +++ b/python-project-template/README.md.jinja @@ -1,3 +1,4 @@ +{%- import 'python-versions.jinja' as py %} # {{project_name}} [![Template](https://img.shields.io/badge/Template-LINCC%20Frameworks%20Python%20Project%20Template-brightgreen)](https://lincc-ppt.readthedocs.io/en/latest/) @@ -29,7 +30,7 @@ environments. If you have conda installed locally, you can run the following to create and activate a new environment. ``` ->> conda create -n python=3.10 +>> conda create -n python={{ py.pref(python_versions) }} >> conda activate ``` diff --git a/python-project-template/pyproject.toml.jinja b/python-project-template/pyproject.toml.jinja index 5d6a9b32..8c4b23ba 100644 --- a/python-project-template/pyproject.toml.jinja +++ b/python-project-template/pyproject.toml.jinja @@ -1,3 +1,4 @@ +{%- import 'python-versions.jinja' as py %} [project] name = "{{project_name}}" license = {file = "LICENSE"} @@ -18,7 +19,7 @@ classifiers = [ "Programming Language :: Python", ] dynamic = ["version"] -requires-python = ">={{ python_versions[0] }}" +requires-python = ">={{ py.min(python_versions) }}" dependencies = [ ] @@ -66,7 +67,7 @@ testpaths = [ [tool.black] line-length = 110 -target-version = ["py{{ python_versions[0] | replace(".", "") }}"] +target-version = ["py{{ py.min(python_versions) | replace(".", "") }}"] [tool.isort] profile = "black" @@ -74,7 +75,7 @@ line_length = 110 [tool.ruff] line-length = 110 -target-version = "py{{ python_versions[0] | replace(".", "") }}" +target-version = "py{{ py.min(python_versions) | replace(".", "") }}" [tool.ruff.lint] select = [ diff --git a/python-project-template/src/{% if 'pylint' in enforce_style %}.pylintrc{% endif %} b/python-project-template/src/{% if 'pylint' in enforce_style %}.pylintrc{% endif %}.jinja similarity index 99% rename from python-project-template/src/{% if 'pylint' in enforce_style %}.pylintrc{% endif %} rename to python-project-template/src/{% if 'pylint' in enforce_style %}.pylintrc{% endif %}.jinja index 7bd3e031..772ee400 100644 --- a/python-project-template/src/{% if 'pylint' in enforce_style %}.pylintrc{% endif %} +++ b/python-project-template/src/{% if 'pylint' in enforce_style %}.pylintrc{% endif %}.jinja @@ -1,3 +1,4 @@ +{%- import 'python-versions.jinja' as py %} [MAIN] # Analyse import fallback blocks. This can be used to support both Python 2 and @@ -87,7 +88,7 @@ persistent=yes # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. -py-version=3.9 +py-version={{ py.min(python_versions) }} # Discover python modules and packages in the file system subtree. recursive=no diff --git a/python-project-template/tests/{% if 'pylint' in enforce_style %}.pylintrc{% endif %} b/python-project-template/tests/{% if 'pylint' in enforce_style %}.pylintrc{% endif %}.jinja similarity index 99% rename from python-project-template/tests/{% if 'pylint' in enforce_style %}.pylintrc{% endif %} rename to python-project-template/tests/{% if 'pylint' in enforce_style %}.pylintrc{% endif %}.jinja index b5afc249..dad61ad6 100644 --- a/python-project-template/tests/{% if 'pylint' in enforce_style %}.pylintrc{% endif %} +++ b/python-project-template/tests/{% if 'pylint' in enforce_style %}.pylintrc{% endif %}.jinja @@ -1,3 +1,4 @@ +{%- import 'python-versions.jinja' as py %} [MAIN] # Analyse import fallback blocks. This can be used to support both Python 2 and @@ -87,7 +88,7 @@ persistent=yes # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. -py-version=3.9 +py-version={{ py.min(python_versions) }} # Discover python modules and packages in the file system subtree. recursive=no diff --git a/python-project-template/{% if include_benchmarks %}benchmarks{% endif %}/asv.conf.json.jinja b/python-project-template/{% if include_benchmarks %}benchmarks{% endif %}/asv.conf.json.jinja index bc65f500..590c0768 100644 --- a/python-project-template/{% if include_benchmarks %}benchmarks{% endif %}/asv.conf.json.jinja +++ b/python-project-template/{% if include_benchmarks %}benchmarks{% endif %}/asv.conf.json.jinja @@ -1,3 +1,4 @@ +{%- import 'python-versions.jinja' as py %} { // The version of the config file format. Do not change, unless // you know what you are doing. @@ -36,7 +37,7 @@ // The Pythons you'd like to test against. If not provided, defaults // to the current version of Python used to run `asv`. "pythons": [ - "3.10" + "{{ py.pref(python_versions) }}" ], // The matrix of dependencies to test. Each key is the name of a // package (in PyPI) and the values are version numbers. An empty diff --git a/python-project-template/{% if include_docs %}.readthedocs.yml{% endif %} b/python-project-template/{% if include_docs %}.readthedocs.yml{% endif %}.jinja similarity index 83% rename from python-project-template/{% if include_docs %}.readthedocs.yml{% endif %} rename to python-project-template/{% if include_docs %}.readthedocs.yml{% endif %}.jinja index 79bfc272..63d9fdaa 100644 --- a/python-project-template/{% if include_docs %}.readthedocs.yml{% endif %} +++ b/python-project-template/{% if include_docs %}.readthedocs.yml{% endif %}.jinja @@ -1,3 +1,4 @@ +{%- import 'python-versions.jinja' as py %} # .readthedocs.yml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details @@ -8,7 +9,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.10" + python: "{{ py.pref(python_versions) }}" # Build documentation in the docs/ directory with Sphinx sphinx: diff --git a/python-project-template/{% if include_docs %}docs{% endif %}/index.rst.jinja b/python-project-template/{% if include_docs %}docs{% endif %}/index.rst.jinja index 4c2dc087..52f8390e 100644 --- a/python-project-template/{% if include_docs %}docs{% endif %}/index.rst.jinja +++ b/python-project-template/{% if include_docs %}docs{% endif %}/index.rst.jinja @@ -1,3 +1,4 @@ +{%- import 'python-versions.jinja' as py %} .. {{package_name}} documentation main file. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. @@ -15,7 +16,7 @@ create and activate a new environment. .. code-block:: console - >> conda create env -n python=3.10 + >> conda create env -n python={{ py.pref(python_versions) }} >> conda activate diff --git a/python-versions.jinja b/python-versions.jinja new file mode 100644 index 00000000..0845287f --- /dev/null +++ b/python-versions.jinja @@ -0,0 +1,35 @@ +{# You use this file by including it via jinja like: + + {%- import 'python-versions.jinja' as py -%} + +Then pass the python_versions list into the various macros like so: + + {{ py.min(python_versions) }} + +This template creates no output, but does allow you to transform python_versions answer into a +number of helpful values for when you need a single python version. + +Note that the import syntax and access MUST BE in the form above. Copier has problems processing import lines +that are any more complex when they occur in files who's paths are also jinja templated. #} + + +{# This gives a middle python version from a potentially long list of versions +For even-length lists we prefer the older of the two middle values. + ["3.9","3.10","3.11","3.12"] -> "3.10" +For odd-length lists we prefer the middle value + ["3.9","3.10","3.11"] -> "3.10" #} +{% macro pref(python_versions) -%} +{%- set n = python_versions | length -%} +{{ python_versions[((n+1)//2 - 1)] }} +{%- endmacro -%} + +{# These give the minimum and maximum python versions supported #} +{% macro min(python_versions) -%} +{%- set n = python_versions | length -%} +{{ python_versions[0] }} +{%- endmacro -%} + +{% macro max(python_versions) -%} +{%- set n = python_versions | length -%} +{{ python_versions[n-1] }} +{%- endmacro -%} \ No newline at end of file