diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9bbc87127..d5ca01a55 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,12 +4,12 @@ name: tests on: push: branches: [master] - paths-ignore: + paths-ignore: - "docs/**" - "README.md" pull_request: branches: [master] - paths-ignore: + paths-ignore: - "docs/**" - "README.md" schedule: @@ -24,19 +24,17 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 + - uses: astral-sh/setup-uv@v5 with: - python-version: "3.11" - cache: "pip" - cache-dependency-path: | + python-version: "3.13" + enable-cache: true + cache-dependency-glob: | pyproject.toml dev-requirements.txt - name: Install dependencies run: | - python -m pip install --upgrade pip - make requirements + uv pip install -r dev-requirements.txt - name: Lint run: | @@ -53,21 +51,26 @@ jobs: defaults: run: shell: bash + env: + TEST_TARGET_PYTHON_VERSION: 3.13 steps: - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + - uses: astral-sh/setup-uv@v5 with: python-version: ${{ matrix.python-version }} - allow-prereleases: true - cache: "pip" - cache-dependency-path: | + enable-cache: true + cache-dependency-glob: | pyproject.toml dev-requirements.txt - - name: Set up Miniconda + - name: Make Python ${{ env.TEST_TARGET_PYTHON_VERSION }} available + run: + # --preview flag adds installed Python into PATH + uv python install $TEST_TARGET_PYTHON_VERSION --preview + + - name: Set up Miniconda uses: conda-incubator/setup-miniconda@v3 with: auto-activate-base: true @@ -96,11 +99,11 @@ jobs: - name: Install dependencies run: | - python -m pip install --upgrade pip - make requirements + uv pip install -r dev-requirements.txt - name: Check dependencies run: | + echo $PATH if [[ -z "${BASH_EXECUTABLE}" ]]; then bash --version else @@ -109,10 +112,14 @@ jobs: fi which make make --version + which python + python --version which conda conda --version which pipenv pipenv --version + which uv + uv --version which virtualenv virtualenv --version diff --git a/dev-requirements.txt b/dev-requirements.txt index a14df9bff..035327523 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -18,3 +18,4 @@ twine uv virtualenvwrapper; sys_platform != 'win32' virtualenvwrapper-win; sys_platform == 'win32' +vspect diff --git a/tests/conftest.py b/tests/conftest.py index a564efe60..fcee590da 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,6 @@ import json +import os import shutil -import sys import tempfile from contextlib import contextmanager from itertools import cycle, product @@ -25,13 +25,13 @@ def config_generator(fast=False): cookiecutter_json = json.load((CCDS_ROOT / "ccds.json").open("r")) - # python versions for the created environment; match the root - # python version since Pipenv needs to be able to find an executable - running_py_version = f"{sys.version_info.major}.{sys.version_info.minor}" - py_version = [("python_version_number", v) for v in [running_py_version]] + # python version for the environment of the created project + # we fix this to specific version, and the test matrix ensures things work + # whether or not it matches the current python version running ccds + test_target_python_version = os.environ.get("TEST_TARGET_PYTHON_VERSION", "3.13") configs = product( - py_version, + [("python_version_number", test_target_python_version)], [ ("environment_manager", opt) for opt in cookiecutter_json["environment_manager"] diff --git a/tests/test_creation.py b/tests/test_creation.py index 4c2069420..42d355735 100644 --- a/tests/test_creation.py +++ b/tests/test_creation.py @@ -178,6 +178,10 @@ def verify_makefile_commands(root, config): f"Environment manager '{config['environment_manager']}' not found in test harnesses." ) + env = os.environ.copy() + env["EXPECTED_PYTHON_VERSION"] = config["python_version_number"] + env["PIPENV_IGNORE_VIRTUALENVS"] = "1" # pipenv should create its own virtualenv + result = run( [ BASH_EXECUTABLE, @@ -187,6 +191,7 @@ def verify_makefile_commands(root, config): ], stderr=PIPE, stdout=PIPE, + env=env, ) stdout_output, stderr_output = _decode_print_stdout_stderr(result) diff --git a/tests/test_functions.sh b/tests/test_functions.sh index 4bb6a4a6c..afac181a0 100644 --- a/tests/test_functions.sh +++ b/tests/test_functions.sh @@ -9,6 +9,15 @@ function run_tests () { exit 99 fi + # test Python version in created venv should be match configured version + CREATED_PYTHON_VERSION=$(python -c "import platform; print(platform.python_version())") + if [[ $(vspect parse $CREATED_PYTHON_VERSION "{major_minor_version}") == $EXPECTED_PYTHON_VERSION ]]; then + echo "Python version $CREATED_PYTHON_VERSION matches expected $EXPECTED_PYTHON_VERSION" + else + echo "Python version $CREATED_PYTHON_VERSION does not match $EXPECTED_PYTHON_VERSION" + exit 99 + fi + # test importable python -c "import $2" @@ -16,4 +25,4 @@ function run_tests () { if [ -f "$2/config.py" ]; then python -c "from $2 import config" fi -} \ No newline at end of file +} diff --git a/{{ cookiecutter.repo_name }}/Makefile b/{{ cookiecutter.repo_name }}/Makefile index 85eb9e5b4..d13c34bdf 100644 --- a/{{ cookiecutter.repo_name }}/Makefile +++ b/{{ cookiecutter.repo_name }}/Makefile @@ -108,7 +108,7 @@ create_environment: {% endif %} @echo ">>> conda env created. Activate with:\nconda activate $(PROJECT_NAME)" {% elif cookiecutter.environment_manager == 'virtualenv' -%} - @bash -c "if [ ! -z `which virtualenvwrapper.sh` ]; then source `which virtualenvwrapper.sh`; mkvirtualenv $(PROJECT_NAME) --python=$(PYTHON_INTERPRETER); else mkvirtualenv.bat $(PROJECT_NAME) --python=$(PYTHON_INTERPRETER); fi" + @bash -c "if [ ! -z `which virtualenvwrapper.sh` ]; then source `which virtualenvwrapper.sh`; mkvirtualenv $(PROJECT_NAME) --python=$(PYTHON_VERSION); else mkvirtualenv.bat $(PROJECT_NAME) --python=$(PYTHON_VERSION); fi" @echo ">>> New virtualenv created. Activate with:\nworkon $(PROJECT_NAME)" {% elif cookiecutter.environment_manager == 'pipenv' -%} pipenv --python $(PYTHON_VERSION)