|
1 | 1 | """
|
2 |
| -A modified version of https://github.com/jupyterhub/autodoc-traits/tree/1.2.2 |
3 |
| -for documenting trait fields that are used to configure another object, but |
4 |
| -where the traitlet cannot be set directly. |
5 |
| -
|
6 |
| -This is used to generate the Server Process options documentation: |
| 2 | +A custom Sphinx directive to generate the Server Process options documentation: |
7 | 3 | https://github.com/jupyterhub/jupyter-server-proxy/blob/main/docs/source/server-process.md
|
8 | 4 | """
|
9 | 5 |
|
| 6 | +import importlib |
| 7 | +from textwrap import dedent |
| 8 | + |
| 9 | +from docutils import nodes |
10 | 10 | from sphinx.application import Sphinx
|
11 |
| -from sphinx.ext.autodoc import ( |
12 |
| - SUPPRESS, |
13 |
| - AttributeDocumenter, |
14 |
| - ClassDocumenter, |
15 |
| - ObjectMember, |
16 |
| -) |
| 11 | +from sphinx.util.docutils import SphinxDirective |
17 | 12 | from sphinx.util.typing import ExtensionMetadata
|
18 |
| -from traitlets import MetaHasTraits, TraitType, Undefined |
19 |
| - |
20 |
| - |
21 |
| -class ServerProcessConfigurableDocumenter(ClassDocumenter): |
22 |
| - """ |
23 |
| - A modified version of autodoc_traits.ConfigurableDocumenter that only documents |
24 |
| - the traits in this class, not the inherited traits. |
25 |
| - https://github.com/jupyterhub/autodoc-traits/blob/1.2.2/autodoc_traits.py#L20-L122 |
26 |
| - """ |
27 |
| - |
28 |
| - objtype = "serverprocessconfigurable" |
29 |
| - directivetype = "class" |
30 |
| - priority = 100 # higher priority than ClassDocumenter's 10 |
31 |
| - |
32 |
| - @classmethod |
33 |
| - def can_document_member(cls, member, membername, isattr, parent): |
34 |
| - return isinstance(member, MetaHasTraits) |
35 |
| - |
36 |
| - def get_object_members(self, want_all): |
37 |
| - """ |
38 |
| - Only document members in this class |
39 |
| - """ |
40 |
| - config_trait_members = self.object.class_traits(config=True).items() |
41 |
| - members = [ObjectMember(name, trait) for (name, trait) in config_trait_members] |
42 |
| - return False, members |
| 13 | +from traitlets import Undefined |
43 | 14 |
|
44 |
| - def should_suppress_directive_header(): |
45 |
| - return True |
46 | 15 |
|
47 |
| - def add_directive_header(self, sig): |
48 |
| - print(f"{sig=}") |
49 |
| - self.options.annotation = SUPPRESS |
50 |
| - super().add_directive_header(sig) |
| 16 | +class ServerProcessDirective(SphinxDirective): |
| 17 | + """A directive to say hello!""" |
51 | 18 |
|
| 19 | + required_arguments = 2 |
52 | 20 |
|
53 |
| -class ServerProcessTraitDocumenter(AttributeDocumenter): |
54 |
| - """ |
55 |
| - A modified version of autodoc_traits.TraitDocumenter that omits the c.ClassName prefix |
56 |
| - https://github.com/jupyterhub/autodoc-traits/blob/1.2.2/autodoc_traits.py#L125-L203 |
57 |
| - """ |
| 21 | + def run(self) -> list[nodes.Node]: |
| 22 | + module = importlib.import_module(self.arguments[0], ".") |
| 23 | + cls = getattr(module, self.arguments[1]) |
| 24 | + config_trait_members = cls.class_traits(config=True).items() |
58 | 25 |
|
59 |
| - objtype = "serverprocesstrait" |
60 |
| - directivetype = "attribute" |
61 |
| - priority = 100 # AttributeDocumenter has 10 |
62 |
| - member_order = 0 # AttributeDocumenter has 60 |
| 26 | + doc = [] |
63 | 27 |
|
64 |
| - @classmethod |
65 |
| - def can_document_member(cls, member, membername, isattr, parent): |
66 |
| - return isinstance(member, TraitType) |
| 28 | + for name, trait in config_trait_members: |
| 29 | + default_value = trait.default_value |
| 30 | + if default_value is Undefined: |
| 31 | + default_value = "" |
| 32 | + else: |
| 33 | + default_value = repr(default_value) |
| 34 | + traitlets_type = trait.__class__.__name__ |
67 | 35 |
|
68 |
| - def add_directive_header(self, sig): |
69 |
| - default_value = self.object.default_value |
70 |
| - if default_value is Undefined: |
71 |
| - default_value = "" |
72 |
| - else: |
73 |
| - default_value = repr(default_value) |
| 36 | + help = self.parse_text_to_nodes(dedent(trait.metadata.get("help", ""))) |
74 | 37 |
|
75 |
| - traitlets_type = self.object.__class__.__name__ |
76 |
| - self.options.annotation = f"{traitlets_type}({default_value})" |
77 |
| - super().add_directive_header(sig) |
| 38 | + definition = nodes.definition_list_item( |
| 39 | + "", |
| 40 | + nodes.term( |
| 41 | + "", |
| 42 | + "", |
| 43 | + nodes.strong(text=f"{name}"), |
| 44 | + nodes.emphasis(text=f" {traitlets_type}({default_value})"), |
| 45 | + ), |
| 46 | + nodes.definition("", *help), |
| 47 | + ) |
| 48 | + doc.append(nodes.definition_list("", definition)) |
| 49 | + return doc |
78 | 50 |
|
79 | 51 |
|
80 | 52 | def setup(app: Sphinx) -> ExtensionMetadata:
|
81 |
| - app.setup_extension("sphinx.ext.autodoc") |
82 |
| - app.add_autodocumenter(ServerProcessConfigurableDocumenter) |
83 |
| - app.add_autodocumenter(ServerProcessTraitDocumenter) |
| 53 | + app.add_directive("serverprocess", ServerProcessDirective) |
84 | 54 | return {
|
85 | 55 | "version": "0.1",
|
86 | 56 | "parallel_read_safe": True,
|
|
0 commit comments