Bug 378083 - Variables from parent function in closures are considered undefined
Summary: Variables from parent function in closures are considered undefined
Status: RESOLVED FIXED
Alias: None
Product: kdev-python
Classification: Developer tools
Component: Language support (show other bugs)
Version: 5.1.0
Platform: unspecified Linux
: NOR normal
Target Milestone: ---
Assignee: Francis Herne
URL:
Keywords:
: 323796 (view as bug list)
Depends on:
Blocks:
 
Reported: 2017-03-25 23:19 UTC by Diego Gangl
Modified: 2017-08-31 01:34 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In: 5.2.0


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Diego Gangl 2017-03-25 23:19:22 UTC
Variables from the parent function in closures are considered "undefined" and marked as a problem.

Code to reproduce: 

----
def test_closures():
    def test_inner():
        print(this)

    this = 'that'
----

The problems dock shows: "Undefined Variable: this"
Comment 1 Sven Brauch 2017-03-26 00:09:53 UTC
Yeah, this is a difficult case. In my opinion the current behaviour is ok: you cannot sensibly call the function before defining the variable, so you can just as well re-order your code to define the variable first ...
Comment 2 Diego Gangl 2017-03-26 22:21:42 UTC
The problem is that when you want to call the inner function or return it, it will also get flagged as an error. And it would be correct since this code fails.

---
def test_closures():
    this = 'that'
    
    return test_inner
    # or test_inner()
    
    def test_inner():
        print(this)
---

The first snippet is the (AFAIK) only way to do closures or nested functions in Python.
Comment 3 Francis Herne 2017-04-03 12:10:05 UTC
In your example, this should work?
---
def test_closures():
    this = 'that'
    
    def test_inner():
        print(this)

    return test_inner
    # or test_inner()
---

But I think it would be possible to create a case where that isn't an option, and the original examples are valid code anyway.

Shouldn't be too hard to fix, we need to continue beyond the current line when searching in parents of a function context.
Comment 4 Diego Gangl 2017-04-03 16:08:48 UTC
Heh never thought about putting functions in the middle.
Yes, that works. It could be a good workaround for new code.
It'd be great if it could be fixed though
Comment 5 Francis Herne 2017-07-27 23:26:06 UTC
Git commit 1a7d3c139ab7b4ab439d757a95a5d7d83575f801 by Francis Herne.
Committed on 27/07/2017 at 23:21.
Pushed by flherne into branch 'master'.

Rewrite declarationForName()

This causes the correct declaration to be found in some unusual cases
 that previously failed.

Only names declared before a function definition, or at module scope,
 were found in its body. Names may be declared later (but before the
 function is called); these were not found.
FIXED-IN: 5.2.0

Class attributes from any enclosing class definition were found in
 default arguments, not only those from a method's parent class.

Class or instance attributes were, correctly, not directly visible
 inside a method body (only with `self.` or similar), but hid
 declarations of the same name in outer contexts that should be found.

M  +35   -33   duchain/helpers.cpp
M  +60   -5    duchain/tests/pyduchaintest.cpp

https://commits.kde.org/kdev-python/1a7d3c139ab7b4ab439d757a95a5d7d83575f801
Comment 6 Francis Herne 2017-08-31 01:34:18 UTC
*** Bug 323796 has been marked as a duplicate of this bug. ***