diff --git a/.cruft.json b/.cruft.json index 3f646eb8..2aa2fd9f 100644 --- a/.cruft.json +++ b/.cruft.json @@ -1,7 +1,7 @@ { "template": "https://github.com/scverse/cookiecutter-scverse", - "commit": "87a407a65408d75a949c0b54b19fd287475a56f8", - "checkout": "v0.4.0", + "commit": "d383d94fadff9e4e6fdb59d77c68cb900d7cedec", + "checkout": "v0.6.0", "context": { "cookiecutter": { "project_name": "scverse-tutorials", @@ -10,19 +10,32 @@ "author_full_name": "scverse team", "author_email": "core-team@scverse.org", "github_user": "scverse", - "project_repo": "https://github.com/scverse/scverse-tutorials", + "github_repo": "scverse-tutorials", "license": "BSD 3-Clause License", + "ide_integration": true, "_copy_without_render": [ ".github/workflows/build.yaml", ".github/workflows/test.yaml", "docs/_templates/autosummary/**.rst" ], + "_exclude_on_template_update": [ + ".github/ISSUE_TEMPLATE/**", + "environment.yml", + "*.md", + "src/**", + "docs/*.md", + "docs/notebooks/**", + "docs/references.bib", + "tests/**", + "tutorial-registry/**" + ], "_render_devdocs": false, "_jinja2_env_vars": { "lstrip_blocks": true, "trim_blocks": true }, - "_template": "https://github.com/scverse/cookiecutter-scverse" + "_template": "https://github.com/scverse/cookiecutter-scverse", + "_commit": "d383d94fadff9e4e6fdb59d77c68cb900d7cedec" } }, "directory": null diff --git a/.editorconfig b/.editorconfig index 050f9118..66678e37 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,10 +8,7 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[*.{yml,yaml}] -indent_size = 2 - -[.cruft.json] +[{*.{yml,yaml,toml},.cruft.json}] indent_size = 2 [Makefile] diff --git a/.github/workflows/execute-nbs.yaml b/.github/workflows/execute-nbs.yaml index 8d695a99..31da05ae 100644 --- a/.github/workflows/execute-nbs.yaml +++ b/.github/workflows/execute-nbs.yaml @@ -83,6 +83,6 @@ jobs: jcache notebook merge $f $f done - - uses: stefanzweifel/git-auto-commit-action@v4 + - uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: Render notebooks diff --git a/.gitignore b/.gitignore index 78455d2a..ccc5c7d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,22 @@ -# Caches -/.*cache/ -/node_modules/ -/data/ -.ipynb_checkpoints/ -__pycache__/ - # Temp files .DS_Store *~ +buck-out/ -# Virtual environments +# Compiled files .venv/ +__pycache__/ +.ipynb_checkpoints/ +.*cache/ -# Build artifacts +# Distribution / packaging /dist/ -/docs/generated/ -/docs/_build/ -# User configuration -/hatch.toml +# Tests and coverage +/data/ +/node_modules/ +/.coverage* -# IDEs -/.idea/ -/.vscode/ +# docs +/docs/generated/ +/docs/_build/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1e5930f0..000848cc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,14 +6,19 @@ default_stages: - pre-push minimum_pre_commit_version: 2.16.0 repos: - - repo: https://github.com/rbubley/mirrors-prettier - rev: v3.6.2 + - repo: https://github.com/biomejs/pre-commit + rev: v2.2.4 hooks: - - id: prettier + - id: biome-format + exclude: ^\.cruft\.json$ # inconsistent indentation with cruft - file never to be modified manually. + - repo: https://github.com/tox-dev/pyproject-fmt + rev: v2.6.0 + hooks: + - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.13.1 + rev: v0.13.2 hooks: - - id: ruff + - id: ruff-check types_or: [python, pyi, jupyter] args: [--fix, --exit-non-zero-on-fix] - id: ruff-format @@ -31,23 +36,14 @@ repos: # Check that there are no merge conflicts (could be generated by template sync) - id: check-merge-conflict args: [--assume-in-merge] - - repo: local - hooks: - - id: forbid-to-commit - name: Don't commit rej files - entry: | - Cannot commit .rej files. These indicate merge conflicts that arise during automated template updates. - Fix the merge conflicts manually and remove the .rej files. - language: fail - files: '.*\.rej$' - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.34.0 + rev: '0.34.0' hooks: - id: check-jsonschema files: "tutorial-registry/schema.json" args: ["--check-metaschema"] - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.34.0 + rev: '0.34.0' hooks: - id: check-jsonschema files: "tutorial-registry/tutorials/.*/meta.yaml" diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 413dc9bc..c3f3f96f 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,16 +1,15 @@ # https://docs.readthedocs.io/en/stable/config-file/v2.html version: 2 build: - os: ubuntu-22.04 + os: ubuntu-24.04 tools: python: "3.12" -sphinx: - configuration: docs/conf.py - fail_on_warning: true -python: - install: - - requirements: docs/patched-deps.txt - - method: pip - path: . - extra_requirements: - - docs + jobs: + create_environment: + - asdf plugin add uv + - asdf install uv latest + - asdf global uv latest + build: + html: + - uvx hatch run docs:build + - mv docs/_build $READTHEDOCS_OUTPUT diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..caaeb4f7 --- /dev/null +++ b/.vscode/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", + "biomejs.biome", + ], +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..89809f4b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,18 @@ +{ + // 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, + }, + ], +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..d5246cc9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "[python][json][jsonc]": { + "editor.formatOnSave": true, + }, + "[python]": { + "editor.defaultFormatter": "charliermarsh.ruff", + "editor.codeActionsOnSave": { + "source.fixAll": "always", + "source.organizeImports": "always", + }, + }, + "[json][jsonc]": { + "editor.defaultFormatter": "biomejs.biome", + }, + "python.analysis.typeCheckingMode": "basic", +} diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index e69de29b..00000000 diff --git a/biome.jsonc b/biome.jsonc new file mode 100644 index 00000000..9f8f2208 --- /dev/null +++ b/biome.jsonc @@ -0,0 +1,17 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.2.0/schema.json", + "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true }, + "formatter": { "useEditorconfig": true }, + "overrides": [ + { + "includes": ["./.vscode/*.json", "**/*.jsonc"], + "json": { + "formatter": { "trailingCommas": "all" }, + "parser": { + "allowComments": true, + "allowTrailingCommas": true, + }, + }, + }, + ], +} diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index d4bb2cbb..00000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/_templates/autosummary/class.rst b/docs/_templates/autosummary/class.rst index e4665dfc..7b4a0cf8 100644 --- a/docs/_templates/autosummary/class.rst +++ b/docs/_templates/autosummary/class.rst @@ -9,11 +9,11 @@ {% block attributes %} {% if attributes %} Attributes table -~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~ .. autosummary:: {% for item in attributes %} - ~{{ fullname }}.{{ item }} + ~{{ name }}.{{ item }} {%- endfor %} {% endif %} {% endblock %} @@ -26,7 +26,7 @@ Methods table .. autosummary:: {% for item in methods %} {%- if item != '__init__' %} - ~{{ fullname }}.{{ item }} + ~{{ name }}.{{ item }} {%- endif -%} {%- endfor %} {% endif %} @@ -35,7 +35,7 @@ Methods table {% block attributes_documentation %} {% if attributes %} Attributes -~~~~~~~~~~~ +~~~~~~~~~~ {% for item in attributes %} diff --git a/docs/conf.py b/docs/conf.py index b5946cff..ce3dca0c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -35,7 +35,7 @@ needs_sphinx = "4.0" html_context = { - "display_github": True, + "display_github": True, # Integrate GitHub "github_user": "scverse", "github_repo": project_name, "github_version": "main", @@ -56,6 +56,7 @@ "sphinx_issues", "sphinxcontrib.bibtex", "sphinx_autodoc_typehints", + "sphinx_tabs.tabs", "sphinx.ext.mathjax", "IPython.sphinxext.ipython_console_highlighting", "sphinxext.opengraph", @@ -85,7 +86,11 @@ nb_merge_streams = True typehints_defaults = "braces" -source_suffix = {".rst": "restructuredtext", ".ipynb": "myst-nb", ".myst": "myst-nb"} +source_suffix = { + ".rst": "restructuredtext", + ".ipynb": "myst-nb", + ".myst": "myst-nb", +} intersphinx_mapping = { "python": ("https://docs.python.org/3", None), @@ -117,14 +122,9 @@ html_theme_options = { "repository_url": repository_url, - "repository_branch": "main", + "use_repository_button": True, "path_to_docs": "docs/", "navigation_with_keys": False, - "use_repository_button": True, - "launch_buttons": { - "binderhub_url": "https://mybinder.org", - # "colab_url": "https://colab.research.google.com", - }, } pygments_style = "default" diff --git a/docs/patched-deps.txt b/docs/patched-deps.txt deleted file mode 100644 index a5aec7b0..00000000 --- a/docs/patched-deps.txt +++ /dev/null @@ -1,2 +0,0 @@ -# fix from here: https://github.com/executablebooks/MyST-NB/pull/597 -myst-nb @ git+https://github.com/flying-sheep/MyST-NB@eval-metadata diff --git a/pyproject.toml b/pyproject.toml index 3bcf1b7d..c94c22e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,142 +1,127 @@ [build-system] build-backend = "hatchling.build" -requires = ["hatchling"] +requires = [ "hatchling" ] [project] name = "scverse-tutorials" version = "0.0.1" description = "Tutorials for single-cell analysis with scverse packages" readme = "README.md" -requires-python = ">=3.10" -license = {file = "LICENSE"} -authors = [ - {name = "scverse team"}, -] +license = "BSD-3-Clause" maintainers = [ - {name = "scverse team", email = "core-team@scverse.org"}, + { name = "scverse team", email = "core-team@scverse.org" }, ] -urls.Documentation = "https://scverse.org/scverse-tutorials" -urls.Source = "https://github.com/scverse/scverse-tutorials" -urls.Home-page = "https://github.com/scverse/scverse-tutorials" +authors = [ + { name = "scverse team" }, +] +requires-python = ">=3.10" classifiers = [ - "Private :: Do Not Upload", # Prevent uploading to PyPI + "Private :: Do Not Upload", # Prevent uploading to PyPI + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] - -[project.optional-dependencies] -dev = ["pre-commit"] -registry = [ - "jsonschema", - "pillow", - "httpx", - "pyyaml", +optional-dependencies.dev = [ "pre-commit" ] +optional-dependencies.docs = [ + # For notebooks + "ipykernel", + "ipython", + "myst-nb>=1.1", + "sphinx>=7", + "sphinx-autodoc-typehints", + "sphinx-book-theme>=1.1", + "sphinx-copybutton", + "sphinx-issues>=5.0.1", + "sphinx-tabs", + "sphinxcontrib-bibtex>=1", + "sphinxext-opengraph", ] -docs = [ - "sphinx>=7", - "sphinx-book-theme>=1.1.0", - "sphinx-issues>=5.0.1", - "myst-nb>=1.1.0", - "sphinxcontrib-bibtex>=1.0.0", - "sphinx-autodoc-typehints", - "sphinxext-opengraph", - # For notebooks - "ipykernel", - "ipython", - "sphinx-copybutton", +optional-dependencies.registry = [ + "httpx", + "jsonschema", + "pillow", + "pyyaml", ] +urls.Documentation = "https://scverse.org/scverse-tutorials" +urls.Home-page = "https://github.com/scverse/scverse-tutorials" +urls.Source = "https://github.com/scverse/scverse-tutorials" [tool.hatch.envs.default] installer = "uv" -features = ["dev"] +features = [ "dev" ] [tool.hatch.envs.registry] -features = ["registry"] -[tool.hatch.envs.registry.scripts] -validate = "python tutorial-registry/validate.py {args}" +features = [ "registry" ] +scripts.validate = "python tutorial-registry/validate.py {args}" [tool.hatch.envs.docs] -features = ["docs"] +features = [ "docs" ] extra-dependencies = [ - "setuptools", # undeclared dependency in pybtex - # fix from here: https://github.com/executablebooks/MyST-NB/pull/597 - "myst-nb @ git+https://github.com/flying-sheep/MyST-NB.git@eval-metadata", + "setuptools", # undeclared dependency in pybtex + # fix from here: https://github.com/executablebooks/MyST-NB/pull/597 + "myst-nb @ git+https://github.com/flying-sheep/MyST-NB.git@eval-metadata", ] -[tool.hatch.envs.docs.scripts] -build = "sphinx-build -M html docs docs/_build {args}" -open = "python3 -m webbrowser -t docs/_build/html/index.html" -clean = "git clean -fdX -- {args:docs}" +scripts.build = "sphinx-build -M html docs docs/_build {args}" +scripts.open = "python3 -m webbrowser -t docs/_build/html/index.html" +scripts.clean = "git clean -fdX -- {args:docs}" [tool.hatch.build.targets.wheel] -bypass-selection = true # This is not a package +bypass-selection = true # This is not a package [tool.ruff] line-length = 120 -src = ["src"] -extend-include = ["*.ipynb"] +src = [ "src" ] +extend-include = [ "*.ipynb" ] + +format.docstring-code-format = true -[tool.ruff.lint] -select = [ - "F", # Errors detected by Pyflakes - "E", # Error detected by Pycodestyle - "W", # Warning detected by Pycodestyle - "I", # isort - "D", # pydocstyle - "B", # flake8-bugbear - "TID", # flake8-tidy-imports - "C4", # flake8-comprehensions - "BLE", # flake8-blind-except - "UP", # pyupgrade - "RUF100", # Report unused noqa directives +lint.select = [ + "B", # flake8-bugbear + "BLE", # flake8-blind-except + "C4", # flake8-comprehensions + "D", # pydocstyle + "E", # Error detected by Pycodestyle + "F", # Errors detected by Pyflakes + "I", # isort + "RUF100", # Report unused noqa directives + "TID", # flake8-tidy-imports + "UP", # pyupgrade + "W", # Warning detected by Pycodestyle ] -ignore = [ - # dict() syntax is fine - "C408", - # line too long -> we accept long comment lines; formatter gets rid of long code lines - "E501", - # Do not assign a lambda expression, use a def -> lambda expression assignments are convenient - "E731", - # allow I, O, l as variable names -> I is the identity matrix - "E741", - # Missing docstring in public package - "D104", - # Missing docstring in public module - "D100", - # Missing docstring in __init__ - "D107", - # Errors from function calls in argument defaults. These are fine when the result is immutable. - "B008", - # __magic__ methods are often self-explanatory, allow missing docstrings - "D105", - # first line should end with a period [Bug: doesn't work with single-line docstrings] - "D400", - # First line should be in imperative mood; try rephrasing - "D401", - ## Disable one in each pair of mutually incompatible rules - # We don’t want a blank line before a class docstring - "D203", - # We want docstrings to start immediately after the opening triple quote - "D213", +lint.ignore = [ + "B008", # Errors from function calls in argument defaults. These are fine when the result is immutable. + "C408", # dict() is nice for some use cases + "D100", # Missing docstring in public module + "D104", # Missing docstring in public package + "D105", # __magic__ methods are often self-explanatory, allow missing docstrings + "D107", # Missing docstring in __init__ + # Disable one in each pair of mutually incompatible rules + "D203", # We don’t want a blank line before a class docstring + "D213", # <> We want docstrings to start immediately after the opening triple quote + "D400", # first line should end with a period [Bug: doesn’t work with single-line docstrings] + "D401", # First line should be in imperative mood; try rephrasing + "E501", # line too long -> we accept long comment lines; formatter gets rid of long code lines + "E731", # Do not assign a lambda expression, use a def -> lambda expression assignments are convenient + "E741", # allow I, O, l as variable names -> I is the identity matrix ] - -[tool.ruff.lint.pydocstyle] -convention = "numpy" - -[tool.ruff.lint.per-file-ignores] -"docs/*" = [ - "B018", # Trailing expressions in notebooks are not “useless” - "D103", # No need for docstrings in functions, we use literate programming - "E402", # Imports in non-top cells are fine +lint.per-file-ignores."docs/**" = [ + "B018", # Trailing expressions in notebooks are not “useless” + "D103", # No need for docstrings in functions, we use literate programming + "E402", # Imports in non-top cells are fine ] -"tests/*" = ["D"] -"*/__init__.py" = ["F401"] +lint.pydocstyle.convention = "numpy" [tool.cruft] skip = [ - "tests", - "src/**/__init__.py", - "src/**/basic.py", - "docs/api.md", - "docs/changelog.md", - "docs/references.bib", - "docs/references.md", - "docs/notebooks/example.ipynb", + ".github/ISSUE_TEMPLATE", + "environment.yml", + "*.md", + "src", + "docs/*.md", + "docs/notebooks", + "docs/references.bib", + "tests", + "tutorial-registry", ]