@@ -2297,20 +2297,38 @@ def _is_variable_violation(
22972297 elif isinstance (defframe , nodes .ClassDef ) and isinstance (
22982298 frame , nodes .FunctionDef
22992299 ):
2300- # Special rule for function return annotations,
2301- # using a name defined earlier in the class containing the function.
2302- if node is frame .returns and defframe .parent_of (frame .returns ):
2303- annotation_return = True
2304- if frame .returns .name in defframe .locals :
2305- definition = defframe .locals [node .name ][0 ]
2306- if definition .lineno is None or definition .lineno < frame .lineno :
2307- # Detect class assignments with a name defined earlier in the
2308- # class. In this case, no warning should be raised.
2309- maybe_before_assign = False
2300+ # Special rules for function return annotations.
2301+ if node is frame .returns :
2302+ # Using a name defined earlier in the class containing the function.
2303+ if defframe .parent_of (frame .returns ):
2304+ annotation_return = True
2305+ if frame .returns .name in defframe .locals :
2306+ definition = defframe .locals [node .name ][0 ]
2307+ # no warning raised if a name was defined earlier in the class
2308+ maybe_before_assign = (
2309+ definition .lineno is not None
2310+ and definition .lineno >= frame .lineno
2311+ )
23102312 else :
23112313 maybe_before_assign = True
2312- else :
2313- maybe_before_assign = True
2314+ # Using a name defined in the module if this is a nested function.
2315+ elif (
2316+ # defframe is the class containing the function.
2317+ # It shouldn't be nested: expect its parent to be a module.
2318+ (defframe_parent := next (defframe .node_ancestors ()))
2319+ and isinstance (defframe_parent , nodes .Module )
2320+ # frame is the function inside the class.
2321+ and (frame_ancestors := tuple (frame .node_ancestors ()))
2322+ # Does that function have any functions as ancestors?
2323+ and any (
2324+ isinstance (ancestor , nodes .FunctionDef )
2325+ for ancestor in frame_ancestors
2326+ )
2327+ # And is its last ancestor the same module as the class's?
2328+ and frame_ancestors [- 1 ] is defframe_parent
2329+ ):
2330+ annotation_return = True
2331+ maybe_before_assign = False
23142332 if isinstance (node .parent , nodes .Arguments ):
23152333 maybe_before_assign = stmt .fromlineno <= defstmt .fromlineno
23162334 elif is_recursive_klass :
0 commit comments