def make_html(self, docstring): with Timer('make_html'): with open(self.doc_file, 'w') as f: f.write(docstring) app = self.app docname = 'index' with sphinx_domains(app.builder.env), rst.default_role( docname, app.builder.env.config.default_role): doctree = read_doc(app.builder.env.app, app.builder.env, app.builder.env.doc2path(docname)) for domain in app.builder.env.domains.values(): domain.process_doc(app.builder.env, docname, doctree) app.emit('doctree-read', doctree) app.builder.prepare_writing({docname}) doctree = app.builder.env.get_and_resolve_doctree( docname, app.builder, doctree) app.builder.write_doc_serialized(docname, doctree) doctree.settings = app.builder.docsettings app.builder.secnumbers = app.builder.env.toc_secnumbers.get( docname, {}) app.builder.fignumbers = app.builder.env.toc_fignumbers.get( docname, {}) app.builder.imgpath = relative_uri( app.builder.get_target_uri(docname), '_images') app.builder.dlpath = relative_uri( app.builder.get_target_uri(docname), '_downloads') app.builder.current_docname = docname app.builder.docwriter.write(doctree, self.destination) app.builder.docwriter.assemble_parts() body = app.builder.docwriter.parts['fragment'] return body
def write_doc(self, docname, doctree): destination = StringOutput(encoding='utf-8') doctree.settings = self.docsettings self.secnumbers = self.env.toc_secnumbers.get(docname, {}) self.imgpath = relative_uri(self.get_target_uri(docname), '_images') self.post_process_images(doctree) self.dlpath = relative_uri(self.get_target_uri(docname), '_downloads') self.docwriter.write(doctree, destination) self.docwriter.assemble_parts() body = self.docwriter.parts['fragment'] metatags = self.docwriter.clean_meta ctx = self.get_doc_context(docname, body, metatags) self.index_page(docname, doctree, ctx.get('title', '')) self.handle_page(docname, ctx, event_arg=doctree)
def render_aafigure(app, text, options): """ Render an ASCII art figure into the requested format output file. """ if aafigure is None: raise AafigError("aafigure module not installed") fname = get_basename(text, options) fname = "{}.{}".format(get_basename(text, options), options["format"]) if app.builder.format == "html": # HTML imgpath = relative_uri(app.builder.env.docname, "_images") relfn = posixpath.join(imgpath, fname) outfn = path.join(app.builder.outdir, "_images", fname) else: # Non-HTML if app.builder.format != "latex": logger.warn("aafig: the builder format %s is not officially " "supported, aafigure images could not work. " "Please report problems and working builder to " "avoid this warning inthe future" % app.builder.format) relfn = fname outfn = path.join(app.builder.outdir, fname) metadata_fname = "%s.aafig" % outfn try: if path.isfile(outfn): extra = None if options["format"].lower() == "svg": f = None try: try: f = open(metadata_fname) extra = f.read() except Exception: raise AafigError() finally: if f is not None: f.close() return relfn, outfn, id, extra except AafigError: pass ensuredir(path.dirname(outfn)) try: (visitor, output) = aafigure.render(text, outfn, options) output.close() except aafigure.UnsupportedFormatError as e: raise AafigError(str(e)) extra = None if options["format"].lower() == "svg": extra = visitor.get_size_attrs() f = open(metadata_fname, "w") f.write(extra) f.close() return relfn, outfn, id, extra
def render_indigorenderer_images(app, doctree): for img in doctree.traverse(nodes.image): if not hasattr(img, 'indigorenderer'): continue text = img.indigorenderer['text'] options = img.indigorenderer['options'] try: relative_paths, output = render_indigorenderer(app, text, options, os.path.dirname(doctree.attributes['source']), os.path.abspath(os.curdir)) imgnodes = [] if 'noimage' not in options: for relative_path in relative_paths: newimg = img.copy() newimg['uri'] = relative_path.replace('\\', '/') newimg['scale'] = 1.0 / float(len(relative_paths)) imgnodes.append(newimg) span = img.copy() span['uri'] = relative_uri(app.builder.env.docname, '_static') + '/span.png' imgnodes.append(span) if output: if 'noimage' not in options: newline = nodes.line() imgnodes.append(newline) if 'nooutputtitle' not in options: title = nodes.Text('Output:') imgnodes.append(title) literal = nodes.literal_block(output, output) literal['classes'] += ['output'] imgnodes.append(literal) img.replace_self(imgnodes) except IndigoRendererError, exc: app.builder.warn('indigorenderer error: ' + str(exc)) img.replace_self(nodes.literal_block(text, text)) continue
def render_ditaa(app, code, options, format, prefix='ditaa'): """Render ditaa code into a PNG output file.""" hashkey = code.encode('utf-8') + str(options) + \ str(app.builder.config.ditaa) + \ str(app.builder.config.ditaa_args) infname = '%s-%s.%s' % (prefix, sha(hashkey).hexdigest(), "ditaa") outfname = '%s-%s.%s' % (prefix, sha(hashkey).hexdigest(), "png") rel_imgpath = (format == "html") and relative_uri( app.builder.env.docname, app.builder.imagedir) or '' infullfn = path.join(app.builder.outdir, app.builder.imagedir, infname) outrelfn = posixpath.join( relative_uri(app.builder.env.docname, app.builder.imagedir), outfname) outfullfn = path.join(app.builder.outdir, app.builder.imagedir, outfname) #inrelfn = posixpath.join(relative_uri(app.builder.env.docname, app.builder.imagedir), infname) if path.isfile(outfullfn): return outrelfn, outfullfn ensuredir(path.dirname(outfullfn)) # ditaa expects UTF-8 by default if isinstance(code, unicode): code = code.encode('utf-8') ditaa_args = [app.builder.config.ditaa] ditaa_args.extend(app.builder.config.ditaa_args) ditaa_args.extend(options) ditaa_args.extend([infname, outfname]) # use relative path f = open(infullfn, 'w') f.write(code.encode('utf-8')) f.close() currpath = os.getcwd() os.chdir(path.join(app.builder.outdir, app.builder.imagedir)) try: if app.builder.config.ditaa_log_enable: print "rending %s" % (outfullfn) #app.builder.warn(ditaa_args) p = Popen(ditaa_args, stdout=PIPE, stdin=PIPE, stderr=PIPE) except OSError, err: if err.errno != ENOENT: # No such file or directory raise app.builder.warn('ditaa command %r cannot be run (needed for ditaa ' 'output), check the ditaa setting' % app.builder.config.ditaa) app.builder._ditaa_warned_dot = True os.chdir(currpath) return None, None
def render_aafigure(app, text, options): """ Render an ASCII art figure into the requested format output file. """ _id = None if aafigure is None: raise AafigError('aafigure module not installed') fname = '%s.%s' % (get_basename(text, options), options['format']) if app.builder.format == 'html': # HTML imgpath = relative_uri(app.builder.env.docname, '_images') relfn = posixpath.join(imgpath, fname) outfn = path.join(app.builder.outdir, '_images', fname) else: # Non-HTML if app.builder.format != 'latex': app.builder.warn( 'aafig: the builder format %s is not officially ' 'supported, aafigure images could not work. Please report ' 'problems and working builder to avoid this warning in ' 'the future' % app.builder.format) relfn = fname outfn = path.join(app.builder.outdir, fname) metadata_fname = '%s.aafig' % outfn try: if path.isfile(outfn): extra = None if options['format'].lower() == 'svg': f = None try: try: with open(metadata_fname, 'r') as f: extra = f.read() except Exception: raise AafigError() finally: if f is not None: f.close() return relfn, outfn, _id, extra except AafigError: pass ensuredir(path.dirname(outfn)) try: (visitor, output) = aafigure.render(text, outfn, options) output.close() except aafigure.UnsupportedFormatError as e: raise AafigError(str(e)) extra = None if options['format'].lower() == 'svg': extra = visitor.get_size_attrs() with open(metadata_fname, 'w') as f: f.write(extra) return relfn, outfn, _id, extra
def render_aafigure(app, text, options): """ Render an ASCII art figure into the requested format output file. """ _id = None if aafigure is None: raise AafigError('aafigure module not installed') fname = '%s.%s' % (get_basename(text, options), options['format']) if app.builder.format == 'html': # HTML imgpath = relative_uri(app.builder.env.docname, '_images') relfn = posixpath.join(imgpath, fname) outfn = path.join(app.builder.outdir, '_images', fname) else: # Non-HTML if app.builder.format != 'latex': app.builder.warn('aafig: the builder format %s is not officially ' 'supported, aafigure images could not work. Please report ' 'problems and working builder to avoid this warning in ' 'the future' % app.builder.format) relfn = fname outfn = path.join(app.builder.outdir, fname) metadata_fname = '%s.aafig' % outfn try: if path.isfile(outfn): extra = None if options['format'].lower() == 'svg': f = None try: try: with open(metadata_fname, 'r') as f: extra = f.read() except Exception: raise AafigError() finally: if f is not None: f.close() return relfn, outfn, _id, extra except AafigError: pass ensuredir(path.dirname(outfn)) try: (visitor, output) = aafigure.render(text, outfn, options) output.close() except aafigure.UnsupportedFormatError as e: raise AafigError(str(e)) extra = None if options['format'].lower() == 'svg': extra = visitor.get_size_attrs() with open(metadata_fname, 'w') as f: f.write(extra) return relfn, outfn, _id, extra
def get_builddir_and_reldir(builder, node: lily_base_node) -> Tuple[str, str]: """ Return the path of Sphinx builder's outdir and its corrsponding relative path. """ builddir = path.join(builder.outdir, _LILYDIR) reluri = relative_uri(builder.get_target_uri(node['docname']), '.') reldir = posixpath.join(reluri, _LILYDIR) return (builddir, reldir)
def render_yuml(app, uri, text, options): """ Render yuml into a image file. """ format_map = DEFAULT_FORMATS.copy() format_map.update(app.builder.config.yuml_format) option_map = DEFAULT_OPTIONS.copy() option_map.update(options) term = format_map[app.builder.format] fname = get_filename(text, options, term) if app.builder.format == 'html': # HTML imgpath = relative_uri(app.builder.env.docname,'_images') relfn = posixpath.join(imgpath, fname) outfn = path.join(app.builder.outdir, '_images', fname) else: # Non-HTML if app.builder.format != 'latex': log_warn(app, 'yuml: the builder format %s is not supported.' % app.builder.format) relfn = fname outfn = path.join(app.builder.outdir, fname) ensuredir(path.dirname(outfn)) docdir = (path.dirname(app.builder.env.docname)) try: debug(app, '[Yuml] generating diagram in %s' % fname) opts = option_map['style'] if 'scale' in option_map: opts += ';scale:%s' % option_map['scale'] opts += ';dir:%s' % option_map['direction'] try: data = urllib.parse.quote(text, encoding='utf-8') except Exception: data = urllib.quote(text.encode('utf-8')) url = '%s/%s/%s/%s.%s' % (app.builder.config.yuml_server_url.strip('/'), opts, option_map['type'], data, term) debug(app, '[Yuml] with URL %s' % url) headers = { 'User-Agent' : 'sphinxcontrib/yuml v0.1', 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8' } req = urllib2.Request(url, None, headers) rep = urllib2.urlopen(req).read() out = open(outfn, 'wb') out.write(rep) out.close() except Exception: (_t, e, _tb) = sys.exc_info() del(_tb) raise YumlError(str(e)) return relfn
def suggest_changes(self, req, page): """ Show a "suggest changes" form. """ page_id, contents = self.get_page_source(page) return Response(render_template(req, 'edit.html', self.globalcontext, dict( contents=contents, pagename=page, doctitle=self.globalcontext['titles'].get(page_id+'.rst') or 'this page', submiturl=relative_uri('/@edit/'+page+'/', '/@submit/'+page), )))
def get_relative_path(app, text, options): # Reset Indigo to use new fresh options format_map = DEFAULT_FORMATS.copy() output_format = format_map[app.builder.format] output_filename = options['imagename'] + '.' + output_format if app.builder.format == 'html': output_folder = relative_uri(app.builder.env.docname,'_images') relative_path = os.path.join(output_folder, output_filename) else: relative_path = output_filename return relative_path
def render_aafigure(app, text, options): """ Render an ASCII art figure into the requested format output file. """ if aafigure is None: raise AafigError("aafigure module not installed") fname = get_basename(text, options) fname = "%s.%s" % (get_basename(text, options), options["format"]) if app.builder.format == "html": # HTML imgpath = relative_uri(app.builder.env.docname, "_images") relfn = posixpath.join(imgpath, fname) outfn = path.join(app.builder.outdir, "_images", fname) else: # Non-HTML if app.builder.format != "latex": app.builder.warn( "aafig: the builder format %s is not officially " "supported, aafigure images could not work. Please report " "problems and working builder to avoid this warning in " "the future" % app.builder.format ) relfn = fname outfn = path.join(app.builder.outdir, fname) metadata_fname = "%s.aafig" % outfn try: if path.isfile(outfn): extra = None if options["format"].lower() == "svg": f = None try: try: f = file(metadata_fname, "r") extra = f.read() except: raise AafigError() finally: if f is not None: f.close() return relfn, outfn, id, extra except AafigError: pass ensuredir(path.dirname(outfn)) try: (visitor, output) = aafigure.render(text, outfn, options) output.close() except aafigure.UnsupportedFormatError, e: raise AafigError(str(e))
def render_indigorenderer(app, text, options, rstdir, curdir): format_map = DEFAULT_FORMATS.copy() format_map.update(app.builder.config.indigorenderer_format) output_format = None if len(app.builder.format) > 0: output_format = format_map[app.builder.format] if 'format' in options: output_format = options['format'] if output_format is None: return hashid = get_hashid(text, options) output_filename = 'indigorenderer_%s.%s' % ( hashid, output_format) if not 'imagename' in options else options[ 'imagename'] + '.' + output_format relative_path = '' if app.builder.format == 'html': output_folder = relative_uri(app.builder.env.docname, '_images') relative_path = os.path.join(output_folder, output_filename) absolute_path = os.path.join(app.builder.outdir, '_images', output_filename) else: relative_path = output_filename absolute_path = os.path.join(app.builder.outdir, output_filename) absolute_path = absolute_path.replace('\\', '\\\\') relative_paths = [ relative_path, ] output = None if _no_indigo: return relative_paths, output # Reset Indigo to use new fresh options resetIndigo() try: if 'indigooptions' in options: strings = options['indigooptions'][1:-1].split(';') for string in strings: key, value = string.split('=') indigo.setOption(key, value.replace('"', '')) indigo.setOption('render-output-format', output_format) result = render(indigo, options, text, absolute_path, relative_path, rstdir, curdir) if result: output, relative_paths = result except IndigoException, exc: raise IndigoRendererError(exc)
def get_keyword_matches(self, req, term=None, avoid_fuzzy=False, is_error_page=False): """ Find keyword matches. If there is an exact match, just redirect: http://docs.python.org/os.path.exists would automatically redirect to http://docs.python.org/library/os.path/#os.path.exists. Else, show a page with close matches. Module references are processed first so that "os.path" is handled as a module and not as member of os. """ if term is None: term = req.path.strip('/') matches = self.env.find_keyword(term, avoid_fuzzy) # if avoid_fuzzy is False matches can be None if matches is None: return if isinstance(matches, tuple): url = get_target_uri(matches[1]) if matches[0] != 'module': url += '#' + matches[2] return RedirectResponse(url) else: # get some close matches close_matches = [] good_matches = 0 for ratio, type, filename, anchorname, desc in matches: link = get_target_uri(filename) if type != 'module': link += '#' + anchorname good_match = ratio > 0.75 good_matches += good_match close_matches.append({ 'href': relative_uri(req.path, link), 'title': anchorname, 'good_match': good_match, 'type': self.pretty_type.get(type, type), 'description': desc, }) return Response(render_template( req, 'keyword_not_found.html', { 'close_matches': close_matches, 'good_matches_count': good_matches, 'keyword': term }, self.globalcontext), status=404)
def html_asciicast(self, node): filename = os.path.basename(node['path']) dst = os.path.join(self.builder.outdir, self.builder.imagedir, filename) html_path = os.path.join( relative_uri(os.path.normpath(node['relpath']), self.builder.imagedir), filename) body = '<asciinema-player src="{}"></asciinema-player>'.format(html_path) try: shutil.copy(node['path'], dst) except shutil.Error as err: self.builder.warn("failed to copy file: {}".format(err)) self.body.append(body) raise nodes.SkipNode
def render_gnuplot(app, text, options): """ Render gnuplot text into a image file. """ format_map = DEFAULT_FORMATS.copy() format_map.update(app.builder.config.gnuplot_format) hashid = get_hashid(text, options) term = format_map[app.builder.format] if app.builder.format == 'html': fname = 'plot-%s.%s' % (hashid, term) # HTML imgpath = relative_uri(app.builder.env.docname, '_images') relfn = posixpath.join(imgpath, fname) outfn = path.join(app.builder.outdir, '_images', fname) else: # Non-HTML if app.builder.format != 'latex': app.builder.warn('gnuplot: the builder format %s ' 'is not officially supported.' % app.builder.format) fname = 'plot-%s.%s' % (hashid, term) relfn = fname outfn = path.join(app.builder.outdir, fname) if path.isfile(outfn): return relfn, outfn, hashid ensuredir(path.dirname(outfn)) docdir = (path.dirname(app.builder.env.docname)) try: plot = Popen('gnuplot -persist', shell=True, bufsize=64, stdin=PIPE) if docdir: plot.stdin.write('cd "%s"\n' % docdir) plot.stdin.write("set terminal %s " % (term, )) if 'size' in options: plot.stdin.write("size %s\n" % options['size']) else: plot.stdin.write("\n") if 'title' in options: plot.stdin.write('set title "%s"\n' % options['title']) plot.stdin.write("set output '%s'\n" % (outfn, )) plot.stdin.write("%s\n" % text) plot.stdin.write("\nquit\n") plot.stdin.flush() except Exception as e: raise GnuplotError(str(e)) return relfn, outfn, hashid
def get_relative_path(app, text, options): # Reset Indigo to use new fresh options format_map = DEFAULT_FORMATS.copy() output_format = format_map[app.builder.format] if output_format is None: return None output_filename = options['imagename'] + '.' + output_format if app.builder.format == 'html': output_folder = relative_uri(app.builder.env.docname, '_images') relative_path = os.path.join(output_folder, output_filename) else: relative_path = output_filename return relative_path
def render_indigorenderer(app, text, options, rstdir, curdir): format_map = DEFAULT_FORMATS.copy() format_map.update(app.builder.config.indigorenderer_format) output_format = None if len(app.builder.format) > 0: output_format = format_map[app.builder.format] if 'format' in options: output_format = options['format'] if output_format is None: return hashid = get_hashid(text, options) output_filename = 'indigorenderer_%s.%s' % (hashid, output_format) if not 'imagename' in options else options['imagename'] + '.' + output_format relative_path = '' if app.builder.format == 'html': output_folder = relative_uri(app.builder.env.docname,'_images') relative_path = os.path.join(output_folder, output_filename) absolute_path = os.path.join(app.builder.outdir, '_images', output_filename) else: relative_path = output_filename absolute_path = os.path.join(app.builder.outdir, output_filename) absolute_path = absolute_path.replace('\\', '\\\\') relative_paths = [relative_path, ] output = None if _no_indigo: return relative_paths, output # Reset Indigo to use new fresh options resetIndigo() try: if 'indigooptions' in options: strings = options['indigooptions'][1:-1].split(';') for string in strings: key, value = string.split('=') indigo.setOption(key, value.replace('"', '')) indigo.setOption('render-output-format', output_format) result = render(indigo, options, text, absolute_path, relative_path, rstdir, curdir) if result: output, relative_paths = result except IndigoException, exc: raise IndigoRendererError(exc)
def render_gnuplot(app, text, options): """ Render gnuplot text into a image file. """ format_map = DEFAULT_FORMATS.copy() format_map.update(app.builder.config.gnuplot_format) hashid = get_hashid(text,options) term = format_map[app.builder.format] if app.builder.format == 'html': fname = 'plot-%s.%s' % (hashid, term) # HTML imgpath = relative_uri(app.builder.env.docname,'_images') relfn = posixpath.join(imgpath,fname) outfn = path.join(app.builder.outdir, '_images', fname) else: # Non-HTML if app.builder.format != 'latex': app.builder.warn('gnuplot: the builder format %s ' 'is not officially supported.' % app.builder.format) fname = 'plot-%s.%s' % (hashid, term) relfn = fname outfn = path.join(app.builder.outdir, fname) if path.isfile(outfn): return relfn, outfn, hashid ensuredir(path.dirname(outfn)) docdir = (path.dirname(app.builder.env.docname)) try: plot = Popen('gnuplot -persist', shell=True, bufsize=64, stdin=PIPE) if docdir: plot.stdin.write('cd "%s"\n' % docdir) plot.stdin.write("set terminal %s " % (term,)) if 'size' in options: plot.stdin.write("size %s\n" % options['size']) else: plot.stdin.write("\n") if 'title' in options: plot.stdin.write('set title "%s"\n' % options['title']) plot.stdin.write("set output '%s'\n" % (outfn,)) plot.stdin.write("%s\n" % text) plot.stdin.write("\nquit\n") plot.stdin.flush() except Exception, e: raise GnuplotError(str(e))
def get_keyword_matches(self, req, term=None, avoid_fuzzy=False, is_error_page=False): """ Find keyword matches. If there is an exact match, just redirect: http://docs.python.org/os.path.exists would automatically redirect to http://docs.python.org/library/os.path/#os.path.exists. Else, show a page with close matches. Module references are processed first so that "os.path" is handled as a module and not as member of os. """ if term is None: term = req.path.strip('/') matches = self.env.find_keyword(term, avoid_fuzzy) # if avoid_fuzzy is False matches can be None if matches is None: return if isinstance(matches, tuple): url = get_target_uri(matches[1]) if matches[0] != 'module': url += '#' + matches[2] return RedirectResponse(url) else: # get some close matches close_matches = [] good_matches = 0 for ratio, type, filename, anchorname, desc in matches: link = get_target_uri(filename) if type != 'module': link += '#' + anchorname good_match = ratio > 0.75 good_matches += good_match close_matches.append({ 'href': relative_uri(req.path, link), 'title': anchorname, 'good_match': good_match, 'type': self.pretty_type.get(type, type), 'description': desc, }) return Response(render_template(req, 'keyword_not_found.html', { 'close_matches': close_matches, 'good_matches_count': good_matches, 'keyword': term }, self.globalcontext), status=404)
def suggest_changes(self, req, page): """ Show a "suggest changes" form. """ page_id, contents = self.get_page_source(page) return Response( render_template( req, 'edit.html', self.globalcontext, dict( contents=contents, pagename=page, doctitle=self.globalcontext['titles'].get(page_id + '.rst') or 'this page', submiturl=relative_uri('/@edit/' + page + '/', '/@submit/' + page), )))
def get_author(self, references): # Used by section_entries to make the listing of links resources # as "tags" resource_references = self.props.references if resource_references: if 'author' in resource_references: pa_label = resource_references['author'][0] pa = references["author"][pa_label] images = pa.props.images first_image = images[0].filename if images else None author_href = relative_uri(self.docname, pa.docname) thumbnail_url = author_href + '/../' + first_image author = dict( title=pa.title, href=author_href, thumbnail_url=thumbnail_url, ) return author
def archive_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ Directive to create a archive (zip) from a sample project """ environment = state.document.settings.env static_path = environment.config.html_static_path[0] directory = arguments[0] if options.has_key('file'): filename = options['file'] else: filename = os.path.basename(directory.rstrip(os.sep)) + '.zip' archive_file = zipfile.ZipFile(os.path.dirname(os.path.abspath(__file__)) + '%s%s%s' % (os.sep, static_path, os.sep) + filename, "w") if directory.startswith(os.sep): dir = directory else: dir = os.path.normpath(os.path.join(environment.config.code_path, directory)) for root, dirs, files in os.walk(dir,topdown=False): for name in files: file = os.path.join(root, name) zipfilename = string.replace(file, dir, '') if zipfilename[0] == os.sep: zipfilename = zipfilename[1:] archive_file.write(file, str(zipfilename), zipfile.ZIP_DEFLATED) archive_file.close() archive = util.relative_uri(state_machine.document.current_source, os.path.dirname(os.path.abspath(__file__)) + '%s%s%s' % (os.sep, static_path, os.sep)) \ + filename role = roles.CustomRole(role_name, archive_role, {'archive' : archive}, content) roles.register_local_role(role_name, role) return
def render_indigorenderer_images(app, doctree): for img in doctree.traverse(nodes.image): if not hasattr(img, 'indigorenderer'): continue text = img.indigorenderer['text'] options = img.indigorenderer['options'] try: res = render_indigorenderer( app, text, options, os.path.dirname(doctree.attributes['source']), os.path.abspath(os.curdir)) if res is None: continue relative_paths, output = res imgnodes = [] if 'noimage' not in options: for relative_path in relative_paths: newimg = img.copy() newimg['uri'] = relative_path.replace('\\', '/') newimg['scale'] = 1.0 / float(len(relative_paths)) imgnodes.append(newimg) span = img.copy() span['uri'] = relative_uri(app.builder.env.docname, '_static') + '/span.png' imgnodes.append(span) if output: if 'noimage' not in options: newline = nodes.line() imgnodes.append(newline) if 'nooutputtitle' not in options: title = nodes.Text('Output:') imgnodes.append(title) literal = nodes.literal_block(output, output) literal['classes'] += ['output'] imgnodes.append(literal) img.replace_self(imgnodes) except IndigoRendererError, exc: app.builder.warn('indigorenderer error: ' + str(exc)) img.replace_self(nodes.literal_block(text, text)) continue
def archive_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ Directive to create a archive (zip) from a sample project """ environment = state.document.settings.env static_path = environment.config.html_static_path[0] directory = arguments[0] if options.has_key('file'): filename = options['file'] else: filename = os.path.basename(directory.rstrip(os.sep)) + '.zip' archive_file = zipfile.ZipFile( os.path.dirname(os.path.abspath(__file__)) + '%s%s%s' % (os.sep, static_path, os.sep) + filename, "w") if directory.startswith(os.sep): dir = directory else: dir = os.path.normpath( os.path.join(environment.config.code_path, directory)) for root, dirs, files in os.walk(dir, topdown=False): for name in files: file = os.path.join(root, name) zipfilename = string.replace(file, dir, '') if zipfilename[0] == os.sep: zipfilename = zipfilename[1:] archive_file.write(file, str(zipfilename), zipfile.ZIP_DEFLATED) archive_file.close() archive = util.relative_uri(state_machine.document.current_source, os.path.dirname(os.path.abspath(__file__)) + '%s%s%s' % (os.sep, static_path, os.sep)) \ + filename role = roles.CustomRole(role_name, archive_role, {'archive': archive}, content) roles.register_local_role(role_name, role) return
def archive_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ Directive to create a archive (zip) from a sample project """ clone_and_pull(state) environment = state.document.settings.env static_path = environment.config.html_static_path[0] directory = arguments[0] if options.has_key('file'): filename = options['file'] else: filename = os.path.basename(directory.rstrip(os.sep)) + '.zip' archive_file = zipfile.ZipFile(os.path.dirname(os.path.abspath(__file__)) + '%s%s%s' % (os.sep, static_path, os.sep) + filename, "w") if options.has_key('root'): base = options['root'] else: base = '' fnames = list_files(state, base) for name in fnames: archive_file.writestr(name, '\n'.join(get_file(state, name))) archive_file.close() archive = util.relative_uri(state_machine.document.current_source, os.path.dirname(os.path.abspath(__file__)) + '%s%s%s' % (os.sep, static_path, os.sep)) \ + filename role = roles.CustomRole(role_name, archive_role, {'archive' : archive}, content) roles.register_local_role(role_name, role) return []
def archive_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ Directive to create a archive (zip) from a sample project """ clone_and_pull(state) environment = state.document.settings.env static_path = environment.config.html_static_path[0] directory = arguments[0] if options.has_key('file'): filename = options['file'] else: filename = os.path.basename(directory.rstrip(os.sep)) + '.zip' archive_file = zipfile.ZipFile( os.path.dirname(os.path.abspath(__file__)) + '%s%s%s' % (os.sep, static_path, os.sep) + filename, "w") if options.has_key('root'): base = options['root'] else: base = '' fnames = list_files(state, base) for name in fnames: archive_file.writestr(name, '\n'.join(get_file(state, name))) archive_file.close() archive = util.relative_uri(state_machine.document.current_source, os.path.dirname(os.path.abspath(__file__)) + '%s%s%s' % (os.sep, static_path, os.sep)) \ + filename role = roles.CustomRole(role_name, archive_role, {'archive': archive}, content) roles.register_local_role(role_name, role) return []
def inject_page(app, pagename, templatename, context, doctree): # This theme expects all values to come in through # validated models. No more globals. So extract the # page-specific stuff into an instance if doctree is None: pass title = get_rst_title(doctree) body = context.get('body', '') # genindex has no body # Make a page page = Page(docname=pagename, title=title, body=body) # Make some breadcrumbs root_href = relative_uri(pagename, 'index') + '.html' breadcrumbs = [dict(label='Home', href=root_href)] parents = context['parents'] for parent in parents: breadcrumbs.append(dict(label=parent['title'], href=parent['link'])) page.breadcrumbs = breadcrumbs # context['page'] = page context['page'] = app.config.bulmaio_jinja2_page
def get_references(self, references): # Used by section_entries to make the listing of links resources # as "tags" # Used by section_entries to make the listing of links resources # as "tags" resource_references = self.props.references if resource_references: # Handle all non-author references for tag-like links these_references = [] for reftype, labels in resource_references.items(): this_reftype = references[reftype] if reftype != 'author': for label in labels: this_ref = this_reftype[label] this_href = relative_uri(self.docname, this_ref.docname) these_references.append( dict( label=label, href=this_href, ) ) return these_references
def pathto(otheruri, resource=False, baseuri=self.get_target_uri(pagename)): if not resource: otheruri = self.get_target_uri(otheruri) return relative_uri(baseuri, otheruri)
def make_rel_link(keyword): return relative_uri(uri, 'q/%s/' % keyword)
def libreoffice_render(app, doctree): """ Render LibreOffice drawing (doctree-read callback) """ for figure in doctree.traverse(nodes.figure): if not hasattr(figure, 'libreoffice'): continue drawing = figure.libreoffice['drawing'] options = figure.libreoffice['options'] # Check for LibreOffice if not app.builder.config.libreoffice_binary: app.builder.warn('Unable to find a LibreOffice installation') figure.replace_self(nodes.literal_block(drawing, drawing)) continue # Update formats with configuration format_map = DEFAULT_FORMATS.copy() format_map.update(app.builder.config.libreoffice_format) # Setup paths inp_fn_abs = app.builder.env.relfn2path(drawing)[1] inp_fn_base, _ = os.path.splitext(os.path.basename(drawing)) out_fext = format_map[app.builder.format] out_fn = '%s.%s' % (inp_fn_base, out_fext) if app.builder.format == 'html': imgpath = relative_uri(app.builder.env.docname, '_images') out_fn_rel = posixpath.join(imgpath, out_fn) out_dir = os.path.join(app.builder.outdir, '_images') out_fn_abs = os.path.join(out_dir, out_fn) else: if app.builder.format != 'latex': app.builder.warn('libreoffice: the builder format %s ' 'is not officially supported.' % app.builder.format) out_fn_rel = out_fn out_dir = app.builder.outdir out_fn_abs = os.path.join(out_dir, out_fn) ensuredir(out_dir) # Run LibreOffice # A solution to run LibreOffice when another instance is already # running is to use a unique UserInstallation folder. More info at: # https://www.libreoffice.org/bugzilla/show_bug.cgi?id=37531 if os.name != 'nt': tmp_folder = tempfile.mkdtemp() tmp_path = 'file://' + tmp_folder else: tmp_path = '$SYSUSERCONFIG/tmp' call([ app.builder.config.libreoffice_binary, '--headless', '-env:UserInstallation=' + tmp_path, '--convert-to', out_fext, '--outdir', out_dir, inp_fn_abs ], stdout=PIPE, stderr=PIPE) if os.name != 'nt': shutil.rmtree(tmp_folder) # Crop white borders (images only) if 'autocrop' in options and out_fext not in ('pdf', 'svg'): if options['autocrop']: im = Image.open(out_fn_abs) im.load() im_box = ImageOps.invert(im).getbbox() im = im.crop(im_box) im.save(out_fn_abs) # Get (w, h) - required to make :scale: work without indicating (w, h) if out_fext not in ('pdf', 'svg'): im = Image.open(out_fn_abs) im.load() (out_width, out_height) = im.size # Fill image information for image in figure.traverse(nodes.image): image['uri'] = out_fn_rel try: image['width'] = str(out_width) image['height'] = str(out_height) except: pass
def visit_toctree(self, node): # div class=row {{ section_type }} # h2 class=col-sm-12 # {{ section title }} # div class=col-sm-6 col-md-3 # figure class=card # a href=current_link style=background-image: document-image-attribute class=card-img # figcaption # {{ card title }} env = self.builder.env conf = self.builder.app.config for title, ref in ((e[0], e[1]) for e in node['entries']): # external URL, no toc, can't recurse into if ref not in env.tocs: continue toc = env.tocs[ref].traverse(addnodes.toctree) classes = env.metadata[ref].get('types', 'tutorials') classes += ' toc-single-entry' if not toc else ' toc-section' self.body.append(self.starttag(node, 'div', CLASS="row " + classes)) self.body.append(u'<div class="col-sm-12"><h2>') self.body.append(title if title else util.nodes.clean_astext(env.titles[ref])) self.body.append(u'</h2></div>') entries = [(title, ref)] if not toc else ((e[0], e[1]) for e in toc[0]['entries']) for subtitle, subref in entries: baseuri = self.builder.get_target_uri(node['parent']) if subref in env.metadata: cover = env.metadata[subref].get('banner', conf.flectra_cover_default) elif subref in conf.flectra_cover_external: cover = conf.flectra_cover_external[subref] else: cover = conf.flectra_cover_default_external if cover: banner = '_static/' + cover base, ext = os.path.splitext(banner) small = "{}.small{}".format(base, ext) if os.path.isfile(url2pathname(small)): banner = small style = u"background-image: url('{}')".format( util.relative_uri(baseuri, banner) or '#') else: style = u'' self.body.append(u""" <div class="col-sm-6 col-md-3"> <figure class="card"> <a href="{link}" class="card-img"> <span style="{style}"></span> <figcaption>{title}</figcaption> </a> </figure> </div> """.format( link=subref if util.url_re.match(subref) else util.relative_uri( baseuri, self.builder.get_target_uri(subref)), style=style, title=subtitle if subtitle else util.nodes.clean_astext(env.titles[subref]), )) self.body.append(u'</div>') raise nodes.SkipNode
def visit_toctree(self, node): # div class=row {{ section_type }} # h2 class=col-sm-12 # {{ section title }} # div class=col-sm-6 col-md-3 # figure class=card # a href=current_link style=background-image: document-image-attribute class=card-img # figcaption # {{ card title }} env = self.builder.env conf = self.builder.app.config for title, ref in ((e[0], e[1]) for e in node['entries']): # external URL, no toc, can't recurse into if ref not in env.tocs: continue toc = env.tocs[ref].traverse(addnodes.toctree) classes = env.metadata[ref].get('types', 'tutorials') classes += ' toc-single-entry' if not toc else ' toc-section' self.body.append(self.starttag(node, 'div', CLASS="row " + classes)) self.body.append(u'<div class="col-sm-12"><h2>') self.body.append(title if title else util.nodes.clean_astext(env.titles[ref])) self.body.append(u'</h2></div>') entries = [(title, ref)] if not toc else ((e[0], e[1]) for e in toc[0]['entries']) for subtitle, subref in entries: baseuri = self.builder.get_target_uri(node['parent']) if subref in env.metadata: cover = env.metadata[subref].get('banner', conf.odoo_cover_default) elif subref in conf.odoo_cover_external: cover = conf.odoo_cover_external[subref] else: cover = conf.odoo_cover_default_external if cover: banner = '_static/' + cover base, ext = os.path.splitext(banner) small = "{}.small{}".format(base, ext) if os.path.isfile(url2pathname(small)): banner = small style = u"background-image: url('{}')".format( util.relative_uri(baseuri, banner) or '#') else: style = u'' self.body.append(u""" <div class="col-sm-6 col-md-3"> <figure class="card"> <a href="{link}" class="card-img"> <span style="{style}"></span> <figcaption>{title}</figcaption> </a> </figure> </div> """.format( link=subref if util.url_re.match(subref) else util.relative_uri( baseuri, self.builder.get_target_uri(subref)), style=style, title=subtitle if subtitle else util.nodes.clean_astext(env.titles[subref]), )) self.body.append(u'</div>') raise nodes.SkipNode
def relative_path_to(otheruri, resource=False): if not resource: otheruri = get_target_uri(otheruri) return relative_uri(path, otheruri)
def submit_changes(self, req, page): """ Submit the suggested changes as a patch. """ if req.method != 'POST': # only available via POST raise NotFound() if req.form.get('cancel'): # handle cancel requests directly return RedirectResponse(page) # raises NotFound if page doesn't exist page_id, orig_contents = self.get_page_source(page) author = req.form.get('name') email = req.form.get('email') summary = req.form.get('summary') contents = req.form.get('contents') fields = (author, email, summary, contents) form_error = None rendered = None if not all(fields): form_error = 'You have to fill out all fields.' elif not _mail_re.search(email): form_error = 'You have to provide a valid e-mail address.' elif req.form.get('homepage') or self.antispam.is_spam(fields): form_error = 'Your text contains blocked URLs or words.' else: if req.form.get('preview'): rendered = self._generate_preview(page_id, contents) else: asctime = time.asctime() contents = contents.splitlines() orig_contents = orig_contents.splitlines() diffname = 'suggestion on %s by %s <%s>' % (asctime, author, email) diff = difflib.unified_diff(orig_contents, contents, n=3, fromfile=page_id, tofile=diffname, lineterm='') diff_text = '\n'.join(diff) try: mail = Email( self.config['patch_mail_from'], 'Python Documentation Patches', self.config['patch_mail_to'], '', 'Patch for %s by %s' % (page_id, author), PATCH_MESSAGE % locals(), self.config['patch_mail_smtp'], ) mail.attachments.add_string('patch.diff', diff_text, 'text/x-diff') mail.send() except: import traceback traceback.print_exc() # XXX: how to report? pass return Response(render_template(req, 'submitted.html', self.globalcontext, dict( backlink=relative_uri('/@submit/'+page+'/', page+'/') ))) return Response(render_template(req, 'edit.html', self.globalcontext, dict( contents=contents, author=author, email=email, summary=summary, pagename=page, form_error=form_error, rendered=rendered, submiturl=relative_uri('/@edit/'+page+'/', '/@submit/'+page), )))
app.emit('doctree-read', doctree) print('docnames', docnames) updated_docnames = set(docnames) print('updated_docnames:', updated_docnames) # app.builder.write(set(), list(updated_docnames), 'update') docnames = set(updated_docnames) app.builder.prepare_writing(docnames) # app.builder._write_serial(sorted(docnames)) for docname in docnames: print('docname:', docname) doctree = app.builder.env.get_and_resolve_doctree(docname, app.builder, doctree) app.builder.write_doc_serialized(docname, doctree) # app.builder.write_doc(docname, doctree) destination = StringOutput(encoding='utf-8') doctree.settings = app.builder.docsettings app.builder.secnumbers = app.builder.env.toc_secnumbers.get(docname, {}) app.builder.fignumbers = app.builder.env.toc_fignumbers.get(docname, {}) app.builder.imgpath = relative_uri(app.builder.get_target_uri(docname), '_images') app.builder.dlpath = relative_uri(app.builder.get_target_uri(docname), '_downloads') app.builder.current_docname = docname app.builder.docwriter.write(doctree, destination) app.builder.docwriter.assemble_parts() body = app.builder.docwriter.parts['fragment'] print(body) print('time elapsed:', time() - start_time)
def render_ditaa(app, code, options, format, prefix='ditaa'): """Render ditaa code into a PNG output file.""" # ditaa expects UTF-8 by default code = code.encode('utf-8') hashkey = str(code) + str(options) + \ str(app.builder.config.ditaa) + \ str(app.builder.config.ditaa_args) infname = '%s-%s.%s' % (prefix, sha( hashkey.encode('utf-8')).hexdigest(), "ditaa") outfname = '%s-%s.%s' % (prefix, sha( hashkey.encode('utf-8')).hexdigest(), "png") rel_imgpath = (format == "html") and relative_uri( app.builder.env.docname, app.builder.imagedir) or '' infullfn = path.join(app.builder.outdir, app.builder.imagedir, infname) outrelfn = posixpath.join( relative_uri(app.builder.env.docname, app.builder.imagedir), outfname) outfullfn = path.join(app.builder.outdir, app.builder.imagedir, outfname) #inrelfn = posixpath.join(relative_uri(app.builder.env.docname, app.builder.imagedir), infname) if path.isfile(outfullfn): return outrelfn, outfullfn ensuredir(path.dirname(outfullfn)) ditaa_args = [app.builder.config.ditaa] ditaa_args.extend(app.builder.config.ditaa_args) ditaa_args.extend(options) ditaa_args.extend([infname, outfname]) # use relative path f = open(infullfn, 'wb') f.write(code) f.close() currpath = os.getcwd() os.chdir(path.join(app.builder.outdir, app.builder.imagedir)) try: if app.builder.config.ditaa_log_enable: print("rending %s" % (outfullfn)) #app.builder.warn(ditaa_args) p = Popen(ditaa_args, stdout=PIPE, stdin=PIPE, stderr=PIPE) except OSError as err: if err.errno != ENOENT: # No such file or directory raise app.builder.warn('ditaa command %r cannot be run (needed for ditaa ' 'output), check the ditaa setting' % app.builder.config.ditaa) app.builder._ditaa_warned_dot = True os.chdir(currpath) return None, None os.chdir(currpath) wentWrong = False try: # Ditaa may close standard input when an error occurs, # resulting in a broken pipe on communicate() stdout, stderr = p.communicate(code) except OSError as err: if err.errno != EPIPE: raise wentWrong = True except IOError as err: if err.errno != EINVAL: raise wentWrong = True if wentWrong: # in this case, read the standard output and standard error streams # directly, to get the error message(s) stdout, stderr = p.stdout.read(), p.stderr.read() p.wait() if p.returncode != 0: raise DitaaError('ditaa exited with error:\n[stderr]\n%s\n' '[stdout]\n%s' % (stderr, stdout)) return outrelfn, outfullfn
def libreoffice_render(app, doctree): """ Render LibreOffice drawing (doctree-read callback) """ for figure in doctree.traverse(nodes.figure): if not hasattr(figure, 'libreoffice'): continue drawing = figure.libreoffice['drawing'] options = figure.libreoffice['options'] # Check for LibreOffice if not app.builder.config.libreoffice_binary: app.builder.warn('Unable to find a LibreOffice installation') figure.replace_self(nodes.literal_block(drawing, drawing)) continue # Update formats with configuration format_map = DEFAULT_FORMATS.copy() format_map.update(app.builder.config.libreoffice_format) # Setup paths inp_fn_abs = app.builder.env.relfn2path(drawing)[1] inp_fn_base, _ = os.path.splitext(os.path.basename(drawing)) out_fext = format_map[app.builder.format] out_fn = '%s.%s' % (inp_fn_base, out_fext) if app.builder.format == 'html': imgpath = relative_uri(app.builder.env.docname, '_images') out_fn_rel = posixpath.join(imgpath, out_fn) out_dir = os.path.join(app.builder.outdir, '_images') out_fn_abs = os.path.join(out_dir, out_fn) else: if app.builder.format != 'latex': app.builder.warn('libreoffice: the builder format %s ' 'is not officially supported.' % app.builder.format) out_fn_rel = out_fn out_dir = app.builder.outdir out_fn_abs = os.path.join(out_dir, out_fn) ensuredir(out_dir) # Run LibreOffice # A solution to run LibreOffice when another instance is already # running is to use a unique UserInstallation folder. More info at: # https://www.libreoffice.org/bugzilla/show_bug.cgi?id=37531 if os.name != 'nt': tmp_folder = tempfile.mkdtemp() tmp_path = 'file://' + tmp_folder else: tmp_path = '$SYSUSERCONFIG/tmp' call([app.builder.config.libreoffice_binary, '--headless', '-env:UserInstallation=' + tmp_path, '--convert-to', out_fext, '--outdir', out_dir, inp_fn_abs], stdout=PIPE, stderr=PIPE) if os.name != 'nt': shutil.rmtree(tmp_folder) # Crop white borders (images only) if 'autocrop' in options and out_fext not in ('pdf', 'svg'): if options['autocrop']: im = Image.open(out_fn_abs) im.load() im_box = ImageOps.invert(im).getbbox() im = im.crop(im_box) im.save(out_fn_abs) # Get (w, h) - required to make :scale: work without indicating (w, h) if out_fext not in ('pdf', 'svg'): im = Image.open(out_fn_abs) im.load() (out_width, out_height) = im.size # Fill image information for image in figure.traverse(nodes.image): image['uri'] = out_fn_rel try: image['width'] = str(out_width) image['height'] = str(out_height) except: pass
def submit_changes(self, req, page): """ Submit the suggested changes as a patch. """ if req.method != 'POST': # only available via POST raise NotFound() if req.form.get('cancel'): # handle cancel requests directly return RedirectResponse(page) # raises NotFound if page doesn't exist page_id, orig_contents = self.get_page_source(page) author = req.form.get('name') email = req.form.get('email') summary = req.form.get('summary') contents = req.form.get('contents') fields = (author, email, summary, contents) form_error = None rendered = None if not all(fields): form_error = 'You have to fill out all fields.' elif not _mail_re.search(email): form_error = 'You have to provide a valid e-mail address.' elif req.form.get('homepage') or self.antispam.is_spam(fields): form_error = 'Your text contains blocked URLs or words.' else: if req.form.get('preview'): rendered = self._generate_preview(page_id, contents) else: asctime = time.asctime() contents = contents.splitlines() orig_contents = orig_contents.splitlines() diffname = 'suggestion on %s by %s <%s>' % (asctime, author, email) diff = difflib.unified_diff(orig_contents, contents, n=3, fromfile=page_id, tofile=diffname, lineterm='') diff_text = '\n'.join(diff) try: mail = Email( self.config['patch_mail_from'], 'Python Documentation Patches', self.config['patch_mail_to'], '', 'Patch for %s by %s' % (page_id, author), PATCH_MESSAGE % locals(), self.config['patch_mail_smtp'], ) mail.attachments.add_string('patch.diff', diff_text, 'text/x-diff') mail.send() except: import traceback traceback.print_exc() # XXX: how to report? pass return Response( render_template( req, 'submitted.html', self.globalcontext, dict(backlink=relative_uri('/@submit/' + page + '/', page + '/')))) return Response( render_template( req, 'edit.html', self.globalcontext, dict( contents=contents, author=author, email=email, summary=summary, pagename=page, form_error=form_error, rendered=rendered, submiturl=relative_uri('/@edit/' + page + '/', '/@submit/' + page), )))