merge with stable

This commit is contained in:
Georg Brandl 2014-01-12 20:30:25 +01:00
commit fc82989a35
13 changed files with 200 additions and 65 deletions

13
CHANGES
View File

@ -83,6 +83,19 @@ Bugs fixed
* #1155: Fix autodocumenting C-defined methods as attributes in Python 3. * #1155: Fix autodocumenting C-defined methods as attributes in Python 3.
* #1233: Allow finding both Python classes and exceptions with the "class" and
"exc" roles in intersphinx.
* #1198: Allow "image" for the "figwidth" option of the :rst:dir:`figure`
directive as documented by docutils.
* #1152: Fix pycode parsing errors of Python 3 code by including two grammar
versions for Python 2 and 3, and loading the appropriate version for the
running Python version.
* #1017: Be helpful and tell the user when the argument to :rst:dir:`option`
does not match the required format.
Documentation Documentation
------------- -------------

View File

@ -20,7 +20,8 @@ recursive-include sphinx/ext/autosummary/templates *
recursive-include tests * recursive-include tests *
recursive-include utils * recursive-include utils *
recursive-include custom_fixers * recursive-include custom_fixers *
include sphinx/pycode/Grammar.txt include sphinx/pycode/Grammar-py2.txt
include sphinx/pycode/Grammar-py3.txt
recursive-include doc * recursive-include doc *
prune doc/_build prune doc/_build

View File

@ -12,7 +12,6 @@
import re import re
from docutils.parsers.rst import Directive, directives from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst.directives import images
from sphinx import addnodes from sphinx import addnodes
from sphinx.util.docfields import DocFieldTransformer from sphinx.util.docfields import DocFieldTransformer
@ -22,15 +21,6 @@ from sphinx.directives.code import *
from sphinx.directives.other import * from sphinx.directives.other import *
# allow units for the figure's "figwidth"
try:
images.Figure.option_spec['figwidth'] = \
directives.length_or_percentage_or_unitless
except AttributeError:
images.figure.options['figwidth'] = \
directives.length_or_percentage_or_unitless
# RE to strip backslash escapes # RE to strip backslash escapes
nl_escape_re = re.compile(r'\\\n') nl_escape_re = re.compile(r'\\\n')
strip_backslash_re = re.compile(r'\\(.)') strip_backslash_re = re.compile(r'\\(.)')

View File

@ -576,8 +576,8 @@ class PythonDomain(Domain):
object_types = { object_types = {
'function': ObjType(l_('function'), 'func', 'obj'), 'function': ObjType(l_('function'), 'func', 'obj'),
'data': ObjType(l_('data'), 'data', 'obj'), 'data': ObjType(l_('data'), 'data', 'obj'),
'class': ObjType(l_('class'), 'class', 'obj'), 'class': ObjType(l_('class'), 'class', 'exc', 'obj'),
'exception': ObjType(l_('exception'), 'exc', 'obj'), 'exception': ObjType(l_('exception'), 'exc', 'class', 'obj'),
'method': ObjType(l_('method'), 'meth', 'obj'), 'method': ObjType(l_('method'), 'meth', 'obj'),
'classmethod': ObjType(l_('class method'), 'meth', 'obj'), 'classmethod': ObjType(l_('class method'), 'meth', 'obj'),
'staticmethod': ObjType(l_('static method'), 'meth', 'obj'), 'staticmethod': ObjType(l_('static method'), 'meth', 'obj'),

View File

@ -27,8 +27,7 @@ from sphinx.util.compat import Directive
# RE for option descriptions # RE for option descriptions
option_desc_re = re.compile( option_desc_re = re.compile(r'((?:/|-|--)[-_a-zA-Z0-9]+)(\s*.*)')
r'((?:/|-|--)[-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)')
class GenericObject(ObjectDescription): class GenericObject(ObjectDescription):
@ -130,14 +129,23 @@ class Target(Directive):
class Cmdoption(ObjectDescription): class Cmdoption(ObjectDescription):
""" """
Description of a command-line option (.. cmdoption). Description of a command-line option (.. option).
""" """
def handle_signature(self, sig, signode): def handle_signature(self, sig, signode):
"""Transform an option description into RST nodes.""" """Transform an option description into RST nodes."""
count = 0 count = 0
firstname = '' firstname = ''
for m in option_desc_re.finditer(sig): for potential_option in sig.split(', '):
potential_option = potential_option.strip()
m = option_desc_re.match(potential_option)
if not m:
self.env.warn(
self.env.docname,
'Malformed option description %r, should '
'look like "-opt args", "--opt args" or '
'"/opt args"' % potential_option, self.lineno)
continue
optname, args = m.groups() optname, args = m.groups()
if count: if count:
signode += addnodes.desc_addname(', ', ', ') signode += addnodes.desc_addname(', ', ', ')

View File

@ -1,18 +1,11 @@
# Grammar for Python. This grammar supports Python 2.x and 3.x. # Grammar for Python 2.x
# Note: Changing the grammar specified in this file will most likely # IMPORTANT: when copying over a new Grammar file, make sure file_input
# require corresponding changes in the parser module # is the first nonterminal in the file!
# (../Modules/parsermodule.c). If you can't make the changes to
# that module yourself, please co-ordinate the required changes
# with someone who can; ask around on python-dev for help. Fred
# Drake <fdrake@acm.org> will probably be listening there.
# NOTE WELL: You should also follow all the steps listed in PEP 306,
# "How to Change Python's Grammar"
# Start symbols for the grammar: # Start symbols for the grammar:
# file_input is a module or sequence of commands read from an input file;
# single_input is a single interactive statement; # single_input is a single interactive statement;
# file_input is a module or sequence of commands read from an input file;
# eval_input is the input for the eval() and input() functions. # eval_input is the input for the eval() and input() functions.
# NB: compound_stmt in single_input is followed by extra NEWLINE! # NB: compound_stmt in single_input is followed by extra NEWLINE!
file_input: (NEWLINE | stmt)* ENDMARKER file_input: (NEWLINE | stmt)* ENDMARKER
@ -22,28 +15,20 @@ eval_input: testlist NEWLINE* ENDMARKER
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+ decorators: decorator+
decorated: decorators (classdef | funcdef) decorated: decorators (classdef | funcdef)
funcdef: 'def' NAME parameters ['->' test] ':' suite funcdef: 'def' NAME parameters ':' suite
parameters: '(' [typedargslist] ')' parameters: '(' [varargslist] ')'
typedargslist: ((tfpdef ['=' test] ',')* varargslist: ((fpdef ['=' test] ',')*
('*' [tname] (',' tname ['=' test])* [',' '**' tname] | '**' tname) ('*' NAME [',' '**' NAME] | '**' NAME) |
| tfpdef ['=' test] (',' tfpdef ['=' test])* [',']) fpdef ['=' test] (',' fpdef ['=' test])* [','])
tname: NAME [':' test] fpdef: NAME | '(' fplist ')'
tfpdef: tname | '(' tfplist ')' fplist: fpdef (',' fpdef)* [',']
tfplist: tfpdef (',' tfpdef)* [',']
varargslist: ((vfpdef ['=' test] ',')*
('*' [vname] (',' vname ['=' test])* [',' '**' vname] | '**' vname)
| vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
vname: NAME
vfpdef: vname | '(' vfplist ')'
vfplist: vfpdef (',' vfpdef)* [',']
stmt: simple_stmt | compound_stmt stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt |
import_stmt | global_stmt | exec_stmt | assert_stmt) import_stmt | global_stmt | exec_stmt | assert_stmt)
expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | expr_stmt: testlist (augassign (yield_expr|testlist) |
('=' (yield_expr|testlist_star_expr))*) ('=' (yield_expr|testlist))*)
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
'<<=' | '>>=' | '**=' | '//=') '<<=' | '>>=' | '**=' | '//=')
# For normal assignments, additional restrictions enforced by the interpreter # For normal assignments, additional restrictions enforced by the interpreter
@ -56,7 +41,7 @@ break_stmt: 'break'
continue_stmt: 'continue' continue_stmt: 'continue'
return_stmt: 'return' [testlist] return_stmt: 'return' [testlist]
yield_stmt: yield_expr yield_stmt: yield_expr
raise_stmt: 'raise' [test ['from' test | ',' test [',' test]]] raise_stmt: 'raise' [test [',' test [',' test]]]
import_stmt: import_name | import_from import_stmt: import_name | import_from
import_name: 'import' dotted_as_names import_name: 'import' dotted_as_names
import_from: ('from' ('.'* dotted_name | '.'+) import_from: ('from' ('.'* dotted_name | '.'+)
@ -66,7 +51,7 @@ dotted_as_name: dotted_name ['as' NAME]
import_as_names: import_as_name (',' import_as_name)* [','] import_as_names: import_as_name (',' import_as_name)* [',']
dotted_as_names: dotted_as_name (',' dotted_as_name)* dotted_as_names: dotted_as_name (',' dotted_as_name)*
dotted_name: NAME ('.' NAME)* dotted_name: NAME ('.' NAME)*
global_stmt: ('global' | 'nonlocal') NAME (',' NAME)* global_stmt: 'global' NAME (',' NAME)*
exec_stmt: 'exec' expr ['in' test [',' test]] exec_stmt: 'exec' expr ['in' test [',' test]]
assert_stmt: 'assert' test [',' test] assert_stmt: 'assert' test [',' test]
@ -82,7 +67,7 @@ try_stmt: ('try' ':' suite
with_stmt: 'with' with_item (',' with_item)* ':' suite with_stmt: 'with' with_item (',' with_item)* ':' suite
with_item: test ['as' expr] with_item: test ['as' expr]
# NB compile.c makes sure that the default except clause is last # NB compile.c makes sure that the default except clause is last
except_clause: 'except' [test [(',' | 'as') test]] except_clause: 'except' [test [('as' | ',') test]]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
# Backward compatibility cruft to support: # Backward compatibility cruft to support:
@ -100,7 +85,6 @@ and_test: not_test ('and' not_test)*
not_test: 'not' not_test | comparison not_test: 'not' not_test | comparison
comparison: expr (comp_op expr)* comparison: expr (comp_op expr)*
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
star_expr: '*' expr
expr: xor_expr ('|' xor_expr)* expr: xor_expr ('|' xor_expr)*
xor_expr: and_expr ('^' and_expr)* xor_expr: and_expr ('^' and_expr)*
and_expr: shift_expr ('&' shift_expr)* and_expr: shift_expr ('&' shift_expr)*
@ -109,32 +93,38 @@ arith_expr: term (('+'|'-') term)*
term: factor (('*'|'/'|'%'|'//') factor)* term: factor (('*'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power factor: ('+'|'-'|'~') factor | power
power: atom trailer* ['**' factor] power: atom trailer* ['**' factor]
atom: ('(' [yield_expr|testlist_gexp] ')' | atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [listmaker] ']' | '[' [listmaker] ']' |
'{' [dictsetmaker] '}' | '{' [dictorsetmaker] '}' |
'`' testlist1 '`' | '`' testlist1 '`' |
NAME | NUMBER | STRING+ | '.' '.' '.') NAME | NUMBER | STRING+)
listmaker: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) listmaker: test ( list_for | (',' test)* [','] )
testlist_gexp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) testlist_comp: test ( comp_for | (',' test)* [','] )
lambdef: 'lambda' [varargslist] ':' test lambdef: 'lambda' [varargslist] ':' test
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)* [','] subscriptlist: subscript (',' subscript)* [',']
subscript: test | [test] ':' [test] [sliceop] subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
sliceop: ':' [test] sliceop: ':' [test]
exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] exprlist: expr (',' expr)* [',']
testlist: test (',' test)* [','] testlist: test (',' test)* [',']
dictsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
(test (comp_for | (',' test)* [','])) ) (test (comp_for | (',' test)* [','])) )
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
arglist: (argument ',')* (argument [','] arglist: (argument ',')* (argument [',']
|'*' test (',' argument)* [',' '**' test] |'*' test (',' argument)* [',' '**' test]
|'**' test) |'**' test)
argument: test [comp_for] | test '=' test # Really [keyword '='] test # The reason that keywords are test nodes instead of NAME is that using NAME
# results in an ambiguity. ast.c makes sure it's a NAME.
argument: test [comp_for] | test '=' test
list_iter: list_for | list_if
list_for: 'for' exprlist 'in' testlist_safe [list_iter]
list_if: 'if' old_test [list_iter]
comp_iter: comp_for | comp_if comp_iter: comp_for | comp_if
comp_for: 'for' exprlist 'in' testlist_safe [comp_iter] comp_for: 'for' exprlist 'in' or_test [comp_iter]
comp_if: 'if' old_test [comp_iter] comp_if: 'if' old_test [comp_iter]
testlist1: test (',' test)* testlist1: test (',' test)*

View File

@ -0,0 +1,126 @@
# Grammar for Python 3.x (with at least x <= 4)
# IMPORTANT: when copying over a new Grammar file, make sure file_input
# is the first nonterminal in the file!
# Start symbols for the grammar:
# single_input is a single interactive statement;
# file_input is a module or sequence of commands read from an input file;
# eval_input is the input for the eval() functions.
# NB: compound_stmt in single_input is followed by extra NEWLINE!
file_input: (NEWLINE | stmt)* ENDMARKER
single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
eval_input: testlist NEWLINE* ENDMARKER
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
decorated: decorators (classdef | funcdef)
funcdef: 'def' NAME parameters ['->' test] ':' suite
parameters: '(' [typedargslist] ')'
typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [','
['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]]
| '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef)
tfpdef: NAME [':' test]
varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [','
['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]]
| '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef)
vfpdef: NAME
stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) |
('=' (yield_expr|testlist_star_expr))*)
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
'<<=' | '>>=' | '**=' | '//=')
# For normal assignments, additional restrictions enforced by the interpreter
del_stmt: 'del' exprlist
pass_stmt: 'pass'
flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
break_stmt: 'break'
continue_stmt: 'continue'
return_stmt: 'return' [testlist]
yield_stmt: yield_expr
raise_stmt: 'raise' [test ['from' test]]
import_stmt: import_name | import_from
import_name: 'import' dotted_as_names
# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+)
'import' ('*' | '(' import_as_names ')' | import_as_names))
import_as_name: NAME ['as' NAME]
dotted_as_name: dotted_name ['as' NAME]
import_as_names: import_as_name (',' import_as_name)* [',']
dotted_as_names: dotted_as_name (',' dotted_as_name)*
dotted_name: NAME ('.' NAME)*
global_stmt: 'global' NAME (',' NAME)*
nonlocal_stmt: 'nonlocal' NAME (',' NAME)*
assert_stmt: 'assert' test [',' test]
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
while_stmt: 'while' test ':' suite ['else' ':' suite]
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
try_stmt: ('try' ':' suite
((except_clause ':' suite)+
['else' ':' suite]
['finally' ':' suite] |
'finally' ':' suite))
with_stmt: 'with' with_item (',' with_item)* ':' suite
with_item: test ['as' expr]
# NB compile.c makes sure that the default except clause is last
except_clause: 'except' [test ['as' NAME]]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
test: or_test ['if' or_test 'else' test] | lambdef
test_nocond: or_test | lambdef_nocond
lambdef: 'lambda' [varargslist] ':' test
lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
or_test: and_test ('or' and_test)*
and_test: not_test ('and' not_test)*
not_test: 'not' not_test | comparison
comparison: expr (comp_op expr)*
# <> isn't actually a valid comparison operator in Python. It's here for the
# sake of a __future__ import described in PEP 401
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
star_expr: '*' expr
expr: xor_expr ('|' xor_expr)*
xor_expr: and_expr ('^' and_expr)*
and_expr: shift_expr ('&' shift_expr)*
shift_expr: arith_expr (('<<'|'>>') arith_expr)*
arith_expr: term (('+'|'-') term)*
term: factor (('*'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power
power: atom trailer* ['**' factor]
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)* [',']
subscript: test | [test] ':' [test] [sliceop]
sliceop: ':' [test]
exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
testlist: test (',' test)* [',']
dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
(test (comp_for | (',' test)* [','])) )
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
arglist: (argument ',')* (argument [',']
|'*' test (',' argument)* [',' '**' test]
|'**' test)
# The reason that keywords are test nodes instead of NAME is that using NAME
# results in an ambiguity. ast.c makes sure it's a NAME.
argument: test [comp_for] | test '=' test # Really [keyword '='] test
comp_iter: comp_for | comp_if
comp_for: 'for' exprlist 'in' or_test [comp_iter]
comp_if: 'if' test_nocond [comp_iter]
# not used in grammar, but may appear in "node" passed from Parser to Compiler
encoding_decl: NAME
yield_expr: 'yield' [yield_arg]
yield_arg: 'from' test | testlist

View File

@ -9,6 +9,7 @@
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import sys
from os import path from os import path
from sphinx import package_dir from sphinx import package_dir
@ -21,7 +22,8 @@ from sphinx.util.docstrings import prepare_docstring, prepare_commentdoc
# load the Python grammar # load the Python grammar
_grammarfile = path.join(package_dir, 'pycode', 'Grammar.txt') _grammarfile = path.join(package_dir, 'pycode',
'Grammar-py%d.txt' % sys.version_info[0])
pygrammar = driver.load_grammar(_grammarfile) pygrammar = driver.load_grammar(_grammarfile)
pydriver = driver.Driver(pygrammar, convert=nodes.convert) pydriver = driver.Driver(pygrammar, convert=nodes.convert)

View File

@ -122,7 +122,8 @@ def load_grammar(gt="Grammar.txt", gp=None,
if tail == ".txt": if tail == ".txt":
tail = "" tail = ""
# embed Sphinx major version for the case we ever change the grammar... # embed Sphinx major version for the case we ever change the grammar...
gp = head + tail + ".".join(map(str, sphinx.version_info[:2])) + ".pickle" gp = head + tail + "-sphinx" + \
".".join(map(str, sphinx.version_info[:2])) + ".pickle"
if force or not _newer(gp, gt): if force or not _newer(gp, gt):
logger.info("Generating grammar tables from %s", gt) logger.info("Generating grammar tables from %s", gt)
g = pgen.generate_grammar(gt) g = pgen.generate_grammar(gt)

View File

@ -162,6 +162,7 @@ opmap_raw = """
// DOUBLESLASH // DOUBLESLASH
//= DOUBLESLASHEQUAL //= DOUBLESLASHEQUAL
-> RARROW -> RARROW
... ELLIPSIS
""" """
opmap = {} opmap = {}

View File

@ -62,7 +62,8 @@ COMMENT = 52
NL = 53 NL = 53
RARROW = 54 RARROW = 54
ERRORTOKEN = 55 ERRORTOKEN = 55
N_TOKENS = 56 ELLIPSIS = 56
N_TOKENS = 57
NT_OFFSET = 256 NT_OFFSET = 256
#--end constants-- #--end constants--

View File

@ -89,6 +89,7 @@ div.sphinxsidebar #searchbox input[type="submit"] {
img { img {
border: 0; border: 0;
max-width: 100%;
} }
/* -- search page ----------------------------------------------------------- */ /* -- search page ----------------------------------------------------------- */

View File

@ -92,6 +92,7 @@ div.sphinxsidebar input {
img { img {
border: 0; border: 0;
max-width: 100%;
} }
/* -- search page ----------------------------------------------------------- */ /* -- search page ----------------------------------------------------------- */