def write_all_rst_pages(): ''' 负责写画廊,细节和索引 rst 页面这项主要任务。 ''' infos = get_infos(screenshots_dir) s = make_gallery_page(infos) write_file(gallery_filename, s) for info in infos: s = make_detail_page(info) detail_name = slash(generation_dir, 'gen__{}.rst'.format(info['dunder'])) write_file(detail_name, s) s = make_index(infos) index_name = slash(generation_dir, 'index.rst') write_file(index_name, s) Logger.info('gallery.py: Created gallery rst documentation pages.')
def iter_filename_info(dir_name): """ Yield info (dict) of each matching screenshot found walking the directory dir_name. A matching screenshot uses double underscores to separate fields, i.e., path__to__filename__py.png as the screenshot for examples/path/to/filename.py. Files not ending with .png are ignored, others are either parsed or yield an error. Info fields 'dunder', 'dir', 'file', 'ext', 'source' if not 'error' """ pattern = re.compile(r'^((.+)__(.+)__([^-]+))\.png') for t in os.walk(dir_name): for filename in t[2]: if filename.endswith('.png'): m = pattern.match(filename) if m is None: yield {'error': 'png filename not following screenshot' ' pattern: {}'.format(filename)} else: d = m.group(2).replace('__', os.path.sep) yield {'dunder': m.group(1), 'dir': d, 'file': m.group(3), 'ext': m.group(4), 'source': slash(d, m.group(3) + '.' + m.group(4)) }
def write_all_rst_pages(): ''' Do the main task of writing the gallery, detail, and index rst pages ''' infos = get_infos(screenshots_dir) s = make_gallery_page(infos) write_file(gallery_filename, s) for info in infos: s = make_detail_page(info) detail_name = slash(generation_dir, 'gen__{}.rst'.format(info['dunder'])) write_file(detail_name, s) s = make_index(infos) index_name = slash(generation_dir, 'index.rst') write_file(index_name, s) Logger.info('gallery.py: Created gallery rst documentation pages.')
def iter_filename_info(dir_name): """ Yield info (dict) of each matching screenshot found walking the directory dir_name. A matching screenshot uses double underscores to separate fields, i.e. path__to__filename__py.png as the screenshot for examples/path/to/filename.py. Files not ending with .png are ignored, others are either parsed or yield an error. Info fields 'dunder', 'dir', 'file', 'ext', 'source' if not 'error' """ pattern = re.compile(r'^((.+)__(.+)__([^-]+))\.png') for t in os.walk(dir_name): for filename in t[2]: if filename.endswith('.png'): m = pattern.match(filename) if m is None: yield { 'error': 'png filename not following screenshot' ' pattern: {}'.format(filename) } else: d = m.group(2).replace('__', sep) yield { 'dunder': m.group(1), 'dir': d, 'file': m.group(3), 'ext': m.group(4), 'source': slash(d, m.group(3) + '.' + m.group(4)) }
def iter_filename_info(dir_name): """ 产生每个匹配截图的信息 (字典) ,通过遍历目录 dir_name 找到的截图。一张匹配的截图使用2个下划线 来分隔区域,例如, path__to__filename__py.png 就是 examples/path/to/filename.py 的一张截图。 没有用 .png 结尾的文件名都会被忽略,其它类型的图片格式经过语义分析后 抛出一个错误。 如果没有 'error' 错误的话,信息区域是 'dunder', 'dir', 'file', 'ext', 'source' """ pattern = re.compile(r'^((.+)__(.+)__([^-]+))\.png') for t in os.walk(dir_name): for filename in t[2]: if filename.endswith('.png'): m = pattern.match(filename) if m is None: yield { 'error': 'png filename not following screenshot' ' pattern: {}'.format(filename) } else: d = m.group(2).replace('__', sep) yield { 'dunder': m.group(1), 'dir': d, 'file': m.group(3), 'ext': m.group(4), 'source': slash(d, m.group(3) + '.' + m.group(4)) }
def iter_filename_info(dir_name): """ Yield info (dict) of each matching screenshot found walking the directory dir_name. A matching screenshot uses double underscores to separate fields, i.e. path__to__filename__py.png as the screenshot for examples/path/to/filename.py. Files not ending with .png are ignored, others are either parsed or yield an error. Info fields 'dunder', 'dir', 'file', 'ext', 'source' if not 'error' """ pattern = re.compile(r"^((.+)__(.+)__([^-]+))\.png") for t in os.walk(dir_name): for filename in t[2]: if filename.endswith(".png"): m = pattern.match(filename) if m is None: yield {"error": "png filename not following screenshot" " pattern: {}".format(filename)} else: d = m.group(2).replace("__", sep) yield { "dunder": m.group(1), "dir": d, "file": m.group(3), "ext": m.group(4), "source": slash(d, m.group(3) + "." + m.group(4)), }
def iter_docstring_info(dir_name): ''' Iterate over screenshots in directory, yield info from the file name and initial parse of the docstring. Errors are logged, but files with errors are skipped. ''' for file_info in iter_filename_info(dir_name): if 'error' in file_info: Logger.error(file_info['error']) continue source = slash(examples_dir, file_info['dir'], file_info['file'] + '.' + file_info['ext']) if not os.path.exists(source): Logger.error( 'Screen shot references source code that does ' 'not exist: %s', source) continue with open(source) as f: text = f.read() docstring_info = parse_docstring_info(text) if 'error' in docstring_info: Logger.error(docstring_info['error'] + ' File: ' + source) continue # don't want to show ugly entries else: file_info.update(docstring_info) yield file_info
def make_detail_page(info): ''' return str of the rst text for the detail page of the file in info. ''' def a(s=''): ''' append formatted s to output, which will be joined into lines ''' output.append(s.format(**info)) output = [] a('{title}') a('=' * len(info['title'])) a('\n.. |pic{num}| image:: /images/examples/{dunder}.png' '\n :width: 50%' '\n :align: middle') a('\n|pic{num}|') a() for paragraph in info['enhanced_description']: for line in paragraph: a(line) a() # include images last_lang = '.py' for fname in info['files']: full_name = slash(info['dir'], fname) ext = re.search(r'\.\w+$', fname).group(0) a('\n.. _`' + full_name.replace(sep, '_') + '`:') # double separator if building on windows (sphinx skips backslash) if '\\' in full_name: full_name = full_name.replace(sep, sep*2) if ext in ['.png', '.jpg', '.jpeg']: title = 'Image **' + full_name + '**' a('\n' + title) a('~' * len(title)) a('\n.. image:: ../../../examples/' + full_name) a(' :align: center') else: # code title = 'File **' + full_name + '**' a('\n' + title) a('~' * len(title)) if ext != last_lang and ext != '.txt': a('\n.. highlight:: ' + ext[1:]) a(' :linenothreshold: 3') last_lang = ext # prevent highlight errors with 'none' elif ext == '.txt': a('\n.. highlight:: none') a(' :linenothreshold: 3') last_lang = ext a('\n.. include:: ../../../examples/' + full_name) a(' :code:') return '\n'.join(output) + '\n'
def make_detail_page(info): ''' 返回信息中文件详细页面的 rst 文本字符串。 ''' def a(s=''): ''' 以追加方式把格式化过的 s 内容增加到输出结果里 ''' output.append(s.format(**info)) output = [] a('{title}') a('=' * len(info['title'])) a('\n.. |pic{num}| image:: /images/examples/{dunder}.png' '\n :width: 50%' '\n :align: middle') a('\n|pic{num}|') a() for paragraph in info['enhanced_description']: for line in paragraph: a(line) a() # 包括图片 last_lang = '.py' for fname in info['files']: full_name = slash(info['dir'], fname) ext = re.search(r'\.\w+$', fname).group(0) a('\n.. _`' + full_name.replace(sep, '_') + '`:') # 如果在 Windows 操作系统上建立的话 (sphinx 跳过反斜杠) ,使用2个分隔符 if '\\' in full_name: full_name = full_name.replace(sep, sep * 2) if ext in ['.png', '.jpg', '.jpeg']: title = 'Image **' + full_name + '**' a('\n' + title) a('~' * len(title)) a('\n.. image:: ../../../examples/' + full_name) a(' :align: center') else: # code title = 'File **' + full_name + '**' a('\n' + title) a('~' * len(title)) if ext != last_lang and ext != '.txt': a('\n.. highlight:: ' + ext[1:]) a(' :linenothreshold: 3') last_lang = ext # 防止使用 'none' 时出现高亮错误 elif ext == '.txt': a('\n.. highlight:: none') a(' :linenothreshold: 3') last_lang = ext a('\n.. include:: ../../../examples/' + full_name) a(' :code:') return '\n'.join(output) + '\n'
def make_detail_page(info): """ return str of the rst text for the detail page of the file in info. """ def a(s=""): """ append formatted s to output, which will be joined into lines """ output.append(s.format(**info)) output = [] a("{title}") a("=" * len(info["title"])) a("\n.. |pic{num}| image:: /images/examples/{dunder}.png" "\n :width: 50%" "\n :align: middle") a("\n|pic{num}|") a() for paragraph in info["enhanced_description"]: for line in paragraph: a(line) a() # include images last_lang = ".py" for fname in info["files"]: full_name = slash(info["dir"], fname) ext = re.search(r"\.\w+$", fname).group(0) a("\n.. _`" + full_name.replace(sep, "_") + "`:") # double separator if building on windows (sphinx skips backslash) if "\\" in full_name: full_name = full_name.replace(sep, sep * 2) if ext in [".png", ".jpg", ".jpeg"]: title = "Image **" + full_name + "**" a("\n" + title) a("~" * len(title)) a("\n.. image:: ../../../examples/" + full_name) a(" :align: center") else: # code title = "File **" + full_name + "**" a("\n" + title) a("~" * len(title)) if ext != last_lang and ext != ".txt": a("\n.. highlight:: " + ext[1:]) a(" :linenothreshold: 3") last_lang = ext # prevent highlight errors with 'none' elif ext == ".txt": a("\n.. highlight:: none") a(" :linenothreshold: 3") last_lang = ext a("\n.. include:: ../../../examples/" + full_name) a(" :code:") return "\n".join(output) + "\n"
def iter_docstring_info(dir_name): """ Iterate over screenshots in directory, yield info from the file name and initial parse of the docstring. Errors are logged, but files with errors are skipped. """ for file_info in iter_filename_info(dir_name): if "error" in file_info: Logger.error(file_info["error"]) continue source = slash(examples_dir, file_info["dir"], file_info["file"] + "." + file_info["ext"]) if not os.path.exists(source): Logger.error("Screen shot references source code that does " "not exist: %s", source) continue with open(source) as f: text = f.read() docstring_info = parse_docstring_info(text) if "error" in docstring_info: Logger.error(docstring_info["error"] + " File: " + source) continue # don't want to show ugly entries else: file_info.update(docstring_info) yield file_info
def iter_docstring_info(dir_name): ''' 迭代目录中的截图,从文件名生成信息,并且初始化文档字符串语义分析。 错误都会被记录下来,但会跳过含有错误的文件。 ''' for file_info in iter_filename_info(dir_name): if 'error' in file_info: Logger.error(file_info['error']) continue source = slash(examples_dir, file_info['dir'], file_info['file'] + '.' + file_info['ext']) if not os.path.exists(source): Logger.error( 'Screen shot references source code that does ' 'not exist: %s', source) continue with open(source) as f: text = f.read() docstring_info = parse_docstring_info(text) if 'error' in docstring_info: Logger.error(docstring_info['error'] + ' File: ' + source) continue # don't want to show ugly entries else: file_info.update(docstring_info) yield file_info
def iter_docstring_info(dir_name): ''' Iterate over screenshots in directory, yield info from the file name and initial parse of the docstring. Errors are logged, but files with errors are skipped. ''' for file_info in iter_filename_info(dir_name): if 'error' in file_info: Logger.error(file_info['error']) continue source = slash(examples_dir, file_info['dir'], file_info['file'] + '.' + file_info['ext']) if not os.path.exists(source): Logger.error('Screen shot references source code that does ' 'not exist: %s', source) continue with open(source) as f: text = f.read() docstring_info = parse_docstring_info(text) if 'error' in docstring_info: Logger.error(docstring_info['error'] + ' File: ' + source) continue # don't want to show ugly entries else: file_info.update(docstring_info) yield file_info
(currently doc/sources/images/examples) along with source code and files in the examples/ directory to create rst files in the generation_dir (doc/sources/examples) gallery.rst, index.rst, and gen__*.rst """ import os import re from os.path import sep from os.path import join as slash # just like that name better from kivy.logger import Logger import textwrap base_dir = ".." # from here to the kivy top examples_dir = slash(base_dir, "examples") screenshots_dir = slash(base_dir, "doc/sources/images/examples") generation_dir = slash(base_dir, "doc/sources/examples") image_dir = "../images/examples/" # relative to generation_dir gallery_filename = slash(generation_dir, "gallery.rst") # Info is a dict built up from # straight filename information, more from reading the docstring, # and more from parsing the description text. Errors are often # shown by setting the key 'error' with the value being the error message. # # It doesn't quite meet the requirements for a class, but is a vocabulary # word in this module.
(doc/sources/examples) gallery.rst, index.rst, and gen__*.rst ''' import os import re from os.path import sep from os.path import join as slash # just like that name better from os.path import dirname, abspath import kivy from kivy.logger import Logger import textwrap # from here to the kivy top base_dir = dirname(dirname(abspath(kivy.__file__))) examples_dir = slash(base_dir, 'examples') screenshots_dir = slash(base_dir, 'doc/sources/images/examples') generation_dir = slash(base_dir, 'doc/sources/examples') image_dir = "../images/examples/" # relative to generation_dir gallery_filename = slash(generation_dir, 'gallery.rst') # Info is a dict built up from # straight filename information, more from reading the docstring, # and more from parsing the description text. Errors are often # shown by setting the key 'error' with the value being the error message. # # It doesn't quite meet the requirements for a class, but is a vocabulary # word in this module.
This uses screenshots in the screenshots_dir (currently doc/sources/images/examples) along with source code and files in the examples/ directory to create rst files in the generation_dir (doc/sources/examples) gallery.rst, index.rst, and gen__*.rst ''' import os import re from os.path import join as slash # just like that name better from kivy.logger import Logger import textwrap base_dir = '..' # from here to the kivy top examples_dir = slash(base_dir, 'examples') screenshots_dir = slash(base_dir, 'doc/sources/images/examples') generation_dir = slash(base_dir, 'doc/sources/examples') image_dir = "../images/examples/" # relative to generation_dir gallery_filename = slash(generation_dir, 'gallery.rst') # Info is a dict built up from # straight filename information, more from reading the docstring, # and more from parsing the description text. Errors are often # shown by setting the key 'error' with the value being the error message. # # It doesn't quite meet the requirements for a class, but is a vocabulary # word in this module.