diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index cd3db918..b4356743 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -58,6 +58,7 @@ jobs: strategy: matrix: smoke_file: + - automation.sh - auto-format-tools.sh - build-systems.sh - containers.sh diff --git a/LICENSE b/LICENSE index ef11565c..3eec1cb0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,27 +1,29 @@ -Copyright (c) Open Science Labs and individual contributors. +BSD License +Copyright (c) 2023, Open Science Labs All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of Audrey Roy Greenfeld nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/guide.md b/docs/guide.md index 29d82b4a..e46f7bbc 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -24,6 +24,7 @@ The structure of the guide is as follows: - [Static analysis of shell scripts](#static-analysis-of-shell-scripts) - [Pre-commit verification](#pre-commit-verification) - [Integration with DevOps tools](#integration-with-devops-tools) + - [Automation tools](#automation-tools) - [Project team](#project-team) - [Code of conduct](#code-of-conduct) - [Governance document](#governance-document) @@ -189,7 +190,7 @@ two alternatives: *src* and *flat*. subdirectories that represent different modules or packages. Each module or package within the "src" directory focuses on a specific aspect of the project's functionality. - + For example, a project following the src structure might have the following layout: @@ -215,7 +216,7 @@ two alternatives: *src* and *flat*. code files directly in the project's root directory without any subdirectories. This means that all modules and packages are at the same level and there is no explicit separation between different aspects of the project. - + Here's an example of a flat structure: ```python @@ -305,7 +306,7 @@ packages. SciCookie support the following: PEP 517 compilation backend, PEP 621 project metadata, a flexible and powerful plugin system. It also offers, among other things, versatile user scripting, PyPI integration and version management. - + - [**Hatch**](https://hatch.pypa.io): It's a PEP 517/PEP 660 compatible build backend used by Hatch, a modern, extensible Python project manager. It provides a standardized build system with reproducible builds by default, @@ -333,7 +334,7 @@ packages. SciCookie support the following: cross-compilation, and efficient dependency locating with their associated build requirements. With its capabilities, it facilitates cross-platform builds using CMake and effortless integration with C/C++ libraries, making - it a valuable asset for research software engineers. + it a valuable asset for research software engineers. - [**setuptools + pybind11**](https://pybind11.readthedocs.io/en/stable/): It's build system designed for C++ library that simplifies the creation of Python bindings for C++ code, @@ -346,8 +347,8 @@ packages. SciCookie support the following: support have made it a popular choice for projects requiring seamless interoperability between C++ and Python, ranging from scientific computing to game development and automation. Staying up-to-date with the latest pybind11 documentation ensures the - best practices are followed. - + best practices are followed. + The idea behind the options in SciCookie is that you can choose from some of the most popular system compilers to suit your needs and preferences for developing Python packages. If you think we should add more options, you can submit your @@ -770,18 +771,18 @@ by selecting the option `None` (this is the default option). ## Automation Tools -An automation tool is software or a platform designed to automate repetitive +An automation tool is software or a platform designed to automate repetitive tasks, processes, or workflows that are traditionally performed manually. -These tools are used to streamline and optimize various operations, reduce +These tools are used to streamline and optimize various operations, reduce human intervention, increase efficiency, and minimize errors. -Currently SciCookie is using `make` and `Makim` +Currently, SciCookie allows you to use `Make` and/or `Makim`. -- [Makim](https://osl-incubator.github.io/makim): MakIm is an innovative tool -inspired by Make, designed to simplify target and dependency definition +- [Makim](https://osl-incubator.github.io/makim): Makim is an innovative tool +inspired by make, designed to simplify target and dependency definition through YAML format. It introduces advanced features such as conditionals, arguments, and dependencies with targeted parameters. It also facilitates organized grouping of targets and supports user-defined variables and environment -variables. MakIm empowers users to streamline documentation and parameterize +variables. Makim empowers users to streamline documentation and parameterize targets effectively. This free and open-source tool offers improved target management while maintaining compatibility with familiar YAML syntax. diff --git a/pyproject.toml b/pyproject.toml index 9a47d918..407e8abf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ include = [ "scicookie" = "scicookie.__main__:app" [tool.poetry.dependencies] -python = "^3.8.1" +python = ">=3.8.1,<4" cookieninja = "1.0.0" sh = "^2.0.4" colorama = "^0.4.6" diff --git a/src/scicookie/cookiecutter.json b/src/scicookie/cookiecutter.json index f17ce578..a4800d6c 100644 --- a/src/scicookie/cookiecutter.json +++ b/src/scicookie/cookiecutter.json @@ -29,10 +29,6 @@ "sphinx", "jupyter-book" ], - "automation_tools": [ - "Makim", - "Make" - ], "documentation_url": "{{ cookiecutter.project_url }}", "code_of_conduct": [ "None", @@ -63,6 +59,8 @@ "use_black": "yes", "use_blue": "no", "use_conda": "yes", + "use_makim": "yes", + "use_make": "no", "use_containers": [ "None", "Docker", diff --git a/src/scicookie/hooks/post_gen_project.py b/src/scicookie/hooks/post_gen_project.py index dd164684..515c6245 100644 --- a/src/scicookie/hooks/post_gen_project.py +++ b/src/scicookie/hooks/post_gen_project.py @@ -33,6 +33,8 @@ USE_CONTAINERS = {{ cookiecutter.use_containers in ['Docker', 'Podman'] }} USE_CLI = {{ cookiecutter.command_line_interface != "No command-line interface" }} USE_CONDA = {{ cookiecutter.use_conda == "yes" }} +USE_MAKE = {{ cookiecutter.use_make == "yes" }} +USE_MAKIM = {{ cookiecutter.use_makim == "yes" }} USE_MYPY = {{ cookiecutter.use_mypy == "yes" }} {% if cookiecutter.code_of_conduct == "contributor-covenant" -%} COC_PATH = PROJECT_DIRECTORY / 'coc' / 'CONTRIBUTOR_COVENANT.md' @@ -106,6 +108,13 @@ def move_selected_doc_dir(): shutil.rmtree(DOCS_SPEC_DIR) +def clean_up_automation(): + if not USE_MAKE: + remove_project_file("Makefile") + + if not USE_MAKIM: + remove_project_file(".makim.yaml") + def clean_up_docs(): remove_dirs(UNUSED_DOCS_DIRS) move_selected_doc_dir() @@ -231,7 +240,7 @@ def clean_up_build_system(): shutil.move( build_system_dir / "setup.py", PROJECT_DIRECTORY / 'setup.py' - ) + ) else: shutil.move( build_system_dir / "base-pyproject.toml", @@ -329,6 +338,7 @@ def post_gen(): # keep this one first, because it changes the package folder clean_up_project_layout() add_binding_source_files() + clean_up_automation() clean_up_cli() clean_up_mypy() clean_up_code_of_conduct() diff --git a/src/scicookie/profiles/base.yaml b/src/scicookie/profiles/base.yaml index 592608d0..a9d8a59d 100644 --- a/src/scicookie/profiles/base.yaml +++ b/src/scicookie/profiles/base.yaml @@ -132,6 +132,8 @@ use_tools: - flake8 - ruff - isort + - make + - makim - mccabe - mypy - pre-commit diff --git a/src/scicookie/{{cookiecutter.project_slug}}/.editorconfig b/src/scicookie/{{cookiecutter.project_slug}}/.editorconfig index d4a2c440..eb618738 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/.editorconfig +++ b/src/scicookie/{{cookiecutter.project_slug}}/.editorconfig @@ -4,18 +4,22 @@ root = true [*] indent_style = space -indent_size = 4 +indent_size = 2 trim_trailing_whitespace = true insert_final_newline = true charset = utf-8 end_of_line = lf +[*.py] +indent_style = space +indent_size = 4 + [*.bat] indent_style = tab end_of_line = crlf [LICENSE] -insert_final_newline = false +insert_final_newline = true [Makefile] indent_style = tab diff --git a/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE.md b/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 4732fbaa..00000000 --- a/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,15 +0,0 @@ -* {{ cookiecutter.project_name }} version: -* Python version: -* Operating System: - -### Description - -Describe what you were trying to get done. -Tell us what happened, what went wrong, and what you expected to happen. - -### What I Did - -``` -Paste the command(s) you ran and the output. -If there was a crash, please include the traceback here. -``` diff --git a/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/bug-report.yml b/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/bug-report.yml index e20480fa..a0fb06f6 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,3 +1,10 @@ +{%- if not cookiecutter.git_https_upstream -%} +{% set github_url = cookiecutter.git_https_upstream -%} +{%- elif not cookiecutter.git_https_origin -%} +{% set github_url = cookiecutter.git_https_origin -%} +{%- else -%} +{% set github_url = "https://github.com/" + cookiecutter.project_name + "/" + cookiecutter.project_name -%} +{%- endif -%} --- name: 🐛 Bug Report description: Create a report to help us improve @@ -15,7 +22,7 @@ body: GitHub][issue search]. - [issue search]: https://github.com/{{ cookiecutter.project_name }}/issues?q=is%3Aopen+is%3Aissue+label%3Abug + [issue search]: {{ github_url }}/issues?q=is%3Aopen+is%3Aissue+label%3Abug - type: textarea attributes: @@ -141,7 +148,7 @@ body: description: | Read the [`{{ cookiecutter.project_name }}` Code of Conduct][CoC] first. - [CoC]: https://github.com/{{cookiecutter.project_slug}}/coc/CODE_OF_CONDUCT.md + [CoC]: {{ github_url }}/coc/CODE_OF_CONDUCT.md options: - label: I agree to follow the Code of Conduct required: true diff --git a/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/config.yml b/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/config.yml index 50f0ebe8..97e7913a 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/config.yml +++ b/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/config.yml @@ -1,15 +1,22 @@ +{%- if not cookiecutter.git_https_upstream -%} +{% set github_url = cookiecutter.git_https_upstream -%} +{%- elif not cookiecutter.git_https_origin -%} +{% set github_url = cookiecutter.git_https_origin -%} +{%- else -%} +{% set github_url = "https://github.com/" + cookiecutter.project_name + "/" + cookiecutter.project_name -%} +{%- endif -%} # Ref: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository#configuring-the-template-chooser blank_issues_enabled: true contact_links: - name: 🙋 Usage Questions - url: https://github.com/{{cookiecutter.project_slug}}/discussions + url: {{ github_url }}/discussions about: | Use {{ cookiecutter.project_name }}'s GitHub Discussions to ask "How do I do X with Cookiecutter?". - name: 📖 Tutorial - url: https://github.com/{{cookiecutter.project_slug}} + url: {{ github_url }} about: | The {{ cookiecutter.project_name }} tutorial is continually updated and provides an in depth walkthrough of how to use the latest release of Cookiecutter. - name: 📝 {{ cookiecutter.project_name }} Code of Conduct - url: https://github.com/{{cookiecutter.project_slug}}/coc/CODE_OF_CONDUCT.md + url: {{ github_url }}/coc/CODE_OF_CONDUCT.md about: Expectations for how people will interact with each other on Cookiecutter's GitHub. diff --git a/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/documentation-report.yml b/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/documentation-report.yml index 757fc9f6..542043e5 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/documentation-report.yml +++ b/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/documentation-report.yml @@ -1,3 +1,10 @@ +{%- if not cookiecutter.git_https_upstream -%} +{% set github_url = cookiecutter.git_https_upstream -%} +{%- elif not cookiecutter.git_https_origin -%} +{% set github_url = cookiecutter.git_https_origin -%} +{%- else -%} +{% set github_url = "https://github.com/" + cookiecutter.project_name + "/" + cookiecutter.project_name -%} +{%- endif -%} --- name: 📝 Documentation Report description: Create a report for problems with the docs @@ -15,7 +22,7 @@ body: GitHub][issue search]. - [issue search]: https://github.com/{{ cookiecutter.project_name }}/issues?q=is%3Aopen+is%3Aissue+label%3Adocs + [issue search]: {{ github_url }}/issues?q=is%3Aopen+is%3Aissue+label%3Adocs - type: textarea attributes: @@ -45,7 +52,7 @@ body: description: | Read the [`{{ cookiecutter.project_name }}` Code of Conduct][CoC] first. - [CoC]: https://github.com/{{ cookiecutter.project_name }}/blob/main/CODE_OF_CONDUCT.md + [CoC]: {{ github_url }}/blob/main/CODE_OF_CONDUCT.md options: - label: I agree to follow the Code of Conduct required: true diff --git a/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/feature-request.yml b/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/feature-request.yml index 745f2b4f..0a5eec2e 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/src/scicookie/{{cookiecutter.project_slug}}/.github/ISSUE_TEMPLATE/feature-request.yml @@ -1,3 +1,10 @@ +{%- if not cookiecutter.git_https_upstream -%} +{% set github_url = cookiecutter.git_https_upstream -%} +{%- elif not cookiecutter.git_https_origin -%} +{% set github_url = cookiecutter.git_https_origin -%} +{%- else -%} +{% set github_url = "https://github.com/" + cookiecutter.project_name + "/" + cookiecutter.project_name -%} +{%- endif -%} --- name: ✨ Feature Request description: Suggest an idea for this project @@ -17,7 +24,7 @@ body: already be implemented in a development release. - [issue search]: https://github.com/{{ cookiecutter.project_name }}/issues?q=is%3Aopen+is%3Aissue+label%3Afeat%2Fenhancement + [issue search]: {{ github_url }}/issues?q=is%3Aopen+is%3Aissue+label%3Afeat%2Fenhancement - type: textarea @@ -73,7 +80,7 @@ body: description: | Read the [`{{ cookiecutter.project_name }}` Code of Conduct][CoC] first. - [CoC]: https://github.com/{{cookiecutter.project_slug}}/coc/CODE_OF_CONDUCT.md + [CoC]: {{ github_url }}/coc/CODE_OF_CONDUCT.md options: - label: I agree to follow the Code of Conduct required: true diff --git a/src/scicookie/{{cookiecutter.project_slug}}/.github/workflows/main.yaml b/src/scicookie/{{cookiecutter.project_slug}}/.github/workflows/main.yaml index 672260ef..ea393e01 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/.github/workflows/main.yaml +++ b/src/scicookie/{{cookiecutter.project_slug}}/.github/workflows/main.yaml @@ -28,20 +28,30 @@ jobs: miniforge-variant: Mambaforge - name: Install dependencies - run: poetry install + run: | + {%- if cookiecutter.build_system == "poetry" %} + poetry install + {%- elif cookiecutter.build_system == "flit" %} + flit install + {%- elif cookiecutter.build_system == "pdm" %} + pdm install + {%- else %} + pip install . + {%- endif %} - name: Run tests run: | - {% if cookiecutter.automation_tools == "makim" %} - makim tests.unittest - {% else %} - make test - {% endif %} + {%- if cookiecutter.use_makim == "yes" %} + makim tests.unit + {%- else %} + make test + {%- endif %} + - name: Run style checks run: | pre-commit install - {% if cookiecutter.automation_tools == "makim" %} - makim tests.lint - {% else %} - make lint - {% endif %} + {%- if cookiecutter.use_makim == "yes" %} + makim tests.linter + {%- else %} + make lint + {%- endif %} diff --git a/src/scicookie/{{cookiecutter.project_slug}}/.github/workflows/release.yaml b/src/scicookie/{{cookiecutter.project_slug}}/.github/workflows/release.yaml index 23c727ff..9beaa606 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/.github/workflows/release.yaml +++ b/src/scicookie/{{cookiecutter.project_slug}}/.github/workflows/release.yaml @@ -7,11 +7,16 @@ on: pull_request: branches: [ main ] +permissions: + contents: write + issues: write + pull-requests: write + jobs: release: name: Release runs-on: ubuntu-latest - timeout-minutes: 10 + timeout-minutes: 10 defaults: run: @@ -32,13 +37,27 @@ jobs: miniforge-variant: Mambaforge - name: Install deps - run: poetry install + run: | + {%- if cookiecutter.build_system == "poetry" %} + poetry install + {%- elif cookiecutter.build_system == "flit" %} + flit install + {%- elif cookiecutter.build_system == "pdm" %} + pdm install + {%- else %} + pip install . + {%- endif %} - name: Run semantic release (for tests) if: ${{ "{{ github.event_name != 'workflow_dispatch' }}" }} env: GITHUB_TOKEN: ${{ "{{ secrets.GITHUB_TOKEN }}" }} - run: make release-dry + run: | + {%- if cookiecutter.use_makim == "yes" %} + makim release.dry + {%- elif cookiecutter.use_make == "yes" -%} + make release-dry + {%- endif %} - name: Release command if: ${{ "{{ github.event_name == 'workflow_dispatch' }}" }} @@ -47,15 +66,31 @@ jobs: PYPI_TOKEN: ${{ "{{ secrets.PYPI_TOKEN }}" }} run: | poetry config pypi-token.pypi ${PYPI_TOKEN} + {%- if cookiecutter.use_makim == "yes" %} + makim release.ci + {%- elif cookiecutter.use_make == "yes" -%} make release-ci + {%- endif %} - name: Generate documentation with changes from semantic-release if: ${{ "{{ github.event_name == 'workflow_dispatch' }}" }} - run: make docs-build + run: | + {%- if cookiecutter.use_makim == "yes" %} + makim docs.build + {%- elif cookiecutter.use_make == "yes" -%} + make docs-build + {%- endif %} - name: GitHub Pages action if: ${{ "{{ github.event_name == 'workflow_dispatch' }}" }} uses: peaceiris/actions-gh-pages@v3.5.9 with: github_token: ${{ "{{ secrets.GITHUB_TOKEN }}" }} - publish_dir: ./docs/_build/html + publish_dir: >- + {%- if cookiecutter.documentation_engine == "jupyter-book" %} + ./docs/_build/html + {%- elif cookiecutter.documentation_engine == "mkdocs" %} + build/ + {%- elif cookiecutter.documentation_engine == "sphinx" %} + docs/_build/html/ + {%- endif %} diff --git a/src/scicookie/{{cookiecutter.project_slug}}/.makim.yaml b/src/scicookie/{{cookiecutter.project_slug}}/.makim.yaml index 3b698383..5ffa22bd 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/.makim.yaml +++ b/src/scicookie/{{cookiecutter.project_slug}}/.makim.yaml @@ -1,8 +1,13 @@ +{%- if cookiecutter.project_layout == "src" -%} +{%- set package_path = "src/" + cookiecutter.package_slug -%} +{%- else -%} +{%- set package_path = cookiecutter.package_slug -%} +{%- endif -%} version: 1.0 groups: - default: + clean: targets: - clean: + all: help: Clean unnecessary temporary files run: | rm -fr build/ @@ -17,18 +22,86 @@ groups: rm -f .coverage rm -fr htmlcov/ rm -fr .pytest_cache + rm -fr .mypy_cache + rm -fr .ruff_cache docs: targets: build: help: Build documentation run: | + {%- if cookiecutter.documentation_engine == "jupyter-book" %} rm -rf docs/_build jupyter-book build docs + {%- elif cookiecutter.documentation_engine == "mkdocs" %} + mkdocs build --config-file docs/mkdocs.yaml + {%- elif cookiecutter.documentation_engine == "sphinx" %} + sphinx-apidoc -o docs/_build {{ package_path }} + {%- endif %} preview: help: Preview documentation page locally - run: echo "[EE] Not implemented yet!" + dependencies: + - target: docs.build + run: | + {%- if cookiecutter.documentation_engine == "jupyter-book" %} + cd docs/_build/html/ && python -m http.server + {%- elif cookiecutter.documentation_engine == "mkdocs" %} + mkdocs build --config-file docs/mkdocs.yaml + {%- elif cookiecutter.documentation_engine == "sphinx" %} + cd docs/_build && python -m http.server + {%- endif %} + + tests: + targets: + linter: + help: Run linter tools + run: | + pre-commit install + pre-commit run --all-files --verbose + + unit: + help: run tests + args: + path: + help: Specify the location of the tests + type: string + default: "" + params: + help: Specify parameters to be used for tests + type: string + default: "-vv" + run: | + pytest {{ "{{ args.path }} {{ args.params }}" }} + + ci: + help: run the sames tests executed on CI + dependencies: + - target: tests.unit + - target: tests.linter + + package: + targets: + build: + help: "Build the package" + run: | + {%- if cookiecutter.build_system == "poetry" %} + poetry build + {%- elif cookiecutter.build_system == "flit" %} + flit build + {%- elif cookiecutter.build_system == "mesonpy" %} + meson build + {%- elif cookiecutter.build_system == "setuptools" %} + python -m build + {%- elif cookiecutter.build_system == "pdm" %} + pdm build + {%- elif cookiecutter.build_system == "hatch" %} + hatch build + {%- elif cookiecutter.build_system == "maturin" %} + maturin build + {%- elif cookiecutter.build_system == "pybind11" %} + python -m build + {%- endif %} release: vars: @@ -44,13 +117,11 @@ groups: -p "@google/semantic-release-replace-plugin" \ semantic-release - - tests: targets: - lint: - help: Run linter tools - run: pre-commit run --all-files --verbose + ci: + help: run semantic release on CI + run: {{ "{{ vars.app }} --ci" }} - unittest: - help: Run tests - run: pytest -s -vv {{cookiecutter.project_slug}} tests + dry: + help: run semantic release in dry-run mode + run: {{ "{{ vars.app }} --dry-run" }} diff --git a/src/scicookie/{{cookiecutter.project_slug}}/.releaserc.json b/src/scicookie/{{cookiecutter.project_slug}}/.releaserc.json index de667626..abfe2459 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/.releaserc.json +++ b/src/scicookie/{{cookiecutter.project_slug}}/.releaserc.json @@ -1,15 +1,15 @@ -{%- if cookiecutter.use_blue %} +{%- if cookiecutter.use_blue -%} {%- set QUOTE = "'" -%} -{%- elif cookiecutter.use_black %} +{%- elif cookiecutter.use_black -%} {%- set QUOTE = '\\"' -%} -{%- else %} +{%- else -%} {%- set QUOTE = "'" -%} -{%- endif %} -{%- if cookiecutter.project_layout == "src" %} - {%- set PROJECT_PATH = "{{ cookiecutter.package_slug }}/src" -%} -{%- else %} - {%- set PROJECT_PATH = "{{ cookiecutter.package_slug }}" -%} -{%- endif %} +{%- endif -%} +{%- if cookiecutter.project_layout == "src" -%} + {%- set PROJECT_PATH = "src/" + cookiecutter.package_slug -%} +{%- else -%} + {%- set PROJECT_PATH = cookiecutter.package_slug -%} +{%- endif -%} { "branches": ["main"], diff --git a/src/scicookie/{{cookiecutter.project_slug}}/Makefile b/src/scicookie/{{cookiecutter.project_slug}}/Makefile index 3e230a4c..34d63b4e 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/Makefile +++ b/src/scicookie/{{cookiecutter.project_slug}}/Makefile @@ -55,10 +55,13 @@ clean: ## remove build artifacts, compiled files, and cache rm -f .coverage rm -fr htmlcov/ rm -fr .pytest_cache + rm -fr .mypy_cache + rm -fr .ruff_cache .PHONY:lint lint: - pre-commit run --all-files + pre-commit install + pre-commit run --all-files --verbose .PHONY: test test: ## run tests quickly with the default Python @@ -101,23 +104,23 @@ docs-preview: docs-build .PHONY:build build: -{%- if cookiecutter.build_system == "poetry" %} + {%- if cookiecutter.build_system == "poetry" %} poetry build -{%- elif cookiecutter.build_system == "flit" %} + {%- elif cookiecutter.build_system == "flit" %} flit build -{%- elif cookiecutter.build_system == "mesonpy" %} + {%- elif cookiecutter.build_system == "mesonpy" %} meson build -{%- elif cookiecutter.build_system == "setuptools" %} + {%- elif cookiecutter.build_system == "setuptools" %} python -m build -{%- elif cookiecutter.build_system == "pdm" %} + {%- elif cookiecutter.build_system == "pdm" %} pdm build -{%- elif cookiecutter.build_system == "hatch" %} + {%- elif cookiecutter.build_system == "hatch" %} hatch build -{%- elif cookiecutter.build_system == "maturin" %} - maturin build -{%- elif cookiecutter.build_system == "pybind11" %} + {%- elif cookiecutter.build_system == "maturin" %} + maturin build + {%- elif cookiecutter.build_system == "pybind11" %} python -m build -{%- endif %} + {%- endif %} .PHONY:release-ci release-ci: diff --git a/src/scicookie/{{cookiecutter.project_slug}}/build-system/base-pyproject.toml b/src/scicookie/{{cookiecutter.project_slug}}/build-system/base-pyproject.toml index 29af48b1..c3d47267 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/build-system/base-pyproject.toml +++ b/src/scicookie/{{cookiecutter.project_slug}}/build-system/base-pyproject.toml @@ -10,6 +10,7 @@ testpaths = [ "tests", ] {% endif %} + {%- if cookiecutter.use_blue == "yes" %} [tool.blue] line-length = 79 @@ -19,6 +20,7 @@ force-exclude = '''(?x)( | .*\\.egg-info )''' # TOML's single-quoted strings do not require escaping backslashes {% endif %} + {%- if cookiecutter.use_black == "yes" %} [tool.black] line-length = 79 @@ -28,6 +30,7 @@ force-exclude = '''(?x)( | .*\\.egg-info )''' # TOML's single-quoted strings do not require escaping backslashes {% endif %} + {%- if cookiecutter.use_isort == "yes" %} [tool.isort] ensure_newline_before_comments = true @@ -36,11 +39,13 @@ multi_line_output = 3 include_trailing_comma = true skip_glob = ["docs/*", "*.egg-info"] {% endif %} + {%- if cookiecutter.use_bandit == "yes" %} [tool.bandit] exclude_dirs = ["tests"] -targets = "{{ package_path }}" +targets = "./" {% endif %} + {%- if cookiecutter.use_vulture == "yes" %} [tool.vulture] exclude = ["tests"] @@ -48,15 +53,16 @@ ignore_decorators = [] ignore_names = [] make_whitelist = true min_confidence = 80 -paths = ["{{ package_path }}"] +paths = ["./"] sort_by_size = true verbose = false {% endif %} + {%- if cookiecutter.use_ruff == "yes" %} [tool.ruff] line-length = 79 force-exclude = true -src = ["{{ package_path }}"] +src = ["./"] exclude = [ 'docs', ] @@ -72,9 +78,20 @@ fixable = ["I001"] [tool.ruff.pydocstyle] convention = "numpy" + +[tool.ruff.isort] +# Use a single line between direct and from import +lines-between-types = 1 {% endif %} + {%- if cookiecutter.use_mypy == "yes" %} [tool.mypy] -no_strict_optional = false +python_version = "3.8" +check_untyped_defs = true +strict = true +ignore_missing_imports = true +warn_unused_ignores = true +warn_redundant_casts = true +warn_unused_configs = true {% endif %} {#- keep this line at the end of the file -#} diff --git a/src/scicookie/{{cookiecutter.project_slug}}/build-system/flit-pyproject.toml b/src/scicookie/{{cookiecutter.project_slug}}/build-system/flit-pyproject.toml index f9be73dc..64a44385 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/build-system/flit-pyproject.toml +++ b/src/scicookie/{{cookiecutter.project_slug}}/build-system/flit-pyproject.toml @@ -45,7 +45,7 @@ classifiers = [ "Typing :: Typed", ] dynamic = ["version"] -requires-python = ">=3.8.1" +requires-python = ">=3.8.1,<4" dependencies = [ {# keep this line here #} {%- if cookiecutter.use_pytest == "yes" -%} @@ -120,7 +120,7 @@ dependencies = [ "jupyter-book >= 0.15.1", "myst-parser >= 0.18.1", {% endif %} -{%- if cookiecutter.automation_tools == "makim" %} +{%- if cookiecutter.use_makim == "yes" %} "makim >=1.8.3", {% endif %} ] diff --git a/src/scicookie/{{cookiecutter.project_slug}}/build-system/hatch-pyproject.toml b/src/scicookie/{{cookiecutter.project_slug}}/build-system/hatch-pyproject.toml index 142af336..ac8be159 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/build-system/hatch-pyproject.toml +++ b/src/scicookie/{{cookiecutter.project_slug}}/build-system/hatch-pyproject.toml @@ -35,7 +35,7 @@ classifiers = [ "Typing :: Typed", ] dynamic = ["version"] -requires-python = ">=3.8.1" +requires-python = ">=3.8.1,<4" dependencies = [ {# keep this line here #} {%- if cookiecutter.use_pytest == "yes" -%} @@ -108,7 +108,7 @@ dependencies = [ "jupyter-book >= 0.15.1", "myst-parser >= 0.18.1", {% endif %} -{%- if cookiecutter.automation_tools == "makim" %} +{%- if cookiecutter.use_makim == "yes" %} "makim >=1.8.3", {% endif %} ] diff --git a/src/scicookie/{{cookiecutter.project_slug}}/build-system/maturin-pyproject.toml b/src/scicookie/{{cookiecutter.project_slug}}/build-system/maturin-pyproject.toml index 11192293..cadea235 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/build-system/maturin-pyproject.toml +++ b/src/scicookie/{{cookiecutter.project_slug}}/build-system/maturin-pyproject.toml @@ -45,7 +45,7 @@ classifiers = [ "Typing :: Typed", ] dynamic = ["version"] -requires-python = ">=3.8" +requires-python = ">=3.8.1,<4" dependencies = [ {# keep this line here #} {%- if cookiecutter.use_pytest == "yes" -%} @@ -120,7 +120,7 @@ dependencies = [ "jupyter-book>=0.15.1", "myst-parser>=0.18.1", {% endif %} -{%- if cookiecutter.automation_tools == "makim" %} +{%- if cookiecutter.use_makim == "yes" %} "makim >=1.8.3", {% endif %} ] diff --git a/src/scicookie/{{cookiecutter.project_slug}}/build-system/mesonpy-pyproject.toml b/src/scicookie/{{cookiecutter.project_slug}}/build-system/mesonpy-pyproject.toml index 00aaa35f..c7143aa9 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/build-system/mesonpy-pyproject.toml +++ b/src/scicookie/{{cookiecutter.project_slug}}/build-system/mesonpy-pyproject.toml @@ -45,7 +45,7 @@ classifiers = [ "Typing :: Typed", ] dynamic = ["version"] -requires-python = ">=3.8" +requires-python = ">=3.8.1,<4" dependencies = [ {# keep this line here #} {%- if cookiecutter.use_pytest == "yes" -%} @@ -120,7 +120,7 @@ dependencies = [ "jupyter-book>=0.15.1", "myst-parser>=0.18.1", {% endif %} -{%- if cookiecutter.automation_tools == "makim" %} +{%- if cookiecutter.use_makim == "yes" %} "makim >=1.8.3", {% endif %} ] diff --git a/src/scicookie/{{cookiecutter.project_slug}}/build-system/pdm-pyproject.toml b/src/scicookie/{{cookiecutter.project_slug}}/build-system/pdm-pyproject.toml index 754f9733..7698fa14 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/build-system/pdm-pyproject.toml +++ b/src/scicookie/{{cookiecutter.project_slug}}/build-system/pdm-pyproject.toml @@ -45,7 +45,7 @@ classifiers = [ "Typing :: Typed", ] dynamic = ["version"] -requires-python = ">=3.8" +requires-python = ">=3.8.1,<4" dependencies = [ {# keep this line here #} {%- if cookiecutter.use_pytest == "yes" -%} @@ -120,7 +120,7 @@ dependencies = [ "jupyter-book>=0.15.1", "myst-parser>=0.18.1", {% endif %} -{%- if cookiecutter.automation_tools == "makim" %} +{%- if cookiecutter.use_makim == "yes" %} "makim >=1.8.3", {% endif %} ] diff --git a/src/scicookie/{{cookiecutter.project_slug}}/build-system/poetry-pyproject.toml b/src/scicookie/{{cookiecutter.project_slug}}/build-system/poetry-pyproject.toml index 3a8b9517..50eab49a 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/build-system/poetry-pyproject.toml +++ b/src/scicookie/{{cookiecutter.project_slug}}/build-system/poetry-pyproject.toml @@ -1,3 +1,9 @@ +{% if cookiecutter.project_layout == "src" -%} +{% set package_path = "src/" + cookiecutter.package_slug -%} +{% else -%} +{% set package_path = cookiecutter.package_slug -%} +{% endif -%} + [tool.poetry] name = "{{ cookiecutter.project_slug }}" version = "{{ cookiecutter.project_version }}" # semantic-release @@ -17,6 +23,9 @@ exclude = [ ".git/*", ".env*", ] +{%- if cookiecutter.use_mypy == "yes" %} +include = ["{{ package_path }}/py.typed"] +{%- endif %} [tool.poetry.dependencies] python = "^3.8.1" @@ -75,7 +84,7 @@ compose-go = "^2.18.1" {% endif -%} ipython = "<8" ipykernel = ">=6.0.0" -{% if cookiecutter.documentation_engine == 'mkdocs' -%} +{%- if cookiecutter.documentation_engine == 'mkdocs' %} Jinja2 = "^3.1.2" mkdocs = "^1.4.3" mkdocs-exclude = "^1.0.2" @@ -85,18 +94,18 @@ mkdocs-macros-plugin = ">=0.7.0,<1" mkdocs-material = "^9.1.15" mkdocstrings = "^0.21.2" mkdocstrings-python = "^1.1.2" -{% elif cookiecutter.documentation_engine == 'sphinx' -%} +{%- elif cookiecutter.documentation_engine == 'sphinx' %} Sphinx = "^6.2.1" sphinx-rtd-theme = "^1.2.2" importlib-metadata = "^6.5.1" myst-parser = "^0.19.2" nbsphinx = "^0.9.2" pandoc = "^2.3" -{% elif cookiecutter.documentation_engine == 'jupyter-book' -%} +{%- elif cookiecutter.documentation_engine == 'jupyter-book' %} jupyter-book = "^0.15.1" myst-parser = "^0.18.1" {% endif %} -{%- if cookiecutter.automation_tools == "makim" %} +{%- if cookiecutter.use_makim == "yes" %} makim ="^1.8.3" {% endif %} diff --git a/src/scicookie/{{cookiecutter.project_slug}}/build-system/pybind11-pyproject.toml b/src/scicookie/{{cookiecutter.project_slug}}/build-system/pybind11-pyproject.toml index 5da00cf7..4f3f25e4 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/build-system/pybind11-pyproject.toml +++ b/src/scicookie/{{cookiecutter.project_slug}}/build-system/pybind11-pyproject.toml @@ -35,7 +35,7 @@ classifiers = [ "Typing :: Typed", ] dynamic = ["version"] -requires-python = ">=3.8.1" +requires-python = ">=3.8.1,<4" dependencies = [ {# keep this line here #} "build>=0.10.0", @@ -111,7 +111,7 @@ dependencies = [ "jupyter-book >= 0.15.1,<1", "myst-parser >= 0.18.1,<1", {% endif %} -{%- if cookiecutter.automation_tools == "makim" %} +{%- if cookiecutter.use_makim == "yes" %} "makim >=1.8.3", {% endif %} ] diff --git a/src/scicookie/{{cookiecutter.project_slug}}/build-system/scikit-build-core-pyproject.toml b/src/scicookie/{{cookiecutter.project_slug}}/build-system/scikit-build-core-pyproject.toml index 503f8329..e643a9a2 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/build-system/scikit-build-core-pyproject.toml +++ b/src/scicookie/{{cookiecutter.project_slug}}/build-system/scikit-build-core-pyproject.toml @@ -44,7 +44,7 @@ classifiers = [ "Typing :: Typed", ] version = "{{ cookiecutter.project_version }}" -requires-python = ">=3.8.1" +requires-python = ">=3.8.1,<4" dependencies = [ {# keep this line here #} {%- if cookiecutter.use_pytest == "yes" -%} @@ -119,7 +119,7 @@ dependencies = [ "jupyter-book >= 0.15.1", "myst-parser >= 0.18.1", {% endif %} -{%- if cookiecutter.automation_tools == "makim" %} +{%- if cookiecutter.use_makim == "yes" %} "makim >=1.8.3", {% endif %} ] diff --git a/src/scicookie/{{cookiecutter.project_slug}}/build-system/setuptools-pyproject.toml b/src/scicookie/{{cookiecutter.project_slug}}/build-system/setuptools-pyproject.toml index 9c14c00d..57188b0b 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/build-system/setuptools-pyproject.toml +++ b/src/scicookie/{{cookiecutter.project_slug}}/build-system/setuptools-pyproject.toml @@ -30,7 +30,7 @@ classifiers = [ "Programming Language :: Python :: 3.12", ] dynamic = ["version"] -requires-python = '>=3.8.1' +requires-python = '>=3.8.1,<4' dependencies = [ {# keep this line here #} {%- if cookiecutter.use_pytest == "yes" -%} @@ -105,7 +105,7 @@ dependencies = [ "jupyter-book >= 0.15.1", "myst-parser >= 0.18.1", {% endif %} -{%- if cookiecutter.automation_tools == "makim" %} +{%- if cookiecutter.use_makim == "yes" %} "makim >=1.8.3", {% endif %} ] diff --git a/src/scicookie/{{cookiecutter.project_slug}}/conda/dev.yaml b/src/scicookie/{{cookiecutter.project_slug}}/conda/dev.yaml index 2250b31f..e30240e4 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/conda/dev.yaml +++ b/src/scicookie/{{cookiecutter.project_slug}}/conda/dev.yaml @@ -3,7 +3,7 @@ channels: - nodefaults - conda-forge dependencies: - - python >=3.8.1 + - python >=3.8.1,<4 - pip {%- if cookiecutter.build_system == "poetry" %} - poetry @@ -23,10 +23,10 @@ dependencies: - rust {%- elif cookiecutter.build_system == "scikit-build-core" %} - scikit-build-core - - cmake + - cmake {%- elif cookiecutter.build_system == "pybind11" %} - pybind11 - - cmake + - cmake {%- endif %} - nodejs # used by semantic-release {%- if cookiecutter.use_shellcheck == "yes" %} @@ -34,7 +34,7 @@ dependencies: {%- endif %} {%- if cookiecutter.documentation_engine == "sphinx" %} - pandoc -{%- endif %} -{%- if cookiecutter.automation_tools == "make" %} - - make +{%- endif %} +{%- if cookiecutter.use_make == "yes" %} + - make {%- endif %} diff --git a/src/scicookie/{{cookiecutter.project_slug}}/tests/test_{{cookiecutter.package_slug}}.py b/src/scicookie/{{cookiecutter.project_slug}}/tests/test_{{cookiecutter.package_slug}}.py index 296bd9d0..d4d23919 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/tests/test_{{cookiecutter.package_slug}}.py +++ b/src/scicookie/{{cookiecutter.project_slug}}/tests/test_{{cookiecutter.package_slug}}.py @@ -2,10 +2,17 @@ {% if cookiecutter.use_pytest == "yes" -%} import pytest {% endif -%} + +{%- if cookiecutter.use_pytest == "yes" and cookiecutter.use_hypothesis == "yes" -%} +{# keep this line here #} +{# keep this line here #} +{%- endif -%} + {% if cookiecutter.use_hypothesis == "yes" -%} from hypothesis import given from hypothesis import strategies as st {% endif -%} + {% if cookiecutter.use_pytest == "yes" %} @pytest.fixture diff --git a/tests/smoke/automation.sh b/tests/smoke/automation.sh new file mode 100755 index 00000000..a55ddfef --- /dev/null +++ b/tests/smoke/automation.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +SMOKE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + + +. ${SMOKE_DIR}/base.sh "use_makim=yes use_make=no" +. ${SMOKE_DIR}/base.sh "use_makim=no use_make=yes" diff --git a/tests/smoke/base.sh b/tests/smoke/base.sh index a843b3d4..85e5cdf1 100755 --- a/tests/smoke/base.sh +++ b/tests/smoke/base.sh @@ -40,7 +40,7 @@ export PATH=$(echo $PATH| sed -E "s/[^:]+\/micromamba\/[^:]+//g") export PATH=$(echo $PATH| sed -E "s/[^:]+\/anaconda3\/[^:]+//g") export PATH="${CONDA_PREFIX}:${CONDA_PREFIX}/bin:$PATH" echo "[II] included env conda to the PATH" -COMMAND_PREFIX= + if command -v poetry &> /dev/null; then poetry install elif command -v flit &> /dev/null; then @@ -50,36 +50,34 @@ elif command -v meson &> /dev/null; then elif command -v pdm &> /dev/null; then pdm install elif command -v hatch &> /dev/null; then - COMMAND_PREFIX="hatch run" + pip install . elif command -v maturin &> /dev/null; then pip install . elif [ "$(pip list|grep -c scikit_build_core)" -ne "0" ]; then pip install . elif [ "$(pip list|grep -c pybind11)" -ne "0" ]; then # Assuming you are inside the root of the CMake source directory - pip install . - + pip install . else - # use setuptools + # use setuptools pip install . fi -$COMMAND_PREFIX ipython kernel install --name "python3" --user - -$COMMAND_PREFIX pre-commit install - -$COMMAND_PREFIX pre-commit run --all-files --verbose +ipython kernel install --name "python3" --user if command -v makim &> /dev/null; then - $COMMAND_PREFIX makim docs.build - makim build + makim tests.linter + makim docs.build + makim package.build +elif command -v make &> /dev/null; then + make lint + make docs-build + make build else - $COMMAND_PREFIX make docs-build - make build + echo "Makim and Make were not found in the system." + exit 1 fi - - export PATH=${PATH_ORI} echo '---------------------------- passed --------------------------'