diff --git a/parso/python/errors.py b/parso/python/errors.py index c67cc3f..5561860 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 a83cede..9cccf61 100644 --- a/test/normalizer_issue_files/allowed_syntax.py +++ b/test/normalizer_issue_files/allowed_syntax.py @@ -135,6 +135,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