def _close_callable(self, node, force=False):
        """Record last line number of callable."""
        # Only nodes that have a line number can be considered for closing
        # callables. Similarly, only nodes with lines greater than the one
        # already processed can be considered for closing callables
        try:
            lineno = node.lineno
        except AttributeError:
            return
        if lineno <= self._processed_line:
            return
        # [[[cog
        # code = """
        # print(pcolor('Close callable @ line = {0}'.format(lineno), 'green'))
        # """
        # cog.out(code)
        # ]]]
        # [[[end]]]
        # Extract node name for property closing. Once a property is found,
        # it can only be closed out by a node type that has a name
        name = ""
        try:
            name = (
                node.name
                if hasattr(node, "name")
                else (
                    node.targets[0].id
                    if hasattr(node.targets[0], "id")
                    else node.targets[0].value.id
                )
            )
        except AttributeError:
            pass
        # Traverse backwards through call stack and close callables as needed
        indent = self._get_indent(node)
        count = -1
        # [[[cog
        # code = """
        # print(
        #     pcolor(
        #         '    Name {0} @ {1}, indent = {2}'.format(
        #             name if name else 'None', lineno, indent
        #         ),
        #         'yellow'
        #     )
        # )
        # """
        # cog.out(code)
        # ]]]
        # [[[end]]]
        dlist = []
        while count >= -len(self._indent_stack):
            element_full_name = self._indent_stack[count]["full_name"]
            edict = self._callables_db.get(element_full_name, None)
            stack_indent = self._indent_stack[count]["level"]
            open_callable = element_full_name and (not edict["last_lineno"])
            # [[[cog
            # code = """
            # print(
            #     pcolor(
            #         '    Name {0}, indent, {1}, stack_indent {2}'.format(
            #             element_full_name, indent, stack_indent
            #         ),
            #         'yellow'
            #     )
            # )
            # """
            # cog.out(code)
            # ]]]
            # [[[end]]]
            if open_callable and (
                force
                or (indent < stack_indent)
                or (
                    (indent == stack_indent)
                    and (
                        (edict["type"] != "prop")
                        or (
                            (edict["type"] == "prop")
                            and (name and (name != element_full_name))
                        )
                    )
                )
            ):
                # [[[cog
                # code = """
                # print(
                #     pcolor(
                #         '    Closing {0} @ {1}'.format(
                #             element_full_name, lineno-1
                #         ),
                #         'yellow'
                #     )
                # )
                # """
                # cog.out(code)
                # ]]]
                # [[[end]]]
                edict["last_lineno"] = lineno - 1
                dlist.append(count)
            if indent > stack_indent:
                break
            count -= 1
        # Callables have to be removed from stack when they are closed,
        # otherwise if a callable is subsequently followed after a few
        # lines by another callable at a further indentation level (like a for
        # loop) the second callable would incorrectly appear within the scope
        # of the first callable
        stack = self._indent_stack
        stack_length = len(self._indent_stack)
        dlist = [item for item in dlist if stack[item]["type"] != "module"]
        for item in dlist:
            del self._indent_stack[stack_length + item]
def _close_callable ( self , node , force = False ) : try : lineno = node . lineno except AttributeError : return if lineno <= self . _processed_line : return name = "" try : name = ( node . name if hasattr ( node , "name" ) else ( node . targets [ 0 ] . id if hasattr ( node . targets [ 0 ] , "id" ) else node . targets [ 0 ] . value . id ) ) except AttributeError : pass indent = self . _get_indent ( node ) count = - 1 dlist = [ ] while count >= - len ( self . _indent_stack ) : element_full_name = self . _indent_stack [ count ] [ "full_name" ] edict = self . _callables_db . get ( element_full_name , None ) stack_indent = self . _indent_stack [ count ] [ "level" ] open_callable = element_full_name and ( not edict [ "last_lineno" ] ) if open_callable and ( force or ( indent < stack_indent ) or ( ( indent == stack_indent ) and ( ( edict [ "type" ] != "prop" ) or ( ( edict [ "type" ] == "prop" ) and ( name and ( name != element_full_name ) ) ) ) ) ) : edict [ "last_lineno" ] = lineno - 1 dlist . append ( count ) if indent > stack_indent : break count -= 1 stack = self . _indent_stack stack_length = len ( self . _indent_stack ) dlist = [ item for item in dlist if stack [ item ] [ "type" ] != "module" ] for item in dlist : del self . _indent_stack [ stack_length + item ]
Record last line number of callable.