#1555 closed enhancement

add check-miscaptures.py script to check for incorrect variable captures in loops — at Version 13

Reported by: davidsarah Owned by: somebody
Priority: major Milestone: 1.9.2
Component: code Version: 1.9.0a2
Keywords: miscapture coding-tools review-needed Cc:
Launchpad Bug:

Description (last modified by davidsarah)

The attached script checks for errors in which a variable declaredmodified in a for loop is captured by a lambda or function definition. If the lambda/function is executed after the loop iteration in which it was created, it will refer to some later value of the variable, which is usually not what was intended.

The script currently produces false positives if a variable is declared and used in the same lambda/function within a for loop (i.e. it is not captured). I don't intend to fix that until after the Tahoe summit in November, probably. However, it produces relatively few false positives already, and found some genuine bugs (see #1556).

Change History (16)

comment:1 Changed at 2011-10-07T02:12:14Z by davidsarah

  • Description modified (diff)

Changed at 2011-10-07T02:19:10Z by davidsarah

Add misc/coding_tools/check-miscaptures.py to detect incorrect captures of variables declared in a for loop, and a 'make check-miscaptures' Makefile target to run it. (It is also run by 'make code-checks'.) refs #1555

comment:2 Changed at 2011-10-07T02:20:09Z by davidsarah

  • Keywords coding-tools review-needed added; coding_tools removed

comment:3 Changed at 2011-10-07T02:20:29Z by davidsarah

  • Type changed from defect to enhancement

Changed at 2011-10-07T07:50:18Z by davidsarah

Add misc/coding_tools/check-miscaptures.py to detect incorrect captures of variables declared in a for loop, and a 'make check-miscaptures' Makefile target to run it. (It is also run by 'make code-checks'.) This is a rewritten version that reports much fewer false positives, by determining captured variables more accurately. fixes #1555

comment:4 Changed at 2011-10-07T07:53:24Z by davidsarah

Gahh, there's a pyflakes warning (for import traceback). Ignore that, I'll fix it before committing.

comment:5 Changed at 2011-10-07T19:39:49Z by david-sarah@…

  • Resolution set to fixed
  • Status changed from new to closed

In [5401/ticket999-S3-backend]:

Add misc/coding_tools/check-miscaptures.py to detect incorrect captures of variables declared in a for loop, and a 'make check-miscaptures' Makefile target to run it. (It is also run by 'make code-checks'.) This is a rewritten version that reports much fewer false positives, by determining captured variables more accurately. fixes #1555

comment:6 Changed at 2011-10-09T19:29:04Z by davidsarah

  • Resolution fixed deleted
  • Status changed from closed to reopened

(reopened after auto-close on a branch)

Changed at 2011-10-09T19:34:20Z by davidsarah

Various improvements: also check while loops and list comprehensions; fewer false positives; say "assigned" instance of "declared"; report number of files not analysed.

comment:7 Changed at 2011-10-09T19:58:48Z by davidsarah

  • Description modified (diff)

The remaining significant false positive cases are where:

  • the capturing function is only used in the same iteration as the values it was intended to capture. For example, in
    for x in xs:
        print map(lambda y: x+y, ys)
    
    the use of each lambda is only in the same iteration as the x it was intended to capture (and map does not retain the function), so there is no bug.
  • the captured variables are only assigned once, before any application of a capturing function. A somewhat artificial example:
    fs = []
    z = None
    for x in range(2):
        if z is None:
            z = 42
        fs.append(lambda y: y+z)
    
    because the captured z is effectively constant, even though it is assigned in the loop.

Both these cases are undecidable to detect in general. You could detect special cases of the first, such as builtin map or filter with a lambda expression as its first argument, but it's probably not worth the complication.

After applying the patches on #1556, Tahoe produces no warnings from make check-miscaptures, so I'd like to include that in the buildbot flow in the same way as pyflakes. (It would be ok to run it in the same step as pyflakes.)

comment:8 Changed at 2011-10-12T21:47:40Z by david-sarah@…

In [5439/ticket999-S3-backend]:

check-miscaptures.py: check while loops and list comprehensions as well as for loops. Also fix a pyflakes warning. refs #1555

comment:9 Changed at 2011-10-12T21:47:41Z by david-sarah@…

In [5440/ticket999-S3-backend]:

check-miscaptures.py: handle destructuring function arguments correctly. refs #1555

comment:10 Changed at 2011-10-12T21:47:41Z by david-sarah@…

In [5441/ticket999-S3-backend]:

check-miscaptures.py: Python doesn't really have declarations; report the topmost assignment. refs #1555

comment:11 Changed at 2011-10-12T21:47:42Z by david-sarah@…

In [5442/ticket999-S3-backend]:

check-miscaptures.py: handle corner cases around default arguments correctly. Also make a minor optimization when there are no assigned variables to consider. refs #1555

comment:12 Changed at 2011-10-12T21:47:43Z by david-sarah@…

In [5443/ticket999-S3-backend]:

check-miscaptures.py: report the number of files that were not analysed due to syntax errors (and don't count them in the number of suspicious captures). refs #1555

comment:13 Changed at 2011-10-20T18:01:25Z by davidsarah

  • Description modified (diff)
  • Summary changed from add check-miscaptures.py script to check for incorrect variable captures in for loops to add check-miscaptures.py script to check for incorrect variable captures in loops

The current version also detects captures of variables declared or modified in list comprehensions and while loops.

Note: See TracTickets for help on using tickets.