def get_stylesheet_reference(self, relative_to=None): settings = self.settings if relative_to == None: relative_to = settings._destination if settings.pep_stylesheet_path: return utils.relative_path(relative_to, settings.pep_stylesheet_path) elif settings.pep_stylesheet: return settings.pep_stylesheet elif settings._stylesheet_path: return utils.relative_path(relative_to, settings.stylesheet_path) else: return settings.stylesheet
def read(self, path): """Read the file.""" if not self.state.document.settings.file_insertion_enabled: raise self.warning('"%s" directive disabled.' % self.name) path = directives.path(path) if False: source = self.state_machine.input_lines.source( self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = os.path.normpath(os.path.join(source_dir, path)) path = utils.relative_path(None, path) path = nodes.reprunicode(path) encoding = self.options.get( 'encoding', self.state.document.settings.input_encoding) e_handler=self.state.document.settings.input_encoding_error_handler try: self.state.document.settings.record_dependencies.add(path) include_file = io.FileInput(source_path=path, encoding=encoding, error_handler=e_handler) except UnicodeEncodeError, error: raise self.severe(u'Problems with "%s" directive path:\n' 'Cannot encode input file path "%s" ' '(wrong locale?).' % (self.name, SafeString(path)))
def add_translation_notes(): for language in supported_translations: build_dir = os.path.join(base_dir, 'build', language) language_dir = os.path.join(localedir, language, 'LC_MESSAGES') for root, dirs, files in os.walk(build_dir): # Skip Sphinx directories. for directory in excluded: if directory in dirs: dirs.remove(directory) if root == build_dir: continue for name in files: # See `sphinx.transforms.i18n.Locale.apply()`. # https://github.com/sphinx-doc/sphinx/blob/v2.2.1/sphinx/transforms/i18n.py source = os.path.join(root, os.path.dirname(name)) domain = relative_path(build_dir, source) path = os.path.join(language_dir, domain, 'index.po') if not os.path.isfile(path): path = os.path.join(language_dir, '%s.po' % domain) if not os.path.isfile(path): add_translation_note(os.path.join(root, name), language, domain) continue # Check the PO files, because Babel sets the msgstr to the msgid if the msgstr is missing. with open(path) as f: for message in read_po(f): if not message.string: add_translation_note(os.path.join(root, name), language, domain) break
def run(self): """Include a reST file as part of the content of this reST file.""" if not self.state.document.settings.file_insertion_enabled: raise self.warning('"%s" directive disabled.' % self.name) source = self.state_machine.input_lines.source(self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = directives.path(self.arguments[0]) if path.startswith("<") and path.endswith(">"): path = os.path.join(self.standard_include_path, path[1:-1]) path = os.path.normpath(os.path.join(source_dir, path)) path = utils.relative_path(None, path) path = nodes.reprunicode(path) encoding = self.options.get("encoding", self.state.document.settings.input_encoding) tab_width = self.options.get("tab-width", self.state.document.settings.tab_width) try: self.state.document.settings.record_dependencies.add(path) include_file = io.FileInput( source_path=path, encoding=encoding, error_handler=(self.state.document.settings.input_encoding_error_handler), handle_io_errors=None, ) except IOError, error: raise self.severe( 'Problems with "%s" directive path:\n%s: %s.' % (self.name, error.__class__.__name__, str(error)) )
def copy_static_entry(source, targetdir, builder, context={}, exclude_matchers=(), level=0): # type: (unicode, unicode, Any, Dict, Tuple[Callable, ...], int) -> None """[DEPRECATED] Copy a HTML builder static_path entry from source to targetdir. Handles all possible cases of files, directories and subdirectories. """ warnings.warn('sphinx.util.copy_static_entry is deprecated for removal', RemovedInSphinx30Warning, stacklevel=2) if exclude_matchers: relpath = relative_path(path.join(builder.srcdir, 'dummy'), source) for matcher in exclude_matchers: if matcher(relpath): return if path.isfile(source): copy_asset_file(source, targetdir, context, builder.templates) elif path.isdir(source): if not path.isdir(targetdir): os.mkdir(targetdir) for entry in os.listdir(source): if entry.startswith('.'): continue newtarget = targetdir if path.isdir(path.join(source, entry)): newtarget = path.join(targetdir, entry) copy_static_entry(path.join(source, entry), newtarget, builder, context, level=level + 1, exclude_matchers=exclude_matchers)
def copy_static_entry(source, targetdir, builder, context={}, exclude_matchers=(), level=0): """Copy a HTML builder static_path entry from source to targetdir. Handles all possible cases of files, directories and subdirectories. """ if exclude_matchers: relpath = relative_path(builder.srcdir, source) for matcher in exclude_matchers: if matcher(relpath): return if path.isfile(source): target = path.join(targetdir, path.basename(source)) if source.lower().endswith('_t') and builder.templates: # templated! fsrc = open(source, 'r', encoding='utf-8') fdst = open(target[:-2], 'w', encoding='utf-8') fdst.write(builder.templates.render_string(fsrc.read(), context)) fsrc.close() fdst.close() else: copyfile(source, target) elif path.isdir(source): if level == 0: for entry in os.listdir(source): if entry.startswith('.'): continue copy_static_entry(path.join(source, entry), targetdir, builder, context, level=1, exclude_matchers=exclude_matchers) else: target = path.join(targetdir, path.basename(source)) if path.exists(target): shutil.rmtree(target) shutil.copytree(source, target)
def run(self): """Include a reST file as part of the content of this reST file.""" #if not self.state.document.settings.file_insertion_enabled: # raise self.warning('"%s" directive disabled.' % self.name) source = self.state_machine.input_lines.source( self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = directives.path(self.arguments[0]) if path.startswith('<') and path.endswith('>'): path = os.path.join(self.standard_include_path, path[1:-1]) path = os.path.normpath(os.path.join(source_dir, path)) path = utils.relative_path(None, path) path = nodes.reprunicode(path) encoding = self.options.get( 'encoding', self.state.document.settings.input_encoding) tab_width = self.options.get( 'tab-width', self.state.document.settings.tab_width) startline = self.options.get('start-line', None) endline = self.options.get('end-line', None) after_text = self.options.get('start-after', None) before_text = self.options.get('end-before', None) self.state.document.settings.record_dependencies.add(path) return [include('', refuri=path, encoding=encoding, tab_width=tab_width, startline=startline, endline=endline, start_after=after_text, end_before=before_text)]
def generate_footer(self): # @@@ Text is hard-coded for now. # Should be made dynamic (language-dependent). settings = self.document.settings if settings.generator or settings.datestamp or settings.source_link or settings.source_url: text = [] if settings.source_link and settings._source or settings.source_url: if settings.source_url: source = settings.source_url else: source = utils.relative_path(settings._destination, settings._source) text.extend([nodes.reference("", "View document source", refuri=source), nodes.Text(".\n")]) if settings.datestamp: datestamp = time.strftime(settings.datestamp, time.gmtime()) text.append(nodes.Text("Generated on: " + datestamp + ".\n")) if settings.generator: text.extend( [ nodes.Text("Generated by "), nodes.reference("", "Docutils", refuri="http://docutils.sourceforge.net/"), nodes.Text(" from "), nodes.reference("", "reStructuredText", refuri="http://" "docutils.sourceforge.net/rst.html"), nodes.Text(" source.\n"), ] ) return [nodes.paragraph("", "", *text)] else: return None
def copy_static_entry(source, targetdir, builder, context={}, exclude_matchers=(), level=0): # type: (str, str, Any, Dict, Tuple[Callable, ...], int) -> None """[DEPRECATED] Copy a HTML builder static_path entry from source to targetdir. Handles all possible cases of files, directories and subdirectories. """ warnings.warn('sphinx.util.copy_static_entry is deprecated for removal', RemovedInSphinx30Warning, stacklevel=2) if exclude_matchers: relpath = relative_path(path.join(builder.srcdir, 'dummy'), source) for matcher in exclude_matchers: if matcher(relpath): return if path.isfile(source): copy_asset_file(source, targetdir, context, builder.templates) elif path.isdir(source): ensuredir(targetdir) for entry in os.listdir(source): if entry.startswith('.'): continue newtarget = targetdir if path.isdir(path.join(source, entry)): newtarget = path.join(targetdir, entry) copy_static_entry(path.join(source, entry), newtarget, builder, context, level=level + 1, exclude_matchers=exclude_matchers)
def run(self): """Include a file as part of the content of this reST file.""" if not self.state.document.settings.file_insertion_enabled: raise self.warning('"%s" directive disabled.' % self.name) source = self.state_machine.input_lines.source( self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = directives.path(self.arguments[0]) if path.startswith('<') and path.endswith('>'): path = os.path.join(self.standard_include_path, path[1:-1]) path = os.path.normpath(os.path.join(source_dir, path)) path = utils.relative_path(None, path) path = nodes.reprunicode(path) encoding = self.options.get( 'encoding', self.state.document.settings.input_encoding) e_handler=self.state.document.settings.input_encoding_error_handler tab_width = self.options.get( 'tab-width', self.state.document.settings.tab_width) try: self.state.document.settings.record_dependencies.add(path) include_file = io.FileInput(source_path=path, encoding=encoding, error_handler=e_handler) except UnicodeEncodeError, error: raise self.severe(u'Problems with "%s" directive path:\n' 'Cannot encode input file path "%s" ' '(wrong locale?).' % (self.name, SafeString(path)))
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 ensuredir(destination) if os.path.isfile(source): copy_asset_file(source, destination, context, renderer) return for root, dirs, files in walk(source): 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 generate_footer(self): # @@@ Text is hard-coded for now. # Should be made dynamic (language-dependent). settings = self.document.settings if settings.generator or settings.datestamp or settings.source_link \ or settings.source_url: text = [] if settings.source_link and settings._source \ or settings.source_url: if settings.source_url: source = settings.source_url else: source = utils.relative_path(settings._destination, settings._source) text.extend([ nodes.reference('', 'View document source', refuri=source), nodes.Text('.\n')]) if settings.datestamp: datestamp = time.strftime(settings.datestamp, time.gmtime()) text.append(nodes.Text('Generated on: ' + datestamp + '.\n')) if settings.generator: text.extend([ nodes.Text('Generated by '), nodes.reference('', 'Docutils', refuri= 'http://docutils.sourceforge.net/'), nodes.Text(' from '), nodes.reference('', 'reStructuredText', refuri='http://' 'docutils.sourceforge.net/rst.html'), nodes.Text(' source.\n')]) return [nodes.paragraph('', '', *text)] else: return None
def apply(self, **kwargs: Any) -> None: source = self.document["source"] msgstr = "" # XXX check if this is reliable assert source.startswith(self.env.srcdir) docname = path.splitext( relative_path(path.join(self.env.srcdir, "dummy"), source))[0] textdomain = docname_to_domain(docname, self.config.gettext_compact) # fetch translations dirs = [ path.join(self.env.srcdir, directory) for directory in self.config.locale_dirs ] # sphinx.locale.init changes its args type by version # so, ignore mypy check for the following call catalog, has_catalog = init_locale( dirs, self.config.language, textdomain # type: ignore ) if not has_catalog: return # for translated text keep original as ORIGINAL_TEXT_ATTR attribute for node, msg in extract_messages(self.document): msgstr = catalog.gettext(msg) if not msgstr or msgstr == msg or not msgstr.strip(): # as-of-yet untranslated continue # self.logger.info("add %s attr to node." % ORIGINAL_TEXT_ATTR) node[ORIGINAL_TEXT_ATTR] = msg
def _create_element_from_result(domain: Domain, inv_name: Optional[str], data: InventoryItem, node: pending_xref, contnode: TextElement) -> Element: proj, version, uri, dispname = data if '://' not in uri and node.get('refdoc'): # get correct path in case of subdirectories uri = path.join(relative_path(node['refdoc'], '.'), uri) if version: reftitle = _('(in %s v%s)') % (proj, version) else: reftitle = _('(in %s)') % (proj, ) newnode = nodes.reference('', '', internal=False, refuri=uri, reftitle=reftitle) if node.get('refexplicit'): # use whatever title was given newnode.append(contnode) elif dispname == '-' or \ (domain.name == 'std' and node['reftype'] == 'keyword'): # use whatever title was given, but strip prefix title = contnode.astext() if inv_name is not None and title.startswith(inv_name + ':'): newnode.append( contnode.__class__(title[len(inv_name) + 1:], title[len(inv_name) + 1:])) else: newnode.append(contnode) else: # else use the given display name (used for :ref:) newnode.append(contnode.__class__(dispname, dispname)) return newnode
def apply(self, **kwargs): for node in self.document.traverse( condition=nodes.image, ): uri = node['uri'] base, ext = os.path.splitext(uri) if ext != '.dot': continue source = self.document['source'] source_rel = utils.relative_path(None, source) source_dir = os.path.dirname(source_rel) uri_from_root = os.path.join(source_dir, uri) png_uri = '%s.png' % base base_from_root, _ = os.path.splitext(uri_from_root) png_path = '%s.png' % base_from_root # TODO would like to use sphinx.ext.graphviz.render_dot, # but it wants an object as self. with file(uri_from_root) as dot_fp: with file(png_path, 'w') as png_fp: with os.tmpfile() as pdf_fp: format_dot( dot_fp=dot_fp, pdf_fp=pdf_fp, png_fp=png_fp, ) node['uri'] = png_uri
def include(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """Include a reST file as part of the content of this reST file.""" if not state.document.settings.file_insertion_enabled: warning = state_machine.reporter.warning( '"%s" directive disabled.' % name, nodes.literal_block(block_text, block_text), line=lineno) return [warning] source = state_machine.input_lines.source( lineno - state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = directives.path(arguments[0]) if path.startswith('<') and path.endswith('>'): path = os.path.join(standard_include_path, path[1:-1]) path = os.path.normpath(os.path.join(source_dir, path)) path = utils.relative_path(None, path) encoding = options.get('encoding', state.document.settings.input_encoding) try: state.document.settings.record_dependencies.add(path) include_file = io.FileInput( source_path=path, encoding=encoding, error_handler=state.document.settings.input_encoding_error_handler, handle_io_errors=None) except IOError, error: severe = state_machine.reporter.severe( 'Problems with "%s" directive path:\n%s: %s.' % (name, error.__class__.__name__, error), nodes.literal_block(block_text, block_text), line=lineno) return [severe]
def run(self): """Include a file as part of the content of this reST file.""" if not self.state.document.settings.file_insertion_enabled: raise self.warning('"%s" directive disabled.' % self.name) source = self.state_machine.input_lines.source( self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = directives.path(self.arguments[0]) if path.startswith('<') and path.endswith('>'): path = os.path.join(self.standard_include_path, path[1:-1]) path = os.path.normpath(os.path.join(source_dir, path)) path = utils.relative_path(None, path) path = nodes.reprunicode(path) encoding = self.options.get( 'encoding', self.state.document.settings.input_encoding) tab_width = self.options.get('tab-width', self.state.document.settings.tab_width) try: self.state.document.settings.record_dependencies.add(path) include_file = io.FileInput( source_path=path, encoding=encoding, error_handler=(self.state.document.settings.\ input_encoding_error_handler), handle_io_errors=None) except IOError, error: raise self.severe(u'Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error)))
def process_images(self, docname, doctree): """ Process and rewrite image URIs. """ docdir = path.dirname(self.doc2path(docname, base=None)) for node in doctree.traverse(nodes.image): # Map the mimetype to the corresponding image. The writer may # choose the best image from these candidates. The special key * is # set if there is only single candidate to be used by a writer. # The special key ? is set for nonlocal URIs. node['candidates'] = candidates = {} imguri = node['uri'] if imguri.find('://') != -1: self.warn(docname, 'nonlocal image URI found: %s' % imguri, node.line) candidates['?'] = imguri continue # imgpath is the image path *from srcdir* if imguri.startswith('/') or imguri.startswith(os.sep): # absolute path (= relative to srcdir) imgpath = path.normpath(imguri[1:]) else: imgpath = path.normpath(path.join(docdir, imguri)) # set imgpath as default URI node['uri'] = imgpath if imgpath.endswith(os.extsep + '*'): for filename in glob(path.join(self.srcdir, imgpath)): new_imgpath = relative_path(self.srcdir, filename) if filename.lower().endswith('.pdf'): candidates['application/pdf'] = new_imgpath elif filename.lower().endswith('.svg'): candidates['image/svg+xml'] = new_imgpath elif ".latex." in filename.lower(): candidates['latex'] = new_imgpath elif ".html." in filename.lower(): candidates['html'] = new_imgpath else: try: f = open(filename, 'rb') try: imgtype = imghdr.what(f) finally: f.close() except ((OSError, IOError), err): self.warn(docname, 'image file %s not ' 'readable: %s' % (filename, err), node.line) if imgtype: candidates['image/' + imgtype] = new_imgpath else: candidates['*'] = imgpath # map image paths to unique image names (so that they can be put # into a single directory) for imgpath in candidates.values(): self.dependencies.setdefault(docname, set()).add(imgpath) if not os.access(path.join(self.srcdir, imgpath), os.R_OK): self.warn(docname, 'image file not readable: %s' % imgpath, node.line) continue self.images.add_file(docname, imgpath)
def run(self): env = self.state.document.settings.env openapi_path = self.arguments[0] _, openapi_path = env.relfn2path(openapi_path) openapi_path = utils.relative_path(None, openapi_path) openapi_path = nodes.reprunicode(openapi_path) self.state.document.settings.record_dependencies.add(openapi_path) with open(openapi_path, 'r') as f: openapi = OpenAPI.load(f) try: rendered = OPENAPI_TEMPLATE.render({ 'tags': openapi.tags.values(), 'servers': openapi.data['servers'] }) except Exception as error: raise self.severe('Failed to render template: {}'.format(ErrorString(error))) rendered_lines = statemachine.string2lines(rendered, 4, convert_whitespace=1) self.state_machine.insert_input(rendered_lines, '') # Allow people to use :ref: to link to resources. Sphinx offers two ways # of doing this: (1) lots of arcane boilerplate, or (2) hacking our way through. # Let's hope this doesn't break... stddomain = env.get_domain('std') labels = stddomain.data['labels'] for method, path, methods in openapi.resources(): method_hash = methods[method]['hash'] if method_hash not in labels: labels[method_hash] = (env.docname, method_hash, '{} {}'.format(method.upper(), path)) return []
def copy_static_entry(source, targetdir, builder, context={}, exclude_matchers=(), level=0): # type: (unicode, unicode, Any, Dict, Tuple[Callable, ...], int) -> None """[DEPRECATED] Copy a HTML builder static_path entry from source to targetdir. Handles all possible cases of files, directories and subdirectories. """ if exclude_matchers: relpath = relative_path(path.join(builder.srcdir, 'dummy'), source) for matcher in exclude_matchers: if matcher(relpath): return if path.isfile(source): copy_asset_file(source, targetdir, context, builder.templates) elif path.isdir(source): if not path.isdir(targetdir): os.mkdir(targetdir) for entry in os.listdir(source): if entry.startswith('.'): continue newtarget = targetdir if path.isdir(path.join(source, entry)): newtarget = path.join(targetdir, entry) copy_static_entry(path.join(source, entry), newtarget, builder, context, level=level + 1, exclude_matchers=exclude_matchers)
def open_file(self, path): """Open a file and register it as a dependency.""" path = os.path.normpath(path) path = utils.relative_path(None, path) path = nodes.reprunicode(path) self.state.document.settings.record_dependencies.add(path) return open(path, 'r')
def run(self): """Most of this method is from ``docutils.parser.rst.Directive``. docutils version: 0.12 """ if not self.state.document.settings.file_insertion_enabled: raise self.warning('"%s" directive disabled.' % self.name) source = self.state_machine.input_lines.source( self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = rst.directives.path(self.arguments[0]) path = os.path.normpath(os.path.join(source_dir, path)) path = utils.relative_path(None, path) path = nodes.reprunicode(path) # get options (currently not use directive-specific options) encoding = self.options.get( 'encoding', self.state.document.settings.input_encoding) e_handler = self.state.document.settings.input_encoding_error_handler tab_width = self.options.get('tab-width', self.state.document.settings.tab_width) # open the including file try: self.state.document.settings.record_dependencies.add(path) include_file = io.FileInput(source_path=path, encoding=encoding, error_handler=e_handler) except UnicodeEncodeError as error: raise self.severe('Problems with "%s" directive path:\n' 'Cannot encode input file path "%s" ' '(wrong locale?).' % (self.name, SafeString(path))) except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error))) # read from the file startline = self.options.get('start-line', None) endline = self.options.get('end-line', None) try: if startline or (endline is not None): lines = include_file.readlines() rawtext = ''.join(lines[startline:endline]) else: rawtext = include_file.read() except UnicodeError as error: raise self.severe('Problem with "%s" directive:\n%s' % (self.name, ErrorString(error))) config = self.state.document.settings.env.config converter = M2R(no_underscore_emphasis=config.no_underscore_emphasis, parse_relative_links=config.m2r_parse_relative_links, anonymous_references=config.m2r_anonymous_references, disable_inline_math=config.m2r_disable_inline_math) include_lines = statemachine.string2lines(converter(rawtext), tab_width, convert_whitespace=True) self.state_machine.insert_input(include_lines, path) return []
def onBtnSelPath(self, event): go_ahead = 1 dlg = wxFileDialog(self, 'Select a file', self.directory, '', '*.*', wxOPEN|wxFILE_MUST_EXIST) if dlg.ShowModal() == wxID_OK: path = dlg.GetPath() else: go_ahead = 0 dlg.Destroy() if go_ahead: if self.project == None: dlg = wxDirDialog(self, 'Calculate path relative' ' to which outputdirectory?', self.directory) if dlg.ShowModal() == wxID_OK: self.directory = dlg.GetPath() else: go_ahead = 0 dlg.Destroy() if go_ahead: self.pathCtrl.SetValue( quote(relative_path('%s%sdummy.html' % (self.directory, os.sep), path)))
def run(self): source = self.state_machine.input_lines.source( self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = directives.path(self.arguments[0]) path = os.path.normpath(os.path.join(source_dir, path)) path = utils.relative_path(None, path) path = nodes.reprunicode(path) img_folder = None img_folder_os = None if "image_folder" in self.options: # This is extremly messy.. # To be able to test if file exist in path we need to use img_path_os # But that cannot be used for the .. image:: tag, instead we need to use the raw option! img_folder_os = os.path.normpath( os.path.join(source_dir, self.options["image_folder"])) img_folder = self.options["image_folder"] rawtext = parse_examples(path, img_folder, img_folder_os) include_lines = statemachine.string2lines( rawtext, self.state.document.settings.tab_width, convert_whitespace=True) self.state_machine.insert_input(include_lines, path) return []
def run(self): self.assert_has_content() #txt = "<b>%s</b>" % self.content #print ' '.join(self.content) #x = self.content[0] #x = x.encode('ascii' #print self.state.document.__dict__ #print self.state.document.settings.env.__dict__ env = self.state.document.settings.env root = env.srcdir src = self.state.document.settings._source srcdir = os.path.dirname(src) #print "##### src:", src #print "##### srcdir:", srcdir #print "##### env" print env.__dict__ #print "##### env ---------" relpath = relative_path(root, src) #print "##### relpath:", relpath dest = os.path.join(root, "_build/html", relpath) destdir = os.path.dirname(dest) #print "##### destdir:", destdir if not os.path.exists(destdir): os.makedirs(destdir) txtout = StringIO.StringIO() txtin = '\n'.join(self.content) p = Parser(txtin,txtout) p.format(srcdir, destdir) txt = txtout.getvalue() return [nodes.raw('', txt, format='html')]
def copy_asset(source, destination, excluded=lambda path: False, context=None, renderer=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 """ if not os.path.exists(source): return ensuredir(destination) if os.path.isfile(source): copy_asset_file(source, destination, context, renderer) return for root, dirs, files in walk(source): 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 copy_static_entry(source, targetdir, builder, context={}, exclude_matchers=(), level=0): """[DEPRECATED] Copy a HTML builder static_path entry from source to targetdir. Handles all possible cases of files, directories and subdirectories. """ if exclude_matchers: relpath = relative_path(path.join(builder.srcdir, 'dummy'), source) for matcher in exclude_matchers: if matcher(relpath): return if path.isfile(source): copy_asset_file(source, targetdir, context, builder.templates) elif path.isdir(source): if not path.isdir(targetdir): os.mkdir(targetdir) for entry in os.listdir(source): if entry.startswith('.'): continue newtarget = targetdir if path.isdir(path.join(source, entry)): newtarget = path.join(targetdir, entry) copy_static_entry(path.join(source, entry), newtarget, builder, context, level=level+1, exclude_matchers=exclude_matchers)
def imap_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """Render an image <map> element.""" encoding = options.get('encoding', state.document.settings.input_encoding) image_alt = options.get('alt', '') image_class = options.get('class', '') attributes['source'] = imap_source = arguments[0] source_dir = os.path.dirname( os.path.abspath(state.document.current_source) ) path = os.path.normpath(os.path.join(source_dir, imap_source)) path = relative_path(None, path) try: state.document.settings.record_dependencies.add(path) raw_file = FileInput( source_path=path, encoding=encoding, error_handler=state.document.settings.input_encoding_error_handler, handle_io_errors=None) except IOError, error: severe = state_machine.reporter.severe( 'Problems with "%s" directive path:\n%s.' % (name, error), nodes.literal_block(block_text, block_text), line=lineno) return [severe]
def run(self): if not self.state.document.settings.raw_enabled or ( not self.state.document.settings.file_insertion_enabled and ("file" in self.options or "url" in self.options) ): raise self.warning('"%s" directive disabled.' % self.name) attributes = {"format": " ".join(self.arguments[0].lower().split())} encoding = self.options.get("encoding", self.state.document.settings.input_encoding) e_handler = self.state.document.settings.input_encoding_error_handler if self.content: if "file" in self.options or "url" in self.options: raise self.error( '"%s" directive may not both specify an external file ' "and have content." % self.name ) text = "\n".join(self.content) elif "file" in self.options: if "url" in self.options: raise self.error( 'The "file" and "url" options may not be simultaneously ' 'specified for the "%s" directive.' % self.name ) source_dir = os.path.dirname(os.path.abspath(self.state.document.current_source)) path = os.path.normpath(os.path.join(source_dir, self.options["file"])) path = utils.relative_path(None, path) try: raw_file = io.FileInput(source_path=path, encoding=encoding, error_handler=e_handler) # TODO: currently, raw input files are recorded as # dependencies even if not used for the chosen output format. self.state.document.settings.record_dependencies.add(path) except IOError, error: raise self.severe(u'Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error))) try: text = raw_file.read() except UnicodeError, error: raise self.severe(u'Problem with "%s" directive:\n%s' % (self.name, ErrorString(error)))
def process_images(self, docname, doctree): """ Process and rewrite image URIs. """ docdir = path.dirname(self.doc2path(docname, base=None)) for node in doctree.traverse(nodes.image): # Map the mimetype to the corresponding image. The writer may # choose the best image from these candidates. The special key * is # set if there is only single candidate to be used by a writer. # The special key ? is set for nonlocal URIs. node['candidates'] = candidates = {} imguri = node['uri'] if imguri.find('://') != -1: self.warn(docname, 'nonlocal image URI found: %s' % imguri, node.line) candidates['?'] = imguri continue # imgpath is the image path *from srcdir* if imguri.startswith('/') or imguri.startswith(os.sep): # absolute path (= relative to srcdir) imgpath = path.normpath(imguri[1:]) else: imgpath = path.normpath(path.join(docdir, imguri)) # set imgpath as default URI node['uri'] = imgpath if imgpath.endswith(os.extsep + '*'): for filename in glob(path.join(self.srcdir, imgpath)): new_imgpath = relative_path(self.srcdir, filename) if filename.lower().endswith('.pdf'): candidates['application/pdf'] = new_imgpath elif filename.lower().endswith('.svg'): candidates['image/svg+xml'] = new_imgpath elif ".latex." in filename.lower(): candidates['latex'] = new_imgpath elif ".html." in filename.lower(): candidates['html'] = new_imgpath else: try: f = open(filename, 'rb') try: imgtype = imghdr.what(f) finally: f.close() except (OSError, IOError), err: self.warn(docname, 'image file %s not ' 'readable: %s' % (filename, err), node.line) if imgtype: candidates['image/' + imgtype] = new_imgpath else: candidates['*'] = imgpath # map image paths to unique image names (so that they can be put # into a single directory) for imgpath in candidates.itervalues(): self.dependencies.setdefault(docname, set()).add(imgpath) if not os.access(path.join(self.srcdir, imgpath), os.R_OK): self.warn(docname, 'image file not readable: %s' % imgpath, node.line) continue self.images.add_file(docname, imgpath)
def copy_static_entry(source, targetdir, builder, context={}, exclude_matchers=(), level=0): """Copy a HTML builder static_path entry from source to targetdir. Handles all possible cases of files, directories and subdirectories. """ if exclude_matchers: relpath = relative_path(path.join(builder.srcdir, 'dummy'), source) for matcher in exclude_matchers: if matcher(relpath): return if path.isfile(source): target = path.join(targetdir, path.basename(source)) if source.lower().endswith('_t') and builder.templates: # templated! fsrc = open(source, 'r', encoding='utf-8') fdst = open(target[:-2], 'w', encoding='utf-8') fdst.write(builder.templates.render_string(fsrc.read(), context)) fsrc.close() fdst.close() else: copyfile(source, target) elif path.isdir(source): if not path.isdir(targetdir): os.mkdir(targetdir) for entry in os.listdir(source): if entry.startswith('.'): continue newtarget = targetdir if path.isdir(path.join(source, entry)): newtarget = path.join(targetdir, entry) copy_static_entry(path.join(source, entry), newtarget, builder, context, level=level+1, exclude_matchers=exclude_matchers)
def copy_extra_entry(source, targetdir, exclude_matchers=()): """Copy a HTML builder extra_path entry from source to targetdir. Handles all possible cases of files, directories and subdirectories. """ def excluded(path): relpath = relative_path(os.path.dirname(source), path) return any(matcher(relpath) for matcher in exclude_matchers) def copy_extra_file(source_, targetdir_): if not excluded(source_): target = path.join(targetdir_, os.path.basename(source_)) copyfile(source_, target) if os.path.isfile(source): copy_extra_file(source, targetdir) return for root, dirs, files in os.walk(source): reltargetdir = os.path.join(targetdir, relative_path(source, root)) for dir in dirs[:]: if excluded(os.path.join(root, dir)): dirs.remove(dir) else: target = os.path.join(reltargetdir, dir) if not path.exists(target): os.mkdir(target) for file in files: copy_extra_file(os.path.join(root, file), reltargetdir)
def missing_reference(app, env, node, contnode): """Attempt to resolve a missing reference via intersphinx references.""" target = node['reftarget'] if node['reftype'] == 'any': # we search anything! objtypes = ['%s:%s' % (domain.name, objtype) for domain in env.domains.values() for objtype in domain.object_types] domain = None elif node['reftype'] == 'doc': domain = 'std' # special case objtypes = ['std:doc'] else: domain = node.get('refdomain') if not domain: # only objects in domains are in the inventory return objtypes = env.domains[domain].objtypes_for_role(node['reftype']) if not objtypes: return objtypes = ['%s:%s' % (domain, objtype) for objtype in objtypes] to_try = [(env.intersphinx_inventory, target)] in_set = None if ':' in target: # first part may be the foreign doc set name setname, newtarget = target.split(':', 1) if setname in env.intersphinx_named_inventory: in_set = setname to_try.append((env.intersphinx_named_inventory[setname], newtarget)) for inventory, target in to_try: for objtype in objtypes: if objtype not in inventory or target not in inventory[objtype]: continue proj, version, uri, dispname = inventory[objtype][target] if '://' not in uri and node.get('refdoc'): # get correct path in case of subdirectories uri = path.join(relative_path(node['refdoc'], env.srcdir), uri) newnode = nodes.reference('', '', internal=False, refuri=uri, reftitle=_('(in %s v%s)') % (proj, version)) if node.get('refexplicit'): # use whatever title was given newnode.append(contnode) elif dispname == '-' or \ (domain == 'std' and node['reftype'] == 'keyword'): # use whatever title was given, but strip prefix title = contnode.astext() if in_set and title.startswith(in_set+':'): newnode.append(contnode.__class__(title[len(in_set)+1:], title[len(in_set)+1:])) else: newnode.append(contnode) else: # else use the given display name (used for :ref:) newnode.append(contnode.__class__(dispname, dispname)) return newnode # at least get rid of the ':' in the target if no explicit title given if in_set is not None and not node.get('refexplicit', True): if len(contnode) and isinstance(contnode[0], nodes.Text): contnode[0] = nodes.Text(newtarget, contnode[0].rawsource)
def raw(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ Pass through content unchanged Content is included in output based on type argument Content may be included inline (content section of directive) or imported from a file or url. """ if options.has_key('file') or options.has_key('url'): raise NotImplementedError, 'File inclusion not allowed!' if ( not state.document.settings.raw_enabled or (not state.document.settings.file_insertion_enabled and (options.has_key('file') or options.has_key('url'))) ): warning = state_machine.reporter.warning( '"%s" directive disabled.' % name, nodes.literal_block(block_text, block_text), line=lineno) return [warning] attributes = {'format': ' '.join(arguments[0].lower().split())} encoding = options.get('encoding', state.document.settings.input_encoding) if content: if options.has_key('file') or options.has_key('url'): error = state_machine.reporter.error( '"%s" directive may not both specify an external file and ' 'have content.' % name, nodes.literal_block(block_text, block_text), line=lineno) return [error] text = '\n'.join(content) elif options.has_key('file'): if options.has_key('url'): error = state_machine.reporter.error( 'The "file" and "url" options may not be simultaneously ' 'specified for the "%s" directive.' % name, nodes.literal_block(block_text, block_text), line=lineno) return [error] source_dir = os.path.dirname( os.path.abspath(state.document.current_source)) path = os.path.normpath(os.path.join(source_dir, options['file'])) path = utils.relative_path(None, path) try: state.document.settings.record_dependencies.add(path) raw_file = io.FileInput( source_path=path, encoding=encoding, error_handler=state.document.settings.input_encoding_error_handler, handle_io_errors=None) except IOError, error: severe = state_machine.reporter.severe( 'Problems with "%s" directive path:\n%s.' % (name, error), nodes.literal_block(block_text, block_text), line=lineno) return [severe] try: text = raw_file.read() except UnicodeError, error: severe = state_machine.reporter.severe( 'Problem with "%s" directive:\n%s: %s' % (name, error.__class__.__name__, error), nodes.literal_block(block_text, block_text), line=lineno) return [severe]
def get_stylesheet_reference(self, relative_to=None): settings = self.settings if settings.stylesheet_path: if relative_to == None: relative_to = settings._destination return utils.relative_path(relative_to, settings.stylesheet_path) else: return settings.stylesheet
def run(self): """Most of this method is from ``docutils.parser.rst.Directive``. docutils version: 0.12 """ if not self.state.document.settings.file_insertion_enabled: raise self.warning('"%s" directive disabled.' % self.name) source = self.state_machine.input_lines.source( self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = rst.directives.path(self.arguments[0]) path = os.path.normpath(os.path.join(source_dir, path)) path = utils.relative_path(None, path) path = nodes.reprunicode(path) # get options (currently not use directive-specific options) encoding = self.options.get( 'encoding', self.state.document.settings.input_encoding) e_handler = self.state.document.settings.input_encoding_error_handler # open the including file try: self.state.document.settings.record_dependencies.add(path) include_file = io.FileInput(source_path=path, encoding=encoding, error_handler=e_handler) except UnicodeEncodeError: raise self.severe('Problems with "%s" directive path:\n' 'Cannot encode input file path "%s" ' '(wrong locale?).' % (self.name, SafeString(path))) except OSError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error))) # read from the file startline = self.options.get('start-line', None) endline = self.options.get('end-line', None) try: if startline or (endline is not None): lines = include_file.readlines() rawtext = ''.join(lines[startline:endline]) else: rawtext = include_file.read() except UnicodeError as error: raise self.severe('Problem with "%s" directive:\n%s' % (self.name, ErrorString(error))) class CustomCommonMarkParser(CommonMarkParser): """Temporary workaround to remove multiple build warnings caused by upstream bug. See https://github.com/readthedocs/recommonmark/issues/177 for details. """ def visit_document(self, node): pass doc = utils.new_document(self.arguments[0]) md_parser = CustomCommonMarkParser() md_parser.parse(rawtext, doc) return [*doc.children]
def raw(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ Pass through content unchanged Content is included in output based on type argument Content may be included inline (content section of directive) or imported from a file or url. """ if ( not state.document.settings.raw_enabled or (not state.document.settings.file_insertion_enabled and (options.has_key('file') or options.has_key('url'))) ): warning = state_machine.reporter.warning( '"%s" directive disabled.' % name, nodes.literal_block(block_text, block_text), line=lineno) return [warning] attributes = {'format': ' '.join(arguments[0].lower().split())} encoding = options.get('encoding', state.document.settings.input_encoding) if content: if options.has_key('file') or options.has_key('url'): error = state_machine.reporter.error( '"%s" directive may not both specify an external file and ' 'have content.' % name, nodes.literal_block(block_text, block_text), line=lineno) return [error] text = '\n'.join(content) elif options.has_key('file'): if options.has_key('url'): error = state_machine.reporter.error( 'The "file" and "url" options may not be simultaneously ' 'specified for the "%s" directive.' % name, nodes.literal_block(block_text, block_text), line=lineno) return [error] source_dir = os.path.dirname( os.path.abspath(state.document.current_source)) path = os.path.normpath(os.path.join(source_dir, options['file'])) path = utils.relative_path(None, path) try: state.document.settings.record_dependencies.add(path) raw_file = io.FileInput( source_path=path, encoding=encoding, error_handler=state.document.settings.input_encoding_error_handler, handle_io_errors=None) except IOError, error: severe = state_machine.reporter.severe( 'Problems with "%s" directive path:\n%s.' % (name, error), nodes.literal_block(block_text, block_text), line=lineno) return [severe] try: text = raw_file.read() except UnicodeError, error: severe = state_machine.reporter.severe( 'Problem with "%s" directive:\n%s: %s' % (name, error.__class__.__name__, error), nodes.literal_block(block_text, block_text), line=lineno) return [severe]
def _get_source_path(self): # Taken from `docutils.parsers.rst.directives.misc.Include` source = self.state_machine.input_lines.source( self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = directives.path(self.arguments[0]) path = os.path.normpath(os.path.join(source_dir, path)) path = relative_path(None, path) return nodes.reprunicode(path)
def run(self): attributes = {'format': ' '.join(self.arguments[0].lower().split())} encoding = self.options.get( 'encoding', self.state.document.settings.input_encoding) title_key = self.options.get('title-key', '') id_key = self.options.get('id-key', '') id_prefix = self.options.get('id-prefix', '') if self.content: if 'file' in self.options: raise self.error( '"%s" directive may not both specify an external file ' 'and have content.' % self.name) text = '\n'.join(self.content) elif 'file' in self.options: source_dir = str( Path(self.state.document.current_source).resolve().parent) path = (Path(source_dir) / self.options['file']).resolve() text = path.read_text(encoding=encoding) attributes['source'] = utils.relative_path(None, path) with io.StringIO(text) as f: rows = list(csv.reader(f)) output = '<div class="csv-list">' header = rows[0] for row in rows[1:]: obj = dict(zip(header, row)) if id_key in obj: output += f'<div class="csv-list-item" id="{id_prefix + obj[id_key]}">' else: output += '<div class="csv-list-item">' for key, value in zip(header, row): if key != title_key: continue value = re.sub(r'[\r\n]+', '<br>', value) output += f'<p class="csv-list-title caption" data-csv-list-key="{key}">' output += f'<span class="csv-list-key">{key}</span>' output += f'<span class="csv-list-value">{value}</span>' if id_key in obj: output += f'<a class="headerlink" href="#{id_prefix + obj[id_key]}" title="{_("Permalink to this headline")}">¶</a>' output += '</p>' for key, value in zip(header, row): if key == title_key: continue value = re.sub(r'[\r\n]+', '<br>', value) output += f'<p class="csv-list-field" data-csv-list-key="{key}">' output += f'<span class="csv-list-key">{key}</span>' output += f'<span class="csv-list-value">{value}</span>' output += '</p>' output += '</div>' output += '</div>' raw_node = nodes.raw('', output, **attributes) (raw_node.source, raw_node.line) = self.state_machine.get_source_and_line(self.lineno) return [raw_node]
def run(self): """Include a file as part of the content of this reST file.""" if not self.state.document.settings.file_insertion_enabled: raise self.warning('"%s" directive disabled.' % self.name) source = self.state_machine.input_lines.source(self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = directives.path(self.arguments[0]) path = os.path.normpath(os.path.join(source_dir, path)) path = utils.relative_path(None, path) path = nodes.reprunicode(path) encoding = self.options.get("encoding", self.state.document.settings.input_encoding) e_handler = self.state.document.settings.input_encoding_error_handler tab_width = self.options.get("tab-width", self.state.document.settings.tab_width) try: self.state.document.settings.record_dependencies.add(path) include_file = io.FileInput(source_path=path, encoding=encoding, error_handler=e_handler) except UnicodeEncodeError as error: raise self.severe( 'Problems with "%s" directive path:\n' 'Cannot encode input file path "%s" ' "(wrong locale?)." % (self.name, SafeString(path)) ) except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error))) startline = self.options.get("start-line", None) endline = self.options.get("end-line", None) try: if startline or (endline is not None): lines = include_file.readlines() rawtext = "".join(lines[startline:endline]) else: rawtext = include_file.read() except UnicodeError as error: raise self.severe('Problem with "%s" directive:\n%s' % (self.name, ErrorString(error))) include_lines = statemachine.string2lines(rawtext, tab_width, convert_whitespace=True) # default lexer to 'text' lexer = self.options.get("lexer", "text") self.options["source"] = path codeblock = Pygments( self.name, [lexer], # arguments {}, # no options for this directive include_lines, # content self.lineno, self.content_offset, self.block_text, self.state, self.state_machine, ) return codeblock.run()
def process_doc(self, app, doctree): # type: (Sphinx, nodes.Node) -> None """Process and rewrite image URIs.""" docname = app.env.docname for node in doctree.traverse(nodes.image): # Map the mimetype to the corresponding image. The writer may # choose the best image from these candidates. The special key * is # set if there is only single candidate to be used by a writer. # The special key ? is set for nonlocal URIs. candidates = {} # type: Dict[unicode, unicode] node['candidates'] = candidates imguri = node['uri'] if imguri.startswith('data:'): candidates['?'] = imguri continue elif imguri.find('://') != -1: candidates['?'] = imguri continue rel_imgpath, full_imgpath = app.env.relfn2path(imguri, docname) if app.config.language: # substitute figures (ex. foo.png -> foo.en.png) i18n_full_imgpath = search_image_for_language( full_imgpath, app.env) if i18n_full_imgpath != full_imgpath: full_imgpath = i18n_full_imgpath rel_imgpath = relative_path(path.join(app.srcdir, 'dummy'), i18n_full_imgpath) # set imgpath as default URI node['uri'] = rel_imgpath if rel_imgpath.endswith(os.extsep + '*'): if app.config.language: # Search language-specific figures at first i18n_imguri = get_image_filename_for_language( imguri, app.env) _, full_i18n_imgpath = app.env.relfn2path( i18n_imguri, docname) self.collect_candidates(app.env, full_i18n_imgpath, candidates, node) self.collect_candidates(app.env, full_imgpath, candidates, node) else: candidates['*'] = rel_imgpath # map image paths to unique image names (so that they can be put # into a single directory) for imgpath in candidates.values(): app.env.dependencies[docname].add(imgpath) if not os.access(path.join(app.srcdir, imgpath), os.R_OK): logger.warning(__('image file not readable: %s') % imgpath, location=node, type='image', subtype='not_readable') continue app.env.images.add_file(docname, imgpath)
def _get_directive_path(self, path): """ Returns transformed path from the directive option/content """ source = self.state_machine.input_lines.source(self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = os.path.normpath(os.path.join(source_dir, path)) return utils.relative_path(None, path)
def _get_directive_path(self, path): """ Returns transformed path from the directive option/content """ source = self.state_machine.input_lines.source( self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = os.path.normpath(os.path.join(source_dir, path)) return utils.relative_path(None, path)
def run(self): # check if raw html is supported if not self.state.document.settings.raw_enabled: raise self.warning('"%s" directive disabled.' % self.name) # set up encoding attributes = {"format": "html"} encoding = self.options.get( "encoding", self.state.document.settings.input_encoding ) e_handler = self.state.document.settings.input_encoding_error_handler # get path to notebook source_dir = os.path.dirname( os.path.abspath(self.state.document.current_source) ) nb_path = os.path.normpath(os.path.join(source_dir, self.arguments[0])) nb_path = utils.relative_path(None, nb_path) # convert notebook to html exporter = HTMLExporter(template_file="full") output, resources = exporter.from_filename(nb_path) header = output.split("<head>", 1)[1].split("</head>", 1)[0] body = output.split("<body>", 1)[1].split("</body>", 1)[0] # add HTML5 scoped attribute to header style tags header = header.replace("<style", '<style scoped="scoped"') header = header.replace("body{background-color:#ffffff;}\n", "") header = header.replace( "body{background-color:white;position:absolute;" "left:0px;right:0px;top:0px;bottom:0px;" "overflow:visible;}\n", "", ) header = header.replace("background-color:#ffffff;", "", 1) # concatenate raw html lines lines = ['<div class="ipynotebook">'] lines.append(header) lines.append(body) lines.append("</div>") text = "\n".join(lines) # add dependency self.state.document.settings.record_dependencies.add(nb_path) attributes["source"] = nb_path # create notebook node nb_node = notebook("", text, **attributes) (nb_node.source, nb_node.line) = self.state_machine.get_source_and_line( self.lineno ) return [nb_node]
def process_doc(self, app, doctree): # type: (Sphinx, nodes.Node) -> None """Process and rewrite image URIs.""" docname = app.env.docname for node in doctree.traverse(nodes.image): # Map the mimetype to the corresponding image. The writer may # choose the best image from these candidates. The special key * is # set if there is only single candidate to be used by a writer. # The special key ? is set for nonlocal URIs. candidates = {} # type: Dict[unicode, unicode] node['candidates'] = candidates imguri = node['uri'] if imguri.startswith('data:'): logger.warning('image data URI found. some builders might not support', location=node, type='image', subtype='data_uri') candidates['?'] = imguri continue elif imguri.find('://') != -1: logger.warning('nonlocal image URI found: %s' % imguri, location=node, type='image', subtype='nonlocal_uri') candidates['?'] = imguri continue rel_imgpath, full_imgpath = app.env.relfn2path(imguri, docname) if app.config.language: # substitute figures (ex. foo.png -> foo.en.png) i18n_full_imgpath = search_image_for_language(full_imgpath, app.env) if i18n_full_imgpath != full_imgpath: full_imgpath = i18n_full_imgpath rel_imgpath = relative_path(path.join(app.srcdir, 'dummy'), i18n_full_imgpath) # set imgpath as default URI node['uri'] = rel_imgpath if rel_imgpath.endswith(os.extsep + '*'): if app.config.language: # Search language-specific figures at first i18n_imguri = get_image_filename_for_language(imguri, app.env) _, full_i18n_imgpath = app.env.relfn2path(i18n_imguri, docname) self.collect_candidates(app.env, full_i18n_imgpath, candidates, node) self.collect_candidates(app.env, full_imgpath, candidates, node) else: candidates['*'] = rel_imgpath # map image paths to unique image names (so that they can be put # into a single directory) for imgpath in itervalues(candidates): app.env.dependencies[docname].add(imgpath) if not os.access(path.join(app.srcdir, imgpath), os.R_OK): logger.warning('image file not readable: %s' % imgpath, location=node, type='image', subtype='not_readable') continue app.env.images.add_file(docname, imgpath)
def run(self): # check if raw html is supported if not self.state.document.settings.raw_enabled: raise self.warning('"%s" directive disabled.' % self.name) # set up encoding attributes = {'format': 'html'} show_count = 'no-count' not in self.options # get path to bibtex file source_file = self.state.document.current_source source_dir = os.path.dirname(os.path.abspath(source_file)) bibtex_path = os.path.normpath( os.path.join(source_dir, self.arguments[0])) bibtex_path = utils.relative_path(None, bibtex_path) # get and sanitize the bibtex with open(bibtex_path, encoding='utf-8') as f: bibtext = f.read() bibtext = bibtext.replace(r'\&', '&') bibtext = bibtext.replace(r'\bf', '') n = 1 while 0 < n: bibtext, n = nested_brace_pattern.subn(nested_brace_replace, bibtext) if show_count: lower_bibtext = bibtext.lower() num_entries = 0 for entry_type in ENTRY_TYPES: num_entries += lower_bibtext.count('@' + entry_type) styletext = BASE_STYLE if 0 == len(self.content) else '\n'.join( self.content) text = '<textarea id="bibtex_input" style="display:none;">\n' text += bibtext text += '</textarea>\n' text += styletext if show_count: text += ('<a style="font-style: bold;">Number of entries: ' '{0}</a><br/><br/>\n'.format(num_entries)) text += '<div id="bibtex_display"></div>\n' # add dependency self.state.document.settings.record_dependencies.add(bibtex_path) attributes['source'] = bibtex_path # create notebook node bibtex_node = bibtex('', text, **attributes) (bibtex_node.source, bibtex_node.line) = \ self.state_machine.get_source_and_line(self.lineno) return [bibtex_node]
def run(self): """Most of this method is from ``docutils.parser.rst.Directive``. docutils version: 0.12 """ if not self.state.document.settings.file_insertion_enabled: raise self.warning('"%s" directive disabled.' % self.name) source = self.state_machine.input_lines.source( self.lineno - self.state_machine.input_offset - 1) source_dir = os.path.dirname(os.path.abspath(source)) path = rst.directives.path(self.arguments[0]) path = os.path.normpath(os.path.join(source_dir, path)) path = utils.relative_path(None, path) path = nodes.reprunicode(path) # get options (currently not use directive-specific options) encoding = self.options.get( 'encoding', self.state.document.settings.input_encoding) e_handler = self.state.document.settings.input_encoding_error_handler tab_width = self.options.get( 'tab-width', self.state.document.settings.tab_width) # open the inclding file try: self.state.document.settings.record_dependencies.add(path) include_file = io.FileInput(source_path=path, encoding=encoding, error_handler=e_handler) except UnicodeEncodeError as error: raise self.severe('Problems with "%s" directive path:\n' 'Cannot encode input file path "%s" ' '(wrong locale?).' % (self.name, SafeString(path))) except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error))) # read from the file try: rawtext = include_file.read() except UnicodeError as error: raise self.severe('Problem with "%s" directive:\n%s' % (self.name, ErrorString(error))) config = self.state.document.settings.env.config converter = M2R(no_underscore_emphasis=config.no_underscore_emphasis) include_lines = statemachine.string2lines(converter(rawtext), tab_width, convert_whitespace=True) self.state_machine.insert_input(include_lines, path) return []
def collect_candidates(imgpath, candidates): globbed = {} for filename in glob(imgpath): new_imgpath = relative_path(path.join(self.srcdir, 'dummy'), filename) try: mimetype = guess_mimetype(filename) if mimetype not in candidates: globbed.setdefault(mimetype, []).append(new_imgpath) except (OSError, IOError) as err: self.warn_node('image file %s not readable: %s' % (filename, err), node) for key, files in iteritems(globbed): candidates[key] = sorted(files, key=len)[0] # select by similarity
def run(self): # check if raw html is supported if not self.state.document.settings.raw_enabled: raise self.warning('"%s" directive disabled.' % self.name) # set up encoding attributes = {'format': 'html'} show_count = 'no-count' not in self.options # get path to bibtex file source_file = self.state.document.current_source source_dir = os.path.dirname(os.path.abspath(source_file)) bibtex_path = os.path.normpath(os.path.join(source_dir, self.arguments[0])) bibtex_path = utils.relative_path(None, bibtex_path) # get and sanitize the bibtex with open(bibtex_path, encoding='utf-8') as f: bibtext = f.read() bibtext = bibtext.replace(r'\&', '&') bibtext = bibtext.replace(r'\bf', '') n = 1 while 0 < n: bibtext, n = nested_brace_pattern.subn(nested_brace_replace, bibtext) if show_count: lower_bibtext = bibtext.lower() num_entries = 0 for entry_type in ENTRY_TYPES: num_entries += lower_bibtext.count('@' + entry_type) styletext = BASE_STYLE if 0 == len(self.content) else '\n'.join(self.content) text = '<textarea id="bibtex_input" style="display:none;">\n' text += bibtext text += '</textarea>\n' text += styletext if show_count: text += ('<a style="font-style: bold;">Number of entries: ' '{0}</a><br/><br/>\n'.format(num_entries)) text += '<div id="bibtex_display"></div>\n' # add dependency self.state.document.settings.record_dependencies.add(bibtex_path) attributes['source'] = bibtex_path # create notebook node bibtex_node = bibtex('', text, **attributes) (bibtex_node.source, bibtex_node.line) = \ self.state_machine.get_source_and_line(self.lineno) return [bibtex_node]
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 process_dependencies(self, docname, doctree): """Process docutils-generated dependency info.""" cwd = getcwd() frompath = path.join(path.normpath(self.srcdir), 'dummy') deps = doctree.settings.record_dependencies if not deps: return for dep in deps.list: # the dependency path is relative to the working dir, so get # one relative to the srcdir if isinstance(dep, bytes): dep = dep.decode(fs_encoding) relpath = relative_path(frompath, path.normpath(path.join(cwd, dep))) self.dependencies.setdefault(docname, set()).add(relpath)
def process_doc(self, app: Sphinx, doctree: nodes.document) -> None: """Process docutils-generated dependency info.""" cwd = os.getcwd() frompath = path.join(path.normpath(app.srcdir), 'dummy') deps = doctree.settings.record_dependencies if not deps: return for dep in deps.list: # the dependency path is relative to the working dir, so get # one relative to the srcdir if isinstance(dep, bytes): dep = dep.decode(fs_encoding) relpath = relative_path(frompath, path.normpath(path.join(cwd, dep))) app.env.dependencies[app.env.docname].add(relpath)
def collect_candidates(self, env, imgpath, candidates, node): # type: (BuildEnvironment, unicode, Dict[unicode, unicode], nodes.Node) -> None globbed = {} # type: Dict[unicode, List[unicode]] for filename in glob(imgpath): new_imgpath = relative_path(path.join(env.srcdir, 'dummy'), filename) try: mimetype = guess_mimetype(filename) if mimetype not in candidates: globbed.setdefault(mimetype, []).append(new_imgpath) except (OSError, IOError) as err: logger.warning(__('image file %s not readable: %s') % (filename, err), location=node, type='image', subtype='not_readable') for key, files in iteritems(globbed): candidates[key] = sorted(files, key=len)[0] # select by similarity
def get_csv_data(self): """ Get CSV data from the directive content, from an external file, or from a URL reference. """ encoding = self.options.get( 'encoding', self.state.document.settings.input_encoding) if self.content: # CSV data is from directive content. if 'file' in self.options or 'url' in self.options: error = self.state_machine.reporter.error( '"%s" directive may not both specify an external file and' ' have content.' % self.name, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) raise SystemMessagePropagation(error) source = self.content.source(0) csv_data = self.content elif 'file' in self.options: # CSV data is from an external file. if 'url' in self.options: error = self.state_machine.reporter.error( 'The "file" and "url" options may not be simultaneously' ' specified for the "%s" directive.' % self.name, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) raise SystemMessagePropagation(error) source_dir = os.path.dirname( os.path.abspath(self.state.document.current_source)) source = os.path.normpath( os.path.join(source_dir, self.options['file'])) source = utils.relative_path(None, source) try: self.state.document.settings.record_dependencies.add(source) csv_file = io.FileInput( source_path=source, encoding=encoding, error_handler=(self.state.document.settings.\ input_encoding_error_handler), handle_io_errors=None) csv_data = csv_file.read().splitlines() except IOError, error: severe = self.state_machine.reporter.severe( 'Problems with "%s" directive path:\n%s.' % (self.name, error), nodes.literal_block(self.block_text, self.block_text), line=self.lineno) raise SystemMessagePropagation(severe)