Deprecate "C function acts like static method when accessed on class" behaviour?

Currently, some caveats arise from the absence of __get__ on the type of functions written in C extension modules. See the following snippet:

def prnt(*a, **k): print(*a, **k)
class A:
    func = print
class B:
    func = prnt
A.func('A')
A().func('A()')
B.func('B')
B().func('B()')

Output:

A
A()
B
<__main__.B object at 0x00000277F0377A10> B()

Would it be beneficial to implement a dummy __get__ on builtin_function_or_method which always raises, say, TypeError, to flag mistakes like this or force the user to more idiomatically use @staticmethod if it was intended?

1 Like

You can try to implement it, and then check how much noise it produces when run the tests.

So should I make a PR? I haven’t much experience writing in C.

I expect this will cause enough breakage in real-world code that we can’t change the behavior.

If we could work from a clean slate I’d want built-in functions to work the same as Python functions.

3 Likes

It reminds me when I modified @staticmethod to become callable and copy attributes like __doc__ in Python 3.10. We had a similar discussion on adding __get__() and how it could break a lot of code: Make static methods created by @staticmethod callable · Issue #87848 · python/cpython · GitHub.

1 Like

Will an extremely long deprecation period work? That is, provisionally implementing __get__ as an identity method which emits DeprecationWarning saying that __get__ will return a method in the future?

Test it locally first. If there is too much breakage, you will abandon the idea yourself. If the impact is minimal and easily fixed, this is discussable.

Since I’m unfamiliar with the C logic, I would like some guidance. Am I to implement meth_descr_get in Objects/methodobject.c that calls PyErr_WarnEx and returns Py_NewRef(self) and run tests locally? Thanks