Skip to content

[stubtest] Support @final decorator on methods as well #14924

Open

Description

@sobolevn

After #14922 is merged, I think we can also add a check that this source code has correct stubs:

class A:
    @final
    def method(self): ...

Right now stubs do not have to add @final decorator, stubtest will allow both versions.

Activity

  1. self-assigned this
    on Mar 19, 2023
  2. sobolevn commented on Mar 19, 2023

    @sobolevn
    MemberAuthor

    After working on for a short time, I've noticed several problems:

    1. @property is not supported
    2. @staticmethod is not supported
    3. @classmethod is not supported

    This happens, because __final__ cannot be set on property objects:

    See:

    >>> def my_final(f):
    ...    f.__final__ = True
    ...    return f
    >>> class P:
    ...    @my_final
    ...    @property
    ...    def p(self) -> int: ...
    ... 
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 4, in P
      File "<stdin>", line 2, in my_final
    AttributeError: 'property' object has no attribute '__final__'

    But, @classmethod and @staticmethod actually change the object when using getattr, this is why this happens:

    >>> class St:
    ...   @my_final
    ...   @staticmethod
    ...   def m() -> None: ...
    ... 
    >>> St.m
    <function St.m at 0x109eeb400>
    >>> St.m.__final__
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'function' object has no attribute '__final__'. Did you mean: '__init__'?
    
    >>> St.__dict__['m']
    <staticmethod(<function St.m at 0x109eeb400>)>
    >>> St.__dict__['m'].__final__
    True

    This needs:

    1. Special-casing properties. They cannot be supported right now
    2. Magic getattr_static to get methods from the class

    This is quite complicated for a Sunday's evening project, so - please feel free to continue it if someone finds it useful.

  3. removed their assignment
    on Mar 19, 2023
  4. AlexWaygood commented on Mar 25, 2023

    @AlexWaygood
    Member

    To update on the status here: following #14951, this is now fully implemented except for cases where the method is overloaded in the stub (implementing that is blocked by #14950).

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions