Skip to content

Receiver binding misses non-bare staticmethod spellings (@builtins.staticmethod) #135

Description

@rahlk

Problem

build_scope decides whether a callable has a receiver by exact string membership against
unparsed decorator text (codeanalyzer/dataflow/access_paths.py:255-257):

decorators= {ast.unparse(d) fordinfunc.decorator_list}
ifparams[0] in ("self", "cls") and"staticmethod"notindecorators:
scope.self_name=params[0]

Only the bare spelling staticmethod is recognised. Any other spelling of the same builtin —
@builtins.staticmethod, or from builtins import staticmethod as sm — fails the membership
test, so a static method gets a receiver it does not have, and scope.self_name is later added
as a definition (access_paths.py:472-473), producing a spurious def in the L3/L4 dataflow.

Verified on a0b94ff:

dotted decorators=['builtins.staticmethod'] self_name='self' <- wrong
plain decorators=['staticmethod'] self_name=None
normal decorators=['staticmethod'] self_name=None

Scope boundary

The receiver-binding predicate only. Does not restructure the decorator schema (#128), and does
not touch classmethod or property handling.

Goals

  • Recognise staticmethod by resolved identity, not by unparsed spelling
  • Cover the dotted form and an aliased import
  • Test asserting self_name is None for each spelling

Caveats and known risks

  • Triggers only when the first parameter is named self or cls; a staticmethod with a normal
    first parameter name is unaffected.
  • Legal but unusual code, so the blast radius is small and no bug report prompted this.
  • A resolved check needs the decorator's qualified_name, which Jedi already computes and stores
    in accessed_symbols; Structured decorator representation: PyDecorator on callable, class, attribute, parameter #128 would make it directly available on the decorator.
  • Unverified: whether any current test would have caught the fix regressing.

Definition of done

  • @builtins.staticmethod def f(self, x) yields self_name is None
  • An aliased-import spelling yields self_name is None
  • Bare @staticmethod and undecorated methods keep their current behaviour
  • Existing dataflow tests pass unchanged

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions