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