# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import yaml from docutils import nodes from docutils.parsers.rst import Directive from docutils.parsers.rst import directives from sphinx.util import logging LOG = logging.getLogger(__name__) class navigator(nodes.General, nodes.Element): pass class service_group(nodes.General, nodes.Element): pass class container_item(nodes.General, nodes.Element): pass YAML_CACHE = {} class ServiceGroup(Directive): node_class = service_group option_spec = { 'class': directives.unchanged, 'data': directives.unchanged_required, 'category': directives.unchanged_required } has_content = False def _load_data(self, fpath): global YAML_CACHE if fpath in YAML_CACHE: return YAML_CACHE[fpath] data = {} try: with open(fpath, 'r') as stream: data = yaml.safe_load(stream) except IOError: LOG.warning( "Parameters file not found, %s", fpath, location=(self.state.document.settings.env.docname, None)) return except yaml.YAMLError as exc: LOG.exception( exc_info=exc, msg="Error while parsing file [%s]." % fpath) raise YAML_CACHE[fpath] = data return data def run(self): node = self.node_class() _, fpath = self.state.document.settings.env.relfn2path( self.options['data']) data = self._load_data(fpath) node['data'] = data['service_categories'][self.options['category']] node['class'] = self.options.get('class', 'navigator-container') return [node] class Navigator(Directive): node_class = navigator option_spec = { 'class': directives.unchanged, 'data': directives.unchanged_required, 'link_type': directives.unchanged } has_content = False def _load_data(self, fpath): global YAML_CACHE if fpath in YAML_CACHE: return YAML_CACHE[fpath] data = {} try: with open(fpath, 'r') as stream: data = yaml.safe_load(stream) except IOError: LOG.warning( "Parameters file not found, %s", fpath, location=(self.state.document.settings.env.docname, None)) return except yaml.YAMLError as exc: LOG.exception( exc_info=exc, msg="Error while parsing file [%s]." % fpath) raise YAML_CACHE[fpath] = data return data def run(self): node = self.node_class() _, fpath = self.state.document.settings.env.relfn2path( self.options['data']) self.data = self._load_data(fpath) node['data'] = self.data node['link_type'] = self.options['link_type'] node['class'] = self.options.get('class', 'navigator-container') return [node] class ContainerItem(Directive): node_class = container_item option_spec = { 'title': directives.unchanged } has_content = True def run(self): doctree_node = container_item() doctree_node['title'] = self.options['title'] services = [] for ent in self.content: _srv = ent.strip('- ') # Split on first ":" srv_parts = _srv.split(':', 1) key = srv_parts[0] data_parts = srv_parts[1].split("|") title = data_parts[0] href = data_parts[1] if len(data_parts) > 1 else key services.append( dict( key=key, title=title, href=href ) ) doctree_node['services'] = services return [doctree_node] def container_item_html(self, node): tmpl = """ """ node['data'] = ( "") self.body.append(tmpl % node) raise nodes.SkipNode def navigator_html(self, node): data = f'
' for k, v in node['data']['service_categories'].items(): data += ( f'' data += '
' self.body.append(data) raise nodes.SkipNode def service_group_html(self, node): data = f'
' for k, v in node['data']['services'].items(): img = k title = v["title"] data += '' # 1st column - title data += ( f'' ) # 3rd column - API-Ref link = v.get("api") data += ( f'' ) if link else ( f'' ) # 4th column - UMN link = v.get("umn") data += ( f'' ) if link else ( f'' ) # all other links for link in v.get("links", []): data += ( f'' ) # Row end data += '' data += "
' f'' f'
' f'{title}
' f'
' f'API Reference' f'' f'User Manual' f'' f'{link["title"]}' f'
" self.body.append(data) raise nodes.SkipNode def setup(app): app.add_node(container_item, html=(container_item_html, None)) app.add_node(navigator, html=(navigator_html, None)) app.add_node(service_group, html=(service_group_html, None)) app.add_directive("container_item", ContainerItem) app.add_directive("navigator", Navigator) app.add_directive("service_group", ServiceGroup) return { 'version': '0.1', 'parallel_read_safe': True, 'parallel_write_safe': True, }