def run(self): env = self.state.document.settings.env baseurl = env.config.rss_baseurl assert baseurl, 'rss_baseurl must be defined in your config.py' source = self.state_machine.input_lines.source( self.lineno - self.state_machine.input_offset - 1) rss_doc = utils.new_document('<rss>', self.state.document.settings) Parser().parse('\n'.join(self.content), rss_doc) path = os.path.relpath(source, env.srcdir) suffixes = env.config.source_suffix # retain backwards compatibility with sphinx < 1.3 if isinstance(suffixes, basestring): suffixes = [suffixes] for suffix in suffixes: if path.endswith(suffix): path = '%s.html' % path[:-len(suffix)] break builder = env.app.builder docwriter = HTMLWriter(self) docsettings = OptionParser( defaults=env.settings, components=(docwriter, )).get_default_values() docsettings.compact_lists = bool(env.config.html_compact_lists) dest = os.path.join(env.app.outdir, os_path(env.docname) + '.rss') pageurl = '%s/%s' % (baseurl, path) with open(dest, 'w') as rss: title = self.options.get('title', '') description = self.options.get('description', None) rss.write('<?xml version="1.0" encoding="ISO-8859-1" ?>\n') rss.write('<rss version="2.0">\n') rss.write('<channel>\n') rss.write('<title>%s</title>\n' % cgi.escape(title)) rss.write('<link>%s</link>\n' % pageurl) if description: rss.write('<description>%s</description>\n' % cgi.escape(description)) for child in rss_doc.children: if not isinstance(child, nodes.section): continue title_index = child.first_child_matching_class(nodes.title) if title_index is None: continue node = nodes.paragraph() node.extend(child.children[title_index + 1:]) sec_doc = utils.new_document('<rss-section>', docsettings) sec_doc.append(node) visitor = RssTranslator(builder, sec_doc) sec_doc.walkabout(visitor) title = child.children[title_index].astext() sectionurl = '%s#%s' % (pageurl, child.get('ids')[0]) description = ''.join(visitor.body) rss.write('<item>\n') rss.write('<title>%s</title>\n' % cgi.escape(title)) rss.write('<link>%s</link>\n' % sectionurl) rss.write('<description><![CDATA[%s]]></description>\n' % description) rss.write('</item>\n') rss.write('</channel>\n') rss.write('</rss>\n') return []
# typedoc src/js/*.ts --tsconfig src/js/tsconfig.json --json docs/sphinx_pyodide/tests/ # gzip docs/sphinx_pyodide/tests/ # rm src/js/pyproxy.gen.ts with gzip.open(test_directory / "tsdoc_dump.json.gz") as fh: jsdoc_json = json.load(fh) settings_json = json.loads((test_directory / "app_settings.json").read_text()) from sphinx_pyodide.jsdoc import ( PyodideAnalyzer, flatten_suffix_tree, get_jsdoc_content_directive, get_jsdoc_summary_directive, ) inner_analyzer = TsAnalyzer(jsdoc_json, "/home/hood/pyodide/src") settings = OptionParser().get_default_values() settings.update(settings_json, OptionParser()) document = new_document("", settings) pyodide_analyzer = PyodideAnalyzer(inner_analyzer) def test_flatten_suffix_tree(): t = SuffixTree() d = { ("a", "b", "c"): 1, ("a", "b", "d"): 2, ("a", "d", "d"): 3, ("a", "x", "y"): 4, ("b", "x", "c"): 5, ("b", "x", "d"): 6,
def make_document(source_path="notset") -> nodes.document: """Create a new docutils document.""" settings = OptionParser(components=(RSTParser, )).get_default_values() return new_document(source_path, settings=settings)
def mock_document(tmp_path) -> nodes.document: settings = OptionParser(components=(RSTParser, )).get_default_values() document = new_document("notset", settings=settings) document.settings.env = MockEnv(tmp_path) with sphinx_domains(document.settings.env): yield document
__docformat__ = 'reStructuredText' import sys from package import parse_package_or_module import transform from docutils.writers.html4css1 import Writer from docutils.frontend import OptionParser usage = '%prog [options] [<package-directory> | <python-file> [html-file]]' description = ('Generates .html documentation for the given Python package' ' or module.') writer = Writer() option_parser = OptionParser(components=[writer], usage=usage, description=description) settings = option_parser.parse_args(sys.argv[1:]) source_path = settings._source target_path = settings._destination nodes = parse_package_or_module(source_path) # That then needs converting to a docutils tree document = transform.make_document(nodes, settings) # And *that* wants converting to the appropriate output format try: target = open(target_path, "w")
def __init__(self, app, need, layout, node, style=None, fromdocname=None): self.app = app self.need = need self.layout_name = layout available_layouts = app.config.needs_layouts if self.layout_name not in available_layouts.keys(): raise SphinxNeedLayoutException( 'Given layout "{}" is unknown for need {}. Registered layouts are: {}' .format(self.layout_name, need['id'], ' ,'.join(available_layouts.keys()))) self.layout = available_layouts[self.layout_name] self.node = node # Used, if need is referenced from another page if fromdocname is None: self.fromdocname = need['docname'] else: self.fromdocname = fromdocname classes = [ "need", 'needs_grid_' + self.layout['grid'], 'needs_layout_' + self.layout_name ] self.style = style or self.need['style'] or getattr( self.app.config, 'needs_default_style', None) if self.style: for style in self.style.strip().split(','): style = style.strip() classes.append('needs_style_' + style) else: classes.append('needs_style_none') classes.append('needs_type_' + ''.join(self.need['type'].split())) self.node_table = nodes.table(classes=classes, ids=[self.need['id']]) self.node_tbody = nodes.tbody() self.grids = { 'simple': { 'func': self._grid_simple, 'configs': { 'colwidths': [100], 'side_left': False, 'side_right': False, 'footer': False } }, 'simple_side_left': { 'func': self._grid_simple, 'configs': { 'colwidths': [30, 70], 'side_left': 'full', 'side_right': False, 'footer': False } }, 'simple_side_right': { 'func': self._grid_simple, 'configs': { 'colwidths': [70, 30], 'side_left': False, 'side_right': 'full', 'footer': False } }, 'simple_side_left_partial': { 'func': self._grid_simple, 'configs': { 'colwidths': [20, 80], 'side_left': 'part', 'side_right': False, 'footer': False } }, 'simple_side_right_partial': { 'func': self._grid_simple, 'configs': { 'colwidths': [80, 20], 'side_left': False, 'side_right': 'part', 'footer': False } }, 'complex': self._grid_complex, 'content': { 'func': self._grid_content, 'configs': { 'colwidths': [100], 'side_left': False, 'side_right': False, 'footer': False } }, 'content_footer': { 'func': self._grid_content, 'configs': { 'colwidths': [100], 'side_left': False, 'side_right': False, 'footer': True } }, 'content_side_left': { 'func': self._grid_content, 'configs': { 'colwidths': [5, 95], 'side_left': True, 'side_right': False, 'footer': False } }, 'content_side_right': { 'func': self._grid_content, 'configs': { 'colwidths': [95, 5], 'side_left': False, 'side_right': True, 'footer': False } }, 'content_footer_side_left': { 'func': self._grid_content, 'configs': { 'colwidths': [5, 95], 'side_left': True, 'side_right': False, 'footer': True } }, 'content_footer_side_right': { 'func': self._grid_content, 'configs': { 'colwidths': [95, 5], 'side_left': False, 'side_right': True, 'footer': True } }, } # Dummy Document setup self.doc_settings = OptionParser( components=(Parser, )).get_default_values() self.dummy_doc = new_document("dummy", self.doc_settings) self.doc_language = languages.get_language( self.dummy_doc.settings.language_code) self.doc_memo = Struct(document=self.dummy_doc, reporter=self.dummy_doc.reporter, language=self.doc_language, title_styles=[], section_level=0, section_bubble_up_kludge=False, inliner=None) self.functions = { 'meta': self.meta, 'meta_all': self.meta_all, 'meta_links': self.meta_links, 'meta_links_all': self.meta_links_all, 'meta_id': self.meta_id, 'image': self.image, 'link': self.link, 'collapse_button': self.collapse_button }
def convert_function_info(function_name, doc_string, defaults=[]): """ Given a documentation string, writes html documentation. First tries to identify the standard docstring format for has_units objects. If sucessful, outputs a nicely formatted html. Otherwise, converts to html with no other changes. Code borrowed from numerical_modelling's has_unit.py """ system = platform.system() stripped_lines = [line.strip() for line in doc_string.splitlines()] # XXX: hack to avoid expensive formatting. Remove later. if len(stripped_lines) > 100: return pre_formatted_html(doc_string) try: # Parse the lines using docutil parser to get a document-tree settings = OptionParser(components=(Parser, )).get_default_values() document = new_document("Docstring", settings) Parser().parse("\n".join(stripped_lines), document) # Filter out children of the root of the document-tree which are tagged # as "sections". Usually section has "title" and "paragraph" as # children. The inputs and outputs we are looking for are in the # "paragraph" section of the "section". sections = [ child for child in document.children if child.tagname.lower() == "section" ] # Inputs are in the section with title "Parameters" and outputs are in # the section with title "Returns". inputtext = [ section.children[1].children[0].data for section in sections if 'parameters' in section['names'] ] outputtext = [ section.children[1].children[0].data for section in sections if 'returns' in section['names'] ] # If things aren't looking right at this point, the docstring isn't # properly formatted, so we're done. if len(sections) == 0 or len(inputtext) == 0 or len(outputtext) == 0: html = _html_header() # For some reason, the font size is huge when the native wx widgt is # used. Reduce its size: if system is not 'Windows' and wx.VERSION[1] < 8: html += '<font size="-2">\n' html += convert_string_fragment(doc_string) if system is not 'Windows' and wx.VERSION[1] < 8: html += '</font>\n' html += "</body>\n</html>" # Continue building the 'proper' html else: # Data in a paragraph comprises of variables in separate lines. # However each line for a variable is a combination of multiple lines, # and we are interested in retrieving only the first line for each # variable (in both inputs and outputs). Hence we join the separated # lines and then split all of them inputlines = "\n".join(inputtext).splitlines() outputlines = "\n".join(outputtext).splitlines() # Split into lines which give description and line which give # variable data with units inputdesc = [ line for line in inputlines if not " :" in line and _count_indent(line) == 0 ] outputdesc = [ line for line in outputlines if not " :" in line and _count_indent(line) == 0 ] inputlines = [ line.split(" :") for line in inputlines if " :" in line or _count_indent(line) > 0 ] outputlines = [ line.split(" :") for line in outputlines if " :" in line or _count_indent(line) > 0 ] # Create first line, listing function parameters and return vals. html = _html_header() if system is not 'Windows' and wx.VERSION[1] < 8: html += '<font size="-2">\n' html += "<p>" check_returns = False for i, var in enumerate(outputlines): check_returns = True html += var[0] if i < len(outputlines) - 1: html += ", " else: html += " " if check_returns: html += "=" html += " <b>" + function_name + "</b>(" for i, var in enumerate(inputlines): html += var[0] if len(defaults) is not 0: index = len(defaults) - len(inputlines) + i if index >= 0: html += "=" + str(defaults[index]) if i < len(inputlines) - 1: html += ", " html += ")\n" # Add a brief description. Should be the first line of docstring. html += "<br>" + stripped_lines[0] + "</p>\n" # Add a list of inputs html += "<p><u>Inputs</u>\n<table>" for var, desc in map(None, inputlines, inputdesc): # fixme: Failing for "marine_environment" function. html += "\n<tr><td></td><td><b>" + var[0] + "</b>" # The format for the units section is ' units=x', so we slice # off the first seven characters. fixme: support for spacing # between equal sign, despite the incorrectness of this syntax. if (len(var) == 3) and (var[2][7:] != 'dimensionless'): html += " [" + var[2][7:] + "]" if desc is None: html += "</td>" else: html += ":</td><td>" + desc + "</td>" html += "</tr>" html += "\n</table></p>" # Add a list of ouputs html += "\n<p><u>Outputs</u>\n<table>" for var, desc in map(None, outputlines, outputdesc): html += "\n<tr><td>" if var is not None: html += "</td><td><b>" + var[0] + "</b>" if (len(var) == 3) and (var[2][7:] != 'dimensionless'): html += " [" + var[2][7:] + "]" if desc is None: html += "</td>" else: html += ":</td><td>" + desc + "</td>" html += "</tr>" html += "\n</table></p>" # Give a more detailed description, if available # Get the description text directly from the string. The parser will not # produce useful output for a description with blank lines in the section # (these are required for certain reST structures) try: desc_html = convert_string_fragment(doc_string) if system is 'Windows': desc_html = desc_html.replace( '<p>', '<p style="margin: 0px; padding:0px">') startSearch = 'ion</a></h5>' start = desc_html.rindex(startSearch) end = desc_html.rindex(r'</div>', start) html += '\n<p style="margin: 0px; padding:0px">' html += '<u>Description</u></p>\n<table><tr><td></td><td>' if system is not 'Windows' and wx.VERSION[1] < 8: html += '<font size="-2">' html += desc_html[start + len(startSearch):end] if system is not 'Windows' and wx.VERSION[1] < 8: html += '</font>' html += "\n</td></tr></table>\n" except ValueError: pass if system is not 'Windows' and wx.VERSION[1] < 8: html += '</font>\n' html += "</body>\n</html>" except Exception, e: logger.warning('Could not parse docstring; %s: %s' % (e.__class__.__name__, e)) html = pre_formatted_html(doc_string)
# --Get the long description from the README file # with open(path.join(here, 'README.md'), encoding='utf-8') as f: # LONG_DESCRIPTION = f.read() try: import pypandoc print('converting readme to RST') LONG_DESCRIPTION = pypandoc.convert(path.join(here, 'README.md'), 'rst').replace('\r', '') # Validate that the generated doc is correct print('validating generated rst readme') from docutils.parsers.rst import Parser from docutils.utils import new_document from docutils.frontend import OptionParser # import pygments settings = OptionParser(components=(Parser, )).get_default_values() document = new_document('(generated) DESCRIPTION.rst', settings=settings) from distutils.command.check import SilentReporter reporter = SilentReporter( '(generated) DESCRIPTION.rst', settings.report_level, settings.halt_level, stream=settings.warning_stream, debug=settings.debug, encoding=settings.error_encoding, error_handler=settings.error_encoding_error_handler) document.reporter = reporter parser = Parser() parser.parse(LONG_DESCRIPTION, document) from warnings import warn
def rst_document(rst_string: str) -> document: default_settings = OptionParser(components=(Parser, )).get_default_values() document = new_document(rst_string, default_settings) parser = Parser() parser.parse(rst_string, document) return document
references.DanglingReferences, misc.Transitions, ] HTML_TRANSFORMS = DEFAULT_TRANSFORMS + [ universal.Messages, universal.FilterMessages, universal.StripClassesAndElements, writer_aux.Admonitions, ] OPTION_PARSER = OptionParser((Parser, Reader)) HTML_OPTION_PARSER = OptionParser((Parser, Reader, HTMLWriter)) LATEX_OPTION_PARSER = OptionParser((Parser, Reader, LaTexWriter)) HTML_SETUP = ('html', HTMLTranslator, HTML_TRANSFORMS, HTML_OPTION_PARSER) LATEX_SETUP = ('tex', LaTeXTranslator, DEFAULT_TRANSFORMS, LATEX_OPTION_PARSER) RAW_SETUP = (None, None, DEFAULT_TRANSFORMS, OPTION_PARSER) # ------------------------------------------------------------------------------ # some pre-kompiled regular expressions # ------------------------------------------------------------------------------ replace_toc_attributes = re.compile( '(?sm)<p class="topic-title(.*?)"><a name="(.*?)">(.*?)</a></p>(.*?)</div>' ).sub
def write(self, *ignored): if self.config.man_pages: # build manpages from config.man_pages as usual ManualPageBuilder.write(self, *ignored) logger.info(bold("scan master tree for kernel-doc man-pages ... ") + darkgreen("{"), nonl=True) master_tree = self.env.get_doctree(self.config.master_doc) master_tree = inline_all_toctrees(self, set(), self.config.master_doc, master_tree, darkgreen, [self.config.master_doc]) logger.info(darkgreen("}")) man_nodes = master_tree.traverse(condition=self.is_manpage) if not man_nodes and not self.config.man_pages: logger.warn( 'no "man_pages" config value nor manual section found; no manual pages ' 'will be written') return logger.info(bold('START writing man pages ... '), nonl=True) for man_parent in man_nodes: doc_tree = self.get_partial_document(man_parent) Section2Manpage(doc_tree).apply() if not doc_tree.man_info["authors"] and self.config.author: doc_tree.man_info["authors"].append(self.config.author) doc_writer = ManualPageWriter(self) doc_settings = OptionParser( defaults=self.env.settings, components=(doc_writer, ), read_config_files=True, ).get_default_values() doc_settings.__dict__.update(doc_tree.man_info) doc_tree.settings = doc_settings targetname = '%s.%s' % (doc_tree.man_info.title, doc_tree.man_info.section) if doc_tree.man_info.decl_type in [ "struct", "enum", "union", "typedef" ]: targetname = "%s_%s" % (doc_tree.man_info.decl_type, targetname) destination = FileOutput(destination_path=path.join( self.outdir, targetname), encoding='utf-8') logger.info(darkgreen(targetname) + " ", nonl=True) self.env.resolve_references(doc_tree, doc_tree.man_info.manpage, self) # remove pending_xref nodes for pendingnode in doc_tree.traverse(addnodes.pending_xref): pendingnode.replace_self(pendingnode.children) doc_writer.write(doc_tree, destination) logger.info("END writing man pages.")
def prepare_writing(self, _doc_names: set[str]) -> None: self.docwriter = HTMLWriter(self) _opt_parser = OptionParser([self.docwriter], defaults=self.env.settings, read_config_files=True) self.docsettings = _opt_parser.get_default_values()
def __init__(self, app, need, layout, node, style=None, fromdocname=None): self.app = app self.need = need self.layout_name = layout available_layouts = app.config.needs_layouts if self.layout_name not in available_layouts.keys(): raise SphinxNeedLayoutException( 'Given layout "{}" is unknown for need {}. Registered layouts are: {}' .format(self.layout_name, need["id"], " ,".join(available_layouts.keys()))) self.layout = available_layouts[self.layout_name] self.node = node # Used, if need is referenced from another page if fromdocname is None: self.fromdocname = need["docname"] else: self.fromdocname = fromdocname # For ReadTheDocs Theme we need to add 'rtd-exclude-wy-table'. classes = [ "need", "needs_grid_" + self.layout["grid"], "needs_layout_" + self.layout_name ] classes.extend(app.config.needs_table_classes) self.style = style or self.need["style"] or getattr( self.app.config, "needs_default_style", None) if self.style: for style in self.style.strip().split(","): style = style.strip() classes.append("needs_style_" + style) else: classes.append("needs_style_none") classes.append("needs_type_" + "".join(self.need["type"].split())) self.node_table = nodes.table(classes=classes, ids=[self.need["id"]]) self.node_tbody = nodes.tbody() self.grids = { "simple": { "func": self._grid_simple, "configs": { "colwidths": [100], "side_left": False, "side_right": False, "footer": False }, }, "simple_side_left": { "func": self._grid_simple, "configs": { "colwidths": [30, 70], "side_left": "full", "side_right": False, "footer": False }, }, "simple_side_right": { "func": self._grid_simple, "configs": { "colwidths": [70, 30], "side_left": False, "side_right": "full", "footer": False }, }, "simple_side_left_partial": { "func": self._grid_simple, "configs": { "colwidths": [20, 80], "side_left": "part", "side_right": False, "footer": False }, }, "simple_side_right_partial": { "func": self._grid_simple, "configs": { "colwidths": [80, 20], "side_left": False, "side_right": "part", "footer": False }, }, "complex": self._grid_complex, "content": { "func": self._grid_content, "configs": { "colwidths": [100], "side_left": False, "side_right": False, "footer": False }, }, "content_footer": { "func": self._grid_content, "configs": { "colwidths": [100], "side_left": False, "side_right": False, "footer": True }, }, "content_side_left": { "func": self._grid_content, "configs": { "colwidths": [5, 95], "side_left": True, "side_right": False, "footer": False }, }, "content_side_right": { "func": self._grid_content, "configs": { "colwidths": [95, 5], "side_left": False, "side_right": True, "footer": False }, }, "content_footer_side_left": { "func": self._grid_content, "configs": { "colwidths": [5, 95], "side_left": True, "side_right": False, "footer": True }, }, "content_footer_side_right": { "func": self._grid_content, "configs": { "colwidths": [95, 5], "side_left": False, "side_right": True, "footer": True }, }, } # Dummy Document setup self.doc_settings = OptionParser( components=(Parser, )).get_default_values() self.dummy_doc = new_document("dummy", self.doc_settings) self.doc_language = languages.get_language( self.dummy_doc.settings.language_code) self.doc_memo = Struct( document=self.dummy_doc, reporter=self.dummy_doc.reporter, language=self.doc_language, title_styles=[], section_level=0, section_bubble_up_kludge=False, inliner=None, ) self.functions = { "meta": self.meta, "meta_all": self.meta_all, "meta_links": self.meta_links, "meta_links_all": self.meta_links_all, "meta_id": self.meta_id, "image": self.image, "link": self.link, "collapse_button": self.collapse_button, } # Prepare string_links dict, so that regex and templates get not recompiled too often. # # Do not set needs_string_links here and update it. # This would lead to deepcopy()-errors, as needs_string_links gets some "pickled" and jinja Environment is # too complex for this. self.string_links = {} for link_name, link_conf in app.config.needs_string_links.items(): self.string_links[link_name] = { "url_template": Environment(loader=BaseLoader).from_string( link_conf["link_url"]), "name_template": Environment(loader=BaseLoader).from_string( link_conf["link_name"]), "regex_compiled": re.compile(link_conf["regex"]), "options": link_conf["options"], "name": link_name, }
def prepare_writing(self, docnames: Set[str]) -> None: # create the search indexer self.indexer = None if self.search: from sphinx.search import IndexBuilder lang = self.config.html_search_language or self.config.language if not lang: lang = 'en' self.indexer = IndexBuilder(self.env, lang, self.config.html_search_options, self.config.html_search_scorer) self.load_indexer(docnames) self.docwriter = HTMLWriter(self) self.docsettings = OptionParser( defaults=self.env.settings, components=(self.docwriter,), read_config_files=True).get_default_values() # type: Any self.docsettings.compact_lists = bool(self.config.html_compact_lists) # determine the additional indices to include self.domain_indices = [] # html_domain_indices can be False/True or a list of index names indices_config = self.config.html_domain_indices if indices_config: for domain_name in sorted(self.env.domains): domain = None # type: Domain domain = self.env.domains[domain_name] for indexcls in domain.indices: indexname = '%s-%s' % (domain.name, indexcls.name) if isinstance(indices_config, list): if indexname not in indices_config: continue content, collapse = indexcls(domain).generate() if content: self.domain_indices.append( (indexname, indexcls, content, collapse)) # format the "last updated on" string, only once is enough since it # typically doesn't include the time of day lufmt = self.config.html_last_updated_fmt if lufmt is not None: self.last_updated = format_date(lufmt or _('%b %d, %Y'), language=self.config.language) else: self.last_updated = None logo = self.config.html_logo and \ path.basename(self.config.html_logo) or '' favicon = self.config.html_favicon and \ path.basename(self.config.html_favicon) or '' if not isinstance(self.config.html_use_opensearch, str): logger.warning(__('html_use_opensearch config value must now be a string')) self.relations = self.env.collect_relations() rellinks = [] # type: List[Tuple[str, str, str, str]] if self.use_index: rellinks.append(('genindex', _('General Index'), 'I', _('index'))) for indexname, indexcls, content, collapse in self.domain_indices: # if it has a short name if indexcls.shortname: rellinks.append((indexname, indexcls.localname, '', indexcls.shortname)) if self.config.html_style is not None: stylename = self.config.html_style elif self.theme: stylename = self.theme.get_config('theme', 'stylesheet') else: stylename = 'default.css' self.globalcontext = { 'embedded': self.embedded, 'project': self.config.project, 'release': return_codes_re.sub('', self.config.release), 'version': self.config.version, 'last_updated': self.last_updated, 'copyright': self.config.copyright, 'master_doc': self.config.master_doc, 'use_opensearch': self.config.html_use_opensearch, 'docstitle': self.config.html_title, 'shorttitle': self.config.html_short_title, 'show_copyright': self.config.html_show_copyright, 'show_sphinx': self.config.html_show_sphinx, 'has_source': self.config.html_copy_source, 'show_source': self.config.html_show_sourcelink, 'sourcelink_suffix': self.config.html_sourcelink_suffix, 'file_suffix': self.out_suffix, 'script_files': self.script_files, 'language': self.config.language, 'css_files': self.css_files, 'sphinx_version': __display_version__, 'style': stylename, 'rellinks': rellinks, 'builder': self.name, 'parents': [], 'logo': logo, 'favicon': favicon, 'html5_doctype': html5_ready and not self.config.html4_writer } if self.theme: self.globalcontext.update( ('theme_' + key, val) for (key, val) in self.theme.get_options(self.theme_options).items()) self.globalcontext.update(self.config.html_context)
def prepare_writing(self, docnames): from sphinx.search import IndexBuilder self.indexer = IndexBuilder(self.env) self.load_indexer(docnames) self.docwriter = HTMLWriter(self) self.docsettings = OptionParser( defaults=self.env.settings, components=(self.docwriter, )).get_default_values() # format the "last updated on" string, only once is enough since it # typically doesn't include the time of day lufmt = self.config.html_last_updated_fmt if lufmt is not None: self.last_updated = ustrftime(lufmt or _('%b %d, %Y')) else: self.last_updated = None logo = self.config.html_logo and \ path.basename(self.config.html_logo) or '' favicon = self.config.html_favicon and \ path.basename(self.config.html_favicon) or '' if favicon and os.path.splitext(favicon)[1] != '.ico': self.warn('html_favicon is not an .ico file') if not isinstance(self.config.html_use_opensearch, basestring): self.warn('html_use_opensearch config value must now be a string') self.relations = self.env.collect_relations() rellinks = [] if self.config.html_use_index: rellinks.append(('genindex', _('General Index'), 'I', _('index'))) if self.config.html_use_modindex and self.env.modules: rellinks.append( ('modindex', _('Global Module Index'), 'M', _('modules'))) if self.config.html_style is not None: stylename = self.config.html_style elif self.theme: stylename = self.theme.get_confstr('theme', 'stylesheet') else: stylename = 'default.css' self.globalcontext = dict( embedded=self.embedded, project=self.config.project, release=self.config.release, version=self.config.version, last_updated=self.last_updated, copyright=self.config.copyright, master_doc=self.config.master_doc, use_opensearch=self.config.html_use_opensearch, docstitle=self.config.html_title, shorttitle=self.config.html_short_title, show_copyright=self.config.html_show_copyright, show_sphinx=self.config.html_show_sphinx, has_source=self.config.html_copy_source, show_source=self.config.html_show_sourcelink, file_suffix=self.out_suffix, script_files=self.script_files, css_files=self.css_files, sphinx_version=__version__, style=stylename, rellinks=rellinks, builder=self.name, parents=[], logo=logo, favicon=favicon, ) if self.theme: self.globalcontext.update( ('theme_' + key, val) for (key, val) in self.theme.get_options( self.config.html_theme_options).iteritems()) self.globalcontext.update(self.config.html_context)
def prepare_writing(self, docnames): # create the search indexer self.indexer = None if self.search: from sphinx.search import IndexBuilder, languages lang = self.config.html_search_language or self.config.language if not lang or lang not in languages: lang = 'en' self.indexer = IndexBuilder(self.env, lang, self.config.html_search_options, self.config.html_search_scorer) self.load_indexer(docnames) self.docwriter = HTMLWriter(self) self.docsettings = OptionParser( defaults=self.env.settings, components=(self.docwriter, ), read_config_files=True).get_default_values() self.docsettings.compact_lists = bool(self.config.html_compact_lists) # determine the additional indices to include self.domain_indices = [] # html_domain_indices can be False/True or a list of index names indices_config = self.config.html_domain_indices if indices_config: for domain_name in sorted(self.env.domains): domain = self.env.domains[domain_name] for indexcls in domain.indices: indexname = '%s-%s' % (domain.name, indexcls.name) if isinstance(indices_config, list): if indexname not in indices_config: continue # deprecated config value if indexname == 'py-modindex' and \ not self.config.html_use_modindex: continue content, collapse = indexcls(domain).generate() if content: self.domain_indices.append( (indexname, indexcls, content, collapse)) # format the "last updated on" string, only once is enough since it # typically doesn't include the time of day lufmt = self.config.html_last_updated_fmt if lufmt is not None: self.last_updated = format_date(lufmt or _('MMM dd, YYYY'), language=self.config.language) else: self.last_updated = None logo = self.config.html_logo and \ path.basename(self.config.html_logo) or '' favicon = self.config.html_favicon and \ path.basename(self.config.html_favicon) or '' if favicon and os.path.splitext(favicon)[1] != '.ico': self.warn('html_favicon is not an .ico file') if not isinstance(self.config.html_use_opensearch, string_types): self.warn('html_use_opensearch config value must now be a string') self.relations = self.env.collect_relations() rellinks = [] if self.get_builder_config('use_index', 'html'): rellinks.append(('genindex', _('General Index'), 'I', _('index'))) for indexname, indexcls, content, collapse in self.domain_indices: # if it has a short name if indexcls.shortname: rellinks.append( (indexname, indexcls.localname, '', indexcls.shortname)) if self.config.html_style is not None: stylename = self.config.html_style elif self.theme: stylename = self.theme.get_confstr('theme', 'stylesheet') else: stylename = 'default.css' self.globalcontext = dict( embedded=self.embedded, project=self.config.project, release=self.config.release, version=self.config.version, last_updated=self.last_updated, copyright=self.config.copyright, master_doc=self.config.master_doc, use_opensearch=self.config.html_use_opensearch, docstitle=self.config.html_title, shorttitle=self.config.html_short_title, show_copyright=self.config.html_show_copyright, show_sphinx=self.config.html_show_sphinx, has_source=self.config.html_copy_source, show_source=self.config.html_show_sourcelink, file_suffix=self.out_suffix, script_files=self.script_files, language=self.config.language, css_files=self.css_files, sphinx_version=__display_version__, style=stylename, rellinks=rellinks, builder=self.name, parents=[], logo=logo, favicon=favicon, ) if self.theme: self.globalcontext.update(('theme_' + key, val) for ( key, val) in iteritems(self.theme.get_options(self.theme_options))) self.globalcontext.update(self.config.html_context)
def parse(self, content): settings = OptionParser(components=(Parser, Writer)) \ .get_default_values() doc = new_document('doc', settings) parser = Parser() parser.parse(content, doc) stories = [] for node in doc: if isinstance(node, docutils.nodes.section): # Каждая секция - это история if isinstance(node[0], docutils.nodes.title): story_title = node.pop(0).astext() else: warnings.warn('Найдена история без заголовка: %r' % node) continue tasks = [] points = None if isinstance(node[-1], docutils.nodes.bullet_list): # Задачи расположены в списке в конце истории tasklist = node.pop() for line in tasklist: line = line.astext() # Оценка задачи указывается в круглых скобках в самом # конце, слово "дней" опционально. match = re.search(ur'^.+\((\d+)[^\)]{0,5}\)$', line, re.UNICODE | re.DOTALL) if match: points = int(match.group(1)) line = re.sub(ur'^(.+?)\(\d+[^\)]{0,5}\)$', r'\1', line) else: points = 0 # Ответственный указывается перед задачей и отделяется # двоеточием. match = re.search(ur'^\+?([\w]+):\s*(.+)$', line, re.UNICODE | re.DOTALL) if match: person = match.group(1) task_title = match.group(2) state = Task.WORK else: task_title = line person = None state = Task.NEW if line.startswith('+'): state = Task.DONE task = Task(task_title, state, person=person, points=points) tasks.append(task) # Все остальное в истории - ее описание. writer = Writer() pseudo_doc = new_document(story_title, settings) pseudo_doc.children = [node] writer.document = pseudo_doc writer.translate() description = ''.join(writer.body) stories.append(Story(story_title, description, tasks)) return stories