mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '1.8'
This commit is contained in:
28
CHANGES
28
CHANGES
@@ -31,6 +31,9 @@ Incompatible changes
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
* ``sphinx.io.SphinxI18nReader.set_lineno_for_reporter()`` is deprecated
|
||||
* ``sphinx.io.SphinxI18nReader.line`` is deprecated
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
@@ -38,7 +41,10 @@ Bugs fixed
|
||||
----------
|
||||
|
||||
* html: search box overrides to other elements if scrolled
|
||||
* i18n: warnings for translation catalogs have wrong line numbers (refs: #5321)
|
||||
* #5325: latex: cross references has been broken by multiply labeled objects
|
||||
* C++, fixes for symbol addition and lookup. Lookup should no longer break
|
||||
in partial builds. See also #5337.
|
||||
|
||||
Testing
|
||||
--------
|
||||
@@ -292,7 +298,7 @@ Documentation
|
||||
* #5083: Fix wrong make.bat option for internationalization.
|
||||
* #5115: napoleon: add admonitions added by #4613 to the docs.
|
||||
|
||||
Release 1.7.8 (in development)
|
||||
Release 1.7.9 (in development)
|
||||
==============================
|
||||
|
||||
Dependencies
|
||||
@@ -310,12 +316,26 @@ Features added
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 1.7.8 (released Aug 29, 2018)
|
||||
=====================================
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
* The type of ``env.included`` has been changed to dict of set
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* #5320: intersphinx: crashed if invalid url given
|
||||
* #5326: manpage: crashed when invalid docname is specified as ``man_pages``
|
||||
* #5322: autodoc: ``Any`` typehint causes formatting error
|
||||
|
||||
Testing
|
||||
--------
|
||||
* #5327: "document isn't included in any toctree" warning on rebuild with
|
||||
generated files
|
||||
* #5335: quickstart: escape sequence has been displayed with MacPorts' python
|
||||
|
||||
Release 1.7.7 (released Aug 19, 2018)
|
||||
=====================================
|
||||
|
||||
@@ -136,6 +136,16 @@ The following is a list of deprecated interface.
|
||||
- 4.0
|
||||
- :confval:`autodoc_default_options`
|
||||
|
||||
* - ``sphinx.io.SphinxI18nReader.set_lineno_for_reporter()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.io.SphinxI18nReader.line``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.directives.other.VersionChanges``
|
||||
- 1.8
|
||||
- 3.0
|
||||
|
||||
@@ -9,9 +9,9 @@ Logging API
|
||||
|
||||
.. autoclass:: SphinxLoggerAdapter(logging.LoggerAdapter)
|
||||
|
||||
.. method:: SphinxLoggerAdapter.error(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.critical(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.warning(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.error(msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.critical(msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.warning(msg, *args, **kwargs)
|
||||
|
||||
Logs a message on this logger with the specified level.
|
||||
Basically, the arguments are as with python's logging module.
|
||||
@@ -33,13 +33,14 @@ Logging API
|
||||
logger.warning('Warning happened!', location=some_node)
|
||||
|
||||
**color**
|
||||
The color of logs. By default, warning level logs are
|
||||
colored as ``"darkred"``. The others are not colored.
|
||||
The color of logs. By default, error level logs are colored as
|
||||
``"darkred"``, critical level ones is not colored, and warning level
|
||||
ones are colored as ``"red"``.
|
||||
|
||||
.. method:: SphinxLoggerAdapter.log(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.info(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.verbose(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.debug(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.info(msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.verbose(msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.debug(msg, *args, **kwargs)
|
||||
|
||||
Logs a message to this logger with the specified level.
|
||||
Basically, the arguments are as with python's logging module.
|
||||
@@ -55,9 +56,8 @@ Logging API
|
||||
:meth:`SphinxLoggerAdapter.warning`.
|
||||
|
||||
**color**
|
||||
The color of logs. By default, debug level logs are
|
||||
colored as ``"darkgray"``, and debug2 level ones are ``"lightgray"``.
|
||||
The others are not colored.
|
||||
The color of logs. By default, info and verbose level logs are not colored,
|
||||
and deug level ones are colored as ``"darkgray"``.
|
||||
|
||||
.. autofunction:: pending_logging()
|
||||
|
||||
|
||||
@@ -61,8 +61,7 @@ if __version__.endswith('+'):
|
||||
__version__ = __version__[:-1] # remove '+' for PEP-440 version spec.
|
||||
try:
|
||||
import subprocess
|
||||
p = subprocess.Popen(['git', 'show', '-s', '--pretty=format:%h',
|
||||
path.join(package_dir, '..')],
|
||||
p = subprocess.Popen(['git', 'show', '-s', '--pretty=format:%h'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = p.communicate()
|
||||
if out:
|
||||
|
||||
@@ -1040,6 +1040,8 @@ class Sphinx(object):
|
||||
And it allows keyword arguments as attributes of script tag.
|
||||
"""
|
||||
self.registry.add_js_file(filename, **kwargs)
|
||||
if hasattr(self.builder, 'add_js_file'):
|
||||
self.builder.add_js_file(filename, **kwargs) # type: ignore
|
||||
|
||||
def add_css_file(self, filename, **kwargs):
|
||||
# type: (unicode, **unicode) -> None
|
||||
@@ -1078,6 +1080,8 @@ class Sphinx(object):
|
||||
"""
|
||||
logger.debug('[app] adding stylesheet: %r', filename)
|
||||
self.registry.add_css_files(filename, **kwargs)
|
||||
if hasattr(self.builder, 'add_css_file'):
|
||||
self.builder.add_css_file(filename, **kwargs) # type: ignore
|
||||
|
||||
def add_stylesheet(self, filename, alternate=False, title=None):
|
||||
# type: (unicode, bool, unicode) -> None
|
||||
|
||||
@@ -26,10 +26,12 @@ try:
|
||||
import readline
|
||||
if readline.__doc__ and 'libedit' in readline.__doc__:
|
||||
readline.parse_and_bind("bind ^I rl_complete")
|
||||
USE_LIBEDIT = True
|
||||
else:
|
||||
readline.parse_and_bind("tab: complete")
|
||||
USE_LIBEDIT = False
|
||||
except ImportError:
|
||||
pass
|
||||
USE_LIBEDIT = False
|
||||
|
||||
from docutils.utils import column_width
|
||||
from six import PY2, PY3, text_type, binary_type
|
||||
@@ -197,7 +199,13 @@ def do_prompt(text, default=None, validator=nonempty):
|
||||
prompt = prompt.encode('utf-8')
|
||||
except UnicodeEncodeError:
|
||||
prompt = prompt.encode('latin1')
|
||||
prompt = colorize(COLOR_QUESTION, prompt, input_mode=True)
|
||||
if USE_LIBEDIT:
|
||||
# Note: libedit has a problem for combination of ``input()`` and escape
|
||||
# sequence (see #5335). To avoid the problem, all prompts are not colored
|
||||
# on libedit.
|
||||
pass
|
||||
else:
|
||||
prompt = colorize(COLOR_QUESTION, prompt, input_mode=True)
|
||||
x = term_input(prompt).strip()
|
||||
if default and not x:
|
||||
x = default
|
||||
|
||||
@@ -3603,6 +3603,8 @@ class SymbolLookupResult(object):
|
||||
|
||||
|
||||
class Symbol(object):
|
||||
debug_lookup = False
|
||||
|
||||
def _assert_invariants(self):
|
||||
# type: () -> None
|
||||
if not self.parent:
|
||||
@@ -3648,43 +3650,9 @@ class Symbol(object):
|
||||
self.parent._children.append(self)
|
||||
if self.declaration:
|
||||
self.declaration.symbol = self
|
||||
# add symbols for the template params
|
||||
# (do it after self._children has been initialised
|
||||
if self.templateParams:
|
||||
for p in self.templateParams.params:
|
||||
if not p.get_identifier():
|
||||
continue
|
||||
# only add a declaration if we our selfs are from a declaration
|
||||
if declaration:
|
||||
decl = ASTDeclaration('templateParam', None, None, p)
|
||||
else:
|
||||
decl = None
|
||||
nne = ASTNestedNameElement(p.get_identifier(), None)
|
||||
nn = ASTNestedName([nne], [False], rooted=False)
|
||||
self._add_symbols(nn, [], decl, docname)
|
||||
# add symbols for function parameters, if any
|
||||
if declaration is not None and declaration.function_params is not None:
|
||||
for p in declaration.function_params:
|
||||
if p.arg is None:
|
||||
continue
|
||||
nn = p.arg.name
|
||||
if nn is None:
|
||||
continue
|
||||
# (comparing to the template params: we have checked that we are a declaration)
|
||||
decl = ASTDeclaration('functionParam', None, None, p)
|
||||
assert not nn.rooted
|
||||
assert len(nn.names) == 1
|
||||
identOrOp = nn.names[0].identOrOp
|
||||
Symbol(parent=self, identOrOp=identOrOp,
|
||||
templateParams=None, templateArgs=None,
|
||||
declaration=decl, docname=docname)
|
||||
|
||||
def remove(self):
|
||||
if self.parent is None:
|
||||
return
|
||||
assert self in self.parent._children
|
||||
self.parent._children.remove(self)
|
||||
self.parent = None
|
||||
# Do symbol addition after self._children has been initialised.
|
||||
self._add_template_and_function_params()
|
||||
|
||||
def _fill_empty(self, declaration, docname):
|
||||
# type: (ASTDeclaration, unicode) -> None
|
||||
@@ -3697,6 +3665,46 @@ class Symbol(object):
|
||||
self.declaration.symbol = self
|
||||
self.docname = docname
|
||||
self._assert_invariants()
|
||||
# and symbol addition should be done as well
|
||||
self._add_template_and_function_params()
|
||||
|
||||
def _add_template_and_function_params(self):
|
||||
# Note: we may be called from _fill_empty, so the symbols we want
|
||||
# to add may actually already be present (as empty symbols).
|
||||
|
||||
# add symbols for the template params
|
||||
if self.templateParams:
|
||||
for p in self.templateParams.params:
|
||||
if not p.get_identifier():
|
||||
continue
|
||||
# only add a declaration if we our self are from a declaration
|
||||
if self.declaration:
|
||||
decl = ASTDeclaration('templateParam', None, None, p)
|
||||
else:
|
||||
decl = None
|
||||
nne = ASTNestedNameElement(p.get_identifier(), None)
|
||||
nn = ASTNestedName([nne], [False], rooted=False)
|
||||
self._add_symbols(nn, [], decl, self.docname)
|
||||
# add symbols for function parameters, if any
|
||||
if self.declaration is not None and self.declaration.function_params is not None:
|
||||
for p in self.declaration.function_params:
|
||||
if p.arg is None:
|
||||
continue
|
||||
nn = p.arg.name
|
||||
if nn is None:
|
||||
continue
|
||||
# (comparing to the template params: we have checked that we are a declaration)
|
||||
decl = ASTDeclaration('functionParam', None, None, p)
|
||||
assert not nn.rooted
|
||||
assert len(nn.names) == 1
|
||||
self._add_symbols(nn, [], decl, self.docname)
|
||||
|
||||
def remove(self):
|
||||
if self.parent is None:
|
||||
return
|
||||
assert self in self.parent._children
|
||||
self.parent._children.remove(self)
|
||||
self.parent = None
|
||||
|
||||
def clear_doc(self, docname):
|
||||
# type: (unicode) -> None
|
||||
@@ -3948,8 +3956,20 @@ class Symbol(object):
|
||||
# Used for adding a whole path of symbols, where the last may or may not
|
||||
# be an actual declaration.
|
||||
|
||||
if Symbol.debug_lookup:
|
||||
print("_add_symbols:")
|
||||
print(" tdecls:", templateDecls)
|
||||
print(" nn: ", nestedName)
|
||||
print(" decl: ", declaration)
|
||||
print(" doc: ", docname)
|
||||
|
||||
def onMissingQualifiedSymbol(parentSymbol, identOrOp, templateParams, templateArgs):
|
||||
# type: (Symbol, Union[ASTIdentifier, ASTOperator], Any, ASTTemplateArgs) -> Symbol
|
||||
if Symbol.debug_lookup:
|
||||
print(" _add_symbols, onMissingQualifiedSymbol:")
|
||||
print(" templateParams:", templateParams)
|
||||
print(" identOrOp: ", identOrOp)
|
||||
print(" templateARgs: ", templateArgs)
|
||||
return Symbol(parent=parentSymbol, identOrOp=identOrOp,
|
||||
templateParams=templateParams,
|
||||
templateArgs=templateArgs, declaration=None,
|
||||
@@ -3964,54 +3984,119 @@ class Symbol(object):
|
||||
recurseInAnon=True,
|
||||
correctPrimaryTemplateArgs=True)
|
||||
assert lookupResult is not None # we create symbols all the way, so that can't happen
|
||||
# TODO: actually do the iteration over results, though let's find a test case first
|
||||
try:
|
||||
symbol = next(lookupResult.symbols)
|
||||
except StopIteration:
|
||||
symbol = None
|
||||
|
||||
if symbol:
|
||||
if not declaration:
|
||||
# good, just a scope creation
|
||||
return symbol
|
||||
if not symbol.declaration:
|
||||
# If someone first opened the scope, and then later
|
||||
# declares it, e.g,
|
||||
# .. namespace:: Test
|
||||
# .. namespace:: nullptr
|
||||
# .. class:: Test
|
||||
symbol._fill_empty(declaration, docname)
|
||||
return symbol
|
||||
# It may simply be a function overload, so let's compare ids.
|
||||
isRedeclaration = True
|
||||
candSymbol = Symbol(parent=lookupResult.parentSymbol,
|
||||
identOrOp=lookupResult.identOrOp,
|
||||
templateParams=lookupResult.templateParams,
|
||||
templateArgs=lookupResult.templateArgs,
|
||||
declaration=declaration,
|
||||
docname=docname)
|
||||
if declaration.objectType == "function":
|
||||
newId = declaration.get_newest_id()
|
||||
oldId = symbol.declaration.get_newest_id()
|
||||
if newId != oldId:
|
||||
# we already inserted the symbol, so return the new one
|
||||
symbol = candSymbol
|
||||
isRedeclaration = False
|
||||
if isRedeclaration:
|
||||
# Redeclaration of the same symbol.
|
||||
# Let the new one be there, but raise an error to the client
|
||||
# so it can use the real symbol as subscope.
|
||||
# This will probably result in a duplicate id warning.
|
||||
candSymbol.isRedeclaration = True
|
||||
raise _DuplicateSymbolError(symbol, declaration)
|
||||
else:
|
||||
symbols = list(lookupResult.symbols)
|
||||
if len(symbols) == 0:
|
||||
if Symbol.debug_lookup:
|
||||
print(" _add_symbols, result, no symbol:")
|
||||
print(" templateParams:", lookupResult.templateParams)
|
||||
print(" identOrOp: ", lookupResult.identOrOp)
|
||||
print(" templateArgs: ", lookupResult.templateArgs)
|
||||
print(" declaration: ", declaration)
|
||||
print(" docname: ", docname)
|
||||
symbol = Symbol(parent=lookupResult.parentSymbol,
|
||||
identOrOp=lookupResult.identOrOp,
|
||||
templateParams=lookupResult.templateParams,
|
||||
templateArgs=lookupResult.templateArgs,
|
||||
declaration=declaration,
|
||||
docname=docname)
|
||||
return symbol
|
||||
return symbol
|
||||
|
||||
if Symbol.debug_lookup:
|
||||
print(" _add_symbols, result, symbols:")
|
||||
print(" number symbols:", len(symbols))
|
||||
|
||||
if not declaration:
|
||||
if Symbol.debug_lookup:
|
||||
print(" no delcaration")
|
||||
# good, just a scope creation
|
||||
# TODO: what if we have more than one symbol?
|
||||
return symbols[0]
|
||||
|
||||
noDecl = []
|
||||
withDecl = []
|
||||
for s in symbols:
|
||||
if s.declaration is None:
|
||||
noDecl.append(s)
|
||||
else:
|
||||
withDecl.append(s)
|
||||
if Symbol.debug_lookup:
|
||||
print(" #noDecl: ", len(noDecl))
|
||||
print(" #withDecl:", len(withDecl))
|
||||
# assert len(noDecl) <= 1 # we should fill in symbols when they are there
|
||||
# TODO: enable assertion when we at some point find out how to do cleanup
|
||||
# With partial builds we may start with a large symbol tree stripped of declarations.
|
||||
|
||||
# First check if one of those with a declaration matches.
|
||||
# If it's a function, we need to compare IDs,
|
||||
# otherwise there should be only one symbol with a declaration.
|
||||
def makeCandSymbol():
|
||||
if Symbol.debug_lookup:
|
||||
print(" begin: creating candidate symbol")
|
||||
symbol = Symbol(parent=lookupResult.parentSymbol,
|
||||
identOrOp=lookupResult.identOrOp,
|
||||
templateParams=lookupResult.templateParams,
|
||||
templateArgs=lookupResult.templateArgs,
|
||||
declaration=declaration,
|
||||
docname=docname)
|
||||
if Symbol.debug_lookup:
|
||||
print(" end: creating candidate symbol")
|
||||
return symbol
|
||||
if len(withDecl) == 0:
|
||||
candSymbol = None
|
||||
else:
|
||||
candSymbol = makeCandSymbol()
|
||||
|
||||
def handleDuplicateDeclaration(symbol, candSymbol):
|
||||
if Symbol.debug_lookup:
|
||||
print(" redeclaration")
|
||||
# Redeclaration of the same symbol.
|
||||
# Let the new one be there, but raise an error to the client
|
||||
# so it can use the real symbol as subscope.
|
||||
# This will probably result in a duplicate id warning.
|
||||
candSymbol.isRedeclaration = True
|
||||
raise _DuplicateSymbolError(symbol, declaration)
|
||||
|
||||
if declaration.objectType != "function":
|
||||
assert len(withDecl) <= 1
|
||||
handleDuplicateDeclaration(withDecl[0], candSymbol)
|
||||
# (not reachable)
|
||||
|
||||
# a function, so compare IDs
|
||||
candId = declaration.get_newest_id()
|
||||
if Symbol.debug_lookup:
|
||||
print(" candId:", candId)
|
||||
for symbol in withDecl:
|
||||
oldId = symbol.declaration.get_newest_id()
|
||||
if Symbol.debug_lookup:
|
||||
print(" oldId: ", oldId)
|
||||
if candId == oldId:
|
||||
handleDuplicateDeclaration(symbol, candSymbol)
|
||||
# (not reachable)
|
||||
# no candidate symbol found with matching ID
|
||||
# if there is an empty symbol, fill that one
|
||||
if len(noDecl) == 0:
|
||||
if Symbol.debug_lookup:
|
||||
print(" no match, no empty, candSybmol is not None?:", candSymbol is not None) # NOQA
|
||||
if candSymbol is not None:
|
||||
return candSymbol
|
||||
else:
|
||||
return makeCandSymbol()
|
||||
else:
|
||||
if Symbol.debug_lookup:
|
||||
print(" no match, but fill an empty declaration, candSybmol is not None?:", candSymbol is not None) # NOQA
|
||||
if candSymbol is not None:
|
||||
candSymbol.remove()
|
||||
# assert len(noDecl) == 1
|
||||
# TODO: enable assertion when we at some point find out how to do cleanup
|
||||
# for now, just take the first one, it should work fine ... right?
|
||||
symbol = noDecl[0]
|
||||
# If someone first opened the scope, and then later
|
||||
# declares it, e.g,
|
||||
# .. namespace:: Test
|
||||
# .. namespace:: nullptr
|
||||
# .. class:: Test
|
||||
symbol._fill_empty(declaration, docname)
|
||||
return symbol
|
||||
|
||||
def merge_with(self, other, docnames, env):
|
||||
# type: (Symbol, List[unicode], BuildEnvironment) -> None
|
||||
@@ -6598,7 +6683,7 @@ class CPPDomain(Domain):
|
||||
def process_doc(self, env, docname, document):
|
||||
# type: (BuildEnvironment, unicode, nodes.Node) -> None
|
||||
# just for debugging
|
||||
# print(docname)
|
||||
# print("process_doc:", docname)
|
||||
# print(self.data['root_symbol'].dump(0))
|
||||
pass
|
||||
|
||||
@@ -6608,6 +6693,12 @@ class CPPDomain(Domain):
|
||||
|
||||
def merge_domaindata(self, docnames, otherdata):
|
||||
# type: (List[unicode], Dict) -> None
|
||||
# print("merge_domaindata:")
|
||||
# print("self")
|
||||
# print(self.data['root_symbol'].dump(0))
|
||||
# print("other:")
|
||||
# print(otherdata['root_symbol'].dump(0))
|
||||
|
||||
self.data['root_symbol'].merge_with(otherdata['root_symbol'],
|
||||
docnames, self.env)
|
||||
ourNames = self.data['names']
|
||||
@@ -6678,6 +6769,7 @@ class CPPDomain(Domain):
|
||||
matchSelf=True, recurseInAnon=True)
|
||||
else:
|
||||
decl = ast # type: ASTDeclaration
|
||||
name = decl.name
|
||||
s = parentSymbol.find_declaration(decl, typ,
|
||||
templateShorthand=True,
|
||||
matchSelf=True, recurseInAnon=True)
|
||||
|
||||
@@ -19,7 +19,7 @@ from os import path
|
||||
|
||||
from docutils.utils import get_source_line
|
||||
from six import BytesIO, next
|
||||
from six.moves import cPickle as pickle
|
||||
from six.moves import cPickle as pickle, reduce
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning, RemovedInSphinx30Warning
|
||||
@@ -139,7 +139,8 @@ class BuildEnvironment(object):
|
||||
self.dependencies = defaultdict(set) # type: Dict[unicode, Set[unicode]]
|
||||
# docname -> set of dependent file
|
||||
# names, relative to documentation root
|
||||
self.included = set() # type: Set[unicode]
|
||||
self.included = defaultdict(set) # type: Dict[unicode, Set[unicode]]
|
||||
# docname -> set of included file
|
||||
# docnames included from other documents
|
||||
self.reread_always = set() # type: Set[unicode]
|
||||
# docnames to re-read unconditionally on
|
||||
@@ -315,8 +316,8 @@ class BuildEnvironment(object):
|
||||
"""Remove all traces of a source file in the inventory."""
|
||||
if docname in self.all_docs:
|
||||
self.all_docs.pop(docname, None)
|
||||
self.included.pop(docname, None)
|
||||
self.reread_always.discard(docname)
|
||||
self.included.discard(docname)
|
||||
|
||||
for domain in self.domains.values():
|
||||
domain.clear_doc(docname)
|
||||
@@ -331,12 +332,17 @@ class BuildEnvironment(object):
|
||||
docnames = set(docnames) # type: ignore
|
||||
for docname in docnames:
|
||||
self.all_docs[docname] = other.all_docs[docname]
|
||||
self.included[docname] = other.included[docname]
|
||||
if docname in other.reread_always:
|
||||
self.reread_always.add(docname)
|
||||
|
||||
for docname in other.included:
|
||||
self.included.add(docname)
|
||||
|
||||
for version, changes in other.versionchanges.items():
|
||||
self.versionchanges.setdefault(version, []).extend(
|
||||
change for change in changes if change[1] in docnames)
|
||||
|
||||
for domainname, domain in self.domains.items():
|
||||
domain.merge_domaindata(docnames, other.domaindata[domainname])
|
||||
app.emit('env-merge-info', self, docnames, other)
|
||||
@@ -552,7 +558,7 @@ class BuildEnvironment(object):
|
||||
|
||||
*filename* should be absolute or relative to the source directory.
|
||||
"""
|
||||
self.included.add(self.path2doc(filename))
|
||||
self.included[self.docname].add(self.path2doc(filename))
|
||||
|
||||
def note_reread(self):
|
||||
# type: () -> None
|
||||
@@ -721,12 +727,13 @@ class BuildEnvironment(object):
|
||||
def check_consistency(self):
|
||||
# type: () -> None
|
||||
"""Do consistency checks."""
|
||||
included = reduce(lambda x, y: x | y, self.included.values(), set()) # type: Set[unicode] # NOQA
|
||||
for docname in sorted(self.all_docs):
|
||||
if docname not in self.files_to_rebuild:
|
||||
if docname == self.config.master_doc:
|
||||
# the master file is not included anywhere ;)
|
||||
continue
|
||||
if docname in self.included:
|
||||
if docname in included:
|
||||
# the document is included from other documents
|
||||
continue
|
||||
if 'orphan' in self.metadata[docname]:
|
||||
|
||||
26
sphinx/io.py
26
sphinx/io.py
@@ -10,6 +10,7 @@
|
||||
"""
|
||||
import codecs
|
||||
import re
|
||||
import warnings
|
||||
|
||||
from docutils.core import Publisher
|
||||
from docutils.io import FileInput, NullOutput
|
||||
@@ -20,6 +21,7 @@ from docutils.writers import UnfilteredWriter
|
||||
from six import text_type, iteritems
|
||||
from typing import Any, Union # NOQA
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||
from sphinx.locale import __
|
||||
from sphinx.transforms import (
|
||||
ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
|
||||
@@ -116,7 +118,6 @@ class SphinxI18nReader(SphinxBaseReader):
|
||||
Because the translated texts are partial and they don't have correct line numbers.
|
||||
"""
|
||||
|
||||
lineno = None # type: int
|
||||
transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
|
||||
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
|
||||
AutoNumbering, SortIds, RemoveTranslatableInline,
|
||||
@@ -127,22 +128,15 @@ class SphinxI18nReader(SphinxBaseReader):
|
||||
def set_lineno_for_reporter(self, lineno):
|
||||
# type: (int) -> None
|
||||
"""Stores the source line number of original text."""
|
||||
self.lineno = lineno
|
||||
warnings.warn('SphinxI18nReader.set_lineno_for_reporter() is deprecated.',
|
||||
RemovedInSphinx30Warning)
|
||||
|
||||
def new_document(self):
|
||||
# type: () -> nodes.document
|
||||
"""Creates a new document object which having a special reporter object for
|
||||
translation.
|
||||
"""
|
||||
document = SphinxBaseReader.new_document(self)
|
||||
reporter = document.reporter
|
||||
|
||||
def get_source_and_line(lineno=None):
|
||||
# type: (int) -> Tuple[unicode, int]
|
||||
return reporter.source, self.lineno
|
||||
|
||||
reporter.get_source_and_line = get_source_and_line
|
||||
return document
|
||||
@property
|
||||
def line(self):
|
||||
# type: () -> int
|
||||
warnings.warn('SphinxI18nReader.line is deprecated.',
|
||||
RemovedInSphinx30Warning)
|
||||
return 0
|
||||
|
||||
|
||||
class SphinxDummyWriter(UnfilteredWriter):
|
||||
|
||||
@@ -51,10 +51,10 @@ def publish_msgstr(app, source, source_path, source_line, config, settings):
|
||||
"""
|
||||
from sphinx.io import SphinxI18nReader
|
||||
reader = SphinxI18nReader(app)
|
||||
reader.set_lineno_for_reporter(source_line)
|
||||
parser = app.registry.create_source_parser(app, 'restructuredtext')
|
||||
doc = reader.read(
|
||||
source=StringInput(source=source, source_path=source_path),
|
||||
source=StringInput(source=source,
|
||||
source_path="%s:%s:<translated>" % (source_path, source_line)),
|
||||
parser=parser,
|
||||
settings=settings,
|
||||
)
|
||||
|
||||
@@ -11,8 +11,10 @@ import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
import docutils
|
||||
import pytest
|
||||
|
||||
import sphinx
|
||||
from sphinx.testing.path import path
|
||||
|
||||
pytest_plugins = 'sphinx.testing.fixtures'
|
||||
@@ -34,8 +36,8 @@ def rootdir():
|
||||
|
||||
|
||||
def pytest_report_header(config):
|
||||
return 'Running Sphinx test suite (with Python %s)...' % (
|
||||
sys.version.split()[0])
|
||||
return ("libraries: Sphinx-%s, docutils-%s" %
|
||||
(sphinx.__display_version__, docutils.__version__))
|
||||
|
||||
|
||||
def _initialize_test_directory(session):
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
from six import text_type
|
||||
@@ -137,8 +138,9 @@ def test_expressions():
|
||||
exprCheck(p + "'\\x0A'", t + "10")
|
||||
exprCheck(p + "'\\u0a42'", t + "2626")
|
||||
exprCheck(p + "'\\u0A42'", t + "2626")
|
||||
exprCheck(p + "'\\U0001f34c'", t + "127820")
|
||||
exprCheck(p + "'\\U0001F34C'", t + "127820")
|
||||
if sys.maxunicode > 65535:
|
||||
exprCheck(p + "'\\U0001f34c'", t + "127820")
|
||||
exprCheck(p + "'\\U0001F34C'", t + "127820")
|
||||
|
||||
# TODO: user-defined lit
|
||||
exprCheck('(... + Ns)', '(... + Ns)')
|
||||
|
||||
@@ -131,8 +131,8 @@ def test_text_emit_warnings(app, warning):
|
||||
app.build()
|
||||
# test warnings in translation
|
||||
warnings = getwarning(warning)
|
||||
warning_expr = u'.*/warnings.txt:4: ' \
|
||||
u'WARNING: Inline literal start-string without end-string.\n'
|
||||
warning_expr = ('.*/warnings.txt:4:<translated>:1: '
|
||||
'WARNING: Inline literal start-string without end-string.\n')
|
||||
assert_re_search(warning_expr, warnings)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user