Source code for docfly.doctree

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Create doc tree if you follows
:ref:`Sanhe Sphinx standard <sanhe_sphinx_doc_project_style_guide>`.
"""

from __future__ import print_function
import warnings
from pathlib_mate import PathCls as Path

try:
    from .util import make_dir, make_file
    from .template import TC
    from .pkg import textfile
except:  # pragma: no cover
    from docfly.util import make_dir, make_file
    from docfly.template import TC
    from docfly.pkg import textfile


[docs]class ArticleFolder(object): """ Represent an ``index.rst`` file with Title sitting in a directory. :param dir_path: A folder contains single rst file. The rst file path will be ``{dir_path}/{_filename}``. :param title: The title line above '==========' **中文文档** 一篇 Article 代表着一个位于文件夹内的 ``index.rst`` 文件. 其中必然有至少一个标题元素. """ _filename = "index.rst" def __init__(self, dir_path=None): self.dir_path = dir_path self._title = None @property def rst_path(self): """ The actual rst file absolute path. """ return Path(self.dir_path, self._filename).abspath @property def rel_path(self): """ File relative path from the folder. """ return "{}/{}".format(Path(self.dir_path).basename, self._filename) @property def title(self): """ Title for the first header. """ if self._title is None: self._title = self.get_title() return self._title
[docs] def get_title(self): """ Get title line from .rst file. **中文文档** 从一个 ``_filename`` 所指定的 .rst 文件中, 找到顶级标题. 也就是第一个 ``====`` 或 ``----`` 或 ``~~~~`` 上面一行. """ header_bar_char_list = "=-~+*#^" cursor_previous_line = None for cursor_line in textfile.readlines(self.rst_path, strip="both"): for header_bar_char in header_bar_char_list: if cursor_line.startswith(header_bar_char): flag_full_bar_char = cursor_line == header_bar_char * len(cursor_line) flag_line_length_greather_than_1 = len(cursor_line) >= 1 flag_previous_line_not_empty = bool(cursor_previous_line) if flag_full_bar_char \ and flag_line_length_greather_than_1 \ and flag_previous_line_not_empty: return cursor_previous_line.strip() cursor_previous_line = cursor_line msg = "Warning, this document doesn't have any %s header!" % header_bar_char_list return None
@property def sub_article_folders(self): """ Returns all valid ArticleFolder sitting inside of :attr:`ArticleFolder.dir_path`. """ l = list() for p in Path.sort_by_fname( Path(self.dir_path).select_dir(recursive=False) ): af = ArticleFolder(dir_path=p.abspath) try: if af.title is not None: l.append(af) except: pass return l
[docs] def toc_directive(self, maxdepth=1): """ Generate toctree directive text. :param table_of_content_header: :param header_bar_char: :param header_line_length: :param maxdepth: :return: """ articles_directive_content = TC.toc.render( maxdepth=maxdepth, article_list=self.sub_article_folders, ) return articles_directive_content
def __repr__(self): return "Article(title=%r)" % (self.title,)
[docs]class DocTree(object): """ This class is designed for taking a rst file, and find all ``.. articles::`` directives, then automatically generate ``.. toctree::`` directive. The file structure has to follow :ref:`Sanhe Sphinx standard <sanhe_sphinx_doc_project_style_guide>`. .. deprecated:: 0. message """
[docs] @classmethod def fly(cls, conf_path, docname, source, maxdepth=1): # pragma: no cover """ Generate toctree directive for rst file. :param conf_path: conf.py file absolute path :param docname: the rst file relpath from conf.py directory. :param source: rst content. :param maxdepth: int, max toc tree depth. """ msg = ("``.. articles::`` directive is going to be deprecated. " "use ``.. autodoctree`` instead.") warnings.warn(msg, FutureWarning) directive_pattern = ".. articles::" if directive_pattern not in source: return source af = ArticleFolder( dir_path=Path(Path(conf_path).parent, docname).parent.abspath) toc_directive = af.toc_directive(maxdepth) lines = list() for line in source.split("\n"): if directive_pattern in line.strip(): if line.strip().startswith(directive_pattern): line = line.replace(directive_pattern, toc_directive, 1) lines.append(line) continue lines.append(line) return "\n".join(lines)