diff --git a/parso/python/normalizer.py b/parso/python/normalizer.py index f4da332..d4c9710 100644 --- a/parso/python/normalizer.py +++ b/parso/python/normalizer.py @@ -33,6 +33,10 @@ def _is_future_import(import_from): return [n.value for n in from_names] == ['__future__'] +def _iter_params(parent_node): + return (n for n in parent_node.children if n.type == 'param') + + def _is_future_import_first(import_from): """ Checks if the import is the first statement of a file. @@ -173,6 +177,16 @@ class ErrorFinder(Normalizer): if first_is_bytes != _is_bytes_literal(string): self._add_syntax_error(message, node) break + elif node.type in ('parameters', 'lambdef'): + default_only = False + for p in _iter_params(node): + if p.default is None: + if default_only: + # def f(x=3, y): pass + message = "non-default argument follows default argument" + self._add_syntax_error(message, node) + else: + default_only = True yield diff --git a/test/test_python_errors.py b/test/test_python_errors.py index ef50e16..478deea 100644 --- a/test/test_python_errors.py +++ b/test/test_python_errors.py @@ -73,6 +73,12 @@ def test_indentation_errors(code, positions): 'try: pass\nexcept: pass\nexcept X: pass', 'f(x for x in bar, 1)', 'from foo import a,', + 'def f(x=3, y): pass', + 'lambda x=3, y: x', + #'None = 1', + #'(True,) = x', + #'([False], a) = x', + #'__debug__ = 1' # IndentationError ' foo', @@ -82,7 +88,6 @@ def test_indentation_errors(code, positions): ] ) def test_python_exception_matches(code): - error, = _get_error_list(code) try: compile(code, '', 'exec') except (SyntaxError, IndentationError) as e: @@ -94,6 +99,8 @@ def test_python_exception_matches(code): # Python 2.6 has a bit different error messages here, so skip it. if sys.version_info[:2] == (2, 6) and wanted == 'SyntaxError: unexpected EOF while parsing': wanted = 'SyntaxError: invalid syntax' + + error, = _get_error_list(code) assert wanted == error.message