From a4f865043f54987497180a64294886dbf5594ecf Mon Sep 17 00:00:00 2001 From: "Luke W. Johnston" Date: Mon, 7 Jul 2025 11:36:49 -0400 Subject: [PATCH] feat: :sparkles: create template folder with initial files --- .copier.yaml | 1 + template/.editorconfig | 23 ++++ template/.github/CODEOWNERS.jinja | 12 ++ template/.github/pull_request_template.md | 12 ++ .../workflows/add-to-project.yml.jinja | 25 +++++ template/.gitignore | 86 +++++++++++++++ template/.pre-commit-config.yaml | 30 +++++ .python-version => template/.python-version | 0 template/.typos.toml | 4 + template/.vscode/extensions.json | 22 ++++ template/.vscode/google-notypes.mustache | 41 +++++++ template/.vscode/json.code-snippets | 103 ++++++++++++++++++ template/.vscode/settings.json | 35 ++++++ template/CITATION.cff.jinja | 31 ++++++ template/LICENSE.md.jinja | 21 ++++ template/README.md.jinja | 0 template/justfile | 43 ++++++++ main.py => template/main.py | 0 template/pyproject.toml.jinja | 33 ++++++ template/ruff.toml | 26 +++++ {scripts => template/scripts}/__init__.py | 0 {scripts => template/scripts}/properties.py | 0 22 files changed, 548 insertions(+) create mode 100644 .copier.yaml create mode 100644 template/.editorconfig create mode 100644 template/.github/CODEOWNERS.jinja create mode 100644 template/.github/pull_request_template.md create mode 100644 template/.github/workflows/add-to-project.yml.jinja create mode 100644 template/.gitignore create mode 100644 template/.pre-commit-config.yaml rename .python-version => template/.python-version (100%) create mode 100644 template/.typos.toml create mode 100644 template/.vscode/extensions.json create mode 100644 template/.vscode/google-notypes.mustache create mode 100644 template/.vscode/json.code-snippets create mode 100644 template/.vscode/settings.json create mode 100644 template/CITATION.cff.jinja create mode 100644 template/LICENSE.md.jinja create mode 100644 template/README.md.jinja create mode 100644 template/justfile rename main.py => template/main.py (100%) create mode 100644 template/pyproject.toml.jinja create mode 100644 template/ruff.toml rename {scripts => template/scripts}/__init__.py (100%) rename {scripts => template/scripts}/properties.py (100%) diff --git a/.copier.yaml b/.copier.yaml new file mode 100644 index 0000000..9978e0c --- /dev/null +++ b/.copier.yaml @@ -0,0 +1 @@ +_subdirectory: template diff --git a/template/.editorconfig b/template/.editorconfig new file mode 100644 index 0000000..6fd615b --- /dev/null +++ b/template/.editorconfig @@ -0,0 +1,23 @@ +# EditorConfig settings. Some editors will read these automatically; +# for those that don't, see here: http://editorconfig.org/ + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +max_line_length = 88 + +# Have a bit shorter line length for text docs +[*.{txt,md,qmd}] +max_line_length = 72 +indent_size = 4 + +# Python always uses 4 spaces for tabs +[*.py] +indent_style = space +indent_size = 4 diff --git a/template/.github/CODEOWNERS.jinja b/template/.github/CODEOWNERS.jinja new file mode 100644 index 0000000..22da67d --- /dev/null +++ b/template/.github/CODEOWNERS.jinja @@ -0,0 +1,12 @@ +# All members on Developers team get added to review PRs +* @seedcase-project/developers + +# Ignore these so we don't get added to sync PRs +/.github/ +/.vscode/ +justfile +.editorconfig +.gitignore +ruff.toml +pyproject.toml +uv.lock diff --git a/template/.github/pull_request_template.md b/template/.github/pull_request_template.md new file mode 100644 index 0000000..f89e3e6 --- /dev/null +++ b/template/.github/pull_request_template.md @@ -0,0 +1,12 @@ +# Description + +This PR will [DESCRIBE CHANGES]. + +Closes # + +This PR needs a quick/an in-depth review. + +## Checklist + +- [ ] Checked that the README is up to date +- [ ] Run `just run-all` diff --git a/template/.github/workflows/add-to-project.yml.jinja b/template/.github/workflows/add-to-project.yml.jinja new file mode 100644 index 0000000..5e50cce --- /dev/null +++ b/template/.github/workflows/add-to-project.yml.jinja @@ -0,0 +1,25 @@ +name: Add to project board + +on: + issues: + types: + - opened + - reopened + - transferred + pull_request: + types: + - reopened + - opened + +permissions: + pull-requests: write + +jobs: + add-to-project: + uses: seedcase-project/.github/.github/workflows/reusable-add-to-project.yml@main + with: + board-number: 18 + app-id: ${{ vars.ADD_TO_BOARD_APP_ID }} + secrets: + add-to-board-token: ${{ secrets.ADD_TO_BOARD }} + gh-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/template/.gitignore b/template/.gitignore new file mode 100644 index 0000000..63bd79f --- /dev/null +++ b/template/.gitignore @@ -0,0 +1,86 @@ +# Development files and folders +_ignore +bin/ +dev/ + +# Temporary files +*.tmp + +# Any IDE specific folders +.idea + +# Any .env files +.env +.env.* +**/.env.* +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Python specific content +venv +__pycache__/ +*.py[cod] + +# Python packaging and distribution +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Python testing and code coverage +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# MacOS +.DS_Store + +# Quarto +/.quarto/ +docs/.quarto/ +*.ipynb +*.quarto_ipynb +*.storage + +# Quartodoc +/docs/reference/ +objects.json + +# Website generation +_site +_book +public +site + + +# Misc files +*.log diff --git a/template/.pre-commit-config.yaml b/template/.pre-commit-config.yaml new file mode 100644 index 0000000..ea46853 --- /dev/null +++ b/template/.pre-commit-config.yaml @@ -0,0 +1,30 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +ci: + autofix_commit_msg: "chore(pre-commit): :pencil2: automatic fixes" + autoupdate_commit_msg: "ci(pre-commit): :construction_worker: update pre-commit CI version" + +repos: + - repo: https://github.com/gitleaks/gitleaks + rev: v8.27.2 + hooks: + - id: gitleaks + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + + - repo: https://github.com/commitizen-tools/commitizen + rev: v4.8.3 + hooks: + - id: commitizen + + # Use the mirror since the main `typos` repo has tags for different + # sub-packages, which confuses pre-commit when it tries to find the latest + # version + - repo: https://github.com/adhtruong/mirrors-typos + rev: v1.33.1 + hooks: + - id: typos diff --git a/.python-version b/template/.python-version similarity index 100% rename from .python-version rename to template/.python-version diff --git a/template/.typos.toml b/template/.typos.toml new file mode 100644 index 0000000..4521615 --- /dev/null +++ b/template/.typos.toml @@ -0,0 +1,4 @@ +[files] +extend-exclude = [ + "*.json", +] diff --git a/template/.vscode/extensions.json b/template/.vscode/extensions.json new file mode 100644 index 0000000..986dc5f --- /dev/null +++ b/template/.vscode/extensions.json @@ -0,0 +1,22 @@ +{ + "recommendations": [ + "eamodio.gitlens", + "github.vscode-github-actions", + "redhat.vscode-yaml", + "donjayamanne.githistory", + "felipecaputo.git-project-manager", + "GitHub.vscode-pull-request-github", + "ms-python.python", + "ms-python.vscode-pylance", + "njpwerner.autodocstring", + "quarto.quarto", + "ms-toolsai.jupyter", + "vivaxy.vscode-conventional-commits", + "charliermarsh.ruff", + "pshaddel.conventional-branch", + "tekumara.typos-vscode", + "EditorConfig.EditorConfig" + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [] +} diff --git a/template/.vscode/google-notypes.mustache b/template/.vscode/google-notypes.mustache new file mode 100644 index 0000000..55477fa --- /dev/null +++ b/template/.vscode/google-notypes.mustache @@ -0,0 +1,41 @@ +{{! Copied from https://github.com/NilsJPWerner/autoDocstring/blob/master/src/docstring/templates/google-notypes.mustache with some edits }} +{{! Google Docstring Template without Types for Args, Returns or Yields }} +{{summaryPlaceholder}}. + +{{extendedSummaryPlaceholder}} +{{#parametersExist}} + +Args: +{{#args}} + {{var}}: {{descriptionPlaceholder}}. +{{/args}} +{{#kwargs}} + {{var}}: {{descriptionPlaceholder}}. Defaults to {{&default}}. +{{/kwargs}} +{{/parametersExist}} +{{#returnsExist}} + +Returns: +{{#returns}} + {{descriptionPlaceholder}}. +{{/returns}} +{{/returnsExist}} +{{#exceptionsExist}} + +Raises: +{{#exceptions}} + {{type}}: {{descriptionPlaceholder}}. +{{/exceptions}} +{{/exceptionsExist}} +{{#yieldsExist}} + +Yields: +{{#yields}} + {{descriptionPlaceholder}}. +{{/yields}} +{{/yieldsExist}} + +Examples: + ```{python} + {{descriptionPlaceholder}} + ``` diff --git a/template/.vscode/json.code-snippets b/template/.vscode/json.code-snippets new file mode 100644 index 0000000..b21dfa2 --- /dev/null +++ b/template/.vscode/json.code-snippets @@ -0,0 +1,103 @@ +{ + // Place your snippets for Quarto here. + // Each snippet is defined under a snippet name and has a prefix, body and description. + // The prefix is what is used to trigger the snippet and the body will be expanded and inserted. + // Possible variables are: + // + // - $1 and $2 for tab stops, + // - $0 for the final cursor position, and + // - ${1:label}, ${2:another} for placeholders + // + // Placeholders with the same ids are connected. + // + // How to use the code snippets: + // After you have set the above settings, a suggestion for one of the code snippets below will pop up automatically, when + // you start writing the prefix. Press "Enter" or "Tab" to insert the code snippet. + "Insert TODO formatting": { + "scope": "quarto,markdown", + "prefix": "TODO", + "body": [ + "" + ], + "description": "Insert TODO formatting" + }, + "Insert bash formatted text": { + "scope": "quarto,markdown", + "prefix": "bash", + "body": [ + "``` bash", + "${0:Write text here}", + "```" + ], + "description": "Insert bash formatted text" + }, + "Insert YAML header for blogs": { + "scope": "quarto,markdown", + "prefix": "post_yaml", + "body": [ + "---", + "title: \"\"", + "description: \"Our reasons for ...\"", + "author: \"\"", + "date: last-modified", + "categories:", + " ${0:Type 'category_keywords' to insert categories}", + "---" + ], + "description": "Insert YAML header for Quarto blog posts." + }, + "Insert a hidden comment section": { + "scope": "quarto,markdown", + "prefix": "hidden", + "body": [ + "::: content-hidden", + "${0:Write comments here}", + ":::" + ], + "description": "Insert a hidden content section" + }, + "Insert a 2 col table": { + "scope": "quarto,markdown", + "prefix": "tbl2", + "body": [ + "|${1:title} |${0:title} |", + "| --- | --- |", + "| | |" + ], + "description": "Insert a 2 col table" + }, + "Insert a 3 col table": { + "scope": "quarto,markdown", + "prefix": "tbl3", + "body": [ + "|${1:title} |${2:title} |${0:title} |", + "| --- | --- | --- |", + "| | | |" + ], + "description": "Insert a 3 col table" + }, + "Insert video": { + "scope": "quarto,markdown", + "prefix": "video", + "body": [ + "{{< video ${0:Insert link here} >}}" + ], + "description": "Insert video that will be shown" + }, + "Insert paneltab": { + "scope": "quarto,markdown", + "prefix": "paneltab", + "body": [ + "::: panel-tabset", + "### ${0:Header}", + "", + "${1:Text body}", + "", + "### ${2:Header}", + "", + "${3:Text body}", + ":::" + ], + "description": "Insert paneltab (including two tabs here). If you want additional tabs, just include more headers." + } +} diff --git a/template/.vscode/settings.json b/template/.vscode/settings.json new file mode 100644 index 0000000..e4aa4df --- /dev/null +++ b/template/.vscode/settings.json @@ -0,0 +1,35 @@ +{ + "files.autoSave": "onFocusChange", + "editor.wordWrap": "off", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": "always" + }, + "git.autofetch": false, + "quarto.visualEditor.markdownWrap": "column", + "quarto.visualEditor.markdownWrapColumn": 72, + "autoDocstring.customTemplatePath": ".vscode/google-notypes.mustache", + "editor.tabCompletion": "on", + "editor.snippetSuggestions": "inline", + "conventional-branch.type": [ + "build", // Changes that affect the build system or external dependencies + "ci", // Changes to our CI configuration files and scripts + "docs", // Documentation only changes + "feat", // A new feature + "fix", // A bug fix + "refactor", // A code change that neither fixes a bug nor adds a feature + "style", // Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) + "test", // Adding missing tests or correcting existing tests + "chore", // Misc things, like renaming or deleting files + ], + "conventional-branch.format": "{Type}/{Branch}", + "[quarto][qmd]": { + "editor.formatOnSave": false + }, + "[python]": { + "editor.defaultFormatter": "charliermarsh.ruff" + }, + "python.defaultInterpreterPath": "${workspaceFolder}/.venv", + "python.languageServer": "Pylance", + "files.insertFinalNewline": true +} diff --git a/template/CITATION.cff.jinja b/template/CITATION.cff.jinja new file mode 100644 index 0000000..ef5080c --- /dev/null +++ b/template/CITATION.cff.jinja @@ -0,0 +1,31 @@ +title: "Template Data Package: An opinionated setup for making FAIR and structured data using Seedcase Python packages" +abstract: "A template for making a Git repository that follows strongly opinionated practices for building and managing a data package. These practices include using Seedcase Python packages, such as Seedcase Sprout, and the Frictionless Data Package standard." +authors: + - family-names: Johnston + given-names: Luke William + orcid: "https://orcid.org/0000-0003-4169-2616" + affiliation: "Steno Diabetes Center Aarhus" + - family-names: Brødbæk + given-names: Signe Kirk + affiliation: "Steno Diabetes Center Aarhus" + - family-names: Beicher + given-names: Kristiane + affiliation: "Steno Diabetes Center Aarhus" + - family-names: Vago + given-names: Marton + affiliation: "Steno Diabetes Center Aarhus" +cff-version: 1.2.0 +# doi: +keywords: + - "template repository" + - "template project" + - "template data package" + - "data engineering" + - "data infrastructure" + - "data package" + - "frictionless data" + - "FAIR data" +license: MIT +message: "If you use this software, please cite it using these metadata." +repository-code: "https://github.com/seedcase-project/template-data-package" +url: "https://template-data-package.seedcase-project.org" diff --git a/template/LICENSE.md.jinja b/template/LICENSE.md.jinja new file mode 100644 index 0000000..aeed825 --- /dev/null +++ b/template/LICENSE.md.jinja @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2023-2025 Aarhus University + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/template/README.md.jinja b/template/README.md.jinja new file mode 100644 index 0000000..e69de29 diff --git a/template/justfile b/template/justfile new file mode 100644 index 0000000..f1842f8 --- /dev/null +++ b/template/justfile @@ -0,0 +1,43 @@ +@_default: + just --list --unsorted + +# Run all build-related recipes in the justfile +run-all: install-deps format-python check-python check-spelling check-commits + +# Install the pre-commit hooks +install-precommit: + # Install pre-commit hooks + uvx pre-commit install + # Run pre-commit hooks on all files + uvx pre-commit run --all-files + # Update versions of pre-commit hooks + uvx pre-commit autoupdate + +# Install Python package dependencies +install-deps: + uv sync --upgrade --dev --all-extras + +# Check Python code with the linter for any errors that need manual attention +check-python: + uv run ruff check . + +# Reformat Python code to match coding style and general structure +format-python: + uv run ruff check --fix . + uv run ruff format . + +# Run checks on commits with non-main branches +check-commits: + #!/bin/zsh + branch_name=$(git rev-parse --abbrev-ref HEAD) + number_of_commits=$(git rev-list --count HEAD ^$branch_name) + if [[ ${branch_name} != "main" && ${number_of_commits} -gt 0 ]] + then + uv run cz check --rev-range main..HEAD + else + echo "Not on main or haven't committed yet." + fi + +# Check for spelling errors in files +check-spelling: + uv run typos diff --git a/main.py b/template/main.py similarity index 100% rename from main.py rename to template/main.py diff --git a/template/pyproject.toml.jinja b/template/pyproject.toml.jinja new file mode 100644 index 0000000..17102b9 --- /dev/null +++ b/template/pyproject.toml.jinja @@ -0,0 +1,33 @@ +[project] +name = "template-data-package" +version = "0.1.0" +description = "A template for structuring all the pieces for a data package." +authors = [ + {name = "Luke W. Johnston", email = "lwjohnst@gmail.com" }, + {name = "Kristiane Beicher", email = "kris.beicher@clin.au.dk" }, +] +maintainers = [ + {name = "Luke W. Johnston", email = "lwjohnst@gmail.com" }, + {name = "Kristiane Beicher", email = "kris.beicher@clin.au.dk" }, +] +readme = "README.md" +license = "MIT" +license-files = ["LICENSE.md"] +requires-python = ">=3.12" +dependencies = [ + "polars>=1.27.0", + "pyjanitor>=0.31.0", + "seedcase-sprout>=0.46.3", +] + +[project.urls] +issues = "https://github.com/seedcase-project/REPO/issues" +repository = "https://github.com/seedcase-project/REPO" + +[dependency-groups] +dev = [ + "commitizen>=4.5.1", + "pre-commit>=4.2.0", + "ruff>=0.11.4", + "typos>=1.32.0", +] diff --git a/template/ruff.toml b/template/ruff.toml new file mode 100644 index 0000000..9171953 --- /dev/null +++ b/template/ruff.toml @@ -0,0 +1,26 @@ +# Support Python 3.12+ +target-version = "py312" + +# In addition to the default formatters/linters, add these as well. +[lint] +extend-select = [ + # Add the `line-too-long` rule to the enforced rule set. + "E501", + # Add rule that all functions have docstrings. + "D", + # Add isort to list. + "I" +] +# Ignore missing docstring at the top of files +ignore = ["D100"] + +[lint.pydocstyle] +convention = "google" + +[format] +docstring-code-format = true + +[lint.per-file-ignores] +# ignore "Module imported but unused" error in all init files +"__init__.py" = ["F401"] +"**/tests/*" = ["D"] diff --git a/scripts/__init__.py b/template/scripts/__init__.py similarity index 100% rename from scripts/__init__.py rename to template/scripts/__init__.py diff --git a/scripts/properties.py b/template/scripts/properties.py similarity index 100% rename from scripts/properties.py rename to template/scripts/properties.py