diff --git a/.github/assets/cookiecutter-scverse-instance.json b/.github/assets/cookiecutter-scverse-instance.json index 41f7a2a6..03a58b5f 100644 --- a/.github/assets/cookiecutter-scverse-instance.json +++ b/.github/assets/cookiecutter-scverse-instance.json @@ -8,6 +8,7 @@ "github_user": "scverse", "github_repo": "cookiecutter-scverse-instance", "license": "BSD 3-Clause License", + "ide_integration": true, "_copy_without_render": [ ".github/workflows/**.yaml", "docs/_templates/autosummary/**.rst" diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 00000000..e96d1dd4 --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,7 @@ +overrides: + # JSON with comments and trailing commas + - files: "**/*.vscode*/*.json" + options: + parser: json5 + quoteProps: preserve + singleQuote: false diff --git a/cookiecutter.json b/cookiecutter.json index cf40b568..87b4324a 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -14,6 +14,7 @@ "GNU General Public License Version 3", "Unlicense" ], + "ide_integration": true, "_copy_without_render": [ ".github/workflows/build.yaml", ".github/workflows/test.yaml", diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index c3191de3..3f1f79ee 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -1,12 +1,27 @@ #!/bin/env python3 +import shutil from subprocess import run -{% if not cookiecutter._render_devdocs %} from pathlib import Path +{% if not cookiecutter._render_devdocs %} # Post processing Path("docs/template_usage.md").unlink() {% endif %} +# Skip directories marked for skipping +def skipped_dirs(): + for toplevel in Path().iterdir(): + if toplevel.name == ".git": + continue + if toplevel.name == "DELETE-ME": + yield toplevel + else: + yield from toplevel.rglob("DELETE-ME") + +for path in skipped_dirs(): + assert path.is_dir(), path + shutil.rmtree(path) + # Update pre commit hooks run("pre-commit autoupdate -c .pre-commit-config.yaml".split(), check=True) run("pre-commit install".split(), check=True) diff --git a/scripts/tests/test_build.py b/scripts/tests/test_build.py index e8d00fb4..698cd32a 100644 --- a/scripts/tests/test_build.py +++ b/scripts/tests/test_build.py @@ -18,14 +18,21 @@ @pytest.mark.parametrize( ("params", "path", "pattern"), [ - ({}, "docs/conf.py", r'"github_repo": project_name,'), - ({"github_repo": "floob"}, "docs/conf.py", r'"github_repo": "floob",'), + pytest.param({}, "docs/conf.py", r'"github_repo": project_name,', id="no_gh_repo"), + pytest.param({"github_repo": "floob"}, "docs/conf.py", r'"github_repo": "floob",', id="gh_repo"), + pytest.param({}, ".vscode/extensions.json", r'"ms-python.python",', id="no_ide_integ"), + pytest.param({"ide_integration": False}, ".vscode", None, id="ide_integ"), ], ) -def test_build(tmp_path: Path, params: Mapping[str, Any], path: Path | str, pattern: re.Pattern | str): +def test_build(tmp_path: Path, params: Mapping[str, Any], path: Path | str, pattern: re.Pattern | str | None): cookiecutter(str(HERE.parent.parent), output_dir=tmp_path, no_input=True, extra_context=params) proj_dir = tmp_path / "project-name" assert proj_dir.is_dir() path = proj_dir / path - pattern = re.compile(pattern, re.MULTILINE) - assert pattern.search(path.read_text()) + if pattern is None: + assert not path.exists() + else: + pattern = re.compile(pattern, re.MULTILINE) + assert pattern.search(path.read_text()) + + assert not list(proj_dir.rglob("DELETE-ME")) diff --git a/{{cookiecutter.project_name}}/.gitignore b/{{cookiecutter.project_name}}/.gitignore index d01a5d5d..2ff7df49 100644 --- a/{{cookiecutter.project_name}}/.gitignore +++ b/{{cookiecutter.project_name}}/.gitignore @@ -3,6 +3,13 @@ *~ buck-out/ +{% if not cookiecutter.ide_integration -%} +# IDEs +/.idea/ +/.vscode/ + +{% endif -%} + # Compiled files .venv/ __pycache__/ @@ -18,7 +25,3 @@ __pycache__/ # docs /docs/generated/ /docs/_build/ - -# IDEs -/.idea/ -/.vscode/ diff --git a/{{cookiecutter.project_name}}/{% if cookiecutter.ide_integration %}.prettierrc.yaml{% endif %} b/{{cookiecutter.project_name}}/{% if cookiecutter.ide_integration %}.prettierrc.yaml{% endif %} new file mode 100644 index 00000000..9aaffcbb --- /dev/null +++ b/{{cookiecutter.project_name}}/{% if cookiecutter.ide_integration %}.prettierrc.yaml{% endif %} @@ -0,0 +1,7 @@ +overrides: + # JSON with comments and trailing commas + - files: .vscode/*.json + options: + parser: json5 + quoteProps: preserve + singleQuote: false diff --git "a/{{cookiecutter.project_name}}/{{\".vscode\" if cookiecutter.ide_integration else \"DELETE-ME\" }}/extensions.json" "b/{{cookiecutter.project_name}}/{{\".vscode\" if cookiecutter.ide_integration else \"DELETE-ME\" }}/extensions.json" new file mode 100644 index 00000000..a6fa5803 --- /dev/null +++ "b/{{cookiecutter.project_name}}/{{\".vscode\" if cookiecutter.ide_integration else \"DELETE-ME\" }}/extensions.json" @@ -0,0 +1,18 @@ +{ + "recommendations": [ + // GitHub integration + "github.vscode-github-actions", + "github.vscode-pull-request-github", + // Language support + "ms-python.python", + "ms-python.vscode-pylance", + "ms-toolsai.jupyter", + "tamasfe.even-better-toml", + // Dependency management + "ninoseki.vscode-mogami", + // Linting and formatting + "editorconfig.editorconfig", + "charliermarsh.ruff", + "esbenp.prettier-vscode", + ], +} diff --git "a/{{cookiecutter.project_name}}/{{\".vscode\" if cookiecutter.ide_integration else \"DELETE-ME\" }}/launch.json" "b/{{cookiecutter.project_name}}/{{\".vscode\" if cookiecutter.ide_integration else \"DELETE-ME\" }}/launch.json" new file mode 100644 index 00000000..36d18746 --- /dev/null +++ "b/{{cookiecutter.project_name}}/{{\".vscode\" if cookiecutter.ide_integration else \"DELETE-ME\" }}/launch.json" @@ -0,0 +1,33 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Build Documentation", + "type": "debugpy", + "request": "launch", + "module": "sphinx", + "args": ["-M", "html", ".", "_build"], + "cwd": "${workspaceFolder}/docs", + "console": "internalConsole", + "justMyCode": false, + }, + { + "name": "Python: Debug Test", + "type": "debugpy", + "request": "launch", + "program": "${file}", + "purpose": ["debug-test"], + "console": "internalConsole", + "justMyCode": false, + "env": { + "PYTEST_ADDOPTS": "--color=yes", + }, + "presentation": { + "hidden": true, + }, + }, + ], +} diff --git "a/{{cookiecutter.project_name}}/{{\".vscode\" if cookiecutter.ide_integration else \"DELETE-ME\" }}/settings.json" "b/{{cookiecutter.project_name}}/{{\".vscode\" if cookiecutter.ide_integration else \"DELETE-ME\" }}/settings.json" new file mode 100644 index 00000000..b6715d6f --- /dev/null +++ "b/{{cookiecutter.project_name}}/{{\".vscode\" if cookiecutter.ide_integration else \"DELETE-ME\" }}/settings.json" @@ -0,0 +1,18 @@ +{ + "[python][jsonc][yaml]": { + "editor.formatOnSave": true, + }, + "[python]": { + "editor.defaultFormatter": "charliermarsh.ruff", + "editor.codeActionsOnSave": { + "source.fixAll": "always", + "source.organizeImports": "always", + }, + }, + "[jsonc][yaml]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + }, + "python.analysis.typeCheckingMode": "basic", + "python.testing.pytestEnabled": true, + "python.testing.pytestArgs": ["-vv", "--color=yes"], +}