Coverage for src/mkdocstrings_handlers/python/_internal/config.py: 77.99%

230 statements  

« prev     ^ index     » next       coverage.py v7.10.3, created at 2025-08-14 23:22 +0200

1# Configuration and options dataclasses. 

2 

3from __future__ import annotations 

4 

5import re 

6import sys 

7from dataclasses import field, fields 

8from typing import TYPE_CHECKING, Annotated, Any, Literal 

9 

10from mkdocstrings import get_logger 

11 

12from mkdocstrings_handlers.python._internal.rendering import Order # noqa: TC001 

13 

14# YORE: EOL 3.10: Replace block with line 2. 

15if sys.version_info >= (3, 11): 

16 from typing import Self 

17else: 

18 from typing_extensions import Self 

19 

20 

21_logger = get_logger(__name__) 

22 

23_DEFAULT_FILTERS = ["!^_[^_]"] 

24 

25try: 

26 # When Pydantic is available, use it to validate options (done automatically). 

27 # Users can therefore opt into validation by installing Pydantic in development/CI. 

28 # When building the docs to deploy them, Pydantic is not required anymore. 

29 

30 # When building our own docs, Pydantic is always installed (see `docs` group in `pyproject.toml`) 

31 # to allow automatic generation of a JSON Schema. The JSON Schema is then referenced by mkdocstrings, 

32 # which is itself referenced by mkdocs-material's schema system. For example in VSCode: 

33 # 

34 # "yaml.schemas": { 

35 # "https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yml" 

36 # } 

37 import pydantic 

38 

39 if getattr(pydantic, "__version__", "1.").startswith("1."): 39 ↛ 40line 39 didn't jump to line 40 because the condition on line 39 was never true

40 raise ImportError # noqa: TRY301 

41 

42 # YORE: EOL 3.9: Remove block. 

43 if sys.version_info < (3, 10): 

44 try: 

45 import eval_type_backport # noqa: F401 

46 except ImportError: 

47 _logger.debug( 

48 "Pydantic needs the `eval-type-backport` package to be installed " 

49 "for modern type syntax to work on Python 3.9. " 

50 "Deactivating Pydantic validation for Python handler options.", 

51 ) 

52 raise 

53 

54 from inspect import cleandoc 

55 

56 from pydantic import Field as BaseField 

57 from pydantic.dataclasses import dataclass 

58 

59 _base_url = "https://mkdocstrings.github.io/python/usage" 

60 

61 def _Field( # noqa: N802 

62 *args: Any, 

63 description: str, 

64 group: Literal["general", "headings", "members", "docstrings", "signatures"] | None = None, 

65 parent: str | None = None, 

66 **kwargs: Any, 

67 ) -> None: 

68 def _add_markdown_description(schema: dict[str, Any]) -> None: 

69 url = f"{_base_url}/{f'configuration/{group}/' if group else ''}#{parent or schema['title']}" 

70 schema["markdownDescription"] = f"[DOCUMENTATION]({url})\n\n{schema['description']}" 

71 

72 return BaseField( 

73 *args, 

74 description=cleandoc(description), 

75 field_title_generator=lambda name, _: name, 

76 json_schema_extra=_add_markdown_description, 

77 **kwargs, 

78 ) 

79except ImportError: 

80 from dataclasses import dataclass # type: ignore[no-redef] 

81 

82 def _Field(*args: Any, **kwargs: Any) -> None: # type: ignore[misc] # noqa: N802 

83 pass 

84 

85 

86if TYPE_CHECKING: 

87 from collections.abc import MutableMapping 

88 

89 

90# YORE: EOL 3.9: Remove block. 

91_dataclass_options = {"frozen": True} 

92if sys.version_info >= (3, 10): 

93 _dataclass_options["kw_only"] = True 

94 

95 

96# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. 

97@dataclass(**_dataclass_options) # type: ignore[call-overload] 

98class GoogleStyleOptions: 

99 """Google style docstring options.""" 

100 

101 ignore_init_summary: Annotated[ 

102 bool, 

103 _Field( 

104 group="docstrings", 

105 parent="docstring_options", 

106 description="Whether to ignore the summary in `__init__` methods' docstrings.", 

107 ), 

108 ] = False 

109 

110 returns_multiple_items: Annotated[ 

111 bool, 

112 _Field( 

113 group="docstrings", 

114 parent="docstring_options", 

115 description="""Whether to parse multiple items in `Yields` and `Returns` sections. 

116 

117 When true, each item's continuation lines must be indented. 

118 When false (single item), no further indentation is required. 

119 """, 

120 ), 

121 ] = True 

122 

123 returns_named_value: Annotated[ 

124 bool, 

125 _Field( 

126 group="docstrings", 

127 parent="docstring_options", 

128 description="""Whether to parse `Yields` and `Returns` section items as name and description, rather than type and description. 

129 

130 When true, type must be wrapped in parentheses: `(int): Description.`. Names are optional: `name (int): Description.`. 

131 When false, parentheses are optional but the items cannot be named: `int: Description`. 

132 """, 

133 ), 

134 ] = True 

135 

136 returns_type_in_property_summary: Annotated[ 

137 bool, 

138 _Field( 

139 group="docstrings", 

140 parent="docstring_options", 

141 description="Whether to parse the return type of properties at the beginning of their summary: `str: Summary of the property`.", 

142 ), 

143 ] = False 

144 

145 receives_multiple_items: Annotated[ 

146 bool, 

147 _Field( 

148 group="docstrings", 

149 parent="docstring_options", 

150 description="""Whether to parse multiple items in `Receives` sections. 

151 

152 When true, each item's continuation lines must be indented. 

153 When false (single item), no further indentation is required. 

154 """, 

155 ), 

156 ] = True 

157 

158 receives_named_value: Annotated[ 

159 bool, 

160 _Field( 

161 group="docstrings", 

162 parent="docstring_options", 

163 description="""Whether to parse `Receives` section items as name and description, rather than type and description. 

164 

165 When true, type must be wrapped in parentheses: `(int): Description.`. Names are optional: `name (int): Description.`. 

166 When false, parentheses are optional but the items cannot be named: `int: Description`. 

167 """, 

168 ), 

169 ] = True 

170 

171 trim_doctest_flags: Annotated[ 

172 bool, 

173 _Field( 

174 group="docstrings", 

175 parent="docstring_options", 

176 description="Whether to remove doctest flags from Python example blocks.", 

177 ), 

178 ] = True 

179 

180 warn_unknown_params: Annotated[ 

181 bool, 

182 _Field( 

183 group="docstrings", 

184 parent="docstring_options", 

185 description="Warn about documented parameters not appearing in the signature.", 

186 ), 

187 ] = True 

188 

189 warn_missing_types: Annotated[ 

190 bool, 

191 _Field( 

192 group="docstrings", 

193 parent="docstring_options", 

194 description="Warn about missing type/annotation for parameters, return values, etc.", 

195 ), 

196 ] = True 

197 

198 warnings: Annotated[ 

199 bool, 

200 _Field( 

201 group="docstrings", 

202 parent="docstring_options", 

203 description="Generally enable/disable warnings when parsing docstrings.", 

204 ), 

205 ] = True 

206 

207 

208# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. 

209@dataclass(**_dataclass_options) # type: ignore[call-overload] 

210class NumpyStyleOptions: 

211 """Numpy style docstring options.""" 

212 

213 ignore_init_summary: Annotated[ 

214 bool, 

215 _Field( 

216 group="docstrings", 

217 parent="docstring_options", 

218 description="Whether to ignore the summary in `__init__` methods' docstrings.", 

219 ), 

220 ] = False 

221 

222 trim_doctest_flags: Annotated[ 

223 bool, 

224 _Field( 

225 group="docstrings", 

226 parent="docstring_options", 

227 description="Whether to remove doctest flags from Python example blocks.", 

228 ), 

229 ] = True 

230 

231 warn_unknown_params: Annotated[ 

232 bool, 

233 _Field( 

234 group="docstrings", 

235 parent="docstring_options", 

236 description="Warn about documented parameters not appearing in the signature.", 

237 ), 

238 ] = True 

239 

240 warn_missing_types: Annotated[ 

241 bool, 

242 _Field( 

243 group="docstrings", 

244 parent="docstring_options", 

245 description="Warn about missing type/annotation for parameters, return values, etc.", 

246 ), 

247 ] = True 

248 

249 warnings: Annotated[ 

250 bool, 

251 _Field( 

252 group="docstrings", 

253 parent="docstring_options", 

254 description="Generally enable/disable warnings when parsing docstrings.", 

255 ), 

256 ] = True 

257 

258 

259# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. 

260@dataclass(**_dataclass_options) # type: ignore[call-overload] 

261class SphinxStyleOptions: 

262 """Sphinx style docstring options.""" 

263 

264 warn_unknown_params: Annotated[ 

265 bool, 

266 _Field( 

267 group="docstrings", 

268 parent="docstring_options", 

269 description="Warn about documented parameters not appearing in the signature.", 

270 ), 

271 ] = True 

272 

273 warn_missing_types: Annotated[ 

274 bool, 

275 _Field( 

276 group="docstrings", 

277 parent="docstring_options", 

278 description="Warn about missing type/annotation for return values.", 

279 ), 

280 ] = True 

281 

282 warnings: Annotated[ 

283 bool, 

284 _Field( 

285 group="docstrings", 

286 parent="docstring_options", 

287 description="Generally enable/disable warnings when parsing docstrings.", 

288 ), 

289 ] = True 

290 

291 

292# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. 

293@dataclass(**_dataclass_options) # type: ignore[call-overload] 

294class PerStyleOptions: 

295 """Per style options.""" 

296 

297 google: Annotated[ 

298 GoogleStyleOptions, 

299 _Field( 

300 group="docstrings", 

301 parent="docstring_options", 

302 description="Google-style options.", 

303 ), 

304 ] = field(default_factory=GoogleStyleOptions) 

305 

306 numpy: Annotated[ 

307 NumpyStyleOptions, 

308 _Field( 

309 group="docstrings", 

310 parent="docstring_options", 

311 description="Numpydoc-style options.", 

312 ), 

313 ] = field(default_factory=NumpyStyleOptions) 

314 

315 sphinx: Annotated[ 

316 SphinxStyleOptions, 

317 _Field( 

318 group="docstrings", 

319 parent="docstring_options", 

320 description="Sphinx-style options.", 

321 ), 

322 ] = field(default_factory=SphinxStyleOptions) 

323 

324 @classmethod 

325 def from_data(cls, **data: Any) -> Self: 

326 """Create an instance from a dictionary.""" 

327 if "google" in data: 

328 data["google"] = GoogleStyleOptions(**data["google"]) 

329 if "numpy" in data: 

330 data["numpy"] = NumpyStyleOptions(**data["numpy"]) 

331 if "sphinx" in data: 

332 data["sphinx"] = SphinxStyleOptions(**data["sphinx"]) 

333 return cls(**data) 

334 

335 

336# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. 

337@dataclass(**_dataclass_options) # type: ignore[call-overload] 

338class AutoStyleOptions: 

339 """Auto style docstring options.""" 

340 

341 method: Annotated[ 

342 Literal["heuristics", "max_sections"], 

343 _Field( 

344 group="docstrings", 

345 parent="docstring_options", 

346 description="The method to use to determine the docstring style.", 

347 ), 

348 ] = "heuristics" 

349 

350 style_order: Annotated[ 

351 list[str], 

352 _Field( 

353 group="docstrings", 

354 parent="docstring_options", 

355 description="The order of the docstring styles to try.", 

356 ), 

357 ] = field(default_factory=lambda: ["sphinx", "google", "numpy"]) 

358 

359 default: Annotated[ 

360 str | None, 

361 _Field( 

362 group="docstrings", 

363 parent="docstring_options", 

364 description="The default docstring style to use if no other style is detected.", 

365 ), 

366 ] = None 

367 

368 per_style_options: Annotated[ 

369 PerStyleOptions, 

370 _Field( 

371 group="docstrings", 

372 parent="docstring_options", 

373 description="Per-style options.", 

374 ), 

375 ] = field(default_factory=PerStyleOptions) 

376 

377 @classmethod 

378 def from_data(cls, **data: Any) -> Self: 

379 """Create an instance from a dictionary.""" 

380 if "per_style_options" in data: 

381 data["per_style_options"] = PerStyleOptions.from_data(**data["per_style_options"]) 

382 return cls(**data) 

383 

384 

385# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. 

386@dataclass(**_dataclass_options) # type: ignore[call-overload] 

387class SummaryOption: 

388 """Summary option.""" 

389 

390 attributes: Annotated[ 

391 bool, 

392 _Field( 

393 group="members", 

394 parent="summary", 

395 description="Whether to render summaries of attributes.", 

396 ), 

397 ] = False 

398 

399 functions: Annotated[ 

400 bool, 

401 _Field( 

402 group="members", 

403 parent="summary", 

404 description="Whether to render summaries of functions (methods).", 

405 ), 

406 ] = False 

407 

408 classes: Annotated[ 

409 bool, 

410 _Field( 

411 group="members", 

412 parent="summary", 

413 description="Whether to render summaries of classes.", 

414 ), 

415 ] = False 

416 

417 modules: Annotated[ 

418 bool, 

419 _Field( 

420 group="members", 

421 parent="summary", 

422 description="Whether to render summaries of modules.", 

423 ), 

424 ] = False 

425 

426 

427# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. 

428@dataclass(**_dataclass_options) # type: ignore[call-overload] 

429class PythonInputOptions: 

430 """Accepted input options.""" 

431 

432 allow_inspection: Annotated[ 

433 bool, 

434 _Field( 

435 group="general", 

436 description="Whether to allow inspecting modules when visiting them is not possible.", 

437 ), 

438 ] = True 

439 

440 force_inspection: Annotated[ 

441 bool, 

442 _Field( 

443 group="general", 

444 description="Whether to force using dynamic analysis when loading data.", 

445 ), 

446 ] = False 

447 

448 annotations_path: Annotated[ 

449 Literal["brief", "source", "full"], 

450 _Field( 

451 group="signatures", 

452 description="The verbosity for annotations path: `brief` (recommended), `source` (as written in the source), or `full`.", 

453 ), 

454 ] = "brief" 

455 

456 backlinks: Annotated[ 

457 Literal["flat", "tree", False], 

458 _Field( 

459 group="general", 

460 description="Whether to render backlinks, and how.", 

461 ), 

462 ] = False 

463 

464 docstring_options: Annotated[ 

465 GoogleStyleOptions | NumpyStyleOptions | SphinxStyleOptions | AutoStyleOptions | None, 

466 _Field( 

467 group="docstrings", 

468 description="""The options for the docstring parser. 

469 

470 See [docstring parsers](https://mkdocstrings.github.io/griffe/reference/docstrings/) and their options in Griffe docs. 

471 """, 

472 ), 

473 ] = None 

474 

475 docstring_section_style: Annotated[ 

476 Literal["table", "list", "spacy"], 

477 _Field( 

478 group="docstrings", 

479 description="The style used to render docstring sections.", 

480 ), 

481 ] = "table" 

482 

483 docstring_style: Annotated[ 

484 Literal["auto", "google", "numpy", "sphinx"] | None, 

485 _Field( 

486 group="docstrings", 

487 description="The docstring style to use: `auto`, `google`, `numpy`, `sphinx`, or `None`.", 

488 ), 

489 ] = "google" 

490 

491 extensions: Annotated[ 

492 list[str | dict[str, Any]], 

493 _Field( 

494 group="general", 

495 description="A list of Griffe extensions to load.", 

496 ), 

497 ] = field(default_factory=list) 

498 

499 filters: Annotated[ 

500 list[str] | Literal["public"], 

501 _Field( 

502 group="members", 

503 description="""A list of filters, or `"public"`. 

504 

505 **List of filters** 

506 

507 A filter starting with `!` will exclude matching objects instead of including them. 

508 The `members` option takes precedence over `filters` (filters will still be applied recursively 

509 to lower members in the hierarchy). 

510 

511 **Filtering methods** 

512 

513 [:octicons-heart-fill-24:{ .pulse } Sponsors only](../insiders/index.md){ .insiders } &mdash; 

514 [:octicons-tag-24: Insiders 1.11.0](../insiders/changelog.md#1.11.0) 

515 

516 The `public` method will include only public objects: 

517 those added to `__all__` or not starting with an underscore (except for special methods/attributes). 

518 """, 

519 ), 

520 ] = field(default_factory=lambda: _DEFAULT_FILTERS.copy()) 

521 

522 find_stubs_package: Annotated[ 

523 bool, 

524 _Field( 

525 group="general", 

526 description="Whether to load stubs package (package-stubs) when extracting docstrings.", 

527 ), 

528 ] = False 

529 

530 group_by_category: Annotated[ 

531 bool, 

532 _Field( 

533 group="members", 

534 description="Group the object's children by categories: attributes, classes, functions, and modules.", 

535 ), 

536 ] = True 

537 

538 heading: Annotated[ 

539 str, 

540 _Field( 

541 group="headings", 

542 description="A custom string to override the autogenerated heading of the root object.", 

543 ), 

544 ] = "" 

545 

546 heading_level: Annotated[ 

547 int, 

548 _Field( 

549 group="headings", 

550 description="The initial heading level to use.", 

551 ), 

552 ] = 2 

553 

554 inherited_members: Annotated[ 

555 bool | list[str], 

556 _Field( 

557 group="members", 

558 description="""A boolean, or an explicit list of inherited members to render. 

559 

560 If true, select all inherited members, which can then be filtered with `members`. 

561 If false or empty list, do not select any inherited member. 

562 """, 

563 ), 

564 ] = False 

565 

566 line_length: Annotated[ 

567 int, 

568 _Field( 

569 group="signatures", 

570 description="Maximum line length when formatting code/signatures.", 

571 ), 

572 ] = 60 

573 

574 members: Annotated[ 

575 list[str] | bool | None, 

576 _Field( 

577 group="members", 

578 description="""A boolean, or an explicit list of members to render. 

579 

580 If true, select all members without further filtering. 

581 If false or empty list, do not render members. 

582 If none, select all members and apply further filtering with filters and docstrings. 

583 """, 

584 ), 

585 ] = None 

586 

587 members_order: Annotated[ 

588 Order | list[Order], 

589 _Field( 

590 group="members", 

591 description="""The members ordering to use. 

592 

593 - `__all__`: order members according to `__all__` module attributes, if declared; 

594 - `alphabetical`: order members alphabetically; 

595 - `source`: order members as they appear in the source file. 

596 

597 Since `__all__` is a module-only attribute, it can't be used to sort class members, 

598 therefore the `members_order` option accepts a list of ordering methods, 

599 indicating ordering preferences. 

600 """, 

601 ), 

602 ] = "alphabetical" 

603 

604 merge_init_into_class: Annotated[ 

605 bool, 

606 _Field( 

607 group="docstrings", 

608 description="Whether to merge the `__init__` method into the class' signature and docstring.", 

609 ), 

610 ] = False 

611 

612 modernize_annotations: Annotated[ 

613 bool, 

614 _Field( 

615 group="signatures", 

616 description="Whether to modernize annotations, for example `Optional[str]` into `str | None`.", 

617 ), 

618 ] = False 

619 

620 overloads_only: Annotated[ 

621 bool, 

622 _Field( 

623 group="signatures", 

624 description="Whether to hide the implementation signature if the overloads are shown.", 

625 ), 

626 ] = False 

627 

628 parameter_headings: Annotated[ 

629 bool, 

630 _Field( 

631 group="headings", 

632 description="Whether to render headings for parameters (therefore showing parameters in the ToC).", 

633 ), 

634 ] = False 

635 

636 preload_modules: Annotated[ 

637 list[str], 

638 _Field( 

639 group="general", 

640 description="""Pre-load modules that are not specified directly in autodoc instructions (`::: identifier`). 

641 

642 It is useful when you want to render documentation for a particular member of an object, 

643 and this member is imported from another package than its parent. 

644 

645 For an imported member to be rendered, you need to add it to the `__all__` attribute 

646 of the importing module. 

647 

648 The modules must be listed as an array of strings. 

649 """, 

650 ), 

651 ] = field(default_factory=list) 

652 

653 relative_crossrefs: Annotated[ 

654 bool, 

655 _Field( 

656 group="docstrings", 

657 description="Whether to enable the relative crossref syntax.", 

658 ), 

659 ] = False 

660 

661 scoped_crossrefs: Annotated[ 

662 bool, 

663 _Field( 

664 group="docstrings", 

665 description="Whether to enable the scoped crossref ability.", 

666 ), 

667 ] = False 

668 

669 show_overloads: Annotated[ 

670 bool, 

671 _Field( 

672 group="signatures", 

673 description="Show the overloads of a function or method.", 

674 ), 

675 ] = True 

676 

677 separate_signature: Annotated[ 

678 bool, 

679 _Field( 

680 group="signatures", 

681 description="""Whether to put the whole signature in a code block below the heading. 

682 

683 If Black or Ruff are installed, the signature is also formatted using them. 

684 """, 

685 ), 

686 ] = False 

687 

688 show_attribute_values: Annotated[ 

689 bool, 

690 _Field( 

691 group="signatures", 

692 description="Show initial values of attributes in classes.", 

693 ), 

694 ] = True 

695 

696 show_bases: Annotated[ 

697 bool, 

698 _Field( 

699 group="general", 

700 description="Show the base classes of a class.", 

701 ), 

702 ] = True 

703 

704 show_category_heading: Annotated[ 

705 bool, 

706 _Field( 

707 group="headings", 

708 description="When grouped by categories, show a heading for each category.", 

709 ), 

710 ] = False 

711 

712 show_docstring_attributes: Annotated[ 

713 bool, 

714 _Field( 

715 group="docstrings", 

716 description="Whether to display the 'Attributes' section in the object's docstring.", 

717 ), 

718 ] = True 

719 

720 show_docstring_classes: Annotated[ 

721 bool, 

722 _Field( 

723 group="docstrings", 

724 description="Whether to display the 'Classes' section in the object's docstring.", 

725 ), 

726 ] = True 

727 

728 show_docstring_description: Annotated[ 

729 bool, 

730 _Field( 

731 group="docstrings", 

732 description="Whether to display the textual block (including admonitions) in the object's docstring.", 

733 ), 

734 ] = True 

735 

736 show_docstring_examples: Annotated[ 

737 bool, 

738 _Field( 

739 group="docstrings", 

740 description="Whether to display the 'Examples' section in the object's docstring.", 

741 ), 

742 ] = True 

743 

744 show_docstring_functions: Annotated[ 

745 bool, 

746 _Field( 

747 group="docstrings", 

748 description="Whether to display the 'Functions' or 'Methods' sections in the object's docstring.", 

749 ), 

750 ] = True 

751 

752 show_docstring_modules: Annotated[ 

753 bool, 

754 _Field( 

755 group="docstrings", 

756 description="Whether to display the 'Modules' section in the object's docstring.", 

757 ), 

758 ] = True 

759 

760 show_docstring_other_parameters: Annotated[ 

761 bool, 

762 _Field( 

763 group="docstrings", 

764 description="Whether to display the 'Other Parameters' section in the object's docstring.", 

765 ), 

766 ] = True 

767 

768 show_docstring_parameters: Annotated[ 

769 bool, 

770 _Field( 

771 group="docstrings", 

772 description="Whether to display the 'Parameters' section in the object's docstring.", 

773 ), 

774 ] = True 

775 

776 show_docstring_raises: Annotated[ 

777 bool, 

778 _Field( 

779 group="docstrings", 

780 description="Whether to display the 'Raises' section in the object's docstring.", 

781 ), 

782 ] = True 

783 

784 show_docstring_receives: Annotated[ 

785 bool, 

786 _Field( 

787 group="docstrings", 

788 description="Whether to display the 'Receives' section in the object's docstring.", 

789 ), 

790 ] = True 

791 

792 show_docstring_returns: Annotated[ 

793 bool, 

794 _Field( 

795 group="docstrings", 

796 description="Whether to display the 'Returns' section in the object's docstring.", 

797 ), 

798 ] = True 

799 

800 show_docstring_warns: Annotated[ 

801 bool, 

802 _Field( 

803 group="docstrings", 

804 description="Whether to display the 'Warns' section in the object's docstring.", 

805 ), 

806 ] = True 

807 

808 show_docstring_yields: Annotated[ 

809 bool, 

810 _Field( 

811 group="docstrings", 

812 description="Whether to display the 'Yields' section in the object's docstring.", 

813 ), 

814 ] = True 

815 

816 show_if_no_docstring: Annotated[ 

817 bool, 

818 _Field( 

819 group="docstrings", 

820 description="Show the object heading even if it has no docstring or children with docstrings.", 

821 ), 

822 ] = False 

823 

824 show_inheritance_diagram: Annotated[ 

825 bool, 

826 _Field( 

827 group="docstrings", 

828 description="Show the inheritance diagram of a class using Mermaid.", 

829 ), 

830 ] = False 

831 

832 show_labels: Annotated[ 

833 bool, 

834 _Field( 

835 group="docstrings", 

836 description="Whether to show labels of the members.", 

837 ), 

838 ] = True 

839 

840 show_object_full_path: Annotated[ 

841 bool, 

842 _Field( 

843 group="docstrings", 

844 description="Show the full Python path of every object.", 

845 ), 

846 ] = False 

847 

848 show_root_full_path: Annotated[ 

849 bool, 

850 _Field( 

851 group="docstrings", 

852 description="Show the full Python path for the root object heading.", 

853 ), 

854 ] = True 

855 

856 show_root_heading: Annotated[ 

857 bool, 

858 _Field( 

859 group="headings", 

860 description="""Show the heading of the object at the root of the documentation tree. 

861 

862 The root object is the object referenced by the identifier after `:::`. 

863 """, 

864 ), 

865 ] = False 

866 

867 show_root_members_full_path: Annotated[ 

868 bool, 

869 _Field( 

870 group="headings", 

871 description="Show the full Python path of the root members.", 

872 ), 

873 ] = False 

874 

875 show_root_toc_entry: Annotated[ 

876 bool, 

877 _Field( 

878 group="headings", 

879 description="If the root heading is not shown, at least add a ToC entry for it.", 

880 ), 

881 ] = True 

882 

883 show_signature_annotations: Annotated[ 

884 bool, 

885 _Field( 

886 group="signatures", 

887 description="Show the type annotations in methods and functions signatures.", 

888 ), 

889 ] = False 

890 

891 show_signature: Annotated[ 

892 bool, 

893 _Field( 

894 group="signatures", 

895 description="Show methods and functions signatures.", 

896 ), 

897 ] = True 

898 

899 show_source: Annotated[ 

900 bool, 

901 _Field( 

902 group="general", 

903 description="Show the source code of this object.", 

904 ), 

905 ] = True 

906 

907 show_submodules: Annotated[ 

908 bool, 

909 _Field( 

910 group="members", 

911 description="When rendering a module, show its submodules recursively.", 

912 ), 

913 ] = False 

914 

915 show_symbol_type_heading: Annotated[ 

916 bool, 

917 _Field( 

918 group="headings", 

919 description="Show the symbol type in headings (e.g. mod, class, meth, func and attr).", 

920 ), 

921 ] = False 

922 

923 show_symbol_type_toc: Annotated[ 

924 bool, 

925 _Field( 

926 group="headings", 

927 description="Show the symbol type in the Table of Contents (e.g. mod, class, methd, func and attr).", 

928 ), 

929 ] = False 

930 

931 skip_local_inventory: Annotated[ 

932 bool, 

933 _Field( 

934 group="general", 

935 description="Whether to prevent objects from being registered in the local objects inventory.", 

936 ), 

937 ] = False 

938 

939 signature_crossrefs: Annotated[ 

940 bool, 

941 _Field( 

942 group="signatures", 

943 description="Whether to render cross-references for type annotations in signatures.", 

944 ), 

945 ] = False 

946 

947 summary: Annotated[ 

948 bool | SummaryOption, 

949 _Field( 

950 group="members", 

951 description="Whether to render summaries of modules, classes, functions (methods) and attributes.", 

952 ), 

953 ] = field(default_factory=SummaryOption) 

954 

955 toc_label: Annotated[ 

956 str, 

957 _Field( 

958 group="headings", 

959 description="A custom string to override the autogenerated toc label of the root object.", 

960 ), 

961 ] = "" 

962 

963 unwrap_annotated: Annotated[ 

964 bool, 

965 _Field( 

966 group="signatures", 

967 description="Whether to unwrap `Annotated` types to show only the type without the annotations.", 

968 ), 

969 ] = False 

970 

971 extra: Annotated[ 

972 dict[str, Any], 

973 _Field( 

974 group="general", 

975 description="Extra options.", 

976 ), 

977 ] = field(default_factory=dict) 

978 

979 @classmethod 

980 def _extract_extra(cls, data: dict[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]: 

981 field_names = {field.name for field in fields(cls)} 

982 copy = data.copy() 

983 return {name: copy.pop(name) for name in data if name not in field_names}, copy 

984 

985 @classmethod 

986 def coerce(cls, **data: Any) -> MutableMapping[str, Any]: 

987 """Coerce data.""" 

988 if "docstring_options" in data: 988 ↛ 989line 988 didn't jump to line 989 because the condition on line 988 was never true

989 docstring_style = data.get("docstring_style", "google") 

990 docstring_options = data["docstring_options"] 

991 if docstring_options is not None: 

992 if docstring_style == "auto": 

993 docstring_options = AutoStyleOptions.from_data(**docstring_options) 

994 elif docstring_style == "google": 

995 docstring_options = GoogleStyleOptions(**docstring_options) 

996 elif docstring_style == "numpy": 

997 docstring_options = NumpyStyleOptions(**docstring_options) 

998 elif docstring_style == "sphinx": 

999 docstring_options = SphinxStyleOptions(**docstring_options) 

1000 data["docstring_options"] = docstring_options 

1001 if "summary" in data: 

1002 summary = data["summary"] 

1003 if summary is True: 1003 ↛ 1004line 1003 didn't jump to line 1004 because the condition on line 1003 was never true

1004 summary = SummaryOption(attributes=True, functions=True, classes=True, modules=True) 

1005 elif summary is False: 1005 ↛ 1006line 1005 didn't jump to line 1006 because the condition on line 1005 was never true

1006 summary = SummaryOption(attributes=False, functions=False, classes=False, modules=False) 

1007 else: 

1008 summary = SummaryOption(**summary) 

1009 data["summary"] = summary 

1010 return data 

1011 

1012 @classmethod 

1013 def from_data(cls, **data: Any) -> Self: 

1014 """Create an instance from a dictionary.""" 

1015 return cls(**cls.coerce(**data)) 

1016 

1017 

1018# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. 

1019@dataclass(**_dataclass_options) # type: ignore[call-overload] 

1020class PythonOptions(PythonInputOptions): # type: ignore[override,unused-ignore] 

1021 """Final options passed as template context.""" 

1022 

1023 filters: list[tuple[re.Pattern, bool]] | Literal["public"] = field( # type: ignore[assignment] 

1024 default_factory=lambda: [ 

1025 (re.compile(filtr.removeprefix("!")), filtr.startswith("!")) for filtr in _DEFAULT_FILTERS 

1026 ], 

1027 ) 

1028 """A list of filters, or `"public"`.""" 

1029 

1030 summary: SummaryOption = field(default_factory=SummaryOption) 

1031 """Whether to render summaries of modules, classes, functions (methods) and attributes.""" 

1032 

1033 @classmethod 

1034 def coerce(cls, **data: Any) -> MutableMapping[str, Any]: 

1035 """Create an instance from a dictionary.""" 

1036 if "filters" in data and not isinstance(data["filters"], str): 

1037 # Filters are `None` or a sequence of strings (tests use tuples). 

1038 data["filters"] = [ 

1039 (re.compile(filtr.removeprefix("!")), filtr.startswith("!")) for filtr in data["filters"] or () 

1040 ] 

1041 return super().coerce(**data) 

1042 

1043 

1044# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. 

1045@dataclass(**_dataclass_options) # type: ignore[call-overload] 

1046class Inventory: 

1047 """An inventory.""" 

1048 

1049 url: Annotated[ 

1050 str, 

1051 _Field( 

1052 parent="inventories", 

1053 description="The URL of the inventory.", 

1054 ), 

1055 ] 

1056 

1057 base_url: Annotated[ 

1058 str | None, 

1059 _Field( 

1060 parent="inventories", 

1061 description="The base URL of the inventory.", 

1062 ), 

1063 ] = None 

1064 

1065 domains: Annotated[ 

1066 list[str], 

1067 _Field( 

1068 parent="inventories", 

1069 description="The domains to load from the inventory.", 

1070 ), 

1071 ] = field(default_factory=lambda: ["py"]) 

1072 

1073 @property 

1074 def _config(self) -> dict[str, Any]: 

1075 return {"base_url": self.base_url, "domains": self.domains} 

1076 

1077 

1078# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. 

1079@dataclass(**_dataclass_options) # type: ignore[call-overload] 

1080class PythonInputConfig: 

1081 """Python handler configuration.""" 

1082 

1083 inventories: Annotated[ 

1084 list[str | Inventory], 

1085 _Field(description="The inventories to load."), 

1086 ] = field(default_factory=list) 

1087 

1088 paths: Annotated[ 

1089 list[str], 

1090 _Field(description="The paths in which to search for Python packages."), 

1091 ] = field(default_factory=lambda: ["."]) 

1092 

1093 load_external_modules: Annotated[ 

1094 bool | None, 

1095 _Field(description="Whether to always load external modules/packages."), 

1096 ] = None 

1097 

1098 options: Annotated[ 

1099 PythonInputOptions, 

1100 _Field(description="Configuration options for collecting and rendering objects."), 

1101 ] = field(default_factory=PythonInputOptions) 

1102 

1103 locale: Annotated[ 

1104 str | None, 

1105 _Field( 

1106 description="Deprecated. Use mkdocstrings' own `locale` setting instead. The locale to use when translating template strings.", 

1107 ), 

1108 ] = None 

1109 

1110 @classmethod 

1111 def coerce(cls, **data: Any) -> MutableMapping[str, Any]: 

1112 """Coerce data.""" 

1113 return data 

1114 

1115 @classmethod 

1116 def from_data(cls, **data: Any) -> Self: 

1117 """Create an instance from a dictionary.""" 

1118 return cls(**cls.coerce(**data)) 

1119 

1120 

1121# YORE: EOL 3.9: Replace `**_dataclass_options` with `frozen=True, kw_only=True` within line. 

1122@dataclass(**_dataclass_options) # type: ignore[call-overload] 

1123class PythonConfig(PythonInputConfig): # type: ignore[override,unused-ignore] 

1124 """Python handler configuration.""" 

1125 

1126 inventories: Annotated[ 

1127 list[Inventory], 

1128 _Field(description="The object inventories to load."), 

1129 ] = field(default_factory=list) # type: ignore[assignment] 

1130 

1131 options: Annotated[ 

1132 dict[str, Any], 

1133 _Field(description="Configuration options for collecting and rendering objects."), 

1134 ] = field(default_factory=dict) # type: ignore[assignment] 

1135 

1136 @classmethod 

1137 def coerce(cls, **data: Any) -> MutableMapping[str, Any]: 

1138 """Coerce data.""" 

1139 if "inventories" in data: 1139 ↛ 1140line 1139 didn't jump to line 1140 because the condition on line 1139 was never true

1140 data["inventories"] = [ 

1141 Inventory(url=inv) if isinstance(inv, str) else Inventory(**inv) for inv in data["inventories"] 

1142 ] 

1143 return data