Kaydet (Commit) 14b5a4da authored tarafından Georg Brandl's avatar Georg Brandl

Closes #22537: Make sphinx extensions compatible with Python 2 or 3, like in the 3.x branches

üst 2f33456e
...@@ -59,6 +59,9 @@ add_function_parentheses = True ...@@ -59,6 +59,9 @@ add_function_parentheses = True
# unit titles (such as .. function::). # unit titles (such as .. function::).
add_module_names = True add_module_names = True
# Require Sphinx 1.2 for build.
needs_sphinx = '1.2'
# Options for HTML output # Options for HTML output
# ----------------------- # -----------------------
......
...@@ -68,4 +68,4 @@ def get_version_info(): ...@@ -68,4 +68,4 @@ def get_version_info():
return version, release return version, release
if __name__ == '__main__': if __name__ == '__main__':
print get_header_version_info('.')[1] print(get_header_version_info('.')[1])
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
Sphinx extension with Python doc-specific markup. Sphinx extension with Python doc-specific markup.
:copyright: 2008-2013 by Georg Brandl. :copyright: 2008-2014 by Georg Brandl.
:license: Python license. :license: Python license.
""" """
...@@ -14,11 +14,10 @@ SOURCE_URI = 'https://hg.python.org/cpython/file/2.7/%s' ...@@ -14,11 +14,10 @@ SOURCE_URI = 'https://hg.python.org/cpython/file/2.7/%s'
from docutils import nodes, utils from docutils import nodes, utils
import sphinx
from sphinx.util.nodes import split_explicit_title from sphinx.util.nodes import split_explicit_title
from sphinx.util.compat import Directive
from sphinx.writers.html import HTMLTranslator from sphinx.writers.html import HTMLTranslator
from sphinx.writers.latex import LaTeXTranslator from sphinx.writers.latex import LaTeXTranslator
from sphinx.locale import versionlabels
# monkey-patch reST parser to disable alphabetic and roman enumerated lists # monkey-patch reST parser to disable alphabetic and roman enumerated lists
from docutils.parsers.rst.states import Body from docutils.parsers.rst.states import Body
...@@ -27,18 +26,6 @@ Body.enum.converters['loweralpha'] = \ ...@@ -27,18 +26,6 @@ Body.enum.converters['loweralpha'] = \
Body.enum.converters['lowerroman'] = \ Body.enum.converters['lowerroman'] = \
Body.enum.converters['upperroman'] = lambda x: None Body.enum.converters['upperroman'] = lambda x: None
if sphinx.__version__[:3] < '1.2':
# monkey-patch HTML translator to give versionmodified paragraphs a class
def new_visit_versionmodified(self, node):
self.body.append(self.starttag(node, 'p', CLASS=node['type']))
text = versionlabels[node['type']] % node['version']
if len(node):
text += ': '
else:
text += '.'
self.body.append('<span class="versionmodified">%s</span>' % text)
HTMLTranslator.visit_versionmodified = new_visit_versionmodified
# monkey-patch HTML and LaTeX translators to keep doctest blocks in the # monkey-patch HTML and LaTeX translators to keep doctest blocks in the
# doctest docs themselves # doctest docs themselves
orig_visit_literal_block = HTMLTranslator.visit_literal_block orig_visit_literal_block = HTMLTranslator.visit_literal_block
...@@ -88,8 +75,6 @@ def source_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): ...@@ -88,8 +75,6 @@ def source_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
# Support for marking up implementation details # Support for marking up implementation details
from sphinx.util.compat import Directive
class ImplementationDetail(Directive): class ImplementationDetail(Directive):
has_content = True has_content = True
...@@ -140,41 +125,6 @@ class PyDecoratorMethod(PyDecoratorMixin, PyClassmember): ...@@ -140,41 +125,6 @@ class PyDecoratorMethod(PyDecoratorMixin, PyClassmember):
return PyClassmember.run(self) return PyClassmember.run(self)
# Support for documenting version of removal in deprecations
from sphinx.locale import versionlabels
from sphinx.util.compat import Directive
versionlabels['deprecated-removed'] = \
'Deprecated since version %s, will be removed in version %s'
class DeprecatedRemoved(Directive):
has_content = True
required_arguments = 2
optional_arguments = 1
final_argument_whitespace = True
option_spec = {}
def run(self):
node = addnodes.versionmodified()
node.document = self.state.document
node['type'] = 'deprecated-removed'
version = (self.arguments[0], self.arguments[1])
node['version'] = version
if len(self.arguments) == 3:
inodes, messages = self.state.inline_text(self.arguments[2],
self.lineno+1)
node.extend(inodes)
if self.content:
self.state.nested_parse(self.content, self.content_offset, node)
ret = [node] + messages
else:
ret = [node]
env = self.state.document.settings.env
env.note_versionchange('deprecated', version[0], node, self.lineno)
return ret
# Support for building "topic help" for pydoc # Support for building "topic help" for pydoc
pydoc_topic_labels = [ pydoc_topic_labels = [
...@@ -231,13 +181,14 @@ class PydocTopicsBuilder(Builder): ...@@ -231,13 +181,14 @@ class PydocTopicsBuilder(Builder):
document.append(doctree.ids[labelid]) document.append(doctree.ids[labelid])
destination = StringOutput(encoding='utf-8') destination = StringOutput(encoding='utf-8')
writer.write(document, destination) writer.write(document, destination)
self.topics[label] = str(writer.output) self.topics[label] = writer.output
def finish(self): def finish(self):
f = open(path.join(self.outdir, 'topics.py'), 'w') f = open(path.join(self.outdir, 'topics.py'), 'wb')
try: try:
f.write('# Autogenerated by Sphinx on %s\n' % asctime()) f.write('# -*- coding: utf-8 -*-\n'.encode('utf-8'))
f.write('topics = ' + pformat(self.topics) + '\n') f.write(('# Autogenerated by Sphinx on %s\n' % asctime()).encode('utf-8'))
f.write(('topics = ' + pformat(self.topics) + '\n').encode('utf-8'))
finally: finally:
f.close() f.close()
...@@ -295,7 +246,6 @@ def setup(app): ...@@ -295,7 +246,6 @@ def setup(app):
app.add_role('issue', issue_role) app.add_role('issue', issue_role)
app.add_role('source', source_role) app.add_role('source', source_role)
app.add_directive('impl-detail', ImplementationDetail) app.add_directive('impl-detail', ImplementationDetail)
app.add_directive('deprecated-removed', DeprecatedRemoved)
app.add_builder(PydocTopicsBuilder) app.add_builder(PydocTopicsBuilder)
app.add_builder(suspicious.CheckSuspiciousMarkupBuilder) app.add_builder(suspicious.CheckSuspiciousMarkupBuilder)
app.add_description_unit('opcode', 'opcode', '%s (opcode)', app.add_description_unit('opcode', 'opcode', '%s (opcode)',
......
...@@ -49,13 +49,15 @@ import sys ...@@ -49,13 +49,15 @@ import sys
from docutils import nodes from docutils import nodes
from sphinx.builders import Builder from sphinx.builders import Builder
detect_all = re.compile(ur''' detect_all = re.compile(r'''
::(?=[^=])| # two :: (but NOT ::=) ::(?=[^=])| # two :: (but NOT ::=)
:[a-zA-Z][a-zA-Z0-9]+| # :foo :[a-zA-Z][a-zA-Z0-9]+| # :foo
`| # ` (seldom used by itself) `| # ` (seldom used by itself)
(?<!\.)\.\.[ \t]*\w+: # .. foo: (but NOT ... else:) (?<!\.)\.\.[ \t]*\w+: # .. foo: (but NOT ... else:)
''', re.UNICODE | re.VERBOSE).finditer ''', re.UNICODE | re.VERBOSE).finditer
py3 = sys.version_info >= (3, 0)
class Rule: class Rule:
def __init__(self, docname, lineno, issue, line): def __init__(self, docname, lineno, issue, line):
...@@ -147,7 +149,11 @@ class CheckSuspiciousMarkupBuilder(Builder): ...@@ -147,7 +149,11 @@ class CheckSuspiciousMarkupBuilder(Builder):
if not self.any_issue: self.info() if not self.any_issue: self.info()
self.any_issue = True self.any_issue = True
self.write_log_entry(lineno, issue, text) self.write_log_entry(lineno, issue, text)
self.warn('[%s:%d] "%s" found in "%-.120s"' % ( if py3:
self.warn('[%s:%d] "%s" found in "%-.120s"' %
(self.docname, lineno, issue, text))
else:
self.warn('[%s:%d] "%s" found in "%-.120s"' % (
self.docname.encode(sys.getdefaultencoding(),'replace'), self.docname.encode(sys.getdefaultencoding(),'replace'),
lineno, lineno,
issue.encode(sys.getdefaultencoding(),'replace'), issue.encode(sys.getdefaultencoding(),'replace'),
...@@ -155,13 +161,19 @@ class CheckSuspiciousMarkupBuilder(Builder): ...@@ -155,13 +161,19 @@ class CheckSuspiciousMarkupBuilder(Builder):
self.app.statuscode = 1 self.app.statuscode = 1
def write_log_entry(self, lineno, issue, text): def write_log_entry(self, lineno, issue, text):
f = open(self.log_file_name, 'ab') if py3:
writer = csv.writer(f, dialect) f = open(self.log_file_name, 'a')
writer.writerow([self.docname.encode('utf-8'), writer = csv.writer(f, dialect)
lineno, writer.writerow([self.docname, lineno, issue, text.strip()])
issue.encode('utf-8'), f.close()
text.strip().encode('utf-8')]) else:
f.close() f = open(self.log_file_name, 'ab')
writer = csv.writer(f, dialect)
writer.writerow([self.docname.encode('utf-8'),
lineno,
issue.encode('utf-8'),
text.strip().encode('utf-8')])
f.close()
def load_rules(self, filename): def load_rules(self, filename):
"""Load database of previously ignored issues. """Load database of previously ignored issues.
...@@ -171,18 +183,26 @@ class CheckSuspiciousMarkupBuilder(Builder): ...@@ -171,18 +183,26 @@ class CheckSuspiciousMarkupBuilder(Builder):
""" """
self.info("loading ignore rules... ", nonl=1) self.info("loading ignore rules... ", nonl=1)
self.rules = rules = [] self.rules = rules = []
try: f = open(filename, 'rb') try:
except IOError: return if py3:
f = open(filename, 'r')
else:
f = open(filename, 'rb')
except IOError:
return
for i, row in enumerate(csv.reader(f)): for i, row in enumerate(csv.reader(f)):
if len(row) != 4: if len(row) != 4:
raise ValueError( raise ValueError(
"wrong format in %s, line %d: %s" % (filename, i+1, row)) "wrong format in %s, line %d: %s" % (filename, i+1, row))
docname, lineno, issue, text = row docname, lineno, issue, text = row
docname = docname.decode('utf-8') if lineno:
if lineno: lineno = int(lineno) lineno = int(lineno)
else: lineno = None else:
issue = issue.decode('utf-8') lineno = None
text = text.decode('utf-8') if not py3:
docname = docname.decode('utf-8')
issue = issue.decode('utf-8')
text = text.decode('utf-8')
rule = Rule(docname, lineno, issue, text) rule = Rule(docname, lineno, issue, text)
rules.append(rule) rules.append(rule)
f.close() f.close()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment