summaryrefslogtreecommitdiffstats
path: root/contrib/python/parso
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2024-04-20 09:18:55 +0300
committerrobot-piglet <[email protected]>2024-04-20 09:39:03 +0300
commit19be936dfe8ff1852437f6a73bb7919cfb06b8be (patch)
treec98e3f559152be2d96b22c2741d19212cb0bf63f /contrib/python/parso
parentaed0d7a803f63c28bb7eb37540614fecd7676220 (diff)
Intermediate changes
Diffstat (limited to 'contrib/python/parso')
-rw-r--r--contrib/python/parso/py3/.dist-info/METADATA14
-rw-r--r--contrib/python/parso/py3/parso/__init__.py2
-rw-r--r--contrib/python/parso/py3/parso/grammar.py10
-rw-r--r--contrib/python/parso/py3/parso/pgen2/generator.py2
-rw-r--r--contrib/python/parso/py3/parso/python/errors.py51
-rw-r--r--contrib/python/parso/py3/parso/python/grammar313.txt169
-rw-r--r--contrib/python/parso/py3/parso/python/tree.py3
-rw-r--r--contrib/python/parso/py3/tests/test_python_errors.py23
-rw-r--r--contrib/python/parso/py3/ya.make3
9 files changed, 255 insertions, 22 deletions
diff --git a/contrib/python/parso/py3/.dist-info/METADATA b/contrib/python/parso/py3/.dist-info/METADATA
index 331fef3a494..10f9cb843e8 100644
--- a/contrib/python/parso/py3/.dist-info/METADATA
+++ b/contrib/python/parso/py3/.dist-info/METADATA
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: parso
-Version: 0.8.3
+Version: 0.8.4
Summary: A Python Parser
Home-page: https://github.com/davidhalter/parso
Author: David Halter
@@ -26,11 +26,12 @@ Classifier: Topic :: Utilities
Classifier: Typing :: Typed
Requires-Python: >=3.6
Provides-Extra: qa
-Requires-Dist: flake8 (==3.8.3) ; extra == 'qa'
-Requires-Dist: mypy (==0.782) ; extra == 'qa'
+Requires-Dist: flake8 (==5.0.4) ; extra == 'qa'
+Requires-Dist: mypy (==0.971) ; extra == 'qa'
+Requires-Dist: types-setuptools (==67.2.0.1) ; extra == 'qa'
Provides-Extra: testing
Requires-Dist: docopt ; extra == 'testing'
-Requires-Dist: pytest (<6.0.0) ; extra == 'testing'
+Requires-Dist: pytest ; extra == 'testing'
###################################################################
parso - A Python Parser
@@ -137,6 +138,11 @@ Changelog
Unreleased
++++++++++
+0.8.4 (2024-04-05)
+++++++++++++++++++
+
+- Add basic support for Python 3.13
+
0.8.3 (2021-11-30)
++++++++++++++++++
diff --git a/contrib/python/parso/py3/parso/__init__.py b/contrib/python/parso/py3/parso/__init__.py
index 0cceabedca5..354aff5c252 100644
--- a/contrib/python/parso/py3/parso/__init__.py
+++ b/contrib/python/parso/py3/parso/__init__.py
@@ -43,7 +43,7 @@ from parso.grammar import Grammar, load_grammar
from parso.utils import split_lines, python_bytes_to_unicode
-__version__ = '0.8.3'
+__version__ = '0.8.4'
def parse(code=None, **kwargs):
diff --git a/contrib/python/parso/py3/parso/grammar.py b/contrib/python/parso/py3/parso/grammar.py
index 1f81148682e..9d6f1a1ea09 100644
--- a/contrib/python/parso/py3/parso/grammar.py
+++ b/contrib/python/parso/py3/parso/grammar.py
@@ -107,14 +107,14 @@ class Grammar(Generic[_NodeT]):
if file_io is None:
if code is None:
- file_io = FileIO(path) # type: ignore
+ file_io = FileIO(path) # type: ignore[arg-type]
else:
file_io = KnownContentFileIO(path, code)
if cache and file_io.path is not None:
module_node = load_module(self._hashed, file_io, cache_path=cache_path)
if module_node is not None:
- return module_node # type: ignore
+ return module_node # type: ignore[no-any-return]
if code is None:
code = file_io.read()
@@ -133,7 +133,7 @@ class Grammar(Generic[_NodeT]):
module_node = module_cache_item.node
old_lines = module_cache_item.lines
if old_lines == lines:
- return module_node # type: ignore
+ return module_node # type: ignore[no-any-return]
new_node = self._diff_parser(
self._pgen_grammar, self._tokenizer, module_node
@@ -145,7 +145,7 @@ class Grammar(Generic[_NodeT]):
# Never pickle in pypy, it's slow as hell.
pickling=cache and not is_pypy,
cache_path=cache_path)
- return new_node # type: ignore
+ return new_node # type: ignore[no-any-return]
tokens = self._tokenizer(lines)
@@ -161,7 +161,7 @@ class Grammar(Generic[_NodeT]):
# Never pickle in pypy, it's slow as hell.
pickling=cache and not is_pypy,
cache_path=cache_path)
- return root_node # type: ignore
+ return root_node # type: ignore[no-any-return]
def _get_token_namespace(self):
ns = self._token_namespace
diff --git a/contrib/python/parso/py3/parso/pgen2/generator.py b/contrib/python/parso/py3/parso/pgen2/generator.py
index db6e1cb3261..30f0b546b8c 100644
--- a/contrib/python/parso/py3/parso/pgen2/generator.py
+++ b/contrib/python/parso/py3/parso/pgen2/generator.py
@@ -276,7 +276,7 @@ def generate_grammar(bnf_grammar: str, token_namespace) -> Grammar:
dfa_state.transitions[transition] = DFAPlan(next_dfa)
_calculate_tree_traversal(rule_to_dfas)
- return Grammar(start_nonterminal, rule_to_dfas, reserved_strings) # type: ignore
+ return Grammar(start_nonterminal, rule_to_dfas, reserved_strings) # type: ignore[arg-type]
def _make_transition(token_namespace, reserved_syntax_strings, label):
diff --git a/contrib/python/parso/py3/parso/python/errors.py b/contrib/python/parso/py3/parso/python/errors.py
index 5da046ab01f..09c5047b612 100644
--- a/contrib/python/parso/py3/parso/python/errors.py
+++ b/contrib/python/parso/py3/parso/python/errors.py
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import codecs
+import sys
import warnings
import re
from contextlib import contextmanager
@@ -33,7 +34,10 @@ def _get_rhs_name(node, version):
return "literal"
else:
if second.children[1] == ":" or second.children[0] == "**":
- return "dict display"
+ if version < (3, 10):
+ return "dict display"
+ else:
+ return "dict literal"
else:
return "set display"
elif (
@@ -47,7 +51,10 @@ def _get_rhs_name(node, version):
elif first == "[":
return "list"
elif first == "{" and second == "}":
- return "dict display"
+ if version < (3, 10):
+ return "dict display"
+ else:
+ return "dict literal"
elif first == "{" and len(node.children) > 2:
return "set display"
elif type_ == "keyword":
@@ -58,7 +65,10 @@ def _get_rhs_name(node, version):
else:
return str(node.value)
elif type_ == "operator" and node.value == "...":
- return "Ellipsis"
+ if version < (3, 10):
+ return "Ellipsis"
+ else:
+ return "ellipsis"
elif type_ == "comparison":
return "comparison"
elif type_ in ("string", "number", "strings"):
@@ -83,7 +93,10 @@ def _get_rhs_name(node, version):
or "_test" in type_
or type_ in ("term", "factor")
):
- return "operator"
+ if version < (3, 10):
+ return "operator"
+ else:
+ return "expression"
elif type_ == "star_expr":
return "starred"
elif type_ == "testlist_star_expr":
@@ -610,7 +623,10 @@ class _NameChecks(SyntaxRule):
@ErrorFinder.register_rule(type='string')
class _StringChecks(SyntaxRule):
- message = "bytes can only contain ASCII literal characters."
+ if sys.version_info < (3, 10):
+ message = "bytes can only contain ASCII literal characters."
+ else:
+ message = "bytes can only contain ASCII literal characters"
def is_issue(self, leaf):
string_prefix = leaf.string_prefix.lower()
@@ -1043,14 +1059,20 @@ class _CheckAssignmentRule(SyntaxRule):
error = 'literal'
else:
if second.children[1] == ':':
- error = 'dict display'
+ if self._normalizer.version < (3, 10):
+ error = 'dict display'
+ else:
+ error = 'dict literal'
else:
error = 'set display'
elif first == "{" and second == "}":
if self._normalizer.version < (3, 8):
error = 'literal'
else:
- error = "dict display"
+ if self._normalizer.version < (3, 10):
+ error = "dict display"
+ else:
+ error = "dict literal"
elif first == "{" and len(node.children) > 2:
if self._normalizer.version < (3, 8):
error = 'literal'
@@ -1083,7 +1105,10 @@ class _CheckAssignmentRule(SyntaxRule):
error = str(node.value)
elif type_ == 'operator':
if node.value == '...':
- error = 'Ellipsis'
+ if self._normalizer.version < (3, 10):
+ error = 'Ellipsis'
+ else:
+ error = 'ellipsis'
elif type_ == 'comparison':
error = 'comparison'
elif type_ in ('string', 'number', 'strings'):
@@ -1098,7 +1123,10 @@ class _CheckAssignmentRule(SyntaxRule):
if node.children[0] == 'await':
error = 'await expression'
elif node.children[-2] == '**':
- error = 'operator'
+ if self._normalizer.version < (3, 10):
+ error = 'operator'
+ else:
+ error = 'expression'
else:
# Has a trailer
trailer = node.children[-1]
@@ -1120,7 +1148,10 @@ class _CheckAssignmentRule(SyntaxRule):
elif ('expr' in type_ and type_ != 'star_expr' # is a substring
or '_test' in type_
or type_ in ('term', 'factor')):
- error = 'operator'
+ if self._normalizer.version < (3, 10):
+ error = 'operator'
+ else:
+ error = 'expression'
elif type_ == "star_expr":
if is_deletion:
if self._normalizer.version >= (3, 9):
diff --git a/contrib/python/parso/py3/parso/python/grammar313.txt b/contrib/python/parso/py3/parso/python/grammar313.txt
new file mode 100644
index 00000000000..f092050d881
--- /dev/null
+++ b/contrib/python/parso/py3/parso/python/grammar313.txt
@@ -0,0 +1,169 @@
+# Grammar for Python
+
+# NOTE WELL: You should also follow all the steps listed at
+# https://devguide.python.org/grammar/
+
+# 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!
+single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
+file_input: stmt* ENDMARKER
+eval_input: testlist NEWLINE* ENDMARKER
+
+decorator: '@' namedexpr_test NEWLINE
+decorators: decorator+
+decorated: decorators (classdef | funcdef | async_funcdef)
+
+async_funcdef: 'async' funcdef
+funcdef: 'def' NAME parameters ['->' test] ':' suite
+
+parameters: '(' [typedargslist] ')'
+typedargslist: (
+ (tfpdef ['=' test] (',' tfpdef ['=' test])* ',' '/' [',' [ tfpdef ['=' test] (
+ ',' tfpdef ['=' test])* ([',' [
+ '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
+ | '**' tfpdef [',']]])
+ | '*' [tfpdef] (',' tfpdef ['=' test])* ([',' ['**' tfpdef [',']]])
+ | '**' tfpdef [',']]] )
+| (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [
+ '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
+ | '**' tfpdef [',']]]
+ | '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
+ | '**' tfpdef [','])
+)
+tfpdef: NAME [':' test]
+varargslist: vfpdef ['=' test ](',' vfpdef ['=' test])* ',' '/' [',' [ (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [
+ '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
+ | '**' vfpdef [',']]]
+ | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
+ | '**' vfpdef [',']) ]] | (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [
+ '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
+ | '**' vfpdef [',']]]
+ | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]]
+ | '**' vfpdef [',']
+)
+vfpdef: NAME
+
+stmt: simple_stmt | compound_stmt | NEWLINE
+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 (annassign | augassign (yield_expr|testlist) |
+ ('=' (yield_expr|testlist_star_expr))*)
+annassign: ':' test ['=' (yield_expr|testlist_star_expr)]
+testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
+augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
+ '<<=' | '>>=' | '**=' | '//=')
+# For normal and annotated 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_star_expr]
+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 | async_stmt
+async_stmt: 'async' (funcdef | with_stmt | for_stmt)
+if_stmt: 'if' namedexpr_test ':' suite ('elif' namedexpr_test ':' suite)* ['else' ':' suite]
+while_stmt: 'while' namedexpr_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
+
+namedexpr_test: test [':=' test]
+test: or_test ['if' or_test 'else' test] | lambdef
+lambdef: 'lambda' [varargslist] ':' test
+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 (which really works :-)
+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_expr ['**' factor]
+atom_expr: ['await'] atom trailer*
+atom: ('(' [yield_expr|testlist_comp] ')' |
+ '[' [testlist_comp] ']' |
+ '{' [dictorsetmaker] '}' |
+ NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
+testlist_comp: (namedexpr_test|star_expr) ( comp_for | (',' (namedexpr_test|star_expr))* [','] )
+trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+subscriptlist: subscript (',' subscript)* [',']
+subscript: test [':=' test] | [test] ':' [test] [sliceop]
+sliceop: ':' [test]
+exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
+testlist: test (',' test)* [',']
+dictorsetmaker: ( ((test ':' test | '**' expr)
+ (comp_for | (',' (test ':' test | '**' expr))* [','])) |
+ ((test [':=' test] | star_expr)
+ (comp_for | (',' (test [':=' test] | star_expr))* [','])) )
+
+classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
+
+arglist: argument (',' argument)* [',']
+
+# 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.
+# "test '=' test" is really "keyword '=' test", but we have no such token.
+# These need to be in a single rule to avoid grammar that is ambiguous
+# to our LL(1) parser. Even though 'test' includes '*expr' in star_expr,
+# we explicitly match '*' here, too, to give it proper precedence.
+# Illegal combinations and orderings are blocked in ast.c:
+# multiple (test comp_for) arguments are blocked; keyword unpackings
+# that precede iterable unpackings are blocked; etc.
+argument: ( test [comp_for] |
+ test ':=' test |
+ test '=' test |
+ '**' test |
+ '*' test )
+
+comp_iter: comp_for | comp_if
+sync_comp_for: 'for' exprlist 'in' or_test [comp_iter]
+comp_for: ['async'] sync_comp_for
+comp_if: 'if' or_test [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_star_expr
+
+strings: (STRING | fstring)+
+fstring: FSTRING_START fstring_content* FSTRING_END
+fstring_content: FSTRING_STRING | fstring_expr
+fstring_conversion: '!' NAME
+fstring_expr: '{' (testlist_comp | yield_expr) ['='] [ fstring_conversion ] [ fstring_format_spec ] '}'
+fstring_format_spec: ':' fstring_content*
diff --git a/contrib/python/parso/py3/parso/python/tree.py b/contrib/python/parso/py3/parso/python/tree.py
index ebb4087030d..0624e6755d6 100644
--- a/contrib/python/parso/py3/parso/python/tree.py
+++ b/contrib/python/parso/py3/parso/python/tree.py
@@ -295,6 +295,8 @@ class FStringEnd(PythonLeaf):
class _StringComparisonMixin:
+ __slots__ = ()
+
def __eq__(self, other):
"""
Make comparisons with strings easy.
@@ -544,6 +546,7 @@ class Function(ClassOrFunc):
4. annotation (if present)
"""
type = 'funcdef'
+ __slots__ = ()
def __init__(self, children):
super().__init__(children)
diff --git a/contrib/python/parso/py3/tests/test_python_errors.py b/contrib/python/parso/py3/tests/test_python_errors.py
index fe43a301ad0..b4986d33f6b 100644
--- a/contrib/python/parso/py3/tests/test_python_errors.py
+++ b/contrib/python/parso/py3/tests/test_python_errors.py
@@ -1,6 +1,7 @@
"""
Testing if parso finds syntax errors and indentation errors.
"""
+import re
import sys
import warnings
@@ -136,6 +137,28 @@ def _get_actual_exception(code):
wanted = 'SyntaxError: invalid syntax'
elif wanted == "SyntaxError: f-string: single '}' is not allowed":
wanted = 'SyntaxError: invalid syntax'
+ elif "Maybe you meant '==' instead of '='?" in wanted:
+ wanted = wanted.removesuffix(" here. Maybe you meant '==' instead of '='?")
+ elif re.match(
+ r"SyntaxError: unterminated string literal \(detected at line \d+\)", wanted
+ ):
+ wanted = "SyntaxError: EOL while scanning string literal"
+ elif re.match(
+ r"SyntaxError: unterminated triple-quoted string literal \(detected at line \d+\)",
+ wanted,
+ ):
+ wanted = 'SyntaxError: EOF while scanning triple-quoted string literal'
+ elif wanted == 'SyntaxError: cannot use starred expression here':
+ wanted = "SyntaxError: can't use starred expression here"
+ elif wanted == 'SyntaxError: f-string: cannot use starred expression here':
+ wanted = "SyntaxError: f-string: can't use starred expression here"
+ elif re.match(
+ r"IndentationError: expected an indented block after '[^']*' statement on line \d",
+ wanted,
+ ):
+ wanted = 'IndentationError: expected an indented block'
+ elif wanted == 'SyntaxError: unterminated string literal':
+ wanted = 'SyntaxError: EOL while scanning string literal'
return [wanted], line_nr
diff --git a/contrib/python/parso/py3/ya.make b/contrib/python/parso/py3/ya.make
index fa4210f7c5d..4a388e26b2a 100644
--- a/contrib/python/parso/py3/ya.make
+++ b/contrib/python/parso/py3/ya.make
@@ -2,7 +2,7 @@
PY3_LIBRARY()
-VERSION(0.8.3)
+VERSION(0.8.4)
LICENSE(PSF-2.0)
@@ -41,6 +41,7 @@ RESOURCE_FILES(
parso/python/grammar310.txt
parso/python/grammar311.txt
parso/python/grammar312.txt
+ parso/python/grammar313.txt
parso/python/grammar36.txt
parso/python/grammar37.txt
parso/python/grammar38.txt