Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sphinx-doc/sphinx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2017-03-18 12:25:50 +0300
committerTakeshi KOMIYA <i.tkomiya@gmail.com>2017-03-18 12:25:50 +0300
commitaa6dfb8b411b68c497d2e7d7b18286a52f6d9cc6 (patch)
treeafb1b69f19ba62d109160dd50505389e7aca2f20
parent0df0a11cfac651222513bff9426455d449f302c3 (diff)
parent2dae11aa6800af78574d27d0bcc1f121b483c00a (diff)
Merge branch 'stable'
-rw-r--r--CHANGES2
-rw-r--r--CONTRIBUTING.rst12
-rw-r--r--doc/latex.rst8
-rw-r--r--sphinx/builders/linkcheck.py4
-rw-r--r--sphinx/domains/python.py71
-rw-r--r--sphinx/util/requests.py38
-rw-r--r--tests/test_domain_py.py7
-rw-r--r--tests/test_markup.py10
8 files changed, 93 insertions, 59 deletions
diff --git a/CHANGES b/CHANGES
index c8b08a6fd..c49327652 100644
--- a/CHANGES
+++ b/CHANGES
@@ -163,6 +163,7 @@ Bugs fixed
rendered as code
* #2665, #2607: Link names in C++ docfields, and make it possible for other domains.
* #3542: C++, fix parsing error of non-type template argument with template.
+* #3065, #3520: python domain fails to recognize nested class
Testing
--------
@@ -200,6 +201,7 @@ Bugs fixed
* #3450: &nbsp is appeared in EPUB docs
* #3418: Search button is misaligned in nature and pyramid theme
* #3421: Could not translate a caption of tables
+* #3552: linkcheck raises UnboundLocalError
Release 1.5.2 (released Jan 22, 2017)
=====================================
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 30dee2774..274bc994a 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -1,3 +1,5 @@
+.. highlight:: console
+
Sphinx Developer's Guide
========================
@@ -129,8 +131,8 @@ These are the basic steps needed to start developing on Sphinx.
* Run code style checks and type checks (type checks require mypy)::
- make style-check
- make type-check
+ make style-check
+ make type-check
* Run the unit tests under different Python environments using
:program:`tox`::
@@ -274,14 +276,12 @@ Debugging Tips
* Set the debugging options in the `Docutils configuration file
<http://docutils.sourceforge.net/docs/user/config.html>`_.
-* JavaScript stemming algorithms in `sphinx/search/*.py` (except `en.py`) are
+* JavaScript stemming algorithms in ``sphinx/search/*.py`` (except ``en.py``) are
generated by this
`modified snowballcode generator <https://github.com/shibukawa/snowball>`_.
Generated `JSX <http://jsx.github.io/>`_ files are
in `this repository <https://github.com/shibukawa/snowball-stemmer.jsx>`_.
- You can get the resulting JavaScript files using the following command:
-
- .. code-block:: bash
+ You can get the resulting JavaScript files using the following command::
$ npm install
$ node_modules/.bin/grunt build # -> dest/*.global.js
diff --git a/doc/latex.rst b/doc/latex.rst
index 56a9e85d9..e2c518058 100644
--- a/doc/latex.rst
+++ b/doc/latex.rst
@@ -438,14 +438,6 @@ Let us now list some macros from the package file
the new macros are wrappers of the formerly hard-coded ``\texttt``,
``\emph``, ... The default definitions can be found in
:file:`sphinx.sty`.
-- macros for directional double quotes: pairs of straight double quote ``"``
- in reST source are converted into LaTeX mark-up
- ``\sphinxquotedblleft{}`` and ``\sphinxquotedblright{}`` which default to
- `````\ ````` and ``''`` (i.e. the TeX mark-up for directional double
- quotes via font ligaturing mechanism.)
-
- .. versionadded:: 1.5.4
- Formerly, produced TeX was directly with `````\ ````` and ``''``.
- paragraph level environments: for each admonition type ``<foo>``, the
used environment is named ``sphinx<foo>``. They may be ``\renewenvironment``
'd individually, and must then be defined with one argument (it is the heading
diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py
index 99778cddf..3693144c3 100644
--- a/sphinx/builders/linkcheck.py
+++ b/sphinx/builders/linkcheck.py
@@ -182,7 +182,9 @@ class CheckExternalLinksBuilder(Builder):
# history contains any redirects, get last
if response.history:
code = response.history[-1].status_code
- return 'redirected', new_url, code
+ return 'redirected', new_url, code
+ else:
+ return 'redirected', new_url, 0
def check():
# type: () -> Tuple[unicode, unicode, int]
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index 1cced3d61..d5ff4a60f 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -163,6 +163,9 @@ class PyTypedField(PyXrefMixin, TypedField):
class PyObject(ObjectDescription):
"""
Description of a general Python object.
+
+ :cvar allow_nesting: Class is an object that allows for nested namespaces
+ :vartype allow_nesting: bool
"""
option_spec = {
'noindex': directives.flag,
@@ -189,6 +192,8 @@ class PyObject(ObjectDescription):
names=('rtype',), bodyrolename='obj'),
]
+ allow_nesting = False
+
def get_signature_prefix(self, sig):
# type: (unicode) -> unicode
"""May return a prefix to put before the object name in the
@@ -316,13 +321,54 @@ class PyObject(ObjectDescription):
def before_content(self):
# type: () -> None
- # needed for automatic qualification of members (reset in subclasses)
- self.clsname_set = False
+ """Handle object nesting before content
+
+ :py:class:`PyObject` represents Python language constructs. For
+ constructs that are nestable, such as a Python classes, this method will
+ build up a stack of the nesting heirarchy so that it can be later
+ de-nested correctly, in :py:meth:`after_content`.
+
+ For constructs that aren't nestable, the stack is bypassed, and instead
+ only the most recent object is tracked. This object prefix name will be
+ removed with :py:meth:`after_content`.
+ """
+ if self.names:
+ # fullname and name_prefix come from the `handle_signature` method.
+ # fullname represents the full object name that is constructed using
+ # object nesting and explicit prefixes. `name_prefix` is the
+ # explicit prefix given in a signature
+ (fullname, name_prefix) = self.names[-1]
+ if self.allow_nesting:
+ prefix = fullname
+ elif name_prefix:
+ prefix = name_prefix.strip('.')
+ else:
+ prefix = None
+ if prefix:
+ self.env.ref_context['py:class'] = prefix
+ if self.allow_nesting:
+ classes = self.env.ref_context.setdefault('py:classes', [])
+ classes.append(prefix)
def after_content(self):
# type: () -> None
- if self.clsname_set:
- self.env.ref_context.pop('py:class', None)
+ """Handle object de-nesting after content
+
+ If this class is a nestable object, removing the last nested class prefix
+ ends further nesting in the object.
+
+ If this class is not a nestable object, the list of classes should not
+ be altered as we didn't affect the nesting levels in
+ :py:meth:`before_content`.
+ """
+ classes = self.env.ref_context.setdefault('py:classes', [])
+ if self.allow_nesting:
+ try:
+ classes.pop()
+ except IndexError:
+ pass
+ self.env.ref_context['py:class'] = (classes[-1] if len(classes) > 0
+ else None)
class PyModulelevel(PyObject):
@@ -353,6 +399,8 @@ class PyClasslike(PyObject):
Description of a class-like object (classes, interfaces, exceptions).
"""
+ allow_nesting = True
+
def get_signature_prefix(self, sig):
# type: (unicode) -> unicode
return self.objtype + ' '
@@ -368,13 +416,6 @@ class PyClasslike(PyObject):
else:
return ''
- def before_content(self):
- # type: () -> None
- PyObject.before_content(self)
- if self.names:
- self.env.ref_context['py:class'] = self.names[0][0]
- self.clsname_set = True
-
class PyClassmember(PyObject):
"""
@@ -450,14 +491,6 @@ class PyClassmember(PyObject):
else:
return ''
- def before_content(self):
- # type: () -> None
- PyObject.before_content(self)
- lastname = self.names and self.names[-1][1]
- if lastname and not self.env.ref_context.get('py:class'):
- self.env.ref_context['py:class'] = lastname.strip('.')
- self.clsname_set = True
-
class PyDecoratorMixin(object):
"""
diff --git a/sphinx/util/requests.py b/sphinx/util/requests.py
index ec5aa232e..fcce42f09 100644
--- a/sphinx/util/requests.py
+++ b/sphinx/util/requests.py
@@ -36,30 +36,34 @@ except ImportError:
# for requests < 2.4.0
InsecureRequestWarning = None
-# try to load requests[security]
+# try to load requests[security] (but only if SSL is available)
try:
- pkg_resources.require(['requests[security]'])
-except (pkg_resources.DistributionNotFound,
- pkg_resources.VersionConflict):
import ssl
- if not getattr(ssl, 'HAS_SNI', False):
- # don't complain on each url processed about the SSL issue
- requests.packages.urllib3.disable_warnings(
- requests.packages.urllib3.exceptions.InsecurePlatformWarning)
+except ImportError:
+ pass
+else:
+ try:
+ pkg_resources.require(['requests[security]'])
+ except (pkg_resources.DistributionNotFound,
+ pkg_resources.VersionConflict):
+ if not getattr(ssl, 'HAS_SNI', False):
+ # don't complain on each url processed about the SSL issue
+ requests.packages.urllib3.disable_warnings(
+ requests.packages.urllib3.exceptions.InsecurePlatformWarning)
+ warnings.warn(
+ 'Some links may return broken results due to being unable to '
+ 'check the Server Name Indication (SNI) in the returned SSL cert '
+ 'against the hostname in the url requested. Recommended to '
+ 'install "requests[security]" as a dependency or upgrade to '
+ 'a python version with SNI support (Python 3 and Python 2.7.9+).'
+ )
+ except pkg_resources.UnknownExtra:
warnings.warn(
'Some links may return broken results due to being unable to '
'check the Server Name Indication (SNI) in the returned SSL cert '
'against the hostname in the url requested. Recommended to '
- 'install "requests[security]" as a dependency or upgrade to '
- 'a python version with SNI support (Python 3 and Python 2.7.9+).'
+ 'install requests-2.4.1+.'
)
-except pkg_resources.UnknownExtra:
- warnings.warn(
- 'Some links may return broken results due to being unable to '
- 'check the Server Name Indication (SNI) in the returned SSL cert '
- 'against the hostname in the url requested. Recommended to '
- 'install requests-2.4.1+.'
- )
if False:
# For type annotation
diff --git a/tests/test_domain_py.py b/tests/test_domain_py.py
index f290bfff3..1f497d69d 100644
--- a/tests/test_domain_py.py
+++ b/tests/test_domain_py.py
@@ -82,8 +82,8 @@ def test_domain_py_xrefs(app, status, warning):
u'subchild_2', u'meth')
assert_refnode(refnodes[8], None, u'NestedParentA.NestedChildA',
u'NestedParentA.child_1', u'meth')
- assert_refnode(refnodes[9], None, None, u'NestedChildA.subchild_1',
- u'meth')
+ assert_refnode(refnodes[9], None, u'NestedParentA',
+ u'NestedChildA.subchild_1', u'meth')
assert_refnode(refnodes[10], None, u'NestedParentB', u'child_1', u'meth')
assert_refnode(refnodes[11], None, u'NestedParentB', u'NestedParentB',
u'class')
@@ -125,6 +125,7 @@ def test_domain_py_objects(app, status, warning):
assert objects['module_a.submodule.ModTopLevel'] == ('module', 'class')
assert objects['module_a.submodule.ModTopLevel.mod_child_1'] == ('module', 'method')
assert objects['module_a.submodule.ModTopLevel.mod_child_2'] == ('module', 'method')
+ assert 'ModTopLevel.ModNoModule' not in objects
assert objects['ModNoModule'] == ('module', 'class')
assert objects['module_b.submodule.ModTopLevel'] == ('module', 'class')
@@ -136,7 +137,7 @@ def test_domain_py_objects(app, status, warning):
assert objects['NestedParentA.NestedChildA'] == ('roles', 'class')
assert objects['NestedParentA.NestedChildA.subchild_1'] == ('roles', 'method')
assert objects['NestedParentA.NestedChildA.subchild_2'] == ('roles', 'method')
- assert objects['child_2'] == ('roles', 'method')
+ assert objects['NestedParentA.child_2'] == ('roles', 'method')
assert objects['NestedParentB'] == ('roles', 'class')
assert objects['NestedParentB.child_1'] == ('roles', 'method')
diff --git a/tests/test_markup.py b/tests/test_markup.py
index 1d5407a27..11776cf44 100644
--- a/tests/test_markup.py
+++ b/tests/test_markup.py
@@ -97,9 +97,9 @@ def verify_re_latex(app, parse):
def verify_re(verify_re_html, verify_re_latex):
def verify_re_(rst, html_expected, latex_expected):
if html_expected:
- return verify_re_html(rst, html_expected)
+ verify_re_html(rst, html_expected)
if latex_expected:
- return verify_re_latex(rst, latex_expected)
+ verify_re_latex(rst, latex_expected)
return verify_re_
@@ -107,9 +107,9 @@ def verify_re(verify_re_html, verify_re_latex):
def verify(verify_re_html, verify_re_latex):
def verify_(rst, html_expected, latex_expected):
if html_expected:
- return verify_re_html(rst, re.escape(html_expected) + '$')
+ verify_re_html(rst, re.escape(html_expected) + '$')
if latex_expected:
- return verify_re_latex(rst, re.escape(latex_expected) + '$')
+ verify_re_latex(rst, re.escape(latex_expected) + '$')
return verify_
@@ -179,7 +179,7 @@ def get_verifier(verify, verify_re):
'verify',
'"John"',
'<p>&#8220;John&#8221;</p>',
- "``John''",
+ r'\sphinxquotedblleft{}John\sphinxquotedblright{}',
),
(
# ... but not in literal text