18
18
from pathlib import Path
19
19
from urllib .parse import urlparse , urlunparse
20
20
21
-
22
21
from jinja2 .filters import FILTERS
23
22
from packaging .version import parse as parse_version
24
23
from pygments .lexers import TOMLLexer
24
+ from sphinx_gallery import gen_rst
25
25
from sphinx_gallery import scrapers
26
26
from sphinx_gallery .sorting import ExampleTitleSortKey
27
27
from sphinx .highlighting import lexers
41
41
42
42
# -- Project information ---------------------------------------------------
43
43
44
- project = ' napari'
45
- copyright = f' { datetime .now ().year } , The napari team'
46
- author = ' The napari team'
44
+ project = " napari"
45
+ copyright = f" { datetime .now ().year } , The napari team"
46
+ author = " The napari team"
47
47
48
48
# -- Sphinx extensions -------------------------------------------------------
49
49
68
68
# -- HTML Theme ------------------------------------------------------------
69
69
70
70
# See https://github.com/napari/napari-sphinx-theme for more information.
71
- html_theme = ' napari_sphinx_theme'
71
+ html_theme = " napari_sphinx_theme"
72
72
html_title = "napari"
73
73
html_sourcelink_suffix = ""
74
74
142
142
# sidebar content
143
143
html_sidebars = {
144
144
"**" : ["search-field.html" , "sidebar-nav-bs" ],
145
- "index" : ["search-field.html" , "sidebar-link-items.html" ],
145
+ "index" : ["search-field.html" , "sidebar-link-items.html" ],
146
146
}
147
147
148
148
# html context is passed into the template engine’s context for all pages.
149
149
html_context = {
150
- # use Light theme only, don't auto switch (default)
151
- "default_mode" : "light" ,
152
- # add release version to context
153
- "release" : release ,
154
- "version" : version ,
150
+ # use Light theme only, don't auto switch (default)
151
+ "default_mode" : "light" ,
152
+ # add release version to context
153
+ "release" : release ,
154
+ "version" : version ,
155
155
}
156
156
157
157
# intersphinx configuration for frequently used links to other projects
158
158
intersphinx_mapping = {
159
- ' python' : [' https://docs.python.org/3' , None ],
160
- ' numpy' : [' https://numpy.org/doc/stable/' , None ],
161
- ' napari_plugin_engine' : [
162
- ' https://napari-plugin-engine.readthedocs.io/en/latest/' ,
163
- ' https://napari-plugin-engine.readthedocs.io/en/latest/objects.inv' ,
159
+ " python" : [" https://docs.python.org/3" , None ],
160
+ " numpy" : [" https://numpy.org/doc/stable/" , None ],
161
+ " napari_plugin_engine" : [
162
+ " https://napari-plugin-engine.readthedocs.io/en/latest/" ,
163
+ " https://napari-plugin-engine.readthedocs.io/en/latest/objects.inv" ,
164
164
],
165
- ' magicgui' : [
166
- ' https://pyapp-kit.github.io/magicgui/' ,
167
- ' https://pyapp-kit.github.io/magicgui/objects.inv' ,
165
+ " magicgui" : [
166
+ " https://pyapp-kit.github.io/magicgui/" ,
167
+ " https://pyapp-kit.github.io/magicgui/objects.inv" ,
168
168
],
169
- ' app-model' : [
170
- ' http://app-model.readthedocs.io/en/latest/' ,
171
- ' http://app-model.readthedocs.io/en/latest/objects.inv' ,
169
+ " app-model" : [
170
+ " http://app-model.readthedocs.io/en/latest/" ,
171
+ " http://app-model.readthedocs.io/en/latest/objects.inv" ,
172
172
],
173
- ' vispy' : [
174
- ' https://vispy.org/' ,
175
- ' https://vispy.org/objects.inv' ,
173
+ " vispy" : [
174
+ " https://vispy.org/" ,
175
+ " https://vispy.org/objects.inv" ,
176
176
],
177
177
}
178
178
179
179
# myst markdown extensions for additional markdown features
180
180
myst_enable_extensions = [
181
- ' colon_fence' ,
182
- ' dollarmath' ,
183
- ' substitution' ,
184
- ' tasklist' ,
185
- ' attrs_inline' ,
186
- ' linkify' ,
181
+ " colon_fence" ,
182
+ " dollarmath" ,
183
+ " substitution" ,
184
+ " tasklist" ,
185
+ " attrs_inline" ,
186
+ " linkify" ,
187
187
]
188
188
myst_footnote_transition = False
189
189
myst_heading_anchors = 4
195
195
lexers ["toml" ] = TOMLLexer (startinline = True )
196
196
napoleon_custom_sections = [("Events" , "params_style" )]
197
197
# use an env var to control whether noteboos are executed
198
- nb_execution_mode = os .environ .get (' NB_EXECUTION_MODE' , ' auto' )
198
+ nb_execution_mode = os .environ .get (" NB_EXECUTION_MODE" , " auto" )
199
199
nb_output_stderr = "show"
200
200
mermaid_d3_zoom = True
201
201
mermaid_version = "11.4.1"
211
211
# OpenGraph configuration for link previews
212
212
213
213
ogp_site_url = "https://napari.org/"
214
- ogp_image = "dev/_static/opengraph_image.png"
214
+ ogp_image = "dev/_static/opengraph_image.png"
215
215
ogp_use_first_image = False
216
216
ogp_description_length = 300
217
217
ogp_type = "website"
218
218
ogp_site_name = "napari"
219
219
ogp_canonical_url = "https://napari.org/stable"
220
220
ogp_social_cards = {
221
- ' image' : ' _static/logo.png' ,
221
+ " image" : " _static/logo.png" ,
222
222
}
223
223
224
224
# glob-style patterns to exclude from docs build source files
235
235
236
236
# -- Versions and switcher -------------------------------------------------
237
237
238
+
238
239
def get_supported_python_versions (project_name ):
239
240
"""
240
241
Get the supported Python versions for a given project
241
242
based on the classifiers in its distribution metadata.
242
243
"""
243
244
dist = distribution (project_name )
244
- classifiers = [value for key , value in dist .metadata .items () if key == 'Classifier' and value .startswith ('Programming Language :: Python ::' )]
245
- return [parse_version (c .split (' :: ' )[- 1 ]) for c in classifiers if not c .endswith ('Only' )]
245
+ classifiers = [
246
+ value
247
+ for key , value in dist .metadata .items ()
248
+ if key == "Classifier" and value .startswith ("Programming Language :: Python ::" )
249
+ ]
250
+ return [
251
+ parse_version (c .split (" :: " )[- 1 ])
252
+ for c in classifiers
253
+ if not c .endswith ("Only" )
254
+ ]
246
255
247
- napari_supported_python_versions = get_supported_python_versions ('napari' )
256
+
257
+ napari_supported_python_versions = get_supported_python_versions ("napari" )
248
258
249
259
min_python_version = min (napari_supported_python_versions )
250
260
max_python_version = max (napari_supported_python_versions )
251
261
252
- version_string = '.' .join (str (x ) for x in __version_tuple__ [:3 ])
262
+ version_string = "." .join (str (x ) for x in __version_tuple__ [:3 ])
253
263
# when updating the version below, ensure to also update napari/napari README
254
- python_version = ' 3.11'
264
+ python_version = " 3.11"
255
265
python_version_range = f"{ min_python_version } -{ max_python_version } "
256
266
257
267
myst_substitutions = {
@@ -288,6 +298,7 @@ def get_attributes(item, obj, modulename):
288
298
289
299
FILTERS ["get_attributes" ] = get_attributes
290
300
301
+
291
302
class FilterSphinxWarnings (logging .Filter ):
292
303
"""Filter autosummary 'duplicate object description' warnings.
293
304
@@ -311,14 +322,16 @@ def filter(self, record: logging.LogRecord) -> bool:
311
322
return False
312
323
return True
313
324
325
+
314
326
# -- Examples gallery -------------------------------------------------------
315
327
328
+
316
329
def reset_napari (gallery_conf , fname ):
317
330
from napari .settings import get_settings
318
331
from qtpy .QtWidgets import QApplication
319
332
320
333
settings = get_settings ()
321
- settings .appearance .theme = ' dark'
334
+ settings .appearance .theme = " dark"
322
335
323
336
# Disabling `QApplication.exec_` means example scripts can call `exec_`
324
337
# (scripts work when run normally) without blocking example execution by
@@ -333,7 +346,7 @@ def napari_scraper(block, block_vars, gallery_conf):
333
346
334
347
`app.processEvents()` allows Qt events to propagateo and prevents hanging.
335
348
"""
336
- imgpath_iter = block_vars [' image_path_iterator' ]
349
+ imgpath_iter = block_vars [" image_path_iterator" ]
337
350
338
351
if app := napari .qt .get_qapp ():
339
352
app .processEvents ()
@@ -351,9 +364,8 @@ def napari_scraper(block, block_vars, gallery_conf):
351
364
napari .Viewer .close_all ()
352
365
app .processEvents ()
353
366
354
- return scrapers .figure_rst (img_paths , gallery_conf [' src_dir' ])
367
+ return scrapers .figure_rst (img_paths , gallery_conf [" src_dir" ])
355
368
356
- from sphinx_gallery import gen_rst
357
369
358
370
gen_rst .EXAMPLE_HEADER = """
359
371
.. DO NOT EDIT.
@@ -380,26 +392,30 @@ def napari_scraper(block, block_vars, gallery_conf):
380
392
sphinx_gallery_conf = {
381
393
# path to your example scripts (this value is set in the Makefile)
382
394
# 'examples_dirs': '../../napari/examples',
383
- 'gallery_dirs' : 'gallery' , # path to where to save gallery generated output
384
- 'filename_pattern' : '/*.py' ,
385
- 'ignore_pattern' : 'README.rst|/*_.py' ,
386
- 'default_thumb_file' : Path (__file__ ).parent / '_static' / 'images' / 'logo.png' ,
387
- 'plot_gallery' : "'True'" , # https://github.com/sphinx-gallery/sphinx-gallery/pull/304/files
388
- 'download_all_examples' : False ,
389
- 'min_reported_time' : 10 ,
390
- 'only_warn_on_example_error' : False ,
391
- 'abort_on_example_error' : True ,
392
- 'image_scrapers' : ("matplotlib" , napari_scraper ,),
393
- 'reset_modules' : (reset_napari ,),
394
- 'reference_url' : {'napari' : None },
395
- 'within_subsection_order' : ExampleTitleSortKey ,
395
+ "gallery_dirs" : "gallery" , # path to where to save gallery generated output
396
+ "filename_pattern" : "/*.py" ,
397
+ "ignore_pattern" : "README.rst|/*_.py" ,
398
+ "default_thumb_file" : Path (__file__ ).parent / "_static" / "images" / "logo.png" ,
399
+ "plot_gallery" : "'True'" , # https://github.com/sphinx-gallery/sphinx-gallery/pull/304/files
400
+ "download_all_examples" : False ,
401
+ "min_reported_time" : 10 ,
402
+ "only_warn_on_example_error" : False ,
403
+ "abort_on_example_error" : True ,
404
+ "image_scrapers" : (
405
+ "matplotlib" ,
406
+ napari_scraper ,
407
+ ),
408
+ "reset_modules" : (reset_napari ,),
409
+ "reference_url" : {"napari" : None },
410
+ "within_subsection_order" : ExampleTitleSortKey ,
396
411
}
397
412
398
413
# -- Calendar ---------------------------------------------------------------
399
414
400
415
# We host a google calendar on the docs website. To keep it up to date, we
401
416
# need an api key to make requests to the Google API for updating calendar events.
402
- GOOGLE_CALENDAR_API_KEY = os .environ .get ('GOOGLE_CALENDAR_API_KEY' , '' )
417
+ GOOGLE_CALENDAR_API_KEY = os .environ .get ("GOOGLE_CALENDAR_API_KEY" , "" )
418
+
403
419
404
420
def add_google_calendar_secrets (app , docname , source ):
405
421
"""Add google calendar api key to meeting schedule page.
@@ -408,8 +424,9 @@ def add_google_calendar_secrets(app, docname, source):
408
424
source file. You can process the contents and replace this item to implement
409
425
source-level transformations.
410
426
"""
411
- if docname == 'community/meeting_schedule' :
412
- source [0 ] = source [0 ].replace ('{API_KEY}' , GOOGLE_CALENDAR_API_KEY )
427
+ if docname == "community/meeting_schedule" :
428
+ source [0 ] = source [0 ].replace ("{API_KEY}" , GOOGLE_CALENDAR_API_KEY )
429
+
413
430
414
431
# -- Links and checks ------------------------------------------------------
415
432
@@ -432,6 +449,7 @@ def add_google_calendar_secrets(app, docname, source):
432
449
"https://onlinelibrary.wiley.com/doi/10.1002/col.20327" ,
433
450
]
434
451
452
+
435
453
def rewrite_github_anchor (app , uri : str ):
436
454
"""Rewrite anchor name of the hyperlink to github.com
437
455
@@ -457,8 +475,10 @@ def rewrite_github_anchor(app, uri: str):
457
475
return urlunparse (parsed ._replace (fragment = fragment ))
458
476
return None
459
477
478
+
460
479
# -- Qt threading docstrings ------------------------------------------------
461
480
481
+
462
482
def qt_docstrings (app , what , name , obj , options , lines ):
463
483
"""Only show first line of Qt threading docstrings.
464
484
@@ -470,8 +490,10 @@ def qt_docstrings(app, what, name, obj, options, lines):
470
490
if len (lines ) > 0 :
471
491
del lines [1 :]
472
492
493
+
473
494
# -- Docs build setup ------------------------------------------------------
474
495
496
+
475
497
def setup (app ):
476
498
"""Set up docs build.
477
499
@@ -484,13 +506,12 @@ def setup(app):
484
506
485
507
"""
486
508
app .registry .source_suffix .pop (".ipynb" , None )
487
- app .connect (' source-read' , add_google_calendar_secrets )
488
- app .connect (' linkcheck-process-uri' , rewrite_github_anchor )
489
- app .connect (' autodoc-process-docstring' , qt_docstrings )
509
+ app .connect (" source-read" , add_google_calendar_secrets )
510
+ app .connect (" linkcheck-process-uri" , rewrite_github_anchor )
511
+ app .connect (" autodoc-process-docstring" , qt_docstrings )
490
512
491
513
logger = logging .getLogger ("sphinx" )
492
514
warning_handler , * _ = [
493
- h for h in logger .handlers
494
- if isinstance (h , sphinx_logging .WarningStreamHandler )
515
+ h for h in logger .handlers if isinstance (h , sphinx_logging .WarningStreamHandler )
495
516
]
496
517
warning_handler .filters .insert (0 , FilterSphinxWarnings (app ))
0 commit comments