)]}'
{"nova/hacking/checks.py":[{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"11a63b68dddafc58bf432c863aa103ce9599c1b7","unresolved":false,"context_lines":[{"line_number":473,"context_line":"    def __init__(self):"},{"line_number":474,"context_line":"        super(FindClosures, self).__init__()"},{"line_number":475,"context_line":"        self._defines \u003d []"},{"line_number":476,"context_line":"        self._closure_calls \u003d []"},{"line_number":477,"context_line":""},{"line_number":478,"context_line":"    def visit_FunctionDef(self, node):"},{"line_number":479,"context_line":"        # Found a closure definition"}],"source_content_type":"text/x-python","patch_set":1,"id":"7af24918_7dedcc8a","line":476,"updated":"2016-03-01 21:13:10.000000000","message":"Technically not closure calls, they\u0027re really references.","commit_id":"012cd3753e47629bb799960c6313931fcb97df85"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"11a63b68dddafc58bf432c863aa103ce9599c1b7","unresolved":false,"context_lines":[{"line_number":475,"context_line":"        self._defines \u003d []"},{"line_number":476,"context_line":"        self._closure_calls \u003d []"},{"line_number":477,"context_line":""},{"line_number":478,"context_line":"    def visit_FunctionDef(self, node):"},{"line_number":479,"context_line":"        # Found a closure definition"},{"line_number":480,"context_line":"        if len(node.args.args) \u003e 0:"},{"line_number":481,"context_line":"            if (isinstance(node.args.args[0], ast.Name) and"}],"source_content_type":"text/x-python","patch_set":1,"id":"7af24918_7dbb0c73","line":478,"updated":"2016-03-01 21:13:10.000000000","message":"If you drop this method and instead iterate through ast.iter_child_nodes(node) in CheckForUncalledClosures you don\u0027t have to worry about filtering out these class methods. It will just pick up methods defined directly in the test methods.\n\nAnd the following are still being caught incorrectly:\n    ./nova/tests/unit/virt/xenapi/test_xenapi.py:3703:5: N666 Defined closures not called: VM_migrate_send\n    ./nova/tests/unit/virt/xenapi/test_xenapi.py:3737:5: N666 Defined closures not called: VM_pool_migrate\n    ./nova/tests/unit/virt/xenapi/test_xenapi.py:3983:5: N666 Defined closures not called: _get_software_version","commit_id":"012cd3753e47629bb799960c6313931fcb97df85"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"11a63b68dddafc58bf432c863aa103ce9599c1b7","unresolved":false,"context_lines":[{"line_number":491,"context_line":"            return"},{"line_number":492,"context_line":"        self._defines.append(node.name)"},{"line_number":493,"context_line":""},{"line_number":494,"context_line":"    def generic_visit(self, node):"},{"line_number":495,"context_line":"        # Look for any use of a thing in a function call, as an"},{"line_number":496,"context_line":"        # argument, etc"},{"line_number":497,"context_line":"        if isinstance(node, ast.Name):"}],"source_content_type":"text/x-python","patch_set":1,"id":"7af24918_7d5f8c72","line":494,"updated":"2016-03-01 21:13:10.000000000","message":"This could be \"def visit_Name\" since you only care about ast.Names.","commit_id":"012cd3753e47629bb799960c6313931fcb97df85"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"11a63b68dddafc58bf432c863aa103ce9599c1b7","unresolved":false,"context_lines":[{"line_number":498,"context_line":"            self._closure_calls.append(node.id)"},{"line_number":499,"context_line":""},{"line_number":500,"context_line":""},{"line_number":501,"context_line":"class CheckForUncalledClosure(BaseASTChecker):"},{"line_number":502,"context_line":"    \"\"\"Look for closures that we define but never call."},{"line_number":503,"context_line":""},{"line_number":504,"context_line":"    This is specifically looking for things like where we define"}],"source_content_type":"text/x-python","patch_set":1,"id":"7af24918_1dabe81e","line":501,"updated":"2016-03-01 21:13:10.000000000","message":"CheckForUnreferencedClosure might be a better name.","commit_id":"012cd3753e47629bb799960c6313931fcb97df85"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"4a66dc1b024e297f06f24948ad0c7a9d2b40a7fb","unresolved":false,"context_lines":[{"line_number":514,"context_line":"        self._fn \u003d filename"},{"line_number":515,"context_line":""},{"line_number":516,"context_line":"    def visit_FunctionDef(self, node):"},{"line_number":517,"context_line":"        if \u0027test_\u0027 not in self._fn:"},{"line_number":518,"context_line":"            return"},{"line_number":519,"context_line":""},{"line_number":520,"context_line":"        fc \u003d FindClosures()"}],"source_content_type":"text/x-python","patch_set":1,"id":"9aed3d3a_dd668328","line":517,"updated":"2016-02-26 15:07:56.000000000","message":"Maybe change to:\n\n    if not self._fn.startswith(\u0027test_\u0027):\n\nto avoid catching stuff like:\n\n    def _some_dumb_test_method():","commit_id":"012cd3753e47629bb799960c6313931fcb97df85"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"7a131dbb922ec133ba60afebf8a120471b1edaee","unresolved":false,"context_lines":[{"line_number":514,"context_line":"        self._fn \u003d filename"},{"line_number":515,"context_line":""},{"line_number":516,"context_line":"    def visit_FunctionDef(self, node):"},{"line_number":517,"context_line":"        if \u0027test_\u0027 not in self._fn:"},{"line_number":518,"context_line":"            return"},{"line_number":519,"context_line":""},{"line_number":520,"context_line":"        fc \u003d FindClosures()"}],"source_content_type":"text/x-python","patch_set":1,"id":"7af24918_fdef1cae","line":517,"in_reply_to":"9aed3d3a_dd668328","updated":"2016-03-01 21:06:08.000000000","message":"The problem is that filename is actually a full path. os.path.basename(self._fn).startswith(\u0027test_\u0027) would work though.","commit_id":"012cd3753e47629bb799960c6313931fcb97df85"},{"author":{"_account_id":5441,"name":"Andrew Laski","email":"andrew@lascii.com","username":"alaski"},"change_message_id":"11a63b68dddafc58bf432c863aa103ce9599c1b7","unresolved":false,"context_lines":[{"line_number":517,"context_line":"        if \u0027test_\u0027 not in self._fn:"},{"line_number":518,"context_line":"            return"},{"line_number":519,"context_line":""},{"line_number":520,"context_line":"        fc \u003d FindClosures()"},{"line_number":521,"context_line":"        for child in ast.walk(node):"},{"line_number":522,"context_line":"            if child \u003d\u003d node:"},{"line_number":523,"context_line":"                continue"}],"source_content_type":"text/x-python","patch_set":1,"id":"7af24918_9de8987e","line":520,"updated":"2016-03-01 21:13:10.000000000","message":"You can drop lines 521-524 and just call fc.generic_visit(node) if you add calls to super(...).generic_visit(node) at the end of your visit_* methods in FindClosures.","commit_id":"012cd3753e47629bb799960c6313931fcb97df85"}]}
