def copy_asset_file(source, destination, context=None, renderer=None): """Copy an asset file to destination. On copying, it expands the template variables if context argument is given and the asset is a template file. :param source: The path to source file :param destination: The path to destination file or directory :param context: The template variables. If not given, template files are simply copied :param renderer: The template engine. If not given, SphinxRenderer is used by default """ if not os.path.exists(source): return if os.path.exists(destination) and os.path.isdir(destination): # Use source filename if destination points a directory destination = os.path.join(destination, os.path.basename(source)) if source.lower().endswith('_t') and context: if renderer is None: from sphinx.util.template import SphinxRenderer renderer = SphinxRenderer() with codecs.open(source, 'r', encoding='utf-8') as fsrc: with codecs.open(destination[:-2], 'w', encoding='utf-8') as fdst: fdst.write(renderer.render_string(fsrc.read(), context)) else: copyfile(source, destination)
def _copy_searchtools(self, renderer=None): """Copy and patch searchtools This uses the included Sphinx version's searchtools, but patches it to remove automatic initialization. This is a fork of ``sphinx.util.fileutil.copy_asset`` """ log.info(bold('copying searchtools... '), nonl=True) if sphinx.version_info < (1, 8): search_js_file = 'searchtools.js_t' else: search_js_file = 'searchtools.js' path_src = os.path.join( package_dir, 'themes', 'basic', 'static', search_js_file ) if os.path.exists(path_src): path_dest = os.path.join(self.outdir, '_static', 'searchtools.js') if renderer is None: # Sphinx 1.4 used the renderer from the existing builder, but # the pattern for Sphinx 1.5 is to pass in a renderer separate # from the builder. This supports both patterns for future # compatibility if sphinx.version_info < (1, 5): renderer = self.templates else: from sphinx.util.template import SphinxRenderer renderer = SphinxRenderer() with codecs.open(path_src, 'r', encoding='utf-8') as h_src: with codecs.open(path_dest, 'w', encoding='utf-8') as h_dest: data = h_src.read() data = self.REPLACEMENT_PATTERN.sub(self.REPLACEMENT_TEXT, data) h_dest.write(renderer.render_string( data, self.get_static_readthedocs_context() )) else: log.warning('Missing {}'.format(search_js_file)) log.info('done')
def copy_asset(source: str, destination: str, excluded: PathMatcher = lambda path: False, context: Dict = None, renderer: "BaseRenderer" = None, onerror: Callable[[str, Exception], None] = None) -> None: """Copy asset files to destination recursively. On copying, it expands the template variables if context argument is given and the asset is a template file. :param source: The path to source file or directory :param destination: The path to destination directory :param excluded: The matcher to determine the given path should be copied or not :param context: The template variables. If not given, template files are simply copied :param renderer: The template engine. If not given, SphinxRenderer is used by default :param onerror: The error handler. """ if not os.path.exists(source): return if renderer is None: from sphinx.util.template import SphinxRenderer renderer = SphinxRenderer() ensuredir(destination) if os.path.isfile(source): copy_asset_file(source, destination, context, renderer) return for root, dirs, files in os.walk(source, followlinks=True): reldir = relative_path(source, root) for dir in dirs[:]: if excluded(posixpath.join(reldir, dir)): dirs.remove(dir) else: ensuredir(posixpath.join(destination, reldir, dir)) for filename in files: if not excluded(posixpath.join(reldir, filename)): try: copy_asset_file(posixpath.join(root, filename), posixpath.join(destination, reldir), context, renderer) except Exception as exc: if onerror: onerror(posixpath.join(root, filename), exc) else: raise
def copy_asset(source, destination, excluded=lambda path: False, context=None, renderer=None): # type: (unicode, unicode, Union[Callable[[unicode], bool], Matcher], Dict, BaseRenderer) -> None # NOQA """Copy asset files to destination recursively. On copying, it expands the template variables if context argument is given and the asset is a template file. :param source: The path to source file or directory :param destination: The path to destination directory :param excluded: The matcher to determine the given path should be copied or not :param context: The template variables. If not given, template files are simply copied :param renderer: The template engine. If not given, SphinxRenderer is used by default """ if not os.path.exists(source): return if renderer is None: from sphinx.util.template import SphinxRenderer renderer = SphinxRenderer() ensuredir(destination) if os.path.isfile(source): copy_asset_file(source, destination, context, renderer) return for root, dirs, files in walk(source, followlinks=True): reldir = relative_path(source, root) for dir in dirs[:]: if excluded(posixpath.join(reldir, dir)): dirs.remove(dir) else: ensuredir(posixpath.join(destination, reldir, dir)) for filename in files: if not excluded(posixpath.join(reldir, filename)): copy_asset_file(posixpath.join(root, filename), posixpath.join(destination, reldir), context, renderer)
def render_file(filename, **kwargs): # type: (unicode, Any) -> unicode pathname = os.path.join(package_dir, 'templates', 'qthelp', filename) return SphinxRenderer.render_from_file(pathname, kwargs)
def render_file(filename: str, **kwargs: Any) -> str: pathname = path.join(package_dir, 'templates', filename) return SphinxRenderer.render_from_file(pathname, kwargs)
def render(self, name: str, context: Dict) -> str: template = SphinxRenderer(template_dir) return template.render(name, context)
def render(self, name, context): # type: (str, Dict) -> str template = SphinxRenderer(template_dir) return template.render(name, context)
def generate(d, overwrite=True, silent=False): """Generate project based on values in *d*.""" template = SphinxRenderer() texescape.init() indent = " " * 4 if "mastertoctree" not in d: d["mastertoctree"] = "" if "mastertocmaxdepth" not in d: d["mastertocmaxdepth"] = 2 d["PY3"] = PY3 d["project_fn"] = make_filename(d["project"]) d["project_url"] = urlquote(d["project"].encode("idna")) d["project_manpage"] = d["project_fn"].lower() d["now"] = time.asctime() d["project_underline"] = column_width(d["project"]) * "=" extensions = (",\n" + indent).join(repr("sphinx.ext." + name) for name in EXTENSIONS if d.get("ext_" + name)) if extensions: d["extensions"] = "\n" + indent + extensions + ",\n" else: d["extensions"] = extensions d["copyright"] = time.strftime("%Y") + ", " + d["author"] d["author_texescaped"] = text_type(d["author"]).translate(texescape.tex_escape_map) d["project_doc"] = d["project"] + " Documentation" d["project_doc_texescaped"] = text_type(d["project"] + " Documentation").translate(texescape.tex_escape_map) # escape backslashes and single quotes in strings that are put into # a Python string literal for key in ( "project", "project_doc", "project_doc_texescaped", "author", "author_texescaped", "copyright", "version", "release", "master", ): d[key + "_str"] = d[key].replace("\\", "\\\\").replace("'", "\\'") if not path.isdir(d["path"]): mkdir_p(d["path"]) srcdir = d["sep"] and path.join(d["path"], "source") or d["path"] mkdir_p(srcdir) if d["sep"]: builddir = path.join(d["path"], "build") d["exclude_patterns"] = "" else: builddir = path.join(srcdir, d["dot"] + "build") exclude_patterns = map(repr, [d["dot"] + "build", "Thumbs.db", ".DS_Store"]) d["exclude_patterns"] = ", ".join(exclude_patterns) mkdir_p(builddir) mkdir_p(path.join(srcdir, d["dot"] + "templates")) mkdir_p(path.join(srcdir, d["dot"] + "static")) def write_file(fpath, content, newline=None): if overwrite or not path.isfile(fpath): print("Creating file %s." % fpath) with open(fpath, "wt", encoding="utf-8", newline=newline) as f: f.write(content) else: print("File %s already exists, skipping." % fpath) with open(os.path.join(package_dir, "templates", "quickstart", "conf.py_t")) as f: conf_text = convert_python_source(f.read()) write_file(path.join(srcdir, "conf.py"), template.render_string(conf_text, d)) masterfile = path.join(srcdir, d["master"] + d["suffix"]) write_file(masterfile, template.render("quickstart/master_doc.rst_t", d)) if d.get("make_mode") is True: makefile_template = "quickstart/Makefile.new_t" batchfile_template = "quickstart/make.bat.new_t" else: makefile_template = "quickstart/Makefile_t" batchfile_template = "quickstart/make.bat_t" if d["makefile"] is True: d["rsrcdir"] = d["sep"] and "source" or "." d["rbuilddir"] = d["sep"] and "build" or d["dot"] + "build" # use binary mode, to avoid writing \r\n on Windows write_file(path.join(d["path"], "Makefile"), template.render(makefile_template, d), u"\n") if d["batchfile"] is True: d["rsrcdir"] = d["sep"] and "source" or "." d["rbuilddir"] = d["sep"] and "build" or d["dot"] + "build" write_file(path.join(d["path"], "make.bat"), template.render(batchfile_template, d), u"\r\n") if silent: return print() print(bold("Finished: An initial directory structure has been created.")) print( """ You should now populate your master file %s and create other documentation source files. """ % masterfile + ( (d["makefile"] or d["batchfile"]) and """\ Use the Makefile to build the docs, like so: make builder """ or """\ Use the sphinx-build command to build the docs, like so: sphinx-build -b builder %s %s """ % (srcdir, builddir) ) + """\ where "builder" is one of the supported builders, e.g. html, latex or linkcheck. """ )
def generate(d, overwrite=True, silent=False): """Generate project based on values in *d*.""" template = SphinxRenderer() texescape.init() indent = ' ' * 4 if 'mastertoctree' not in d: d['mastertoctree'] = '' if 'mastertocmaxdepth' not in d: d['mastertocmaxdepth'] = 2 d['PY3'] = PY3 d['project_fn'] = make_filename(d['project']) d['project_url'] = urlquote(d['project'].encode('idna')) d['project_manpage'] = d['project_fn'].lower() d['now'] = time.asctime() d['project_underline'] = column_width(d['project']) * '=' extensions = (',\n' + indent).join( repr('sphinx.ext.' + name) for name in EXTENSIONS if d.get('ext_' + name)) if extensions: d['extensions'] = '\n' + indent + extensions + ',\n' else: d['extensions'] = extensions d['copyright'] = time.strftime('%Y') + ', ' + d['author'] d['author_texescaped'] = text_type(d['author']).\ translate(texescape.tex_escape_map) d['project_doc'] = d['project'] + ' Documentation' d['project_doc_texescaped'] = text_type(d['project'] + ' Documentation').\ translate(texescape.tex_escape_map) # escape backslashes and single quotes in strings that are put into # a Python string literal for key in ('project', 'project_doc', 'project_doc_texescaped', 'author', 'author_texescaped', 'copyright', 'version', 'release', 'master'): d[key + '_str'] = d[key].replace('\\', '\\\\').replace("'", "\\'") if not path.isdir(d['path']): mkdir_p(d['path']) srcdir = d['sep'] and path.join(d['path'], 'source') or d['path'] mkdir_p(srcdir) if d['sep']: builddir = path.join(d['path'], 'build') d['exclude_patterns'] = '' else: builddir = path.join(srcdir, d['dot'] + 'build') exclude_patterns = map(repr, [ d['dot'] + 'build', 'Thumbs.db', '.DS_Store', ]) d['exclude_patterns'] = ', '.join(exclude_patterns) mkdir_p(builddir) mkdir_p(path.join(srcdir, d['dot'] + 'templates')) mkdir_p(path.join(srcdir, d['dot'] + 'static')) def write_file(fpath, content, newline=None): if overwrite or not path.isfile(fpath): print('Creating file %s.' % fpath) with open(fpath, 'wt', encoding='utf-8', newline=newline) as f: f.write(content) else: print('File %s already exists, skipping.' % fpath) with open(os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t')) as f: conf_text = convert_python_source(f.read()) write_file(path.join(srcdir, 'conf.py'), template.render_string(conf_text, d)) masterfile = path.join(srcdir, d['master'] + d['suffix']) write_file(masterfile, template.render('quickstart/master_doc.rst_t', d)) if d.get('make_mode') is True: makefile_template = 'quickstart/Makefile.new_t' batchfile_template = 'quickstart/make.bat.new_t' else: makefile_template = 'quickstart/Makefile_t' batchfile_template = 'quickstart/make.bat_t' if d['makefile'] is True: d['rsrcdir'] = d['sep'] and 'source' or '.' d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' # use binary mode, to avoid writing \r\n on Windows write_file(path.join(d['path'], 'Makefile'), template.render(makefile_template, d), u'\n') if d['batchfile'] is True: d['rsrcdir'] = d['sep'] and 'source' or '.' d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' write_file(path.join(d['path'], 'make.bat'), template.render(batchfile_template, d), u'\r\n') if silent: return print() print(bold('Finished: An initial directory structure has been created.')) print(''' You should now populate your master file %s and create other documentation source files. ''' % masterfile + ((d['makefile'] or d['batchfile']) and '''\ Use the Makefile to build the docs, like so: make builder ''' or '''\ Use the sphinx-build command to build the docs, like so: sphinx-build -b builder %s %s ''' % (srcdir, builddir)) + '''\ where "builder" is one of the supported builders, e.g. html, latex or linkcheck. ''')