mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add new env method to get the real path to a file reference, and use it.
This commit is contained in:
@@ -7,10 +7,8 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import codecs
|
||||
from os import path
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import Directive, directives
|
||||
@@ -93,23 +91,11 @@ class LiteralInclude(Directive):
|
||||
|
||||
def run(self):
|
||||
document = self.state.document
|
||||
filename = self.arguments[0]
|
||||
if not document.settings.file_insertion_enabled:
|
||||
return [document.reporter.warning('File insertion disabled',
|
||||
line=self.lineno)]
|
||||
env = document.settings.env
|
||||
if filename.startswith('/') or filename.startswith(os.sep):
|
||||
rel_fn = filename[1:]
|
||||
else:
|
||||
docdir = path.dirname(env.doc2path(env.docname, base=None))
|
||||
rel_fn = path.join(docdir, filename)
|
||||
try:
|
||||
fn = path.join(env.srcdir, rel_fn)
|
||||
except UnicodeDecodeError:
|
||||
# the source directory is a bytestring with non-ASCII characters;
|
||||
# let's try to encode the rel_fn in the file system encoding
|
||||
rel_fn = rel_fn.encode(sys.getfilesystemencoding())
|
||||
fn = path.join(env.srcdir, rel_fn)
|
||||
rel_filename, filename = env.relfn2path(self.arguments[0])
|
||||
|
||||
if 'pyobject' in self.options and 'lines' in self.options:
|
||||
return [document.reporter.warning(
|
||||
@@ -119,7 +105,7 @@ class LiteralInclude(Directive):
|
||||
encoding = self.options.get('encoding', env.config.source_encoding)
|
||||
codec_info = codecs.lookup(encoding)
|
||||
try:
|
||||
f = codecs.StreamReaderWriter(open(fn, 'rb'),
|
||||
f = codecs.StreamReaderWriter(open(filename, 'rb'),
|
||||
codec_info[2], codec_info[3], 'strict')
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
@@ -136,7 +122,7 @@ class LiteralInclude(Directive):
|
||||
objectname = self.options.get('pyobject')
|
||||
if objectname is not None:
|
||||
from sphinx.pycode import ModuleAnalyzer
|
||||
analyzer = ModuleAnalyzer.for_file(fn, '')
|
||||
analyzer = ModuleAnalyzer.for_file(filename, '')
|
||||
tags = analyzer.find_tags()
|
||||
if objectname not in tags:
|
||||
return [document.reporter.warning(
|
||||
@@ -178,13 +164,13 @@ class LiteralInclude(Directive):
|
||||
text = ''.join(lines)
|
||||
if self.options.get('tab-width'):
|
||||
text = text.expandtabs(self.options['tab-width'])
|
||||
retnode = nodes.literal_block(text, text, source=fn)
|
||||
retnode = nodes.literal_block(text, text, source=filename)
|
||||
retnode.line = 1
|
||||
if self.options.get('language', ''):
|
||||
retnode['language'] = self.options['language']
|
||||
if 'linenos' in self.options:
|
||||
retnode['linenos'] = True
|
||||
document.settings.env.note_dependency(rel_fn)
|
||||
env.note_dependency(rel_filename)
|
||||
return [retnode]
|
||||
|
||||
|
||||
|
||||
@@ -369,14 +369,13 @@ from docutils.parsers.rst.directives.misc import Include as BaseInclude
|
||||
class Include(BaseInclude):
|
||||
"""
|
||||
Like the standard "Include" directive, but interprets absolute paths
|
||||
correctly.
|
||||
"correctly", i.e. relative to source directory.
|
||||
"""
|
||||
|
||||
def run(self):
|
||||
if self.arguments[0].startswith('/') or \
|
||||
self.arguments[0].startswith(os.sep):
|
||||
env = self.state.document.settings.env
|
||||
self.arguments[0] = os.path.join(env.srcdir, self.arguments[0][1:])
|
||||
env = self.state.document.settings.env
|
||||
rel_filename, filename = env.relfn2path(self.arguments[0])
|
||||
self.arguments[0] = filename
|
||||
return BaseInclude.run(self)
|
||||
|
||||
|
||||
|
||||
@@ -433,6 +433,27 @@ class BuildEnvironment:
|
||||
else:
|
||||
return path.join(base, docname) + suffix
|
||||
|
||||
def relfn2path(self, filename, docname=None):
|
||||
"""Return paths to a file referenced from a document, relative to
|
||||
documentation root and absolute.
|
||||
|
||||
Absolute filenames are relative to the source dir, while relative
|
||||
filenames are relative to the dir of the containing document.
|
||||
"""
|
||||
if filename.startswith('/') or filename.startswith(os.sep):
|
||||
rel_fn = filename[1:]
|
||||
else:
|
||||
docdir = path.dirname(self.doc2path(docname or self.docname,
|
||||
base=None))
|
||||
rel_fn = path.join(docdir, filename)
|
||||
try:
|
||||
return rel_fn, path.join(self.srcdir, rel_fn)
|
||||
except UnicodeDecodeError:
|
||||
# the source directory is a bytestring with non-ASCII characters;
|
||||
# let's try to encode the rel_fn in the file system encoding
|
||||
enc_rel_fn = rel_fn.encode(sys.getfilesystemencoding())
|
||||
return rel_fn, path.join(self.srcdir, enc_rel_fn)
|
||||
|
||||
def find_files(self, config):
|
||||
"""Find all source files in the source dir and put them in
|
||||
self.found_docs.
|
||||
@@ -806,25 +827,19 @@ class BuildEnvironment:
|
||||
|
||||
def process_downloads(self, docname, doctree):
|
||||
"""Process downloadable file paths. """
|
||||
docdir = path.dirname(self.doc2path(docname, base=None))
|
||||
for node in doctree.traverse(addnodes.download_reference):
|
||||
targetname = node['reftarget']
|
||||
if targetname.startswith('/') or targetname.startswith(os.sep):
|
||||
# absolute
|
||||
filepath = targetname[1:]
|
||||
else:
|
||||
filepath = path.normpath(path.join(docdir, node['reftarget']))
|
||||
self.dependencies.setdefault(docname, set()).add(filepath)
|
||||
if not os.access(path.join(self.srcdir, filepath), os.R_OK):
|
||||
self.warn(docname, 'download file not readable: %s' % filepath,
|
||||
rel_filename, filename = self.relfn2path(targetname, docname)
|
||||
self.dependencies.setdefault(docname, set()).add(rel_filename)
|
||||
if not os.access(filename, os.R_OK):
|
||||
self.warn(docname, 'download file not readable: %s' % filename,
|
||||
getattr(node, 'line', None))
|
||||
continue
|
||||
uniquename = self.dlfiles.add_file(docname, filepath)
|
||||
uniquename = self.dlfiles.add_file(docname, filename)
|
||||
node['filename'] = uniquename
|
||||
|
||||
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
|
||||
@@ -837,16 +852,11 @@ class BuildEnvironment:
|
||||
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))
|
||||
rel_imgpath, full_imgpath = self.relfn2path(imguri, docname)
|
||||
# set imgpath as default URI
|
||||
node['uri'] = imgpath
|
||||
if imgpath.endswith(os.extsep + '*'):
|
||||
for filename in glob(path.join(self.srcdir, imgpath)):
|
||||
node['uri'] = rel_imgpath
|
||||
if rel_imgpath.endswith(os.extsep + '*'):
|
||||
for filename in glob(full_imgpath):
|
||||
new_imgpath = relative_path(self.srcdir, filename)
|
||||
if filename.lower().endswith('.pdf'):
|
||||
candidates['application/pdf'] = new_imgpath
|
||||
@@ -866,7 +876,7 @@ class BuildEnvironment:
|
||||
if imgtype:
|
||||
candidates['image/' + imgtype] = new_imgpath
|
||||
else:
|
||||
candidates['*'] = imgpath
|
||||
candidates['*'] = rel_imgpath
|
||||
# map image paths to unique image names (so that they can be put
|
||||
# into a single directory)
|
||||
for imgpath in candidates.itervalues():
|
||||
|
||||
Reference in New Issue
Block a user