]>
Commit | Line | Data |
---|---|---|
f67539c2 | 1 | import fileinput |
20effc67 TL |
2 | import glob |
3 | import logging | |
f67539c2 | 4 | import os |
f91f0fd5 | 5 | import shutil |
7c673cae | 6 | import sys |
f67539c2 | 7 | import yaml |
20effc67 | 8 | import sphinx.util |
f67539c2 TL |
9 | |
10 | ||
11 | top_level = \ | |
12 | os.path.dirname( | |
13 | os.path.dirname( | |
14 | os.path.abspath(__file__))) | |
15 | ||
20effc67 TL |
16 | pybind_rgw_mod = __import__('rgw', globals(), locals(), [], 0) |
17 | sys.modules['pybind_rgw_mod'] = pybind_rgw_mod | |
18 | ||
f67539c2 TL |
19 | |
20 | def parse_ceph_release(): | |
21 | with open(os.path.join(top_level, 'src/ceph_release')) as f: | |
22 | lines = f.readlines() | |
23 | assert(len(lines) == 3) | |
24 | # 16, pacific, dev | |
25 | version, codename, status = [line.strip() for line in lines] | |
26 | return version, codename, status | |
27 | ||
28 | ||
29 | def latest_stable_release(): | |
30 | with open(os.path.join(top_level, 'doc/releases/releases.yml')) as input: | |
31 | releases = yaml.safe_load(input)['releases'] | |
32 | # get the first release | |
33 | return next(iter(releases.keys())) | |
34 | ||
35 | ||
36 | def is_release_eol(codename): | |
37 | with open(os.path.join(top_level, 'doc/releases/releases.yml')) as input: | |
38 | releases = yaml.safe_load(input)['releases'] | |
39 | return 'actual_eol' in releases.get(codename, {}) | |
40 | ||
41 | ||
42 | # project information | |
43 | project = 'Ceph' | |
44 | copyright = ('2016, Ceph authors and contributors. ' | |
45 | 'Licensed under Creative Commons Attribution Share Alike 3.0 ' | |
46 | '(CC-BY-SA-3.0)') | |
47 | version, codename, release = parse_ceph_release() | |
48 | pygments_style = 'sphinx' | |
49 | ||
50 | # HTML output options | |
51 | html_theme = 'ceph' | |
20effc67 TL |
52 | html_theme_options = { |
53 | 'logo_only': True, | |
54 | 'display_version': False, | |
55 | 'prev_next_buttons_location': 'bottom', | |
56 | 'style_external_links': False, | |
1e59de90 | 57 | 'vcs_pageview_mode': 'edit', |
20effc67 TL |
58 | 'style_nav_header_background': '#eee', |
59 | # Toc options | |
60 | 'collapse_navigation': True, | |
61 | 'sticky_navigation': True, | |
62 | 'navigation_depth': 4, | |
63 | 'includehidden': True, | |
64 | 'titles_only': False | |
65 | } | |
f67539c2 TL |
66 | html_theme_path = ['_themes'] |
67 | html_title = "Ceph Documentation" | |
68 | html_logo = 'logo.png' | |
69 | html_context = {'is_release_eol': is_release_eol(codename)} | |
70 | html_favicon = 'favicon.ico' | |
71 | html_show_sphinx = False | |
72 | html_static_path = ["_static"] | |
73 | html_sidebars = { | |
74 | '**': ['smarttoc.html', 'searchbox.html'] | |
75 | } | |
76 | ||
77 | html_css_files = ['css/custom.css'] | |
7c673cae | 78 | |
f67539c2 | 79 | # general configuration |
7c673cae FG |
80 | templates_path = ['_templates'] |
81 | source_suffix = '.rst' | |
f67539c2 TL |
82 | exclude_patterns = ['**/.#*', |
83 | '**/*~', | |
84 | 'start/quick-common.rst', | |
85 | '**/*.inc.rst'] | |
86 | if tags.has('man'): # noqa: F821 | |
11fdf7f2 | 87 | master_doc = 'man_index' |
f67539c2 TL |
88 | exclude_patterns += ['index.rst', |
89 | 'architecture.rst', | |
90 | 'glossary.rst', | |
91 | 'release*.rst', | |
7c673cae | 92 | 'api/*', |
9f95a23c | 93 | 'cephadm/*', |
7c673cae FG |
94 | 'cephfs/*', |
95 | 'dev/*', | |
11fdf7f2 | 96 | 'governance.rst', |
9f95a23c | 97 | 'foundation.rst', |
7c673cae FG |
98 | 'install/*', |
99 | 'mon/*', | |
100 | 'rados/*', | |
b5b8bbf5 FG |
101 | 'mgr/*', |
102 | 'ceph-volume/*', | |
7c673cae FG |
103 | 'radosgw/*', |
104 | 'rbd/*', | |
11fdf7f2 TL |
105 | 'start/*', |
106 | 'releases/*'] | |
107 | else: | |
f67539c2 | 108 | master_doc = 'index' |
11fdf7f2 | 109 | exclude_patterns += ['man_index.rst'] |
7c673cae | 110 | |
f67539c2 | 111 | build_with_rtd = os.environ.get('READTHEDOCS') == 'True' |
7c673cae | 112 | |
f64942e4 AA |
113 | sys.path.insert(0, os.path.abspath('_ext')) |
114 | ||
1e59de90 TL |
115 | smartquotes_action = "qe" |
116 | ||
7c673cae FG |
117 | extensions = [ |
118 | 'sphinx.ext.autodoc', | |
119 | 'sphinx.ext.graphviz', | |
f67539c2 | 120 | 'sphinx.ext.mathjax', |
7c673cae | 121 | 'sphinx.ext.todo', |
f91f0fd5 | 122 | 'sphinx-prompt', |
f67539c2 | 123 | 'sphinx_autodoc_typehints', |
f91f0fd5 | 124 | 'sphinx_substitution_extensions', |
7c673cae | 125 | 'breathe', |
f67539c2 | 126 | 'ceph_commands', |
11fdf7f2 | 127 | 'ceph_releases', |
20effc67 | 128 | 'ceph_confval', |
1e59de90 | 129 | 'sphinxcontrib.mermaid', |
20effc67 TL |
130 | 'sphinxcontrib.openapi', |
131 | 'sphinxcontrib.seqdiag', | |
7c673cae | 132 | ] |
f91f0fd5 TL |
133 | |
134 | ditaa = shutil.which("ditaa") | |
135 | if ditaa is not None: | |
20effc67 TL |
136 | # in case we don't have binfmt_misc enabled or jar is not registered |
137 | ditaa_args = ['-jar', ditaa] | |
138 | ditaa = 'java' | |
f91f0fd5 TL |
139 | extensions += ['sphinxcontrib.ditaa'] |
140 | else: | |
141 | extensions += ['plantweb.directive'] | |
142 | plantweb_defaults = { | |
143 | 'engine': 'ditaa' | |
144 | } | |
145 | ||
f91f0fd5 TL |
146 | if build_with_rtd: |
147 | extensions += ['sphinx_search.extension'] | |
148 | ||
f67539c2 | 149 | # sphinx.ext.todo options |
7c673cae FG |
150 | todo_include_todos = True |
151 | ||
f67539c2 TL |
152 | # sphinx_substitution_extensions options |
153 | rst_prolog = f""" | |
154 | .. |stable-release| replace:: {latest_stable_release()} | |
f91f0fd5 TL |
155 | """ |
156 | ||
f67539c2 | 157 | # breath options |
7c673cae FG |
158 | breathe_default_project = "Ceph" |
159 | # see $(top_srcdir)/Doxyfile | |
160 | ||
161 | breathe_build_directory = os.path.join(top_level, "build-doc") | |
162 | breathe_projects = {"Ceph": os.path.join(top_level, breathe_build_directory)} | |
163 | breathe_projects_source = { | |
164 | "Ceph": (os.path.join(top_level, "src/include/rados"), | |
165 | ["rados_types.h", "librados.h"]) | |
166 | } | |
f67539c2 TL |
167 | breathe_domain_by_extension = {'py': 'py', |
168 | 'c': 'c', 'h': 'c', | |
169 | 'cc': 'cxx', 'hpp': 'cxx'} | |
170 | breathe_doxygen_config_options = { | |
171 | 'EXPAND_ONLY_PREDEF': 'YES', | |
172 | 'MACRO_EXPANSION': 'YES', | |
1d09f67e TL |
173 | 'PREDEFINED': 'CEPH_RADOS_API= ', |
174 | 'WARN_IF_UNDOCUMENTED': 'NO', | |
f67539c2 | 175 | } |
f64942e4 | 176 | |
f67539c2 TL |
177 | # graphviz options |
178 | graphviz_output_format = 'svg' | |
179 | ||
180 | def generate_state_diagram(input_paths, output_path): | |
181 | sys.path.append(os.path.join(top_level, 'doc', 'scripts')) | |
182 | from gen_state_diagram import do_filter, StateMachineRenderer | |
183 | inputs = [os.path.join(top_level, fn) for fn in input_paths] | |
184 | output = os.path.join(top_level, output_path) | |
185 | ||
186 | def process(app): | |
187 | with fileinput.input(files=inputs) as f: | |
188 | input = do_filter(f) | |
189 | render = StateMachineRenderer() | |
190 | render.read_input(input) | |
191 | with open(output, 'w') as dot_output: | |
192 | render.emit_dot(dot_output) | |
193 | ||
194 | return process | |
195 | ||
11fdf7f2 TL |
196 | |
197 | # mocking ceph_module offered by ceph-mgr. `ceph_module` is required by | |
198 | # mgr.mgr_module | |
199 | class Dummy(object): | |
200 | def __getattr__(self, _): | |
201 | return lambda *args, **kwargs: None | |
202 | ||
f67539c2 | 203 | |
11fdf7f2 TL |
204 | class Mock(object): |
205 | __all__ = [] | |
f67539c2 | 206 | |
11fdf7f2 TL |
207 | def __init__(self, *args, **kwargs): |
208 | pass | |
209 | ||
210 | def __call__(self, *args, **kwargs): | |
211 | return Mock() | |
212 | ||
213 | @classmethod | |
214 | def __getattr__(cls, name): | |
215 | mock = type(name, (Dummy,), {}) | |
216 | mock.__module__ = __name__ | |
217 | return mock | |
218 | ||
f67539c2 TL |
219 | |
220 | # autodoc options | |
11fdf7f2 TL |
221 | sys.modules['ceph_module'] = Mock() |
222 | ||
f91f0fd5 | 223 | if build_with_rtd: |
f67539c2 | 224 | autodoc_mock_imports = ['ceph'] |
f91f0fd5 TL |
225 | pybinds = ['pybind/mgr', |
226 | 'python-common'] | |
227 | else: | |
228 | pybinds = ['pybind', | |
229 | 'pybind/mgr', | |
230 | 'python-common'] | |
231 | ||
232 | for c in pybinds: | |
233 | pybind = os.path.join(top_level, 'src', c) | |
11fdf7f2 TL |
234 | if pybind not in sys.path: |
235 | sys.path.insert(0, pybind) | |
f67539c2 | 236 | |
20effc67 TL |
237 | # openapi |
238 | openapi_logger = sphinx.util.logging.getLogger('sphinxcontrib.openapi.openapi30') | |
239 | openapi_logger.setLevel(logging.WARNING) | |
240 | ||
241 | # seqdiag | |
242 | seqdiag_antialias = True | |
243 | seqdiag_html_image_format = 'SVG' | |
244 | ||
245 | # ceph_confval | |
246 | ceph_confval_imports = glob.glob(os.path.join(top_level, | |
247 | 'src/common/options', | |
248 | '*.yaml.in')) | |
249 | ceph_confval_mgr_module_path = 'src/pybind/mgr' | |
250 | ceph_confval_mgr_python_path = 'src/pybind' | |
f67539c2 TL |
251 | |
252 | # handles edit-on-github and old version warning display | |
253 | def setup(app): | |
f67539c2 TL |
254 | if ditaa is None: |
255 | # add "ditaa" as an alias of "diagram" | |
256 | from plantweb.directive import DiagramDirective | |
257 | app.add_directive('ditaa', DiagramDirective) | |
258 | app.connect('builder-inited', | |
259 | generate_state_diagram(['src/osd/PeeringState.h', | |
260 | 'src/osd/PeeringState.cc'], | |
261 | 'doc/dev/peering_graph.generated.dot')) |