Skip to content

python3.8 support - #435

Closed
keisuke-nakata wants to merge 3 commits into
autocomplete-python:masterfrom
keisuke-nakata:work-with-python38
Closed

keisuke-nakata wants to merge 3 commits into
autocomplete-python:masterfrom
keisuke-nakata:work-with-python38

Conversation

@keisuke-nakata

@keisuke-nakata keisuke-nakata commented Apr 27, 2020 •

Copy link
Copy Markdown

Current version is missing grammar3.8.txt file.

I just add the grammar file from https://raw.githubusercontent.com/python/cpython/3.8/Lib/lib2to3/Grammar.txt

Here is diff between existing grammar3.7.txt and this PR's grammer3.8.txt ; I did not check all of the diff below, but I think it contains reasonable changes only, and actually autocomplete-plus works well with this grammar3.8.txt file.

diff -y grammar3.7.txt grammar3.8.txt:

# Grammar for Python						# Grammar for Python

# Note:  Changing the grammar specified in this file will mos <
#        require corresponding changes in the parser module   <
#        (../Modules/parsermodule.c).  If you can't make the  <
#        that module yourself, please co-ordinate the require <
#        with someone who can; ask around on python-dev for h <
#        Drake <[email protected]> will probably be listening th <
							      <
# NOTE WELL: You should also follow all the steps listed at	# NOTE WELL: You should also follow all the steps listed at
# https://docs.python.org/devguide/grammar.html		      |	# https://devguide.python.org/grammar/

# Start symbols for the grammar:				# Start symbols for the grammar:
#       file_input is a module or sequence of commands read f |	#	file_input is a module or sequence of commands read f
#       single_input is a single interactive statement;	      |	#	single_input is a single interactive statement;
#       eval_input is the input for the eval() functions.     |	#	eval_input is the input for the eval() and input() fu
# NB: compound_stmt in single_input is followed by extra NEWL	# NB: compound_stmt in single_input is followed by extra NEWL
file_input: (NEWLINE | stmt)* ENDMARKER				file_input: (NEWLINE | stmt)* ENDMARKER
single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE	single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
eval_input: testlist NEWLINE* ENDMARKER				eval_input: testlist NEWLINE* ENDMARKER

decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE	decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+						decorators: decorator+
decorated: decorators (classdef | funcdef | async_funcdef)	decorated: decorators (classdef | funcdef | async_funcdef)
							      |	async_funcdef: ASYNC funcdef
# NOTE: Francisco Souza/Reinoud Elhorst, using ASYNC/'await'  <
# skipping python3.5+ compatibility, in favour of 3.7 solutio <
async_funcdef: 'async' funcdef				      <
funcdef: 'def' NAME parameters ['->' test] ':' suite		funcdef: 'def' NAME parameters ['->' test] ':' suite
							      <
parameters: '(' [typedargslist] ')'				parameters: '(' [typedargslist] ')'
typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [' |	typedargslist: ((tfpdef ['=' test] ',')*
        '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpd |	                ('*' [tname] (',' tname ['=' test])* [',' ['*
      | '**' tfpdef [',']]]				      |	                | tfpdef ['=' test] (',' tfpdef ['=' test])* 
  | '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [ |	tname: NAME [':' test]
  | '**' tfpdef [','])					      |	tfpdef: tname | '(' tfplist ')'
tfpdef: NAME [':' test]					      |	tfplist: tfpdef (',' tfpdef)* [',']
varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' |	varargslist: ((vfpdef ['=' test] ',')*
        '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpd |	              ('*' [vname] (',' vname ['=' test])*  [',' ['**
      | '**' vfpdef [',']]]				      |	              | vfpdef ['=' test] (',' vfpdef ['=' test])* ['
  | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [ |	vname: NAME
  | '**' vfpdef [',']					      |	vfpdef: vname | '(' vfplist ')'
)							      |	vfplist: vfpdef (',' vfpdef)* [',']
vfpdef: NAME						      <

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 | del_stmt | pass_stmt | flow_stmt |   |	small_stmt: (expr_stmt | print_stmt  | del_stmt | pass_stmt |
             import_stmt | global_stmt | nonlocal_stmt | asse |	             import_stmt | global_stmt | exec_stmt | assert_s
expr_stmt: testlist_star_expr (annassign | augassign (yield_e	expr_stmt: testlist_star_expr (annassign | augassign (yield_e
                     ('=' (yield_expr|testlist_star_expr))*)	                     ('=' (yield_expr|testlist_star_expr))*)
annassign: ':' test ['=' test]					annassign: ':' test ['=' test]
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* 	testlist_star_expr: (test|star_expr) (',' (test|star_expr))* 
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | 	augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | 
            '<<=' | '>>=' | '**=' | '//=')			            '<<=' | '>>=' | '**=' | '//=')
# For normal and annotated assignments, additional restrictio	# For normal and annotated assignments, additional restrictio
							      >	print_stmt: 'print' ( [ test (',' test)* [','] ] |
							      >	                      '>>' test [ (',' test)+ [','] ] )
del_stmt: 'del' exprlist					del_stmt: 'del' exprlist
pass_stmt: 'pass'						pass_stmt: 'pass'
flow_stmt: break_stmt | continue_stmt | return_stmt | raise_s	flow_stmt: break_stmt | continue_stmt | return_stmt | raise_s
break_stmt: 'break'						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]]		      |	raise_stmt: 'raise' [test ['from' 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
# note below: the ('.' | '...') is necessary because '...' is |	import_from: ('from' ('.'* dotted_name | '.'+)
import_from: ('from' (('.' | '...')* dotted_name | ('.' | '.. <
              'import' ('*' | '(' import_as_names ')' | impor	              'import' ('*' | '(' import_as_names ')' | impor
import_as_name: NAME ['as' NAME]				import_as_name: NAME ['as' NAME]
dotted_as_name: dotted_name ['as' NAME]				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' NAME (',' NAME)*			      |	global_stmt: ('global' | 'nonlocal') NAME (',' NAME)*
nonlocal_stmt: 'nonlocal' NAME (',' NAME)*		      |	exec_stmt: 'exec' expr ['in' test [',' test]]
assert_stmt: 'assert' test [',' test]				assert_stmt: 'assert' test [',' test]

compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | w	compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | w
async_stmt: 'async' (funcdef | with_stmt | for_stmt)	      |	async_stmt: ASYNC (funcdef | with_stmt | for_stmt)
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' |	if_stmt: 'if' namedexpr_test ':' suite ('elif' namedexpr_test
while_stmt: 'while' test ':' suite ['else' ':' suite]	      |	while_stmt: 'while' namedexpr_test ':' suite ['else' ':' suit
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' 	for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' 
try_stmt: ('try' ':' suite					try_stmt: ('try' ':' suite
           ((except_clause ':' suite)+				           ((except_clause ':' suite)+
            ['else' ':' suite]				      |		    ['else' ':' suite]
            ['finally' ':' suite] |			      |		    ['finally' ':' suite] |
           'finally' ':' suite))			      |		   'finally' ':' 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]
							      >	with_var: 'as' expr
# NB compile.c makes sure that the default except clause is l	# NB compile.c makes sure that the default except clause is l
except_clause: 'except' [test ['as' NAME]]		      |	except_clause: 'except' [test [(',' | 'as') test]]
# Edit by Francisco Souza/David Halter: The stmt is now optio |	suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
# how Jedi allows classes and functions to be empty, which is |
# autocompletion.					      |	# Backward compatibility cruft to support:
suite: simple_stmt | NEWLINE INDENT stmt* DEDENT	      |	# [ x for x in lambda: True, lambda: False if x() ]
							      >	# even while also allowing:
							      >	# lambda x: 5 if x else 2
							      >	# (But not a mix of the two)
							      >	testlist_safe: old_test [(',' old_test)+ [',']]
							      >	old_test: or_test | old_lambdef
							      >	old_lambdef: 'lambda' [varargslist] ':' old_test

							      >	namedexpr_test: test [':=' test]
test: or_test ['if' or_test 'else' test] | lambdef		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)*				or_test: and_test ('or' and_test)*
and_test: not_test ('and' not_test)*				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)*
# <> isn't actually a valid comparison operator in Python. It <
# sake of a __future__ import described in PEP 401 (which rea <
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is	comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is
star_expr: '*' expr						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)*
shift_expr: arith_expr (('<<'|'>>') arith_expr)*		shift_expr: arith_expr (('<<'|'>>') arith_expr)*
arith_expr: term (('+'|'-') term)*				arith_expr: term (('+'|'-') term)*
term: factor (('*'|'@'|'/'|'%'|'//') factor)*			term: factor (('*'|'@'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power				factor: ('+'|'-'|'~') factor | power
power: atom_expr ['**' factor]				      |	power: [AWAIT] atom trailer* ['**' factor]
atom_expr: ['await'] atom trailer*			      |	atom: ('(' [yield_expr|testlist_gexp] ')' |
atom: ('(' [yield_expr|testlist_comp] ')' |		      |	       '[' [listmaker] ']' |
       '[' [testlist_comp] ']' |			      |	       '{' [dictsetmaker] '}' |
       '{' [dictorsetmaker] '}' |			      |	       '`' testlist1 '`' |
       NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'F |	       NAME | NUMBER | STRING+ | '.' '.' '.')
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_ |	listmaker: (namedexpr_test|star_expr) ( comp_for | (',' (name
							      >	testlist_gexp: (namedexpr_test|star_expr) ( comp_for | (',' (
							      >	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|star_expr) (',' (expr|star_expr))* [',']
testlist: test (',' test)* [',']				testlist: test (',' test)* [',']
dictorsetmaker: ( ((test ':' test | '**' expr)		      |	dictsetmaker: ( ((test ':' test | '**' expr)
                   (comp_for | (',' (test ':' test | '**' exp |	                 (comp_for | (',' (test ':' test | '**' expr)
                  ((test | star_expr)			      |	                ((test | star_expr)
                   (comp_for | (',' (test | star_expr))* [',' |			 (comp_for | (',' (test | star_expr))* [','])

classdef: 'class' NAME ['(' [arglist] ')'] ':' suite		classdef: 'class' NAME ['(' [arglist] ')'] ':' suite

arglist: argument (',' argument)*  [',']		      |	arglist: argument (',' argument)* [',']

# The reason that keywords are test nodes instead of NAME is  <
# results in an ambiguity. ast.c makes sure it's a NAME.      <
# "test '=' test" is really "keyword '=' test", but we have n	# "test '=' test" is really "keyword '=' test", but we have n
# These need to be in a single rule to avoid grammar that is 	# These need to be in a single rule to avoid grammar that is 
# to our LL(1) parser. Even though 'test' includes '*expr' in	# to our LL(1) parser. Even though 'test' includes '*expr' in
# we explicitly match '*' here, too, to give it proper preced	# we explicitly match '*' here, too, to give it proper preced
# Illegal combinations and orderings are blocked in ast.c:	# Illegal combinations and orderings are blocked in ast.c:
# multiple (test comp_for) arguments are blocked; keyword unp	# multiple (test comp_for) arguments are blocked; keyword unp
# that precede iterable unpackings are blocked; etc.		# that precede iterable unpackings are blocked; etc.
argument: ( test [comp_for] |					argument: ( test [comp_for] |
							      >	            test ':=' test |
            test '=' test |					            test '=' test |
            '**' test |						            '**' test |
            '*' test )					      |		        '*' test )

comp_iter: comp_for | comp_if					comp_iter: comp_for | comp_if
comp_for: ['async'] 'for' exprlist 'in' or_test [comp_iter]   |	comp_for: [ASYNC] 'for' exprlist 'in' testlist_safe [comp_ite
comp_if: 'if' test_nocond [comp_iter]			      |	comp_if: 'if' old_test [comp_iter]
							      >
							      >	testlist1: test (',' test)*

# not used in grammar, but may appear in "node" passed from P	# not used in grammar, but may appear in "node" passed from P
encoding_decl: NAME						encoding_decl: NAME

yield_expr: 'yield' [yield_arg]					yield_expr: 'yield' [yield_arg]
yield_arg: 'from' test | testlist				yield_arg: 'from' test | testlist
							      >

@keisuke-nakata keisuke-nakata changed the title make autocomplete-python support python3.8 support python3.8 Apr 27, 2020
@keisuke-nakata keisuke-nakata changed the title support python3.8 python3.8 support Apr 27, 2020
@keisuke-nakata

Copy link
Copy Markdown
Author

This did not work...
I will reopen more naive PR (just copy the grammer3.7.txt as grammer3.8.txt ).

It seems that the parse does not support := syntax introduced in recent python?


Traceback (most recent call last):
  File "/Users/keisuke.nakata/.atom/packages/autocomplete-python/lib/jedi/parser/__init__.py", line 56, in load_grammar
    return _loaded_grammars[path]
KeyError: '/Users/keisuke.nakata/.atom/packages/autocomplete-python/lib/jedi/parser/grammar3.8.txt'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/Users/keisuke.nakata/.atom/packages/autocomplete-python/lib/completion.py", line 376, in watch
    self._process_request(request)
  File "/Users/keisuke.nakata/.atom/packages/autocomplete-python/lib/completion.py", line 338, in _process_request
    script = jedi.api.Script(
  File "/Users/keisuke.nakata/.atom/packages/autocomplete-python/lib/jedi/api/__init__.py", line 126, in __init__
    self._grammar = load_grammar(version='%s.%s' % sys.version_info[:2])
  File "/Users/keisuke.nakata/.atom/packages/autocomplete-python/lib/jedi/parser/__init__.py", line 58, in load_grammar
    return _loaded_grammars.setdefault(path, generate_grammar(path))
  File "/Users/keisuke.nakata/.atom/packages/autocomplete-python/lib/jedi/parser/pgen2/pgen.py", line 394, in generate_grammar
    return p.make_grammar()
  File "/Users/keisuke.nakata/.atom/packages/autocomplete-python/lib/jedi/parser/pgen2/pgen.py", line 46, in make_grammar
    arcs.append((self.make_label(c, label), dfa.index(next)))
  File "/Users/keisuke.nakata/.atom/packages/autocomplete-python/lib/jedi/parser/pgen2/pgen.py", line 102, in make_label
    itoken = token.opmap[value]  # Fails if unknown token
KeyError: ':='

@keisuke-nakata
keisuke-nakata deleted the work-with-python38 branch April 27, 2020 06:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant