diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml new file mode 100644 index 00000000..c8eda6bc --- /dev/null +++ b/.github/workflows/deploy_docs.yml @@ -0,0 +1,60 @@ +name: Deploy Documentation + +on: + push: + branches: + - main + tags: + - 'v*' + workflow_dispatch: + +# Only allow one docs build at a time so that overlapping stale builds will get +# cancelled automatically. +concurrency: + group: deploy_docs + cancel-in-progress: true + +jobs: + build-and-deploy: + name: Build & Deploy + runs-on: ubuntu-latest + + permissions: + contents: write # so we can write to github pages without a token + pages: write # to deploy to Pages + id-token: write # to verify the deployment originates from an appropriate source + + steps: + - name: Clone repo + uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - uses: tlambert03/setup-qt-libs@v1 + + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + python -m pip install "napari[all]" + python -m pip install -e ".[docs]" + + - name: Build Docs + uses: aganders3/headless-gui@v2 + with: + run: make docs + + - name: Check file tree contents + run: tree + + # At a minimum this job should upload artifacts using actions/upload-pages-artifact + - name: Upload GitHub Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + name: github-pages + path: docs/_build + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 # or specific "vX.X.X" version tag for this action diff --git a/.gitignore b/.gitignore index e51cf90a..e822007a 100644 --- a/.gitignore +++ b/.gitignore @@ -87,4 +87,33 @@ target/ # spyder stuff .spyproject/ +# Environment variables file .env + +# Sphinx documentation +docs/_build/ + +# MkDocs documentation +/site/ + +# PyBuilder +target/ + +# IPython Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# OS +.DS_Store + +# written by setuptools_scm +*/_version.py + +# vscode +.vscode + +# Images +docs/images/ + diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..aefe310d --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ +.PHONY: docs clean + +SPHINXOPTS = + +mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) +current_dir := $(dir $(mkfile_path)) +docs_dir := $(current_dir)docs + +clean: + echo clean + echo $(current_dir) + rm -rf $(docs_dir)/_build/ + rm -rf $(docs_dir)/images/ + mkdir $(docs_dir)/images/ + cp images/*.png $(docs_dir)/images/ + +docs-build: + NAPARI_CONFIG="" NAPARI_APPLICATION_IPY_INTERACTIVE=0 sphinx-build -b html docs/ docs/_build $(SPHINXOPTS) + +docs-xvfb: + NAPARI_CONFIG="" NAPARI_APPLICATION_IPY_INTERACTIVE=0 xvfb-run --auto-servernum sphinx-build -b html docs/ docs/_build $(SPHINXOPTS) + +docs: clean docs-build + +serve: + python -m http.server -d $(docs_dir)/_build +# Implies noplot, but no clean - call 'make clean' manually if needed +# Autogenerated paths need to be ignored to prevent reload loops +html-live: + NAPARI_APPLICATION_IPY_INTERACTIVE=0 \ + sphinx-autobuild \ + -b html \ + docs/ \ + docs/_build \ + --open-browser \ + --port=0 \ + $(SPHINXOPTS) + +html-noplot: clean + NAPARI_APPLICATION_IPY_INTERACTIVE=0 sphinx-build -b html docs/ docs/_build $(SPHINXOPTS) + +linkcheck-files: + NAPARI_APPLICATION_IPY_INTERACTIVE=0 sphinx-build -b linkcheck --color docs/ docs/_build ${FILES} $(SPHINXOPTS) diff --git a/README.md b/README.md index bab5668d..603c2ddf 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,175 @@ # napari-plugin-manager -> WIP, under active development - [![License](https://img.shields.io/pypi/l/napari-plugin-manager.svg?color=green)](https://github.com/napari/napari-plugin-manager/raw/main/LICENSE) [![PyPI](https://img.shields.io/pypi/v/napari-plugin-manager.svg?color=green)](https://pypi.org/project/napari-plugin-manager) [![Python Version](https://img.shields.io/pypi/pyversions/napari-plugin-manager.svg?color=green)](https://python.org) -[![tests](https://github.com/napari/napari-plugin-manager/workflows/test_and_deploy/badge.svg)](https://github.com/napari/napari-plugin-manager/actions) +[![tests](https://github.com/napari/napari-plugin-manager/actions/workflows/test_and_deploy.yml/badge.svg)](https://github.com/napari/napari-plugin-manager/actions/workflows/test_and_deploy.yml) [![codecov](https://codecov.io/gh/napari/napari-plugin-manager/branch/main/graph/badge.svg)](https://codecov.io/gh/napari/napari-plugin-manager) [napari] plugin manager to provide a graphical user interface for installing [napari] plugins. ----------------------------------- +You can read the documentation at [napari.org/napari-plugin-manager](https://napari.org/napari-plugin-manager). + +## Overview + +The `napari-plugin-manager` used to be part of the [napari] codebase before the 0.5.x release +series. It's now maintained as a separate project and package to allow uncoupled iterations outside +of the `napari` release cycle. + +Future work will allow other applications with a plugin ecosytem to customize and +use the `plugin-manager`. This package remains under active development and contributions +are very welcome. Please [open an issue] to discuss potential improvements. + +This package currently provides: + +- A package installer process queue that supports both [pip] and [conda] installs. +- An easy to use GUI for searching, installing, uninstalling and updating plugins that make part of + the napari ecosystem. Each plugin entry provides a summary and information on the authors that + created the package. The REST API used to query for plugins and plugin information is provided by + the [npe2api service](https://api.napari.org). +- The ability to install other packages via URL of by dragging and dropping artifacts from [PyPI]. + +![Screenshot of the napari-plugin-manager interface, showcasing the plugin descriptions](./images/description.png) + +`napari-plugin-manager` knows how to detect if napari was installed using `conda` or `pip` and +provide the appropriate default installer tool on the `Installation Info` dropdown for each plugin. + +`conda` provides an efficient dependency solver that guarantees the stability and correctness of +the napari installation and work environment. This is the reason why `conda` is the default tool +used for the [napari +bundle](https://napari.org/stable/tutorials/fundamentals/installation_bundle_conda.html), a 1-click +installer available for Mac, Linux and Windows. This installation method is best if you mainly want +to use napari as a standalone GUI app. However, certain plugins may not be supported. ## Installation -You can install `napari-plugin-manager` via [pip]: +### PyPI + +`napari-plugin-manager` is available through the Python Package Index and can be installed using [pip]. + +```bash +pip install napari-plugin-manager +``` + +### Conda + +`napari-plugin-manager` is also available for install using [conda] through the [conda-forge channel](https://conda-forge.org/docs/#what-is-conda-forge). + + +```bash +conda install napari-plugin-manager -c conda-forge +``` + +## Using the napari plugin manager + +### Enabling/Disabling plugins + +Installed plugins found on the current napari installation are displayed on the top list of the UI. + +Users of napari can choose to enable/disable a specific plugin by checking/unchecking the checkbox +to the left of each plugin item in the list. + +### Filtering + +You can filter available plugins by name or description by typing on the search box +on the top left corner of the UI. Only plugins that match the filter criteria will be shown. + +In the image below filtering by the word `arcos` yields a single plugin, the +`arcos-gui` plugin. Notice that plugins that provide a display name, will show +the package name to the right in parenthesis. + +![Screenshot of the napari-plugin-manager interface showcasing the filtering features with the query 'arcos'](./images/filter.png) + +### Refreshing + +If a new plugin has been released but it is not available on the list, you can click on the +`Refresh` button located at the top right corner, to clear the cache and load all newly +available plugins. + +### Installing a plugin - pip install napari-plugin-manager +To install a plugin: + +1. Select it by scrolling the available plugins list on the bottom, or by directly +filtering by name or description. +2. Select the tool (`conda` or `pip`) and version on the `Installation Info` dropdown. +3. Start the installation process by clicking on the `Install` button. + +You can cancel the process at any time by clicking the `Cancel` button of each plugin. + +**Note**: Not all napari plugins are currently available on conda via the +[conda-forge channel](https://anaconda.org/conda-forge/). Some plugins will require +a restart to be properly configured. + +![Screenshot of the napari-plugin-manager showing the process of installing a plugin](./images/install.png) + +### Uninstalling a plugin + +To uninstall a plugin: + +1. Select it by scrolling the installed plugins list on the top, or by directly +filtering by name or description. +2. Start the removal process by clicking on the `Uninstall` button. + +You can cancel the process at any time by clicking the `Cancel` button of each plugin. + +**Note**: Some plugins will require a restart to be properly removed. + +![Screenshot of the napari-plugin-manager showing the process of uninstalling a plugin](./images/uninstall.png) + +### Updating a plugin + +When a new version of an installed plugin is available, an `Update (vX.Y.Z)` +button will appear to the left of the `Installation Info` dropdown. + +To update a plugin: + +1. Select it by scrolling the install plugins list on the top, or by directly +filtering by name or description. +2. Start the update process by clicking on the `Update (vX.Y.Z)` button. + +You can cancel the process at any time by clicking the `Cancel` button of each plugin. + +![Screenshot of the napari-plugin-manager showing the process of updating a plugin](./images/update.png) + +### Batch actions + +You don't need wait for one action to finish before you can start another one. You can add more +tasks to the queue (install/uninstall/update) by clicking on the corresponding action buttons +plugin by plugin. The actions will be carried out sequentially and in the order in which you +started them. + +You can cancel all the started installer actions at any time by clicking `Cancel all` +button at the bottom of the UI. + +## Troubleshooting + +In order to visualize more detailed information on the installer process output, you can +click on the `Show status` button located at the bottom left corner of the UI. To hide +this detailed information you can click on the `Hide status` button. + +Some issues that you might experience when using the installer include: + +* Incompatible packages due to conflicting dependencies. +* Network connectivity errors. + +![Screenshot of the napari-plugin-amanger interface showcasing the status information, which is initially hidden by default.](./images/status.png) ## License -Distributed under the terms of the [BSD-3] license, -"napari-plugin-manager" is free and open source software +Distributed under the terms of the [BSD-3] license, "napari-plugin-manager" is free and open source +software. ## Issues If you encounter any problems, please [file an issue] along with a detailed description. [napari]: https://github.com/napari/napari -[Cookiecutter]: https://github.com/audreyr/cookiecutter [@napari]: https://github.com/napari [BSD-3]: http://opensource.org/licenses/BSD-3-Clause [file an issue]: https://github.com/napari/napari-plugin-manager/issues -[napari]: https://github.com/napari/napari -[tox]: https://tox.readthedocs.io/en/latest/ +[open an issue]: https://github.com/napari/napari-plugin-manager/issues [pip]: https://pypi.org/project/pip/ +[conda]: https://conda.org [PyPI]: https://pypi.org/ diff --git a/docs/__init__.py b/docs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 00000000..e69de29b diff --git a/docs/_static/favicon/logo-noborder-180.png b/docs/_static/favicon/logo-noborder-180.png new file mode 100644 index 00000000..88b21dd1 Binary files /dev/null and b/docs/_static/favicon/logo-noborder-180.png differ diff --git a/docs/_static/favicon/logo-silhouette-192.png b/docs/_static/favicon/logo-silhouette-192.png new file mode 100644 index 00000000..31f4f5cc Binary files /dev/null and b/docs/_static/favicon/logo-silhouette-192.png differ diff --git a/docs/_static/favicon/logo-silhouette-dark-light.svg b/docs/_static/favicon/logo-silhouette-dark-light.svg new file mode 100644 index 00000000..7120e739 --- /dev/null +++ b/docs/_static/favicon/logo-silhouette-dark-light.svg @@ -0,0 +1,28 @@ + + + + + + + diff --git a/docs/_templates/navbar-project.html b/docs/_templates/navbar-project.html new file mode 100644 index 00000000..90062dd6 --- /dev/null +++ b/docs/_templates/navbar-project.html @@ -0,0 +1,4 @@ + + + napari-plugin-manager + diff --git a/docs/_toc.yml b/docs/_toc.yml new file mode 100644 index 00000000..595eac5e --- /dev/null +++ b/docs/_toc.yml @@ -0,0 +1,4 @@ +root: index +subtrees: +- entries: + - file: developers/contributing diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..e8faeb76 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,150 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# 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 os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + +from napari_plugin_manager._version import ( + version as napari_plugin_manager_version, +) + +release = napari_plugin_manager_version +if "dev" in release: # noqa: SIM108 + version = "dev" +else: + version = release + +# -- Project information ----------------------------------------------------- + +project = "napari-plugin-manager" +copyright = "2024, The napari team" # noqa: A001 +author = "The napari team" + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. + +extensions = [ + "sphinx.ext.intersphinx", + "sphinx_external_toc", + "myst_nb", + "sphinx.ext.viewcode", + "sphinx_favicon", + "sphinx_copybutton", +] + +external_toc_path = "_toc.yml" + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "napari_sphinx_theme" + +# # Define the json_url for our version switcher. +# json_url = "https://napari.org/dev/_static/version_switcher.json" + +# if version == "dev": +# version_match = "latest" +# else: +# version_match = release + +html_theme_options = { + "external_links": [{"name": "napari", "url": "https://napari.org"}], + "github_url": "https://github.com/napari/napari-plugin-manager", + "navbar_start": ["navbar-logo", "navbar-project"], + "navbar_end": ["navbar-icon-links"], + # "switcher": { + # "json_url": json_url, + # "version_match": version_match, + # }, + "navbar_persistent": [], + "header_links_before_dropdown": 6, + "secondary_sidebar_items": ["page-toc"], + "pygments_light_style": "napari", + "pygments_dark_style": "napari", +} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] +html_logo = "images/logo.png" +html_sourcelink_suffix = "" +html_title = "napari plugin manager" + +favicons = [ + { + # the SVG is the "best" and contains code to detect OS light/dark mode + "static-file": "favicon/logo-silhouette-dark-light.svg", + "type": "image/svg+xml", + }, + { + # Safari in Oct. 2022 does not support SVG + # an ICO would work as well, but PNG should be just as good + # setting sizes="any" is needed for Chrome to prefer the SVG + "sizes": "any", + "static-file": "favicon/logo-silhouette-192.png", + }, + { + # this is used on iPad/iPhone for "Save to Home Screen" + # apparently some other apps use it as well + "rel": "apple-touch-icon", + "sizes": "180x180", + "static-file": "favicon/logo-noborder-180.png", + }, +] + +html_css_files = [ + "custom.css", +] + +intersphinx_mapping = { + "python": ["https://docs.python.org/3", None], + "numpy": ["https://numpy.org/doc/stable/", None], + "napari_plugin_engine": [ + "https://napari-plugin-engine.readthedocs.io/en/latest/", + "https://napari-plugin-engine.readthedocs.io/en/latest/objects.inv", + ], + "napari": [ + "https://napari.org/dev", + "https://napari.org/dev/objects.inv", + ], +} + +myst_enable_extensions = [ + "colon_fence", + "dollarmath", + "substitution", + "tasklist", +] + +myst_heading_anchors = 4 +suppress_warnings = ["etoc.toctree"] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [ + "_build", + "Thumbs.db", + ".DS_Store", + ".jupyter_cache", + "jupyter_execute", +] diff --git a/docs/developers/contributing.md b/docs/developers/contributing.md new file mode 100644 index 00000000..e711a903 --- /dev/null +++ b/docs/developers/contributing.md @@ -0,0 +1,186 @@ +# Contributing Guide + +We welcome your contributions! Please see the provided steps below and never hesitate to contact us. + +If you are a new user, we recommend checking out the detailed [Github Guides](https://guides.github.com). + +## Setting up a development installation + +In order to make changes to `napari-plugin-manager`, you will need to [fork](https://guides.github.com/activities/forking/#fork) the +[repository](https://github.com/napari/napari-plugin-manager). + +If you are not familiar with `git`, we recommend reading up on [this guide](https://guides.github.com/introduction/git-handbook/#basic-git). + +Clone the forked repository to your local machine and change directories: +```sh +git clone https://github.com/your-username/napari-plugin-manager.git +cd napari-plugin-manager +``` + +Set the `upstream` remote to the base `napari` repository: +```sh +git remote add upstream https://github.com/napari/napari-plugin-manager.git +``` + +Install the package in editable mode, along with all of the developer tools: +```sh +pip install -e ".[dev]" +``` + +We use [`pre-commit`](https://pre-commit.com) to sort imports with +[`isort`](https://github.com/timothycrosley/isort), format code with +[`black`](https://github.com/psf/black), and lint with +[`flake8`](https://github.com/PyCQA/flake8) automatically prior to each commit +as implemented in `ruff`. +To minimize test errors when submitting pull requests, please install `pre-commit` +in your environment as follows: + +```sh +pre-commit install +``` + +Upon committing, your code will be formatted and linted according to our [`ruff` +configuration](https://github.com/napari/napari-plugin-manager/blob/main/pyproject.toml). To learn +more, see [`ruff`'s documentation](https://docs.astral.sh/ruff/). + +You can also execute `pre-commit` at any moment by running the following: + +```sh +pre-commit run -a +``` + +If you wish to tell the linter to ignore a specific line use the `# noqa` +comment along with the specific error code (e.g. `import sys # noqa: E402`) but +please do not ignore errors lightly. + +## Translations + +Starting with version 0.4.7, napari codebase include internationalization +(i18n) and now offers the possibility of installing language packs, which +provide localization (l10n) enabling the user interface to be displayed in +different languages. + +To learn more about the current languages that are in the process of +translation, visit the [language packs repository](https://github.com/napari/napari-language-packs). + +To make your code translatable (localizable), please use the `trans` helper +provided by the napari utilities. + +```python +from napari.utils.translations import trans + +some_string = trans._("Localizable string") +``` + +To learn more, please see the [translations guide](https://napari.org/guides/stable/translations.html). + +## Making changes + +Create a new feature branch: + +```sh +git checkout main -b your-branch-name +``` + +`git` will automatically detect changes to a repository. +You can view them with: + +```sh +git status +``` + +Add and commit your changed files: +```sh +git add my-file-or-directory +git commit -m "my message" +``` + +## Tests + +We use unit tests and integration tests to ensure that +napari-plugin-manager works as intended. Writing tests for new code is a critical part of +keeping napari-plugin-manager maintainable as it grows. + +Check out the dedicated documentation on testing over at [napari.org](https://napari.org/dev/developers/testing.html) that we recommend you +read as you're working on your first contribution. + +Run this command to ensure the testing dependencies are available: + +```sh +pip install -e ".[testing]" +``` + +### Help us make sure it's you + +Each commit you make must have a [GitHub-registered email](https://github.com/settings/emails) +as the `author`. You can read more [here](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/setting-your-commit-email-address). + +To set it, use `git config --global user.email your-address@example.com`. + +## Keeping your branches up-to-date + +Switch to the `main` branch: +```sh +git checkout main +``` + +Fetch changes and update `main`: +```sh +git pull upstream main --tags +``` + +This is shorthand for: +```sh +git fetch upstream main --tags +git merge upstream/main +``` + +Update your other branches: +```sh +git checkout your-branch-name +git merge main +``` + +## Sharing your changes + +Update your remote branch: +```sh +git push -u origin your-branch-name +``` + +You can then make a [pull-request](https://guides.github.com/activities/forking/#making-a-pull-request) to `napari-plugin-manager`'s `main` branch. + +## Building the docs + +First, make sure the documentation dependencies are up-to-date: + +```sh +pip install -e ".[docs]" +``` + +Then, from the project root +```sh +make docs +``` + +The docs will be built at `docs/_build/html`. You can see them in your browser by running + +```sh +make serve +``` + +and opening a new tab for `http://localhost:8000`. + +Most web browsers will also allow you to preview HTML pages directly. +Try entering `file:///absolute/path/to/napari-plugin-manager/docs/_build/html/index.html` in your address bar. + +## Code of conduct + +`napari` has a [Code of Conduct](https://napari.org/stable/community/code_of_conduct.html) that should be honored by everyone who participates in the `napari` community, including `napari-plugin-manager`. + +## Questions, comments, and feedback + +If you have questions, comments, suggestions for improvement, or any other inquiries +regarding the project, feel free to open an [issue](https://github.com/napari/napari-plugin-manager/issues). + +Issues and pull-requests are written in [Markdown](https://guides.github.com/features/mastering-markdown/#what). You can find a comprehensive guide [here](https://guides.github.com/features/mastering-markdown/#syntax). diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..451bedae --- /dev/null +++ b/docs/index.md @@ -0,0 +1,2 @@ +```{include} ../README.md +``` diff --git a/images/description.png b/images/description.png new file mode 100644 index 00000000..20f2fb04 Binary files /dev/null and b/images/description.png differ diff --git a/images/filter.png b/images/filter.png new file mode 100644 index 00000000..df0b85f4 Binary files /dev/null and b/images/filter.png differ diff --git a/images/install.png b/images/install.png new file mode 100644 index 00000000..cba07663 Binary files /dev/null and b/images/install.png differ diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 00000000..736ee208 Binary files /dev/null and b/images/logo.png differ diff --git a/images/status.png b/images/status.png new file mode 100644 index 00000000..22ff3ebe Binary files /dev/null and b/images/status.png differ diff --git a/images/uninstall.png b/images/uninstall.png new file mode 100644 index 00000000..1e19583f Binary files /dev/null and b/images/uninstall.png differ diff --git a/images/update.png b/images/update.png new file mode 100644 index 00000000..540560d8 Binary files /dev/null and b/images/update.png differ diff --git a/pyproject.toml b/pyproject.toml index 8ec38cc6..d38b1d9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,12 @@ build-backend = "setuptools.build_meta" [tool.setuptools_scm] write_to = "napari_plugin_manager/_version.py" +[tool.setuptools.packages.find] +where = ["."] +include = ["napari_plugin_manager"] +exclude = [] +namespaces = false + [project] name = "napari-plugin-manager" description = "Install plugins for napari, in napari." @@ -26,9 +32,9 @@ classifiers = [ "Programming Language :: C", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Visualization", "Topic :: Scientific/Engineering :: Information Analysis", @@ -51,6 +57,11 @@ dynamic = [ ] [project.optional-dependencies] +dev = [ + "PyQt5", + "pre-commit", +] + testing = [ "pytest", "virtualenv", @@ -58,11 +69,21 @@ testing = [ "pytest-qt", ] +docs = [ + "sphinx>6", + "sphinx-autobuild", + "sphinx-external-toc", + "sphinx-copybutton", + "sphinx-favicon", + "myst-nb", + "napari-sphinx-theme>=0.3.0", +] + [project.urls] homepage = "https://github.com/napari/napari-plugin-manager" [tool.black] -target-version = ['py38', 'py39', 'py310'] +target-version = ['py39', 'py310', 'py311'] skip-string-normalization = true line-length = 79