diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4eaae9f..1bdda00 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -33,7 +33,12 @@ jobs: python-version: ${{ matrix.python-version }} cache: pip allow-prereleases: true - - run: pip install tox + - uses: prefix-dev/setup-pixi@v0.6.0 + with: + pixi-version: v0.20.1 + run-install: false + + - run: pip install tox-uv - name: Run tests. shell: bash -l {0} diff --git a/.gitignore b/.gitignore index 8e3b795..04dcee8 100644 --- a/.gitignore +++ b/.gitignore @@ -144,9 +144,10 @@ _generated *.egg-info .eggs -.pytask.sqlite3 +.pytask build dist -version.py +.ruff_cache +.mypy_cache diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..8531a3b --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.12.2 diff --git a/README.md b/README.md index 2143705..7d1619e 100644 --- a/README.md +++ b/README.md @@ -5,79 +5,17 @@ [![image](https://img.shields.io/github/actions/workflow/status/pytask-dev/cookiecutter-pytask-project/main.yml?branch=main)](https://github.com/pytask-dev/cookiecutter-pytask-project/actions?query=branch%3Amain) [![image](https://codecov.io/gh/pytask-dev/cookiecutter-pytask-project/branch/main/graph/badge.svg)](https://codecov.io/gh/pytask-dev/cookiecutter-pytask-project) [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/pytask-dev/cookiecutter-pytask-project/main.svg)](https://results.pre-commit.ci/latest/github/pytask-dev/cookiecutter-pytask-project/main) -[![image](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) +[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) This repository contains a minimal cookiecutter template for a project with [pytask](https://github.com/pytask-dev/pytask). -## Usage - -First, install cookiecutter. - -```console -$ pip install cookiecutter - -$ conda install -c conda-forge cookiecutter -``` - -Then, set up the template with - -```console -$ cookiecutter https://github.com/pytask-dev/cookiecutter-pytask-project -``` - ## Documentation -If you are new to pytask, just follow the -[tutorials](https://pytask-dev.readthedocs.io/en/stable/tutorials/index.html) which will -help you with your first steps like how to write the first task. - -If you are already familiar with pytask, the -[how-to guides](https://pytask-dev.readthedocs.io/en/stable/how_to_guides/index.html) -offer more in-depth guidance on complex projects. - -In general, you will find most guidance in the -[documentation](https://pytask-dev.readthedocs.io/en/stable/index.html) and some advice -in the FAQ below. - -## FAQ - -Q: Why are the source files nested in `src/`? - -A: This is called the src layout and the advantages are discussed in this -[article by Hynek Schlawack](https://hynek.me/articles/testing-packaging/). - -Although the article discusses the src layout in terms of Python packages, it is also -beneficial to structure a project the same way. Next to the reasons discussed there, it -is possible to use a single Python environment for multiple projects without messing -with your PYTHONPATH (via `pip install -e .` or `conda develop .`) each time and still -import modules. - -Q: My project is a Python package, but it does not seem to have a version. Where is it? - -A: The cookiecutter uses [setuptools_scm](https://github.com/pypa/setuptools_scm/) to -manage the version number. When you install your created project as a Python package -with `pip install -e .`, setuptools_scm tries to infer the version number from the tags -created on the repo. - -For example, if you have switched to a commit associated with the tag `v0.2.0`, -setuptools_scm will create a `src//_version.py` with a variable containing -`version = '0.2.0'` which you can use in your `src//__init__.py`. If you -are one commit ahead of the tag, you version will be something like `0.2.0.dev1+...` -indicating you are one commit ahead of the tag `v0.2.0`. - -If you want to switch to the tradition setup, replace the following code in your -`pyproject.toml` - -```toml -[build-system] -requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.0"] -``` +You find the documentation at . -with +## Changes -```toml -[build-system] -requires = ["setuptools"] -build-backend = "setuptools.build_meta" -``` +Consult the +[release notes](https://cookiecutter-pytask-project.readthedocs.io/en/latest/changes.html) +to find out about what is new. diff --git a/cookiecutter.json b/cookiecutter.json index 761bb8e..364b088 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -20,7 +20,5 @@ "Not open source" ], "make_initial_commit": ["no", "yes"], - "conda_environment_name": "{{ cookiecutter.project_slug }}", - "create_conda_environment_at_finish": ["no", "yes"], "_copy_without_render": [".github/workflows/main.yml"] } diff --git a/docs/source/faq.md b/docs/source/faq.md deleted file mode 100644 index 58d8eb2..0000000 --- a/docs/source/faq.md +++ /dev/null @@ -1,41 +0,0 @@ -# FAQ - -Q: Why are the source files nested in `src/`? - -A: This is called the src layout and the advantages are discussed in this -[article by Hynek Schlawack](https://hynek.me/articles/testing-packaging/). - -Although the article discusses the src layout in terms of Python packages, it is also -beneficial to structure a project the same way. Next to the reasons discussed there, it -is possible to use a single Python environment for multiple projects without messing -with your PYTHONPATH (via `pip install -e .` or `conda develop .`) each time and still -import modules. - -Q: My project is a Python package, but it does not seem to have a version. Where is it? - -A: The cookiecutter uses [setuptools_scm](https://github.com/pypa/setuptools_scm/) to -manage the version number. When you install your created project as a Python package -with `pip install -e .`, setuptools_scm tries to infer the version number from the tags -created on the repo. - -For example, if you have switched to a commit associated with the tag `v0.2.0`, -setuptools_scm will create a `src//_version.py` with a variable containing -`version = '0.2.0'` which you can use in your `src//__init__.py`. If you -are one commit ahead of the tag, you version will be something like `0.2.0.dev1+...` -indicating you are one commit ahead of the tag `v0.2.0`. - -If you want to switch to the tradition setup, replace the following code in your -`pyproject.toml` - -```toml -[build-system] -requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.0"] -``` - -with - -```toml -[build-system] -requires = ["setuptools"] -build-backend = "setuptools.build_meta" -``` diff --git a/docs/source/index.md b/docs/source/index.md index 0093590..2dfa30e 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -10,41 +10,94 @@ This repository contains a minimal cookiecutter template for a project with [pytask](https://github.com/pytask-dev/pytask). -## Usage +## Installation -First, install cookiecutter. +The template uses [pixi](https://pixi.sh/) as the package and environment manager which +is the successor of conda/mamba/micromamba. Please, install it. + +```{note} +Of course, the template can be used with any other package manager. But, we recommend +pixi which can install packages from conda, PyPI, etc.. or [rye](https://rye-up.com/) +for PyPI-only projects. +``` + +Then, install cookiecutter. ```console -$ pip install cookiecutter +pixi global install cookiecutter +``` + +Now, set up the template with -$ conda install -c conda-forge cookiecutter +```console +pixi run cookiecutter https://github.com/pytask-dev/cookiecutter-pytask-project ``` -Then, set up the template with +Many formatting issues exist after the project is created. Run pre-commit to polish the +template. ```console -$ cookiecutter https://github.com/pytask-dev/cookiecutter-pytask-project +pixi global install pre-commit +pixi run pre-commit run -a ``` -## Documentation +## Features + +Here is a feature list of the template. + +- [pixi](https://pixi.sh/latest/) as the environment and package manager. +- Supports pre-commit and some popular hooks like ruff and refurb. +- Initialized documentation in `docs`. +- Preconfigured GitHub actions and dependabot. +- Preconfigured readthedocs. +- Preconfigured CodeCov. + +## FAQ -If you are new to pytask, just follow the -[tutorials](https://pytask-dev.readthedocs.io/en/stable/tutorials/index.html) which will -help you with your first steps like how to write the first task. +Q: Why are the source files nested in `src/`? -If you are already familiar with pytask, the -[how-to guides](https://pytask-dev.readthedocs.io/en/stable/how_to_guides/index.html) -offer more in-depth guidance on complex projects. +A: This is called the src layout and the advantages are discussed in this +[article by Hynek Schlawack](https://hynek.me/articles/testing-packaging/). -In general, you will find most guidance in the -[documentation](https://pytask-dev.readthedocs.io/en/stable/index.html) and some advice -in the FAQ below. +Although the article discusses the src layout in terms of Python packages, it is also +beneficial to structure a project the same way. Next to the reasons discussed there, it +is possible to use a single Python environment for multiple projects without messing +with your PYTHONPATH (via `pip install -e .` or `conda develop .`) each time and still +import modules. + +Q: My project is a Python package, but it does not seem to have a version. Where is it? + +A: The cookiecutter uses [setuptools_scm](https://github.com/pypa/setuptools_scm/) to +manage the version number. When you install your created project as a Python package +with `pip install -e .`, setuptools_scm tries to infer the version number from the tags +created on the repo. + +For example, if you have switched to a commit associated with the tag `v0.2.0`, +setuptools_scm will create a `src//_version.py` with a variable containing +`version = '0.2.0'` which you can use in your `src//__init__.py`. If you +are one commit ahead of the tag, you version will be something like `0.2.0.dev1+...` +indicating you are one commit ahead of the tag `v0.2.0`. + +If you want to switch to the tradition setup, replace the following code in your +`pyproject.toml` + +```toml +[build-system] +requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.0"] +``` + +with + +```toml +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" +``` ```{toctree} --- caption: 'Contents:' maxdepth: 1 --- -faq changes ``` diff --git a/environment.yml b/environment.yml deleted file mode 100644 index 6090cbf..0000000 --- a/environment.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: cp - -channels: - - conda-forge - - nodefaults - -dependencies: - - python >=3.8 - - pip >=21.1 - - setuptools_scm - - toml - - # Package dependencies - - cookiecutter >=2.1.0 - - pytask >=0.2 - - # Misc - - black - - ipython - - mypy - - pre-commit - - pytest - # - pytest-cookies>=0.6.2 - - pytest-cov - - pytest-xdist - - tox-conda - - # Documentation - - furo - - myst-parser - - nbsphinx - - sphinx - - sphinx-copybutton - - sphinx-panels - - - pip: - - sphinxext-opengraph - - git+https://github.com/andriihomiak/pytest-cookies.git@fix/quotes_in_user_config diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index d45c3c6..002affb 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -4,7 +4,6 @@ import shutil import subprocess -import warnings from contextlib import suppress from pathlib import Path @@ -62,56 +61,6 @@ def main() -> None: capture_output=True, ) - if "{{ cookiecutter.create_conda_environment_at_finish }}" == "yes": - if shutil.which("mamba") is not None: - conda_exe = shutil.which("mamba") - else: - conda_exe = shutil.which("conda") - - if conda_exe: - subprocess.run( - ( - conda_exe, - "env", - "create", - "-f", - (project_path / "environment.yml").absolute().as_posix(), - "--force", - ), - check=True, - capture_output=True, - ) - # Install pre-commit hooks and run them. - subprocess.run( # noqa: PLW1510 - ( - conda_exe, - "run", - "-n", - "{{ cookiecutter.conda_environment_name }}", - "pre-commit", - "install", - ), - capture_output=True, - ) - subprocess.run( # noqa: PLW1510 - ( - conda_exe, - "run", - "-n", - "{{ cookiecutter.conda_environment_name }}", - "pre-commit", - "run", - "--all-files", - ), - capture_output=True, - ) - else: - warnings.warn( - "conda environment could not be created since no conda or mamba " - "executable was found.", - stacklevel=1, - ) - if __name__ == "__main__": main() diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py index 139ff03..e3db32d 100644 --- a/hooks/pre_gen_project.py +++ b/hooks/pre_gen_project.py @@ -4,7 +4,7 @@ MODULE_REGEX = r"^[_a-zA-Z][_a-zA-Z0-9]*$" ENVIRON_REGEX = r"^[-_a-zA-Z0-9]*$" -PYTHONVERSION_REGEX = r"^(3\.(1[0-9]|[7-9])(\.[0-9]{1,2})?)$" +PYTHONVERSION_REGEX = r"^(3\.(1[0-9]|[8-9])(\.[0-9]{1,2})?)$" PYTHONVERSION_MIN = "3.8" EXCEPTION_MSG_MODULE_NAME = """ @@ -33,13 +33,6 @@ def main() -> None: if not re.match(MODULE_REGEX, module_name): raise ValueError(EXCEPTION_MSG_MODULE_NAME.format(module_name=module_name)) - environment_name = "{{ cookiecutter.conda_environment_name }}" - - if not re.match(ENVIRON_REGEX, environment_name): - raise ValueError( - EXCEPTION_MSG_ENVIRON_NAME.format(environment_name=environment_name), - ) - python_version = "{{ cookiecutter.python_version }}" if not re.match(PYTHONVERSION_REGEX, python_version): diff --git a/pyproject.toml b/pyproject.toml index a450727..94ed373 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,16 +1,21 @@ -[build-system] -requires = ["setuptools", "wheel", "setuptools_scm[toml]"] -build-backend = "setuptools.build_meta" - -[tool.setuptools_scm] -write_to = "version.py" - [project] name = "cookiecutter_pytask_project" +version = "1.7.0" description = "A minimal cookiecutter template for a project with pytask." -classifiers = [ "Development Status :: 3 - Alpha", "Environment :: Console", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Topic :: Scientific/Engineering", "Topic :: Software Development :: Build Tools",] +classifiers = [ + "Development Status :: 3 - Alpha", + "Environment :: Console", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Topic :: Scientific/Engineering", + "Topic :: Software Development :: Build Tools", +] requires-python = ">=3.8" -dynamic = ["version"] dependencies = ["cookiecutter"] [[project.authors]] @@ -19,16 +24,16 @@ email = "raabe@posteo.de" [project.optional-dependencies] docs = [ - "furo", - "ipython", - "myst-parser", - "nbsphinx", - "sphinx", - "sphinx-click", - "sphinx-copybutton", - "sphinx-design>=0.3", - "sphinx-toolbox", - "sphinxext-opengraph", + "furo", + "ipython", + "myst-parser", + "nbsphinx", + "sphinx", + "sphinx-click", + "sphinx-copybutton", + "sphinx-design>=0.3", + "sphinx-toolbox", + "sphinxext-opengraph", ] test = ["pytest", "pytest-cookies", "pytest-cov"] @@ -46,10 +51,12 @@ Documentation = "https://cookiecutter-pytask-project.readthedocs.io/en/latest" Github = "https://github.com/pytask-dev/cookiecutter-pytask-project" Tracker = "https://github.com/pytask-dev/cookiecutter-pytask-project/issues" -[tool.setuptools] -platforms = [ "unix", "linux", "osx", "cygwin", "win32",] -license-files = [ "LICENSE"] -include-package-data = false +[tool.rye] +managed = true +virtual = true +dev-dependencies = [ + "tox-uv>=1.8.2", +] [tool.mypy] files = ["hooks", "tests"] @@ -74,9 +81,8 @@ unsafe-fixes = true [tool.ruff.lint] extend-ignore = [ - # Others. - "COM812", # Comply with ruff-format. - "ISC001", # Comply with ruff-format. + "COM812", # Comply with ruff-format. + "ISC001", # Comply with ruff-format. ] select = ["ALL"] diff --git a/requirements-dev.lock b/requirements-dev.lock new file mode 100644 index 0000000..e848340 --- /dev/null +++ b/requirements-dev.lock @@ -0,0 +1,80 @@ +# generated by rye +# use `rye lock` or `rye sync` to update this lockfile +# +# last locked with the following flags: +# pre: false +# features: [] +# all-features: true +# with-sources: false + +arrow==1.3.0 + # via cookiecutter +binaryornot==0.4.4 + # via cookiecutter +cachetools==5.3.3 + # via tox +certifi==2024.2.2 + # via requests +chardet==5.2.0 + # via binaryornot + # via tox +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via cookiecutter +colorama==0.4.6 + # via tox +cookiecutter==2.6.0 +distlib==0.3.8 + # via virtualenv +filelock==3.14.0 + # via tox + # via virtualenv +idna==3.7 + # via requests +jinja2==3.1.3 + # via cookiecutter +markdown-it-py==3.0.0 + # via rich +markupsafe==2.1.5 + # via jinja2 +mdurl==0.1.2 + # via markdown-it-py +packaging==24.0 + # via pyproject-api + # via tox + # via tox-uv +platformdirs==4.2.1 + # via tox + # via virtualenv +pluggy==1.5.0 + # via tox +pygments==2.17.2 + # via rich +pyproject-api==1.6.1 + # via tox +python-dateutil==2.9.0.post0 + # via arrow +python-slugify==8.0.4 + # via cookiecutter +pyyaml==6.0.1 + # via cookiecutter +requests==2.31.0 + # via cookiecutter +rich==13.7.1 + # via cookiecutter +six==1.16.0 + # via python-dateutil +text-unidecode==1.3 + # via python-slugify +tox==4.15.0 + # via tox-uv +tox-uv==1.8.2 +types-python-dateutil==2.9.0.20240316 + # via arrow +urllib3==2.2.1 + # via requests +uv==0.1.39 + # via tox-uv +virtualenv==20.26.1 + # via tox diff --git a/requirements.lock b/requirements.lock new file mode 100644 index 0000000..c7f16f0 --- /dev/null +++ b/requirements.lock @@ -0,0 +1,52 @@ +# generated by rye +# use `rye lock` or `rye sync` to update this lockfile +# +# last locked with the following flags: +# pre: false +# features: [] +# all-features: true +# with-sources: false + +arrow==1.3.0 + # via cookiecutter +binaryornot==0.4.4 + # via cookiecutter +certifi==2024.2.2 + # via requests +chardet==5.2.0 + # via binaryornot +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via cookiecutter +cookiecutter==2.6.0 +idna==3.7 + # via requests +jinja2==3.1.3 + # via cookiecutter +markdown-it-py==3.0.0 + # via rich +markupsafe==2.1.5 + # via jinja2 +mdurl==0.1.2 + # via markdown-it-py +pygments==2.17.2 + # via rich +python-dateutil==2.9.0.post0 + # via arrow +python-slugify==8.0.4 + # via cookiecutter +pyyaml==6.0.1 + # via cookiecutter +requests==2.31.0 + # via cookiecutter +rich==13.7.1 + # via cookiecutter +six==1.16.0 + # via python-dateutil +text-unidecode==1.3 + # via python-slugify +types-python-dateutil==2.9.0.20240316 + # via arrow +urllib3==2.2.1 + # via requests diff --git a/tests/test_cookie.py b/tests/test_cookie.py index 79aa5ce..6f3d27f 100644 --- a/tests/test_cookie.py +++ b/tests/test_cookie.py @@ -89,58 +89,43 @@ def test_remove_license(cookies): @pytest.mark.end_to_end() @pytest.mark.skipif(os.environ.get("CI") is None, reason="Run only in CI.") -def test_check_conda_environment_creation_and_run_all_checks(cookies): - """Test that the conda environment is created and pre-commit passes.""" +def test_check_pixi_and_run_all_checks(cookies): + """Test pixi and pre-commit passes.""" result = cookies.bake( - extra_context={ - "conda_environment_name": "__test__", - "make_initial_commit": "yes", - "create_conda_environment_at_finish": "yes", - "python_version": _PYTHON_VERSION, - }, + extra_context={"make_initial_commit": "yes", "python_version": _PYTHON_VERSION}, ) assert result.exit_code == 0 assert result.exception is None - if sys.platform != "win32": - # Switch branch before pre-commit because otherwise failure because on main - # branch. - subprocess.run( - ("git", "checkout", "-b", "test"), - cwd=result.project_path, - check=True, - ) - - # Check linting, but not on the first try since formatters fix stuff. - subprocess.run( - ("conda", "run", "-n", "__test__", "pre-commit", "run", "--all-files"), - cwd=result.project_path, - check=False, - ) - subprocess.run( - ("conda", "run", "-n", "__test__", "pre-commit", "run", "--all-files"), - cwd=result.project_path, - check=True, - ) - - # Install package. - subprocess.run( - ("conda", "run", "-n", "__test__", "pip", "install", "-e", "."), - cwd=result.project_path, - check=True, - ) - - # Run tests. - subprocess.run( - ("conda", "run", "-n", "__test__", "pytest"), - cwd=result.project_path, - check=True, - ) - - # Test building documentation - subprocess.run( - ("conda", "run", "-n", "__test__", "make", "html"), - cwd=result.project_path / "docs", - check=True, - ) + # Switch branch before pre-commit because otherwise failure because on main + # branch. + subprocess.run( + ("git", "checkout", "-b", "test"), + cwd=result.project_path, + check=True, + ) + + # Install pre-commit. + subprocess.run( + ("pixi", "global", "install", "pre-commit"), + cwd=result.project_path, + check=True, + ) + # Check linting, but not on the first try since formatters fix stuff. + subprocess.run( + ("pixi", "run", "pre-commit", "run", "--all-files"), + cwd=result.project_path, + check=False, + ) + subprocess.run( + ("pixi", "run", "pre-commit", "run", "--all-files"), + cwd=result.project_path, + check=True, + ) + + # Run tests. + subprocess.run(("pixi", "run", "test"), cwd=result.project_path, check=True) + + # Test building documentation + subprocess.run(("pixi", "run", "docs"), cwd=result.project_path, check=True) diff --git a/tox.ini b/tox.ini index dd200b0..49f3e59 100644 --- a/tox.ini +++ b/tox.ini @@ -1,20 +1,21 @@ [tox] -envlist = test, docs +requires = tox>=4 +envlist = docs, test [testenv] -usedevelop = true passenv = CI - -[testenv:test] -allowlist_externals = pytest -extras = test - -commands = - pytest {posargs} +package = editable [testenv:docs] -extras = docs -changedir = docs/source +extras = docs, test commands = - sphinx-build -T -b html -d {envtmpdir}/doctrees . {envtmpdir}/html - - sphinx-build -T -b linkcheck -d {envtmpdir}/doctrees . {envtmpdir}/linkcheck + sphinx-build -n -T -b html -d {envtmpdir}/doctrees docs/source docs/build/html + - sphinx-build -n -T -b doctest -d {envtmpdir}/doctrees docs/source docs/build/html + +[testenv:typing] +extras = typing +commands = mypy + +[testenv:test] +extras = test +commands = pytest {posargs} diff --git a/{{cookiecutter.project_slug}}/.github/workflows/main.yml b/{{cookiecutter.project_slug}}/.github/workflows/main.yml index f61c9b2..381a926 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/main.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/main.yml @@ -5,9 +5,6 @@ concurrency: group: ${{ github.head_ref || github.run_id }} cancel-in-progress: true -env: - CONDA_EXE: mamba - on: push: branches: @@ -31,20 +28,14 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: mamba-org/provision-with-micromamba@main + - uses: prefix-dev/setup-pixi@v0.6.0 with: - environment-file: false - environment-name: gha-testing - channels: conda-forge,nodefaults - extra-specs: | - python=${{ matrix.python-version }} - mamba - tox-conda - cache-downloads: true + pixi-version: v0.20.1 + cache: true - name: Run tests and doctests. shell: bash -l {0} - run: tox -e pytest + run: pixi run test - name: Upload coverage report uses: codecov/codecov-action@v4 diff --git a/{{cookiecutter.project_slug}}/MANIFEST.in b/{{cookiecutter.project_slug}}/MANIFEST.in deleted file mode 100644 index 95e45be..0000000 --- a/{{cookiecutter.project_slug}}/MANIFEST.in +++ /dev/null @@ -1,9 +0,0 @@ -include CITATION -{% if cookiecutter.open_source_license != 'Not open source' %}include LICENSE -{% endif %} -exclude *.yaml -exclude *.yml -exclude tox.ini - -prune docs -prune tests diff --git a/{{cookiecutter.project_slug}}/README.md b/{{cookiecutter.project_slug}}/README.md index bf38756..5e0e5a1 100644 --- a/{{cookiecutter.project_slug}}/README.md +++ b/{{cookiecutter.project_slug}}/README.md @@ -17,18 +17,16 @@ cookiecutter.github_username }}/{{ cookiecutter.project_slug cookiecutter.github_username }}/{{ cookiecutter.project_slug }}/main) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) -## Usage +## Installation -To get started, create the environment with +To work with the project, you should have [pixi](https://pixi.sh/latest/) installed. -```console -$ mamba env create -``` +## Usage To build the project, type ```console -$ pytask +pixi run pytask ``` ## Credits diff --git a/{{cookiecutter.project_slug}}/dependabot.yml b/{{cookiecutter.project_slug}}/dependabot.yml deleted file mode 100644 index fbb58d4..0000000 --- a/{{cookiecutter.project_slug}}/dependabot.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: 2 - -updates: - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - - groups: - github-actions: - patterns: - - "*" diff --git a/{{cookiecutter.project_slug}}/docs/source/conf.py b/{{cookiecutter.project_slug}}/docs/source/conf.py index d9c3d2c..0afcfcc 100644 --- a/{{cookiecutter.project_slug}}/docs/source/conf.py +++ b/{{cookiecutter.project_slug}}/docs/source/conf.py @@ -37,8 +37,8 @@ "sphinxext.opengraph", "sphinx.ext.viewcode", "sphinx_copybutton", - "sphinx_panels", "myst_parser", + "sphinx_design", ] # Add any paths that contain templates here, relative to this directory. diff --git a/{{cookiecutter.project_slug}}/environment.yml b/{{cookiecutter.project_slug}}/environment.yml deleted file mode 100644 index e135210..0000000 --- a/{{cookiecutter.project_slug}}/environment.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: {{ cookiecutter.conda_environment_name }} - -channels: - - conda-forge - - nodefaults - -dependencies: - - python =={{ cookiecutter.python_version }} - - pip >=21.1 - - setuptools_scm - - toml - - # Reproducibility - - conda-lock - - # Package dependencies - - pytask >=0.4 - - # Misc - - black - - ipython - - pre-commit - - pytest - - pytest-cov - - pytest-xdist - - tox-conda - - # Documentation - - furo - - myst-parser - - nbsphinx - - sphinx - - sphinx-copybutton - - sphinx-panels - - - pip: - - sphinxext-opengraph - - -e . diff --git a/{{cookiecutter.project_slug}}/pyproject.toml b/{{cookiecutter.project_slug}}/pyproject.toml index f06690c..e41393b 100644 --- a/{{cookiecutter.project_slug}}/pyproject.toml +++ b/{{cookiecutter.project_slug}}/pyproject.toml @@ -1,23 +1,21 @@ [build-system] -requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.0"] - -[tool.setuptools_scm] -write_to = "src/{{ cookiecutter.project_slug }}/_version.py" +requires = ["hatchling"] +build-backend = "hatchling.build" [project] name = "{{ cookiecutter.project_slug }}" +version = "0.1.0" description = "{{ cookiecutter.project_description }}" requires-python = ">=3.8" classifiers = [ - "Intended Audience :: Science/Research", - "License :: OSI Approved :: {{ cookiecutter.open_source_license }} License", - "Operating System :: MacOS :: MacOS X", - "Operating System :: Microsoft :: Windows", - "Operating System :: POSIX", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3 :: Only", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: {{ cookiecutter.open_source_license }} License", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", ] -dynamic = ["version"] dependencies = ["pytask"] [project.readme] @@ -43,7 +41,7 @@ docs = [ "sphinx-toolbox", "sphinxext-opengraph", ] -test = [] +test = ["pytest", "pytest-cov", "pytest-xdist"] [project.urls] Changelog = "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }}" @@ -51,19 +49,6 @@ Documentation = "https://github.com/{{ cookiecutter.github_username }}/{{ cookie Github = "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }}" Tracker = "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }}/issues" -[tool.setuptools] -include-package-data = true -zip-safe = false -platforms = ["unix", "linux", "osx", "win32"] -license-files = ["LICENSE"] - -[tool.setuptools.package-dir] -"" = "src" - -[tool.setuptools.packages.find] -where = ["src"] -namespaces = false - {% if cookiecutter.add_mypy == "yes" %}[tool.mypy] files = ["src", "tests"] check_untyped_defs = true @@ -75,10 +60,10 @@ warn_redundant_casts = true warn_unused_ignores = true [[tool.mypy.overrides]] +ignore_errors = true module = "tests.*" disallow_untyped_defs = false -ignore_errors = true{% endif %} - +{% endif %} [tool.pytask.ini_options] paths = ["src/{{ cookiecutter.project_slug }}"] @@ -89,8 +74,8 @@ unsafe-fixes = true [tool.ruff.lint] extend-ignore = [ - "COM812", # Comply with ruff-format. - "ISC001", # Comply with ruff-format. + "COM812", # Comply with ruff-format. + "ISC001", # Comply with ruff-format. ] select = ["ALL"] @@ -108,3 +93,26 @@ convention = "numpy" addopts = ["--doctest-modules"] testpaths = ["src", "tests"] norecursedirs = [".idea", ".tox"] + +[tool.pixi.project] +channels = ["conda-forge"] +platforms = ["win-64", "linux-64", "osx-64", "osx-arm64"] + +[tool.pixi.dependencies] +pytask = ">=0.4.7,<0.5" + +[tool.pixi.pypi-dependencies] +{{ cookiecutter.project_slug }} = { path = ".", editable = true } + +[tool.pixi.environments] +default = { solve-group = "default" } +docs = { features = ["docs"], solve-group = "default" } +test = { features = ["test"], solve-group = "default" } + +[tool.pixi.tasks] + +[tool.pixi.feature.test.tasks] +test = "pytest --cov src --cov tests" + +[tool.pixi.feature.docs.tasks] +docs = "sphinx-build -b html docs/source docs/build" diff --git a/{{cookiecutter.project_slug}}/tox.ini b/{{cookiecutter.project_slug}}/tox.ini deleted file mode 100644 index 76e568a..0000000 --- a/{{cookiecutter.project_slug}}/tox.ini +++ /dev/null @@ -1,25 +0,0 @@ -[tox] -requires = tox>=4 -envlist = docs, test - -[testenv] -package = editable - -[testenv:test] -conda_channels = - conda-forge - nodefaults -conda_deps = - # pytest - pytest - pytest-cov - pytest-xdist - -commands = - pytest {posargs} - -[testenv:docs] -extras = docs, test -commands = - - sphinx-build -n -T -b html -d {envtmpdir}/doctrees docs/source docs/build/html - - sphinx-build -n -T -b doctest -d {envtmpdir}/doctrees docs/source docs/build/html