From e5d6663721d5b8c5be5d7e4a3971a6d09c8cb4ca Mon Sep 17 00:00:00 2001 From: Terseus Date: Sun, 21 Feb 2021 00:38:46 +0100 Subject: [PATCH] Prevent incorrect syntax error with nonlocal of a parameter Also includes a test for the error "name 'x' is assigned before nonlocal declaration" Fixes #175 --- parso/python/errors.py | 7 ++++++ test/failing_examples.py | 7 ++++++ test/normalizer_issue_files/allowed_syntax.py | 23 +++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/parso/python/errors.py b/parso/python/errors.py index 364f72e..a9d2ee1 100644 --- a/parso/python/errors.py +++ b/parso/python/errors.py @@ -241,6 +241,7 @@ class _Context: self.parent_context = parent_context self._used_name_dict = {} self._global_names = [] + self._local_params_names = [] self._nonlocal_names = [] self._nonlocal_names_in_subscopes = [] self._add_syntax_error = add_syntax_error @@ -264,6 +265,10 @@ class _Context: self._global_names.append(name) elif parent_type == 'nonlocal_stmt': self._nonlocal_names.append(name) + elif parent_type == 'funcdef': + self._local_params_names.extend( + [param.name.value for param in name.parent.get_params()] + ) else: self._used_name_dict.setdefault(name.value, []).append(name) @@ -291,6 +296,8 @@ class _Context: nonlocals_not_handled = [] for nonlocal_name in self._nonlocal_names_in_subscopes: search = nonlocal_name.value + if search in self._local_params_names: + continue if search in global_name_strs or self.parent_context is None: message = "no binding for nonlocal '%s' found" % nonlocal_name.value self._add_syntax_error(nonlocal_name, message) diff --git a/test/failing_examples.py b/test/failing_examples.py index a26c690..09714d3 100644 --- a/test/failing_examples.py +++ b/test/failing_examples.py @@ -337,6 +337,13 @@ FAILING_EXAMPLES = [ def z(): nonlocal a '''), + # Name is assigned before nonlocal declaration + dedent(''' + def x(a): + def y(): + a = 10 + nonlocal a + '''), ] if sys.version_info[:2] >= (3, 7): diff --git a/test/normalizer_issue_files/allowed_syntax.py b/test/normalizer_issue_files/allowed_syntax.py index 88df565..c4e7dcb 100644 --- a/test/normalizer_issue_files/allowed_syntax.py +++ b/test/normalizer_issue_files/allowed_syntax.py @@ -113,6 +113,29 @@ def x(): nonlocal a +def x(a): + def y(): + nonlocal a + + +def x(a, b): + def y(): + nonlocal b + nonlocal a + + +def x(a): + def y(): + def z(): + nonlocal a + + +def x(): + def y(a): + def z(): + nonlocal a + + a = *args, *args error[(*args, *args)] = 3 *args, *args