diff --git a/docs/_static/colors.sass b/docs/_static/colors.sass new file mode 100644 index 00000000..927d69e0 --- /dev/null +++ b/docs/_static/colors.sass @@ -0,0 +1,6 @@ +/* Main theme colors */ +.md-primary {color: var(--color-brand-primary)} +.md-secondary {color: var(--color-brand-content)} + +/* Color for Font Awesome icons */ +span.fa {color: var(--color-brand-primary)} \ No newline at end of file diff --git a/docs/images/favicon.ico b/docs/_static/favicon.ico similarity index 100% rename from docs/images/favicon.ico rename to docs/_static/favicon.ico diff --git a/docs/_static/pyinaturalist_logo.png b/docs/_static/pyinaturalist_logo.png new file mode 100644 index 00000000..bb309fa7 Binary files /dev/null and b/docs/_static/pyinaturalist_logo.png differ diff --git a/docs/conf.py b/docs/conf.py index 33587ed9..ec343582 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -48,7 +48,6 @@ # General information about the project. copyright = '2021, Nicolas Noé, Jordan Cook' exclude_patterns = ['_build', f'{MODULE_DOCS_DIR}/pyinaturalist.rst'] -html_static_path = ['_static'] master_doc = 'index' needs_sphinx = '4.0' project = 'pyinaturalist' @@ -68,6 +67,7 @@ 'sphinx_automodapi.smart_resolver', 'sphinx_copybutton', 'sphinx_inline_tabs', + 'sphinx_panels', 'sphinxcontrib.apidoc', 'myst_parser', 'nbsphinx', @@ -134,11 +134,16 @@ numpydoc_show_class_members = False # HTML general settings -html_logo = join('images', 'pyinaturalist_logo.png') -# html_logo = join('images', 'python-logo-green.png') -html_favicon = join('images', 'favicon.ico') +html_static_path = ['_static'] +html_favicon = join('_static', 'favicon.ico') +html_logo = join('_static', 'pyinaturalist_logo.png') html_js_files = ['collapsible_container.js'] -html_css_files = ['collapsible_container.css', 'table.css'] +html_css_files = [ + 'collapsible_container.css', + 'colors.sass', + 'table.css', + 'https://use.fontawesome.com/releases/v5.15.3/css/all.css', +] html_show_sphinx = False pygments_style = 'friendly' pygments_dark_style = 'material' diff --git a/poetry.lock b/poetry.lock index cc46c79f..70881557 100644 --- a/poetry.lock +++ b/poetry.lock @@ -128,7 +128,7 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "bleach" -version = "3.3.0" +version = "3.3.1" description = "An easy safelist-based HTML-sanitizing tool." category = "main" optional = true @@ -381,18 +381,17 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [[package]] name = "importlib-resources" -version = "5.2.0" +version = "3.0.0" description = "Read resources from Python packages" -category = "dev" +category = "main" optional = false -python-versions = ">=3.6" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [package.dependencies] -zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} +zipp = {version = ">=0.4", markers = "python_version < \"3.8\""} [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["sphinx", "rst.linker", "jaraco.packaging"] [[package]] name = "iniconfig" @@ -1233,7 +1232,7 @@ python-versions = ">=3.6" [[package]] name = "sphinx" -version = "4.1.0" +version = "4.1.1" description = "Python documentation generator" category = "main" optional = true @@ -1252,10 +1251,10 @@ requests = ">=2.5.0" snowballstemmer = ">=1.1" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" -sphinxcontrib-htmlhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" sphinxcontrib-jsmath = "*" sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = "*" +sphinxcontrib-serializinghtml = ">=1.1.5" [package.extras] docs = ["sphinxcontrib-websupport"] @@ -1321,6 +1320,25 @@ sphinx = ">=3" doc = ["myst-parser", "furo"] test = ["pytest", "pytest-cov", "pytest-xdist"] +[[package]] +name = "sphinx-panels" +version = "0.6.0" +description = "A sphinx extension for creating panels in a grid layout." +category = "main" +optional = true +python-versions = "*" + +[package.dependencies] +docutils = "*" +importlib-resources = {version = ">=3.0.0,<3.1.0", markers = "python_version < \"3.7\""} +sphinx = ">=2,<5" + +[package.extras] +code_style = ["pre-commit (>=2.7.0,<2.8.0)"] +live-dev = ["sphinx-autobuild", "web-compile (>=0.2.0,<0.3.0)"] +testing = ["pytest (>=6.0.1,<6.1.0)", "pytest-regressions (>=2.0.1,<2.1.0)"] +themes = ["sphinx-rtd-theme", "pydata-sphinx-theme (>=0.4.0,<0.5.0)", "sphinx-book-theme (>=0.0.36,<0.1.0)", "myst-parser (>=0.12.9,<0.13.0)"] + [[package]] name = "sphinxcontrib-apidoc" version = "0.3.0" @@ -1505,7 +1523,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.5.0" +version = "20.6.0" description = "Virtual Python Environment builder" category = "dev" optional = false @@ -1554,12 +1572,12 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [extras] all = [] -docs = ["furo", "linkify-it-py", "myst-parser", "nbsphinx", "sphinx", "sphinx-automodapi", "sphinx-autodoc-typehints", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxcontrib-apidoc"] +docs = ["furo", "linkify-it-py", "myst-parser", "nbsphinx", "sphinx", "sphinx-automodapi", "sphinx-panels", "sphinx-autodoc-typehints", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxcontrib-apidoc"] [metadata] lock-version = "1.1" python-versions = "^3.6" -content-hash = "5a1cf256fc0de385edc70c3f393f23c06e2a0d6290a6f9b3281e448d154fc005" +content-hash = "4026546db8a24b8e6b321aca8385c30c8b0095d20d6e4ce57f3473f6d6750c53" [metadata.files] alabaster = [ @@ -1608,8 +1626,8 @@ black = [ {file = "black-21.6b0.tar.gz", hash = "sha256:dc132348a88d103016726fe360cb9ede02cecf99b76e3660ce6c596be132ce04"}, ] bleach = [ - {file = "bleach-3.3.0-py2.py3-none-any.whl", hash = "sha256:6123ddc1052673e52bab52cdc955bcb57a015264a1c57d37bea2f6b817af0125"}, - {file = "bleach-3.3.0.tar.gz", hash = "sha256:98b3170739e5e83dd9dc19633f074727ad848cbedb6026708c8ac2d3b697a433"}, + {file = "bleach-3.3.1-py2.py3-none-any.whl", hash = "sha256:ae976d7174bba988c0b632def82fdc94235756edfb14e6558a9c5be555c9fb78"}, + {file = "bleach-3.3.1.tar.gz", hash = "sha256:306483a5a9795474160ad57fce3ddd1b50551e981eed8e15a582d34cef28aafa"}, ] certifi = [ {file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"}, @@ -1807,8 +1825,8 @@ importlib-metadata = [ {file = "importlib_metadata-4.6.1.tar.gz", hash = "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac"}, ] importlib-resources = [ - {file = "importlib_resources-5.2.0-py3-none-any.whl", hash = "sha256:a0143290bef3cbc99de9e40176e4987780939a955b8632f02ce6c935f42e9bfc"}, - {file = "importlib_resources-5.2.0.tar.gz", hash = "sha256:22a2c42d8c6a1d30aa8a0e1f57293725bfd5c013d562585e46aff469e0ff78b3"}, + {file = "importlib_resources-3.0.0-py2.py3-none-any.whl", hash = "sha256:d028f66b66c0d5732dae86ba4276999855e162a749c92620a38c1d779ed138a7"}, + {file = "importlib_resources-3.0.0.tar.gz", hash = "sha256:19f745a6eca188b490b1428c8d1d4a0d2368759f32370ea8fb89cad2ab1106c3"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, @@ -2252,8 +2270,8 @@ soupsieve = [ {file = "soupsieve-2.2.1.tar.gz", hash = "sha256:052774848f448cf19c7e959adf5566904d525f33a3f8b6ba6f6f8f26ec7de0cc"}, ] sphinx = [ - {file = "Sphinx-4.1.0-py3-none-any.whl", hash = "sha256:51028bb0d3340eb80bcc1a2d614e8308ac78d226e6b796943daf57920abc1aea"}, - {file = "Sphinx-4.1.0.tar.gz", hash = "sha256:4219f14258ca5612a0c85ed9b7222d54da69724d7e9dd92d1819ad1bf65e1ad2"}, + {file = "Sphinx-4.1.1-py3-none-any.whl", hash = "sha256:3d513088236eef51e5b0adb78b0492eb22cc3b8ccdb0b36dd021173b365d4454"}, + {file = "Sphinx-4.1.1.tar.gz", hash = "sha256:23c846a1841af998cb736218539bb86d16f5eb95f5760b1966abcd2d584e62b8"}, ] sphinx-autodoc-typehints = [ {file = "sphinx-autodoc-typehints-1.12.0.tar.gz", hash = "sha256:193617d9dbe0847281b1399d369e74e34cd959c82e02c7efde077fca908a9f52"}, @@ -2271,6 +2289,10 @@ sphinx-inline-tabs = [ {file = "sphinx_inline_tabs-2021.4.11b9-py3-none-any.whl", hash = "sha256:5fddeefb97630df3334341a2fd5434f62ed6d76301ff30a81cb50363abf98fb9"}, {file = "sphinx_inline_tabs-2021.4.11b9.tar.gz", hash = "sha256:09267b9980b405bada41e63f9912769a394731e0e015068cda7feab1a13f8fe5"}, ] +sphinx-panels = [ + {file = "sphinx-panels-0.6.0.tar.gz", hash = "sha256:d36dcd26358117e11888f7143db4ac2301ebe90873ac00627bf1fe526bf0f058"}, + {file = "sphinx_panels-0.6.0-py3-none-any.whl", hash = "sha256:bd64afaf85c07f8096d21c8247fc6fd757e339d1be97832c8832d6ae5ed2e61d"}, +] sphinxcontrib-apidoc = [ {file = "sphinxcontrib-apidoc-0.3.0.tar.gz", hash = "sha256:729bf592cf7b7dd57c4c05794f732dc026127275d785c2a5494521fdde773fb9"}, {file = "sphinxcontrib_apidoc-0.3.0-py2.py3-none-any.whl", hash = "sha256:6671a46b2c6c5b0dca3d8a147849d159065e50443df79614f921b42fbd15cb09"}, @@ -2408,8 +2430,8 @@ urllib3 = [ {file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"}, ] virtualenv = [ - {file = "virtualenv-20.5.0-py2.py3-none-any.whl", hash = "sha256:b7afa7f32abbf7dd4c24269a596cfbb0a422bb83c47215a785a7bf607cb88e1b"}, - {file = "virtualenv-20.5.0.tar.gz", hash = "sha256:6b0e3eeb6cb081c9c81ec85633785e29edcdf6ff271d70e0d1e2bd616495c08c"}, + {file = "virtualenv-20.6.0-py2.py3-none-any.whl", hash = "sha256:e4fc84337dce37ba34ef520bf2d4392b392999dbe47df992870dc23230f6b758"}, + {file = "virtualenv-20.6.0.tar.gz", hash = "sha256:51df5d8a2fad5d1b13e088ff38a433475768ff61f202356bb9812c454c20ae45"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, diff --git a/pyinaturalist/models/comment.py b/pyinaturalist/models/comment.py index dc3a7887..6290dc5f 100644 --- a/pyinaturalist/models/comment.py +++ b/pyinaturalist/models/comment.py @@ -6,7 +6,7 @@ @define_model class Comment(BaseModel): - """📝 An observation comment, based on the schema of comments + """:fa:`comment` An observation comment, based on the schema of comments from `GET /observations `_. """ diff --git a/pyinaturalist/models/controlled_term.py b/pyinaturalist/models/controlled_term.py index 51b3fe7a..06869e08 100644 --- a/pyinaturalist/models/controlled_term.py +++ b/pyinaturalist/models/controlled_term.py @@ -6,7 +6,7 @@ @define_model class Annotation(BaseModel): - """📝 An annotation, meaning a **controlled term value** applied by a **user** to an **observation**. + """:fa:`tag` An annotation, meaning a **controlled term value** applied by a **user** to an **observation**. Based on the schema of annotations from `GET /observations `_. """ @@ -45,7 +45,7 @@ def __str__(self) -> str: @define_model class ControlledTermValue(BaseModel): - """📋 A controlled term **value**, based on the schema of + """:fa:`tag` A controlled term **value**, based on the schema of `GET /controlled_terms `_. """ @@ -62,7 +62,7 @@ def __str__(self): @define_model class ControlledTerm(BaseModel): - """📋 A controlled term, based on the schema of + """:fa:`tag` A controlled term, based on the schema of `GET /controlled_terms `_. """ diff --git a/pyinaturalist/models/identification.py b/pyinaturalist/models/identification.py index 802071d0..e3fe6085 100644 --- a/pyinaturalist/models/identification.py +++ b/pyinaturalist/models/identification.py @@ -14,7 +14,7 @@ @define_model class Identification(BaseModel): - """🔎 An observation identification, based on the schema of + """:fa:`fingerprint` An observation identification, based on the schema of `GET /identifications `_. """ diff --git a/pyinaturalist/models/life_list.py b/pyinaturalist/models/life_list.py index cd14cb5a..639b07c0 100644 --- a/pyinaturalist/models/life_list.py +++ b/pyinaturalist/models/life_list.py @@ -14,7 +14,7 @@ @define_model class LifeListTaxon(TaxonCount): - """🐦 A single :py:class:`.Taxon` in a user's :py:class:`.LifeList`""" + """:fa:`dove` :fa:`list` A single :py:class:`.Taxon` in a user's :py:class:`.LifeList`""" descendant_obs_count: int = field(default=0, doc='Number of observations of taxon children') direct_obs_count: int = field( @@ -42,7 +42,7 @@ def __str__(self) -> str: @define_model_collection class LifeList(TaxonCounts): - """🐦✅📓 A user's life list, based on the schema of ``GET /observations/taxonomy``""" + """:fa:`dove` :fa:`list` A user's life list, based on the schema of ``GET /observations/taxonomy``""" count_without_taxon: int = field(default=0) data: List[LifeListTaxon] = field(factory=list, converter=LifeListTaxon.from_json_list) # type: ignore diff --git a/pyinaturalist/models/observation.py b/pyinaturalist/models/observation.py index 628cb39d..abc27037 100644 --- a/pyinaturalist/models/observation.py +++ b/pyinaturalist/models/observation.py @@ -38,7 +38,7 @@ @define(auto_attribs=False, init=False, field_transformer=add_lazy_attrs) class Observation(BaseModel): - """👤🔎🐦 An observation, based the schema of + """:fa:`binoculars` An observation, based the schema of `GET /observations `_. """ @@ -232,7 +232,7 @@ def __str__(self) -> str: @define_model_collection class Observations(BaseModelCollection): - """👥🔍🐦 A collection of observations""" + """:fa:`binoculars` A collection of observations""" data: List[Observation] = field(factory=list, converter=Observation.from_json_list) diff --git a/pyinaturalist/models/observation_field.py b/pyinaturalist/models/observation_field.py index 46ba36fc..437e1c98 100644 --- a/pyinaturalist/models/observation_field.py +++ b/pyinaturalist/models/observation_field.py @@ -28,7 +28,7 @@ @define_model class ObservationField(BaseModel): - """📋 An observation field **definition**, based on the schema of + """:fa:`tag` An observation field **definition**, based on the schema of `GET /observation_fields `_. """ @@ -59,7 +59,7 @@ def __str__(self) -> str: @define_model class ObservationFieldValue(BaseModel): - """📝 An observation field **value**, based on the schema of ``Observation.ofvs`` + """:fa:`tag` An observation field **value**, based on the schema of ``Observation.ofvs`` from `GET /observations `_. """ diff --git a/pyinaturalist/models/photo.py b/pyinaturalist/models/photo.py index 098bcc33..c5330886 100644 --- a/pyinaturalist/models/photo.py +++ b/pyinaturalist/models/photo.py @@ -10,7 +10,7 @@ @define_model class Photo(BaseModel): - """📷 An observation photo, based on the schema of photos from: + """:fa:`camera` An observation photo, based on the schema of photos from: * `GET /observations `_ * `GET /taxa ` diff --git a/pyinaturalist/models/place.py b/pyinaturalist/models/place.py index ab169e6f..0c46875e 100644 --- a/pyinaturalist/models/place.py +++ b/pyinaturalist/models/place.py @@ -20,7 +20,7 @@ def convert_optional_lat_long(obj: Union[Dict, List, None, str]): @define_model class Place(BaseModel): - """📍 A curated or community-contributed place. Handles data from the following endpoints: + """:fa:`map-marker-alt` A curated or community-contributed place. Handles data from the following endpoints: * `GET /places/{id} `_ * `GET /places/nearby `_ diff --git a/pyinaturalist/models/project.py b/pyinaturalist/models/project.py index 4342bfa3..1387ca50 100644 --- a/pyinaturalist/models/project.py +++ b/pyinaturalist/models/project.py @@ -24,7 +24,7 @@ @define_model class ProjectObservation(BaseModel): - """👤🔎🐦 Metadata about an observation that has been added to a project""" + """:fa:`binoculars` Metadata about an observation that has been added to a project""" preferences: Dict = field(factory=dict) # Example: {'allows_curator_coordinate_access': True} project: Dict = field(factory=dict) # Example: {'id': 24237} @@ -37,7 +37,7 @@ class ProjectObservation(BaseModel): @define_model class ProjectObservationField(ObservationField): - """📋 An :py:class:`.ObservationField` with additional project-specific information""" + """:fa:`tag` An :py:class:`.ObservationField` with additional project-specific information""" project_observation_field_id: int = field(default=None) position: int = field(default=None) @@ -55,7 +55,7 @@ def from_json(cls, value: JsonResponse, **kwargs) -> 'ProjectObservationField': @define_model class ProjectUser(User): - """👤 A :py:class:`.User` with additional project-specific information""" + """:fa:`user` A :py:class:`.User` with additional project-specific information""" project_id: int = field(default=None) project_user_id: int = field(default=None) @@ -73,7 +73,7 @@ def from_json(cls, value: JsonResponse, **kwargs) -> 'ProjectUser': @define_model class Project(BaseModel): - """👥 An iNaturalist project, based on the schema of + """:fa:`users` An iNaturalist project, based on the schema of `GET /projects `_. """ diff --git a/pyinaturalist/models/search.py b/pyinaturalist/models/search.py index 22f8bc44..4b946133 100644 --- a/pyinaturalist/models/search.py +++ b/pyinaturalist/models/search.py @@ -10,7 +10,7 @@ @define_model class SearchResult(BaseModel): - """🔍 A search result of any type, based on the schema of + """:fa:`search` A search result of any type, based on the schema of `GET /search `_. """ diff --git a/pyinaturalist/models/taxon.py b/pyinaturalist/models/taxon.py index 2348a48a..8e4f8695 100644 --- a/pyinaturalist/models/taxon.py +++ b/pyinaturalist/models/taxon.py @@ -34,7 +34,7 @@ # TODO: Include codes from other sources? Currently only including IUCN codes. @define_model class ConservationStatus(BaseModel): - """‼️ The conservation status of a taxon in a given location, based on the schema of: + """:fa:`exclamation-triangle` The conservation status of a taxon in a given location, based on the schema of: * ``Taxon.conservation_status`` from `GET /taxa `_ * ``Observation.taxon.conservation_statuses`` from `GET /observations `_ @@ -75,7 +75,7 @@ class ConservationStatus(BaseModel): @define_model class EstablishmentMeans(BaseModel): - """‼️ The establishment means for a taxon in a given location""" + """:fa:`exclamation-triangle` The establishment means for a taxon in a given location""" establishment_means: str = field( default=None, options=ESTABLISTMENT_MEANS, doc='Establishment means description' @@ -90,7 +90,7 @@ def __str__(self) -> str: @define_model class Taxon(BaseModel): - """🐦 An iNaturalist taxon, based on the schema of + """:fa:`dove` An iNaturalist taxon, based on the schema of `GET /taxa `_. Can be constructed from either a full or partial JSON record. Examples of partial records @@ -266,7 +266,7 @@ def __str__(self) -> str: @define_model class TaxonCount(Taxon): - """🐦#️⃣ A :py:class:`.Taxon` with an associated count, used in a :py:class:`.TaxonCounts` + """:fa:`dove` :fa:`list` A :py:class:`.Taxon` with an associated count, used in a :py:class:`.TaxonCounts` collection """ @@ -296,7 +296,7 @@ def __str__(self) -> str: @define_model_collection class TaxonCounts(BaseModelCollection): - """🐦#️⃣📓 A collection of taxa with an associated counts. Used with + """:fa:`dove` :fa:`list` A collection of taxa with an associated counts. Used with `GET /observations/species_counts `_. as well as :py:class:`.LifeList`. """ diff --git a/pyinaturalist/models/user.py b/pyinaturalist/models/user.py index 60e33d38..0f8e9a1b 100644 --- a/pyinaturalist/models/user.py +++ b/pyinaturalist/models/user.py @@ -7,7 +7,7 @@ @define_model class User(BaseModel): - """👤 An iNaturalist user, based on the schema of + """:fa:`user` An iNaturalist user, based on the schema of `GET /users/{id} `_. """ diff --git a/pyproject.toml b/pyproject.toml index 161b4efd..d75cec58 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,7 @@ pyrate-limiter = ">=2.3.3" rich = ">=10.0" # Documentation dependencies needed for Readthedocs builds -furo = {version = ">=2021.6.24-beta.37", optional = true} +furo = {version = "2021.7.5b38", optional = true} linkify-it-py = {version = "^1.0.1", optional = true} myst-parser = {version = "^0.15.1", optional = true} nbsphinx = { version = "^0.8.5", optional = true } @@ -47,12 +47,14 @@ sphinx-automodapi = { version=">=0.13", optional = true} sphinx-autodoc-typehints = { version = "^1.11", optional = true } sphinx-copybutton = { version = ">=0.3,<0.5", optional = true } sphinx-inline-tabs = {version = "^2021.4.11-beta.9", optional = true, python = ">=3.8"} +sphinx-panels = {version = "^0.6.0", optional = true} sphinxcontrib-apidoc = { version = "^0.3", optional = true } [tool.poetry.extras] all = [] # Placeholder for optional dependencies needed to run examples in docs docs = ["furo", "linkify-it-py", "myst-parser", "nbsphinx", "sphinx", "sphinx-automodapi", - "sphinx-autodoc-typehints", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxcontrib-apidoc"] + "sphinx-autodoc-typehints", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-panels", + "sphinxcontrib-apidoc"] [tool.poetry.dev-dependencies] black = {version = "21.6b0", python = ">=3.6.2, <3.10"}