@@ -2282,20 +2282,38 @@ def _is_variable_violation(
22822282 elif isinstance (defframe , nodes .ClassDef ) and isinstance (
22832283 frame , nodes .FunctionDef
22842284 ):
2285- # Special rule for function return annotations,
2286- # using a name defined earlier in the class containing the function.
2287- if node is frame .returns and defframe .parent_of (frame .returns ):
2288- annotation_return = True
2289- if frame .returns .name in defframe .locals :
2290- definition = defframe .locals [node .name ][0 ]
2291- if definition .lineno is None or definition .lineno < frame .lineno :
2292- # Detect class assignments with a name defined earlier in the
2293- # class. In this case, no warning should be raised.
2294- maybe_before_assign = False
2285+ # Special rules for function return annotations.
2286+ if node is frame .returns :
2287+ # Using a name defined earlier in the class containing the function.
2288+ if defframe .parent_of (frame .returns ):
2289+ annotation_return = True
2290+ if frame .returns .name in defframe .locals :
2291+ definition = defframe .locals [node .name ][0 ]
2292+ # no warning raised if a name was defined earlier in the class
2293+ maybe_before_assign = (
2294+ definition .lineno is not None
2295+ and definition .lineno >= frame .lineno
2296+ )
22952297 else :
22962298 maybe_before_assign = True
2297- else :
2298- maybe_before_assign = True
2299+ # Using a name defined in the module if this is a nested function.
2300+ elif (
2301+ # defframe is the class containing the function.
2302+ # It shouldn't be nested: expect its parent to be a module.
2303+ (defframe_parent := next (defframe .node_ancestors ()))
2304+ and isinstance (defframe_parent , nodes .Module )
2305+ # frame is the function inside the class.
2306+ and (frame_ancestors := tuple (frame .node_ancestors ()))
2307+ # Does that function have any functions as ancestors?
2308+ and any (
2309+ isinstance (ancestor , nodes .FunctionDef )
2310+ for ancestor in frame_ancestors
2311+ )
2312+ # And is its last ancestor the same module as the class's?
2313+ and frame_ancestors [- 1 ] is defframe_parent
2314+ ):
2315+ annotation_return = True
2316+ maybe_before_assign = False
22992317 if isinstance (node .parent , nodes .Arguments ):
23002318 maybe_before_assign = stmt .fromlineno <= defstmt .fromlineno
23012319 elif is_recursive_klass :
0 commit comments