]>
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, | |
57 | 'vcs_pageview_mode': '', | |
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 | ||
7c673cae FG |
115 | extensions = [ |
116 | 'sphinx.ext.autodoc', | |
117 | 'sphinx.ext.graphviz', | |
f67539c2 | 118 | 'sphinx.ext.mathjax', |
7c673cae | 119 | 'sphinx.ext.todo', |
f91f0fd5 | 120 | 'sphinx-prompt', |
f67539c2 | 121 | 'sphinx_autodoc_typehints', |
f91f0fd5 | 122 | 'sphinx_substitution_extensions', |
7c673cae | 123 | 'breathe', |
f67539c2 | 124 | 'ceph_commands', |
11fdf7f2 | 125 | 'ceph_releases', |
20effc67 TL |
126 | 'ceph_confval', |
127 | 'sphinxcontrib.openapi', | |
128 | 'sphinxcontrib.seqdiag', | |
7c673cae | 129 | ] |
f91f0fd5 TL |
130 | |
131 | ditaa = shutil.which("ditaa") | |
132 | if ditaa is not None: | |
20effc67 TL |
133 | # in case we don't have binfmt_misc enabled or jar is not registered |
134 | ditaa_args = ['-jar', ditaa] | |
135 | ditaa = 'java' | |
f91f0fd5 TL |
136 | extensions += ['sphinxcontrib.ditaa'] |
137 | else: | |
138 | extensions += ['plantweb.directive'] | |
139 | plantweb_defaults = { | |
140 | 'engine': 'ditaa' | |
141 | } | |
142 | ||
f91f0fd5 TL |
143 | if build_with_rtd: |
144 | extensions += ['sphinx_search.extension'] | |
145 | ||
f67539c2 | 146 | # sphinx.ext.todo options |
7c673cae FG |
147 | todo_include_todos = True |
148 | ||
f67539c2 TL |
149 | # sphinx_substitution_extensions options |
150 | rst_prolog = f""" | |
151 | .. |stable-release| replace:: {latest_stable_release()} | |
f91f0fd5 TL |
152 | """ |
153 | ||
f67539c2 | 154 | # breath options |
7c673cae FG |
155 | breathe_default_project = "Ceph" |
156 | # see $(top_srcdir)/Doxyfile | |
157 | ||
158 | breathe_build_directory = os.path.join(top_level, "build-doc") | |
159 | breathe_projects = {"Ceph": os.path.join(top_level, breathe_build_directory)} | |
160 | breathe_projects_source = { | |
161 | "Ceph": (os.path.join(top_level, "src/include/rados"), | |
162 | ["rados_types.h", "librados.h"]) | |
163 | } | |
f67539c2 TL |
164 | breathe_domain_by_extension = {'py': 'py', |
165 | 'c': 'c', 'h': 'c', | |
166 | 'cc': 'cxx', 'hpp': 'cxx'} | |
167 | breathe_doxygen_config_options = { | |
168 | 'EXPAND_ONLY_PREDEF': 'YES', | |
169 | 'MACRO_EXPANSION': 'YES', | |
1d09f67e TL |
170 | 'PREDEFINED': 'CEPH_RADOS_API= ', |
171 | 'WARN_IF_UNDOCUMENTED': 'NO', | |
f67539c2 | 172 | } |
f64942e4 | 173 | |
f67539c2 TL |
174 | # graphviz options |
175 | graphviz_output_format = 'svg' | |
176 | ||
177 | def generate_state_diagram(input_paths, output_path): | |
178 | sys.path.append(os.path.join(top_level, 'doc', 'scripts')) | |
179 | from gen_state_diagram import do_filter, StateMachineRenderer | |
180 | inputs = [os.path.join(top_level, fn) for fn in input_paths] | |
181 | output = os.path.join(top_level, output_path) | |
182 | ||
183 | def process(app): | |
184 | with fileinput.input(files=inputs) as f: | |
185 | input = do_filter(f) | |
186 | render = StateMachineRenderer() | |
187 | render.read_input(input) | |
188 | with open(output, 'w') as dot_output: | |
189 | render.emit_dot(dot_output) | |
190 | ||
191 | return process | |
192 | ||
11fdf7f2 TL |
193 | |
194 | # mocking ceph_module offered by ceph-mgr. `ceph_module` is required by | |
195 | # mgr.mgr_module | |
196 | class Dummy(object): | |
197 | def __getattr__(self, _): | |
198 | return lambda *args, **kwargs: None | |
199 | ||
f67539c2 | 200 | |
11fdf7f2 TL |
201 | class Mock(object): |
202 | __all__ = [] | |
f67539c2 | 203 | |
11fdf7f2 TL |
204 | def __init__(self, *args, **kwargs): |
205 | pass | |
206 | ||
207 | def __call__(self, *args, **kwargs): | |
208 | return Mock() | |
209 | ||
210 | @classmethod | |
211 | def __getattr__(cls, name): | |
212 | mock = type(name, (Dummy,), {}) | |
213 | mock.__module__ = __name__ | |
214 | return mock | |
215 | ||
f67539c2 TL |
216 | |
217 | # autodoc options | |
11fdf7f2 TL |
218 | sys.modules['ceph_module'] = Mock() |
219 | ||
f91f0fd5 | 220 | if build_with_rtd: |
f67539c2 | 221 | autodoc_mock_imports = ['ceph'] |
f91f0fd5 TL |
222 | pybinds = ['pybind/mgr', |
223 | 'python-common'] | |
224 | else: | |
225 | pybinds = ['pybind', | |
226 | 'pybind/mgr', | |
227 | 'python-common'] | |
228 | ||
229 | for c in pybinds: | |
230 | pybind = os.path.join(top_level, 'src', c) | |
11fdf7f2 TL |
231 | if pybind not in sys.path: |
232 | sys.path.insert(0, pybind) | |
f67539c2 | 233 | |
20effc67 TL |
234 | # openapi |
235 | openapi_logger = sphinx.util.logging.getLogger('sphinxcontrib.openapi.openapi30') | |
236 | openapi_logger.setLevel(logging.WARNING) | |
237 | ||
238 | # seqdiag | |
239 | seqdiag_antialias = True | |
240 | seqdiag_html_image_format = 'SVG' | |
241 | ||
242 | # ceph_confval | |
243 | ceph_confval_imports = glob.glob(os.path.join(top_level, | |
244 | 'src/common/options', | |
245 | '*.yaml.in')) | |
246 | ceph_confval_mgr_module_path = 'src/pybind/mgr' | |
247 | ceph_confval_mgr_python_path = 'src/pybind' | |
f67539c2 TL |
248 | |
249 | # handles edit-on-github and old version warning display | |
250 | def setup(app): | |
f67539c2 TL |
251 | if ditaa is None: |
252 | # add "ditaa" as an alias of "diagram" | |
253 | from plantweb.directive import DiagramDirective | |
254 | app.add_directive('ditaa', DiagramDirective) | |
255 | app.connect('builder-inited', | |
256 | generate_state_diagram(['src/osd/PeeringState.h', | |
257 | 'src/osd/PeeringState.cc'], | |
258 | 'doc/dev/peering_graph.generated.dot')) |