Skip to content

Report access to abstract static and class methods on the class - #21806

Open
Endika wants to merge 1 commit into
python:masterfrom
Endika:fix/abstract-static-method-access
Open

Report access to abstract static and class methods on the class#21806
Endika wants to merge 1 commit into
python:masterfrom
Endika:fix/abstract-static-method-access

Conversation

@Endika

@Endika Endika commented Aug 3, 2026

Copy link
Copy Markdown

Fixes #14939.

This follows the implementation @JukkaL outlined on the issue: report accessing
an abstract static method, and a class method too, on a direct reference to the
type object, but not through type[T], since there the runtime class may be a
subclass which implements it. That is the same distinction the existing
instantiation check makes with not callee.from_type_type.

from abc import ABC, abstractmethod

class Foo(ABC):
    @staticmethod
    @abstractmethod
    def s() -> int: ...

Foo.s()  # now: Cannot access abstract static method "s" of abstract class "Foo"

What is and is not reported

Reported
Foo.s(), Foo.c() on the abstract class itself yes
Foo.s without calling it yes
Through type[Foo] no
On an instance no
Unbound instance method, Foo.m no
On a subclass which implements it no
On a subclass which is still abstract yes, naming the subclass

Instance methods are excluded for the reason type[T] is: whatever is passed as
self may implement the method. The check hangs off
analyze_type_callable_member_access, which is only reached for a direct class
reference — analyze_type_type_member_access handles type[T] and is left
alone. It reuses the existing [abstract] error code.

Tests

Two cases in check-abstract.test, both of which fail on master:

  • testAccessAbstractStaticAndClassMethodOnClass — the static and class method
    are reported on the class and on a bare reference, and not through type[A],
    on an instance, or for an unbound instance method.
  • testAccessAbstractStaticAndClassMethodOnSubclass — a subclass implementing
    both is silent, a subclass which implements only one is reported for the other
    and named in the message.

I checked what the tests actually catch by breaking each exclusion in turn:

Exclusion removed Caught by
Instance methods excluded OnClass
type[T] path left alone OnClass
abstract_attributes consulted OnSubclass

The first of those initially had no coverage: the test called the method on an
instance, which never reaches this code at all. Accessing the unbound method
through the class does, so g = A.m was added.

Full suites locally on Python 3.14 / Linux, uncompiled: testcheck 8202 passed,
testfinegrained / testmerge / testtransform / testdeps / testpythoneval
1453 passed. Self-check clean.

Performance

The check runs on class attribute access, so it returns immediately unless the
class is abstract. Self-check with a cold cache, three runs each, uncompiled:

run 1 run 2 run 3
this branch 14.23s 14.17s 14.36s
master 14.05s 14.22s 14.03s

The ranges overlap, so I read this as noise, but the medians do put it 1% on the
slow side and I have not measured a compiled build.

Notes for review

LLM disclosure

Per the contributing guidelines: this PR text was written with LLM assistance, and I am a
first-time contributor here, so I understand that may weigh against it — say so
and I will close it without any fuss. The design is @JukkaL's from the issue
rather than mine, and I can explain and defend every decision above.

One thing worth recording, since it came out of verification rather than the
first draft: the check first tested isinstance(func, FuncBase), and self-check
correctly flagged everything after it as unreachable. FuncBase is not a
SymbolNodeFuncDef reaches it through FuncItem — so the narrowing gave
Never. nodes.py says as much right above the class and points at
SYMBOL_FUNCBASE_TYPES, which is what the code uses now.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

no error when calling abstract staticmethod/classmethod

1 participant