Skip to content

Commit 4314fad

Browse files
kevalmorabia97yeyu-nvidia
authored andcommitted
Add source code for 0.25.0 docs
1 parent f610503 commit 4314fad

40 files changed

+4640
-0
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
"""A small extension on top of the autodoc_pydantic extension to show default configs."""
17+
18+
import json
19+
import types
20+
from contextlib import contextmanager, nullcontext
21+
from typing import Any, Callable
22+
23+
from sphinx.application import Sphinx
24+
from sphinxcontrib.autodoc_pydantic import __version__
25+
from sphinxcontrib.autodoc_pydantic.directives.autodocumenters import (
26+
PydanticFieldDocumenter,
27+
PydanticModelDocumenter,
28+
)
29+
from sphinxcontrib.autodoc_pydantic.directives.templates import to_collapsable
30+
31+
32+
def _wrap_into_collabsable(summary: str):
33+
"""Decorator to wrap the lines written by the function into a collapsable block."""
34+
35+
# patch self.add_line to intercept the lines instead of writing them to the output
36+
def add_line_intercepted(
37+
self: "ModeloptPydanticModelDocumenter", line: str, source: str, *lineno: int
38+
):
39+
if self._source_intercepted is None:
40+
self._source_intercepted = source
41+
else:
42+
assert self._source_intercepted == source, "Only one source supported!"
43+
assert not lineno, "No optional lineno argument supported!"
44+
self._lines_intercepted.append(line)
45+
46+
def decorator(func: Callable) -> Callable:
47+
def func_with_collabsable(self: "ModeloptPydanticModelDocumenter", *args, **kwargs) -> Any:
48+
# patch the add_line method
49+
self._lines_intercepted = []
50+
self._source_intercepted = None
51+
self.add_line_unpatched = self.add_line.__func__
52+
self.add_line = types.MethodType(add_line_intercepted, self)
53+
54+
# run method
55+
ret = func(self, *args, **kwargs)
56+
57+
# clean up
58+
lines = self._lines_intercepted
59+
source = self._source_intercepted
60+
self.add_line = types.MethodType(self.add_line_unpatched, self)
61+
del self._lines_intercepted
62+
del self._source_intercepted
63+
del self.add_line_unpatched
64+
65+
# check if we have any lines to wrap
66+
if lines:
67+
lines = to_collapsable(lines, summary, "autodoc_pydantic_collapsable_json")
68+
for line in lines:
69+
self.add_line(line, source)
70+
71+
# return the original return value
72+
return ret
73+
74+
return func_with_collabsable
75+
76+
return decorator
77+
78+
79+
def _skip_lines(func: Callable) -> Callable:
80+
def func_with_skip_lines(self: "ModeloptPydanticModelDocumenter", *args, **kwargs) -> Any:
81+
# patch the add_line method
82+
self.add_line_unpatched = self.add_line.__func__
83+
self.add_line = types.MethodType(lambda self, *args, **kwargs: None, self)
84+
85+
# run method
86+
ret = func(self, *args, **kwargs)
87+
88+
# clean up
89+
self.add_line = types.MethodType(self.add_line_unpatched, self)
90+
del self.add_line_unpatched
91+
92+
# return the original return value
93+
return ret
94+
95+
return func_with_skip_lines
96+
97+
98+
class ModeloptPydanticModelDocumenter(PydanticModelDocumenter):
99+
"""We add the option to print defaults."""
100+
101+
def __init__(self, *args: Any) -> None:
102+
super().__init__(*args)
103+
exclude_members = self.options["exclude-members"]
104+
exclude_members.add("model_computed_fields")
105+
106+
@_wrap_into_collabsable("Show default config as JSON")
107+
def add_default_dict(self) -> None:
108+
# we use sanitized schema which means errors in the schema are ignored
109+
schema = self.pydantic.inspect.schema.sanitized
110+
config = {k: v.get("default") for k, v in schema["properties"].items()}
111+
112+
# create valid rst lines from the config
113+
config_json = json.dumps(config, default=str, indent=3)
114+
lines = [f" {line}" for line in config_json.split("\n")]
115+
lines = [":Default config (JSON):", "", ".. code-block:: json", ""] + lines + [""]
116+
117+
# add lines to autodoc
118+
source_name = self.get_sourcename()
119+
for line in lines:
120+
self.add_line(line, source_name)
121+
122+
def add_collapsable_schema(self):
123+
if self.pydantic.options.is_true("modelopt-show-default-dict", True):
124+
self.add_default_dict()
125+
with (
126+
nullcontext()
127+
if self.pydantic.options.is_true("modelopt-show-json-schema", True)
128+
else self._skip_lines()
129+
):
130+
super().add_collapsable_schema()
131+
132+
@_wrap_into_collabsable("Show field summary")
133+
def add_field_summary(self):
134+
return super().add_field_summary()
135+
136+
@contextmanager
137+
def _skip_lines(self):
138+
self.add_line_unpatched = self.add_line.__func__
139+
self.add_line = types.MethodType(lambda self, *args, **kwargs: None, self)
140+
yield
141+
self.add_line = types.MethodType(self.add_line_unpatched, self)
142+
del self.add_line_unpatched
143+
144+
145+
class ModeloptPydanticFieldDocumenter(PydanticFieldDocumenter):
146+
"""Collabsing field doc string by default and only showing summary."""
147+
148+
@_wrap_into_collabsable("Show details")
149+
def add_description(self):
150+
super().add_description()
151+
152+
153+
def setup(app: Sphinx) -> dict[str, Any]:
154+
"""Setup the extension."""
155+
# we have one new option that we enable
156+
app.add_config_value("autodoc_pydantic_model_modelopt_show_default_dict", True, True, bool)
157+
app.add_config_value("autodoc_pydantic_model_modelopt_show_json_schema", True, True, bool)
158+
159+
# we require this extension to be loaded first
160+
app.setup_extension("sphinx.ext.autodoc")
161+
app.setup_extension("sphinxcontrib.autodoc_pydantic")
162+
163+
# we modify the model and field documenter on top of autodoch_pydantic
164+
app.add_autodocumenter(ModeloptPydanticModelDocumenter, override=True)
165+
app.add_autodocumenter(ModeloptPydanticFieldDocumenter, override=True)
166+
167+
return {
168+
"version": __version__,
169+
"parallel_read_safe": True,
170+
"parallel_write_safe": True,
171+
}

docs/source/_static/custom.css

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/* Hide Warnings outputs from rendered Jupyter Notebooks */
2+
div.nboutput.container div.output_area.stderr {
3+
display: none;
4+
visibility: hidden;
5+
}
6+
7+
/* Increase the width of the content area (default 800px) */
8+
div.wy-nav-content {
9+
max-width: 1000px;
10+
}
11+
12+
/* Show a `$` sign before bash code-blocks */
13+
div.highlight-bash pre::before {
14+
content: "$ ";
15+
}
16+
17+
/* Reduce margin from left sidebar titles */
18+
p.caption {
19+
margin-top: 0.25em !important;
20+
}
21+
22+
/* Reduce padding from left sidebar items */
23+
a.reference.internal {
24+
padding-top: 0;
25+
}
26+
27+
.wy-table-responsive table td,
28+
.wy-table-responsive table th {
29+
white-space: normal;
30+
}
31+
32+
.wy-table-responsive {
33+
margin-bottom: 24px;
34+
max-width: 100%;
35+
overflow: visible;
36+
}
37+
38+
.wy-table-responsive th p {
39+
margin-bottom: unset;
40+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{{ name | escape | underline}}
2+
3+
.. List the submodules
4+
5+
{% block modules %}
6+
{% if modules %}
7+
.. rubric:: Modules
8+
9+
.. autosummary::
10+
:toctree:
11+
:recursive:
12+
{% for item in modules %}
13+
{% if '.plugins.' not in item or item == 'modelopt.torch.opt.plugins.huggingface' %}
14+
{{ item }}
15+
{% endif %}
16+
{%- endfor %}
17+
{% endif %}
18+
{% endblock %}
19+
20+
.. Autodoc anything defined in the module itself
21+
22+
TODO: WE DON'T USE THIS OPTION RIGHT NOW BUT WE CAN REACTIVATE IF WANTED
23+
We use :ignore-module-all: so sphinx does not document the same module twice, even if it is reimported
24+
For reimports that should be documented somewhere other than where they are defined, the re-imports
25+
__module__ should be manually overridden -- i.e. in the ``__init__.py`` which contains ``from xxx import YYY``,
26+
add in ``YYY.__module__ = __name__``.
27+
28+
.. automodule:: {{ fullname }}
29+
:members:
30+
:undoc-members:
31+
32+
.. Also show members without docstrings. Only members from __all__ are considered as per conf.py
33+
.. Ideally we should add docstrings for these members.
34+
35+
36+
.. Overview table of available classes in the module
37+
{% block classes %}
38+
{% if classes %}
39+
.. rubric:: Classes
40+
41+
.. autosummary::
42+
:nosignatures:
43+
{% for item in classes %}
44+
{{ item }}
45+
{%- endfor %}
46+
{% endif %}
47+
{% endblock %}
48+
49+
50+
.. Overview table of available functions in the module
51+
{% block functions %}
52+
{% if functions %}
53+
.. rubric:: Functions
54+
55+
.. autosummary::
56+
:nosignatures:
57+
{% for item in functions %}
58+
{{ item }}
59+
{%- endfor %}
60+
{% endif %}
61+
{% endblock %}

0 commit comments

Comments
 (0)