diff --git a/.flake8 b/.flake8 index 79f1780..7bc8e6c 100644 --- a/.flake8 +++ b/.flake8 @@ -1,6 +1,6 @@ [flake8] count = True -ignore = E123, E203, W504 +ignore = E123, E203, W503 max-doc-length = 79 max-complexity = 15 jobs = 1 diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a229a24..917bc20 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -20,7 +20,7 @@ permissions: jobs: build: - name: Build and Deploy + name: Build and Deploy Autodoc=${{ matrix.build-autodoc }} runs-on: ubuntu-latest @@ -28,10 +28,18 @@ jobs: IS_DEPLOY: ${{ (github.event_name == 'push' && '1') || '0' }} IS_STAGING: ${{ (github.ref == 'refs/heads/staging' && '1') || '0' }} IS_MAIN: ${{ ((github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') && '1') || '0' }} + BUILD_AUTODOC: ${{ matrix.build-autodoc }} + + strategy: + fail-fast: false + matrix: + build-autodoc: ['Yes', 'No'] steps: - name: Check out repository uses: actions/checkout@v4 + with: + submodules: true - name: Set up Python uses: actions/setup-python@v5 with: @@ -45,12 +53,13 @@ jobs: echo Deploy: $IS_DEPLOY echo Prod: $IS_PROD echo Main: $IS_MAIN + echo Autodoc: $BUILD_AUTODOC pip list - name: Build project shell: bash run: ./ci/build.sh - name: Deploy to GitHub Pages - if: env.IS_DEPLOY == '1' + if: env.IS_DEPLOY == '1' && env.BUILD_AUTODOC == 'Yes' uses: JamesIves/github-pages-deploy-action@v4 with: folder: docs/_build/html diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index cb5632b..09bba5d 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -31,6 +31,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + submodules: true - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.gitignore b/.gitignore index 0102260..24a2785 100644 --- a/.gitignore +++ b/.gitignore @@ -110,7 +110,9 @@ instance/ .scrapy # Sphinx documentation +doc/_autosummary/ doc/_build/ +docs/_autosummary/ docs/_build/ # PyBuilder diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3de7289 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,5 @@ +[submodule "spyder"] + path = spyder + url = https://github.com/spyder-ide/spyder.git + branch = 6.x + update = rebase diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c86b2b3..4ec7f31 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,9 +25,9 @@ Let us know if you have any further questions, and we look forward to your contr - [Cloning the Repository](#cloning-the-repository) - [Setting Up a Development Environment with Nox (Recommended)](#setting-up-a-development-environment-with-nox-recommended) - [Setting Up a Development Environment Manually](#setting-up-a-development-environment-manually) + - [Configure Git](#configure-git) - [Create and activate a fresh environment](#create-and-activate-a-fresh-environment) - [Install dependencies](#install-dependencies) - - [Add the upstream remote](#add-the-upstream-remote) - [Installing and Using the Pre-Commit Hooks](#installing-and-using-the-pre-commit-hooks) - [Building the Project](#building-the-project) - [Build with Nox](#build-with-nox) @@ -35,7 +35,8 @@ Let us know if you have any further questions, and we look forward to your contr - [Contributing Changes](#contributing-changes) - [Decide which branch to use](#decide-which-branch-to-use) - [Prepare your topic branch](#prepare-your-topic-branch) - - [Commit your changes](#commit-your-changes) + - [Sync the latest Spyder docstrings (optional)](#sync-the-latest-spyder-docstrings-optional) + - [Make and commit your changes](#make-and-commit-your-changes) - [Push your branch](#push-your-branch) - [Submit a Pull Request](#submit-a-pull-request) - [Standards and Conventions](#standards-and-conventions) @@ -58,10 +59,10 @@ If referring to a specific line or file, please be sure to provide a snippet of ## Cloning the Repository First, navigate to the [project repository](https://github.com/spyder-ide/spyder-api-docs) in your web browser and press the ``Fork`` button to make a personal copy of the repository on your own GitHub account. -Then, click the ``Clone or Download`` button on your repository, copy the link and run the following on the command line to clone the repo: +Then, click the ``Clone or Download`` button on your repository, copy the link and run the following on the command line to clone the repo (with submodules): ```shell -git clone +git clone --recurse-submodules ``` After cloning the repository, navigate to its new directory using the `cd` command: @@ -119,6 +120,22 @@ For advanced users, if you'd prefer to also have your own local environment with **Note**: You may need to substitute ``python3`` for ``python`` in the commands below on some Linux distros where ``python`` isn't mapped to ``python3`` (yet). +### Configure Git + +Make sure to set the upstream Git remote to the official Spyder-API-Docs repo with: + +```shell +git remote add upstream https://github.com/spyder-ide/spyder-api-docs.git +``` + +It's also a good idea to configure Git to automatically pull, checkout and push submodules: + +```shell +git config --local submodule.recurse true +git config --local push.recurseSubmodules check +``` + + ### Create and activate a fresh environment We highly recommend you create and activate a virtual environment to avoid any conflicts with other packages on your system or causing any other issues. @@ -128,7 +145,7 @@ Regardless of the tool you use, make sure to remember to always activate your en #### Conda -To create an environment with Conda (recommended), simply execute the following: +To create an environment with Conda (recommended), execute the following: ```shell conda create -c conda-forge -n spyder-api-docs-env python @@ -177,17 +194,14 @@ Or if using ``pip``, you can grab them with: python -m pip install -r requirements.txt ``` - -### Add the upstream remote - -Make sure to set the upstream Git remote to the official Spyder-API-Docs repo with: +If you plan to generate and build the API reference documentation extracted from Spyder's docstrings, you'll also need to install Spyder in development mode as well as its dev dependencies. +To do so, you can run the ``install_dev_repos.py`` script in the ``spyder`` submodule: ```shell -git remote add upstream https://github.com/spyder-ide/spyder-api-docs.git +python install_dev_repos.py ``` - ## Installing and Using the Pre-Commit Hooks This repository uses [Pre-Commit](https://pre-commit.com/) to install, configure and update a suite of pre-commit hooks that check for common problems and issues, and fix many of them automatically. @@ -240,7 +254,13 @@ To build the project using Nox, just run nox -s build ``` -and can then open the rendered output in your default web browser with +or, to also extract, generate and build the API reference from Spyder's docstrings (expensive the first time), pass the ``-t autodoc`` argument to any build command: + +```shell +nox -s build -- -t autodoc +``` + +and then open the rendered output in your default web browser with ```shell nox -s serve @@ -249,7 +269,7 @@ nox -s serve Alternatively, to automatically rebuild the project when changes occur, you can invoke ```shell -nox -s autobuild +nox -s autorebuild ``` You can also pass your own custom [Sphinx build options](https://www.sphinx-doc.org/en/master/man/sphinx-build.html) after a ``--`` separator, which are added to the default set. @@ -259,6 +279,12 @@ For example, to rebuild just the install guide and FAQ in verbose mode with the nox -s build -- --verbose --builder dirhtml -- index.rst ``` +When changing build options (particularly autodoc), cleaning the generated files avoids spurious errors: + +```shell +nox -s clean +``` + ### Build manually @@ -268,8 +294,21 @@ For manual installations, you can invoke Sphinx yourself with the appropriate op python -m sphinx -n -W --keep-going docs docs/_build/html ``` +or to also extract, generate and build the API reference from Spyder's docstrings (requires Spyder and its dependencies to be installed in your environment): + +```shell +python -I -m sphinx -n --keep-going -t autodoc docs docs/_build/html +``` + Then, navigate to the ``_build/html`` directory inside the ``spyder-docs`` repository and open ``index.html`` (the main page of the docs) in your preferred browser. +When changing build options (particularly autodoc), cleaning the generated files first avoids spurious errors: + +```shell +rm -r docs/_autosummary/ +rm -r docs/_build/ +``` + ## Contributing Changes @@ -295,7 +334,40 @@ git switch -c ``` -### Commit your changes +### Sync the latest Spyder docstrings (optional) + +*If* your pull request requires the latest docstring changes from the Spyder repo, or there's a reason to manually update them, you can update the submodule to the latest stable branch either with Nox: + +```shell +nox -s sync-spyder +``` + +or manually: + +```shell +git submodule update --remote +``` + +**Note**: If using the manual command and you've checked out the submodule to a topic branch tracking your fork rather than the upstream Spyder repository, you'll need to either check out `6.x` first (setting it to track the main Spyder repo if it isn't already): + +```shell +cd spyder +git switch 6.x +git --set-upstream-to upstream 6.x # If required +cd .. +``` + +Or, to integrate the changes into your own branch (assuming `upstream` is the Spyder repository): + +```shell +cd spyder +git fetch upstream 6.x +git rebase FETCH_HEAD +cd .. +``` + + +### Make and commit your changes Once you've made and tested your changes, add them to the staging area, and then commit them with a descriptive message. Commit messages should be diff --git a/ci/build.sh b/ci/build.sh index 35a7754..cf6b7a0 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -1,3 +1,9 @@ #!/bin/bash -ex -nox -s build +if [ "$BUILD_AUTODOC" = "No" ]; then + ARGS='' +else + ARGS='-t autodoc' +fi + +nox -s build -- $ARGS diff --git a/docs/_templates/custom-module-template.rst b/docs/_templates/custom-module-template.rst new file mode 100644 index 0000000..79c8049 --- /dev/null +++ b/docs/_templates/custom-module-template.rst @@ -0,0 +1,63 @@ +{{ fullname | escape | underline}} + +.. automodule:: {{ fullname }} + + {% block attributes %} + {%- if attributes %} + .. rubric:: {{ _('Module Attributes') }} + + .. autosummary:: + {% for item in attributes %} + {{ item }} + {%- endfor %} + {% endif %} + {%- endblock %} + + {%- block functions %} + {%- if functions %} + .. rubric:: {{ _('Functions') }} + + .. autosummary:: + {% for item in functions %} + {{ item }} + {%- endfor %} + {% endif %} + {%- endblock %} + + {%- block classes %} + {%- if classes %} + .. rubric:: {{ _('Classes') }} + + .. autosummary:: + {% for item in classes %} + {{ item }} + {%- endfor %} + {% endif %} + {%- endblock %} + + {%- block exceptions %} + {%- if exceptions %} + .. rubric:: {{ _('Exceptions') }} + + .. autosummary:: + {% for item in exceptions %} + {{ item }} + {%- endfor %} + {% endif %} + {%- endblock %} + +{%- block modules %} +{%- if modules %} +.. rubric:: Modules + +.. autosummary:: + :toctree: + :template: custom-module-template.rst + :recursive: +{% for item in modules %} + {% if not 'tests' in item %} + {{ item }} + {%- endif %} +{%- endfor %} +{% endif %} +{%- endblock %} diff --git a/docs/conf.py b/docs/conf.py index 57107b4..03d4a27 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -15,48 +15,43 @@ # serve to show the default. -# If extensions (or modules to document with autodoc) are in another -# directory, add these directories to sys.path here. If the directory is -# relative to the documentation root, use os.path.abspath to make it -# absolute, like shown here. -# -# import sys -# sys.path.insert(0, os.path.abspath('.')) - - # Standard library imports import datetime +import sys +from pathlib import Path # Third party imports -# pylint: disable-next = import-error from docutils import nodes - -# pylint: disable-next = import-error from docutils.parsers.rst import Directive, directives # Constants UTC_DATE = datetime.datetime.now(datetime.timezone.utc) +# Make Spyder available on $PATH for API documentation +sys.path.insert(0, str(Path(__file__).parents[1].resolve() / "spyder")) + # -- General configuration --------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # -# needs_sphinx = "1.0" +needs_sphinx = "5" # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named "sphinx.ext.*") or your custom ones. extensions = [ "myst_parser", "sphinx.ext.autodoc", + "sphinx.ext.autosummary", "sphinx.ext.githubpages", "sphinx.ext.intersphinx", + "sphinx.ext.napoleon", "sphinx.ext.viewcode", ] # Add any paths that contain templates here, relative to this directory. -templates_path = [] # "_templates" +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: @@ -104,7 +99,9 @@ todo_include_todos = False # Intersphinx configuration +# pylint: disable-next = consider-using-namedtuple-or-dataclass intersphinx_mapping = { + "python": ("https://docs.python.org/", None), "spyder": ("https://docs.spyder-ide.org/current/", None), } @@ -137,6 +134,9 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] +# Warning suppression +suppress_warnings = [] + # -- Options for HTMLHelp output --------------------------------------- @@ -215,7 +215,7 @@ # } -# -- Options for Linkcheck -------------------------------------------------- +# -- Options for Linkcheck --------------------------------------------- linkcheck_ignore = [ # Virtual fragment ids @@ -237,6 +237,35 @@ myst_config = {} +# -- Options for Autodoc/Autosummary ----------------------------------- + +# Include Python objects as they appear in source files +# Default: alphabetically ('alphabetical') +autodoc_member_order = "bysource" + +# Default flags used by autodoc directives +autodoc_default_options = { + "members": True, + "show-inheritance": True, +} + +# Disable imports that cause crashes +autodoc_mock_imports = [ + # "qtpy.QtGui", + # "qdarkstyle", + # "qstylizer", +] + +# Generate autosummaries if the autodoc tag is passed +# pylint: disable-next = undefined-variable +if "autodoc" in tags: # noqa: F821 + autosummary_generate = True +else: + autosummary_generate = False + suppress_warnings += ["autodoc", "autosummary", "toc.excluded"] + exclude_patterns += ["reference.rst"] + + # -- Additional Directives --------------------------------------------------- # ReST directive for embedding Youtube and Vimeo videos. @@ -299,7 +328,6 @@ class Youtube(IFrameVideo): '', ] diff --git a/docs/index.md b/docs/index.md index d12ba21..daa5caf 100644 --- a/docs/index.md +++ b/docs/index.md @@ -40,4 +40,5 @@ Plugin Development with Spyder Extending Spyder Design Patterns FAQ +API Reference ``` diff --git a/docs/reference.rst b/docs/reference.rst new file mode 100644 index 0000000..f8cb533 --- /dev/null +++ b/docs/reference.rst @@ -0,0 +1,11 @@ +API Reference +============= + +API reference for all modules in the Spyder application. + +.. autosummary:: + :toctree: _autosummary + :template: custom-module-template.rst + :recursive: + + spyder.api diff --git a/noxfile.py b/noxfile.py index 920f382..0d0da79 100644 --- a/noxfile.py +++ b/noxfile.py @@ -4,15 +4,16 @@ import contextlib import logging import os -import tempfile import shutil import sys +import tempfile import webbrowser from pathlib import Path # Third party imports -import nox # pylint: disable=import-error -import nox.logger # pylint: disable=import-error +import nox +import nox.logger +import packaging.requirements # --- Global constants --- # @@ -29,7 +30,7 @@ REPO_URL_SSH = "git@github.com:{user}/{repo}.git" # Build config -BUILD_INVOCATION = ("python", "-m", "sphinx") +BUILD_INVOCATION = ("python", "-I", "-m", "sphinx") SOURCE_DIR = Path("docs").resolve() BUILD_DIR = Path("docs/_build").resolve() BUILD_OPTIONS = ("-n", "-W", "--keep-going") @@ -56,12 +57,30 @@ BASE_URL = "https://spyder-ide.github.io/spyder-api-docs/" # Other config -CANARY_COMMAND = ("pre-commit", "--version") +# pylint: disable-next = consider-using-namedtuple-or-dataclass +CANARY_COMMANDS = { + "doc": { + "cmd": ("pre-commit", "--version"), + "default": True, + "env": {}, + }, + "autodoc": { + "cmd": ("python", "-I", "-m", "spyder.app.start", "--help"), + "default": False, + "env": {"HOME": str(Path().home())}, + }, +} IGNORE_REVS_FILE = ".git-blame-ignore-revs" PRE_COMMIT_VERSION_SPEC = ">=2.10.0,<4" # Custom config SCRIPT_DIR = Path("scripts").resolve() +AUTOSUMMARY_DIR = SOURCE_DIR / "_autosummary" +SPYDER_PATH = Path("spyder").resolve() +DEPS_PATH = SPYDER_PATH / "external-deps" + +# Post config +DIRS_TO_CLEAN = [BUILD_DIR, AUTOSUMMARY_DIR] # ---- Helpers ---- # @@ -145,6 +164,9 @@ def construct_sphinx_invocation( builder = builders[-1] if builders else builder build_dir = BUILD_DIR / builder if build_dir is None else build_dir + if "autodoc" in cli_options: + build_options = [item for item in build_options if item != "-W"] + if CI: build_options = list(build_options) + ["--color"] @@ -163,6 +185,43 @@ def construct_sphinx_invocation( return sphinx_invocation +def list_spyder_dev_repos(): + """List the development repos included as subrepos of Spyder.""" + repos = [] + for p in [SPYDER_PATH] + list(DEPS_PATH.iterdir()): + if ( + p.name.startswith(".") + or not p.is_dir() + and not ( + (p / "setup.py").exists() or (p / "pyproject.toml").exists() + ) + ): + continue + + repos.append(p) + return repos + + +def get_python_lsp_version(): + """Get current version to pass it to setuptools-scm.""" + req_file = SPYDER_PATH / "requirements" / "main.yml" + with open(req_file, "r", encoding="UTF-8") as f: + for line in f: + if "python-lsp-server" not in line: + continue + parts = line.split("-")[-1] + specifiers = packaging.requirements.Requirement(parts).specifier + break + else: + return "0.0.0" + + for specifier in specifiers: + if "=" in specifier.operator: + return specifier.version + + return "0.0.0" + + # ---- Dispatch ---- # @@ -176,16 +235,28 @@ def _execute(session): "Must pass a list of functions to execute as first posarg" ) + canary_commands = {} + install_tags = set() + for arg, properties in CANARY_COMMANDS.items(): + cmd = properties["cmd"] + if properties["default"] or arg in session.posargs: + canary_commands[arg] = cmd + env = properties["env"] if properties["env"] else None + if not session.posargs or session.posargs[0] is not _install: - # pylint: disable=too-many-try-statements - try: - with set_log_level(): - session.run( - *CANARY_COMMAND, include_outer_env=False, silent=True - ) - except nox.command.CommandFailed: - print("Installing dependencies in isolated environment...") - _install(session, use_posargs=False) + for arg, cmd in canary_commands.items(): + # pylint: disable=too-many-try-statements + try: + with set_log_level(): + session.run( + *cmd, env=env, include_outer_env=False, silent=True + ) + except nox.command.CommandFailed: + install_tags.add(arg) + + if install_tags: + print("Installing dependencies in isolated environment...") + _install(session, use_posargs=False, install_tags=install_tags) if session.posargs: for task in session.posargs[0]: @@ -195,13 +266,49 @@ def _execute(session): # ---- Install ---- # -def _install(session, *, use_posargs=True): - """Execute the dependency installation.""" - posargs = session.posargs[1:] if use_posargs else () +def _install_doc(session, posargs=()): + """Install the basic documentation and dev dependencies.""" session.install(f"pre-commit{PRE_COMMIT_VERSION_SPEC}") session.install("-r", "requirements.txt", *posargs) +def _install_autodoc(session, posargs=()): + """Install the dependencies to generate API autodocs.""" + dev_repos = list_spyder_dev_repos() + for dev_repo in dev_repos: + env = None + if "python-lsp-server" in str(dev_repo): + env = {**os.environ} + env.update( + {"SETUPTOOLS_SCM_PRETEND_VERSION": get_python_lsp_version()} + ) + session.install("-e", dev_repo, *posargs, env=env) + + +INSTALL_FUNCTIONS = { + "doc": _install_doc, + "autodoc": _install_autodoc, +} + + +def _install(session, *, use_posargs=True, install_tags=None): + """Execute the dependency installation.""" + posargs = session.posargs[1:] if use_posargs else () + + install_tags = {"doc"} if install_tags is None else install_tags + for arg in CANARY_COMMANDS: + if f"--{arg}" in session.posargs: + install_tags.add(arg) + if posargs: + posargs.remove(f"--{arg}") + # pylint: disable-next = confusing-consecutive-elif + elif arg in session.posargs: + install_tags.add(arg) + + for tag in install_tags: + INSTALL_FUNCTIONS[tag](session, posargs) + + @nox.session def install(session): """Install the project's dependencies (passes through args to pip).""" @@ -230,7 +337,7 @@ def _run(session): session.run(*posargs) -@nox.session() +@nox.session def run(session): """Run any command.""" session.notify("_execute", posargs=([_run], *session.posargs)) @@ -238,17 +345,21 @@ def run(session): def _clean(session): """Remove the build directory.""" - print(f"Removing build directory {BUILD_DIR.as_posix()!r}") ignore_flag = "--ignore" should_ignore = ignore_flag in session.posargs - try: - shutil.rmtree(BUILD_DIR, ignore_errors=should_ignore) - except FileNotFoundError: - pass - except Exception: - print(f"\nError removing files; pass {ignore_flag!r} flag to ignore\n") - raise + for dir_to_clean in DIRS_TO_CLEAN: + if not dir_to_clean.exists(): + continue + print(f"Removing generated directory {dir_to_clean.as_posix()!r}") + try: + shutil.rmtree(dir_to_clean, ignore_errors=should_ignore) + except FileNotFoundError: + pass + except Exception: + print(f"\nError removing files in {dir_to_clean.as_posix()!r}") + print(f"Pass {ignore_flag!r} flag to ignore\n") + raise @nox.session @@ -257,6 +368,22 @@ def clean(session): _clean(session) +def _sync_spyder(session): + """Sync the latest docstrings from upstream Spyder into the submodule.""" + foreach_cmd = ["git", "submodule", "--quiet", "foreach"] + session.run( + *foreach_cmd, + "git fetch upstream 6.x && git rebase FETCH_HEAD", + external=True, + ) + + +@nox.session(name="sync-spyder") +def sync_spyder(session): + """Sync the latest docstrings from upstream Spyder into the submodule.""" + _sync_spyder(session) + + # --- Set up --- # @@ -323,6 +450,43 @@ def setup_remotes(session): _setup_remotes(session) +def _setup_submodule_remotes(session): + """Set up the upstream submodule remote to point to the Spyder repo.""" + foreach_cmd = ["git", "submodule", "--quiet", "foreach"] + spyder_repo = "spyder" + + # Check if an upstream remote already exists + existing_remotes = ( + session.run( + *foreach_cmd, + "git remote", + external=True, + silent=True, + log=False, + ) + .strip() + .split("\n") + ) + + if "upstream" in existing_remotes: + return + + spyder_repo_url = REPO_URL_HTTPS.format(user=ORG_NAME, repo=spyder_repo) + session.run( + *foreach_cmd, + f"git remote add upstream '{spyder_repo_url}'", + external=True, + ) + + session.run(*foreach_cmd, "git fetch --all", external=True) + + +@nox.session(name="setup-submodule-remotes") +def setup_submodule_remotes(session): + """Set up the upstream submodule remote to point to the Spyder repo.""" + _setup_submodule_remotes(session) + + def _ignore_revs(session): """Configure the Git ignore revs file to the repo default.""" if not IGNORE_REVS_FILE: @@ -342,7 +506,50 @@ def ignore_revs(session): _ignore_revs(session) -@nox.session() +def _config_submodules(session): + """Configure Git to automatically recurse into Git submodules.""" + session.run( + "git", + "config", + "--local", + "submodule.recurse", + "true", + external=True, + ) + session.run( + "git", + "config", + "--local", + "push.recurseSubmodules", + "check", + external=True, + ) + + +@nox.session(name="config-submodules") +def config_submodules(session): + """Initialize and download all Git submodules.""" + _config_submodules(session) + + +def _init_submodules(session): + """Initialize and download all Git submodules.""" + session.run( + "git", + "submodule", + "update", + "--init", + external=True, + ) + + +@nox.session(name="init-submodules") +def init_submodules(session): + """Initialize and download all Git submodules.""" + _init_submodules(session) + + +@nox.session def setup(session): """Set up the project; pass --https or --ssh to specify Git URL type.""" session.notify( @@ -350,6 +557,9 @@ def setup(session): posargs=( [ _ignore_revs, + _config_submodules, + _init_submodules, + _setup_submodule_remotes, _setup_remotes, _install_hooks, _clean, @@ -373,15 +583,15 @@ def build(session): session.notify("_execute", posargs=([_build], *session.posargs)) -def _autobuild(session): +def _autorebuild(session): """Use Sphinx-Autobuild to rebuild the project and open in browser.""" - _autodocs(session) + _docs_autobuild(session) @nox.session -def autobuild(session): +def autorebuild(session): """Rebuild the project continuously as source files are changed.""" - session.notify("_execute", posargs=([_autobuild], *session.posargs)) + session.notify("_execute", posargs=([_autorebuild], *session.posargs)) # --- Docs --- # @@ -401,7 +611,7 @@ def docs(session): session.notify("_execute", posargs=([_docs], *session.posargs)) -def _autodocs(session): +def _docs_autobuild(session): """Use Sphinx-Autobuild to rebuild the project and open in browser.""" session.install("sphinx-autobuild") @@ -420,10 +630,10 @@ def _autodocs(session): session.run(*sphinx_invocation) -@nox.session -def autodocs(session): +@nox.session(name="docs-autobuild") +def docs_autobuild(session): """Rebuild the docs continuously as source files are changed.""" - session.notify("_execute", posargs=([_autodocs], *session.posargs)) + session.notify("_execute", posargs=([_docs_autobuild], *session.posargs)) def _build_languages(session): @@ -485,7 +695,6 @@ def serve_docs(_session): def _prepare_multiversion(_session=None): """Execute the pre-deployment steps for multi-version support.""" # pylint: disable=import-outside-toplevel - # pylint: disable=import-error sys.path.append(str(SCRIPT_DIR)) import generateredirects diff --git a/spyder b/spyder new file mode 160000 index 0000000..fdc3eb1 --- /dev/null +++ b/spyder @@ -0,0 +1 @@ +Subproject commit fdc3eb174a44d2293ffdf9879fb5e197a210bdff diff --git a/tutorial/my-spyder-plugin/my_spyder_plugin/plugin.py b/tutorial/my-spyder-plugin/my_spyder_plugin/plugin.py index 5fcdf48..5af09cf 100644 --- a/tutorial/my-spyder-plugin/my_spyder_plugin/plugin.py +++ b/tutorial/my-spyder-plugin/my_spyder_plugin/plugin.py @@ -1,3 +1,5 @@ +# pylint: disable = no-name-in-module + # Third party imports from spyder.api.plugins import Plugins, SpyderPluginV2 from spyder.plugins.core.api import ApplicationMenus, HelpMenuSections