Skip to content

Update stubs for classmethod and staticmethod in both Pythons. #1089

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 29, 2017

Conversation

sproshev
Copy link
Contributor

@sproshev sproshev commented Mar 24, 2017

Runtime tests are below

@sproshev
Copy link
Contributor Author

Python 2

# test __init__
def a():
    pass

assert isinstance(classmethod(a), classmethod)


# test __new__
def b():
    pass


def c():
    pass


def d():
    pass


def e():
    pass


assert isinstance(classmethod.__new__(classmethod, b, c, d=d, e=e), classmethod)


# test __func__
def f():
    pass


assert classmethod(f).__func__ == f


# test __get__
class WrappedWithSM:
    @classmethod
    def foo(cls):
        return 10


class ReassignedWithSM:
    def foo(cls):
        return 10
    foo = classmethod(foo)


assert type(WrappedWithSM.__dict__["foo"].__get__(WrappedWithSM, type)).__name__ == "instancemethod"
assert type(WrappedWithSM.__dict__["foo"].__get__(WrappedWithSM)).__name__ == "instancemethod"
assert type(ReassignedWithSM.__dict__["foo"].__get__(ReassignedWithSM, type)).__name__ == "instancemethod"
assert type(ReassignedWithSM.__dict__["foo"].__get__(ReassignedWithSM)).__name__ == "instancemethod"


# test __getattribute__
def g():
    pass


assert classmethod(g).__getattribute__("__func__") == g


# test __dict__.keys()
assert set(classmethod.__dict__.keys()) == {'__init__', '__new__', '__func__', '__get__', '__getattribute__', '__doc__'}
# test __init__
def a():
    pass

assert isinstance(staticmethod(a), staticmethod)


# test __new__
def b():
    pass


def c():
    pass


def d():
    pass


def e():
    pass


assert isinstance(staticmethod.__new__(staticmethod, b, c, d=d, e=e), staticmethod)


# test __func__
def f():
    pass


assert staticmethod(f).__func__ == f


# test __get__
class WrappedWithSM:
    @staticmethod
    def foo():
        return 10


class ReassignedWithSM:
    def foo():
        return 10
    foo = staticmethod(foo)


assert type(WrappedWithSM.__dict__["foo"].__get__(WrappedWithSM, type)).__name__ == "function"
assert type(WrappedWithSM.__dict__["foo"].__get__(WrappedWithSM)).__name__ == "function"
assert type(ReassignedWithSM.__dict__["foo"].__get__(ReassignedWithSM, type)).__name__ == "function"
assert type(ReassignedWithSM.__dict__["foo"].__get__(ReassignedWithSM)).__name__ == "function"


# test __getattribute__
def g():
    pass


assert staticmethod(g).__getattribute__("__func__") == g


# test __dict__.keys()
assert set(staticmethod.__dict__.keys()) == {'__init__', '__new__', '__func__', '__get__', '__getattribute__', '__doc__'}

@sproshev
Copy link
Contributor Author

Python 3

import abc


# test __init__
def a():
    pass


assert isinstance(classmethod(a), classmethod)


# test __new__
def b():
    pass


def c():
    pass


def d():
    pass


def e():
    pass


assert isinstance(classmethod.__new__(classmethod, b, c, d=d, e=e), classmethod)


# test __func__
def f():
    pass


assert classmethod(f).__func__ == f


# test __isabstractmethod__
@abc.abstractmethod
def g():
    pass


def h():
    pass


assert classmethod(g).__isabstractmethod__
assert not classmethod(h).__isabstractmethod__


# test __get__
class WrappedWithSM:
    @classmethod
    def foo(cls):
        return 10


class ReassignedWithSM:
    def foo(cls):
        return 10
    foo = classmethod(foo)


assert type(WrappedWithSM.__dict__["foo"].__get__(WrappedWithSM, type)).__name__ == "method"
assert type(WrappedWithSM.__dict__["foo"].__get__(WrappedWithSM)).__name__ == "method"
assert type(ReassignedWithSM.__dict__["foo"].__get__(ReassignedWithSM, type)).__name__ == "method"
assert type(ReassignedWithSM.__dict__["foo"].__get__(ReassignedWithSM)).__name__ == "method"


# test __dict__.keys()
assert set(classmethod.__dict__.keys()) == {'__init__', '__new__', '__func__', '__isabstractmethod__', '__get__', 
                                             '__dict__', '__doc__'}
import abc


# test __init__
def a():
    pass


assert isinstance(staticmethod(a), staticmethod)


# test __new__
def b():
    pass


def c():
    pass


def d():
    pass


def e():
    pass


assert isinstance(staticmethod.__new__(staticmethod, b, c, d=d, e=e), staticmethod)


# test __func__
def f():
    pass


assert staticmethod(f).__func__ == f


# test __isabstractmethod__
@abc.abstractmethod
def g():
    pass


def h():
    pass


assert staticmethod(g).__isabstractmethod__
assert not staticmethod(h).__isabstractmethod__


# test __get__
class WrappedWithSM:
    @staticmethod
    def foo():
        return 10


class ReassignedWithSM:
    def foo():
        return 10
    foo = staticmethod(foo)


assert type(WrappedWithSM.__dict__["foo"].__get__(WrappedWithSM, type)).__name__ == "function"
assert type(WrappedWithSM.__dict__["foo"].__get__(WrappedWithSM)).__name__ == "function"
assert type(ReassignedWithSM.__dict__["foo"].__get__(ReassignedWithSM, type)).__name__ == "function"
assert type(ReassignedWithSM.__dict__["foo"].__get__(ReassignedWithSM)).__name__ == "function"


# test __dict__.keys()
assert set(staticmethod.__dict__.keys()) == {'__init__', '__new__', '__func__', '__isabstractmethod__', '__get__',
                                             '__dict__', '__doc__'}

@gvanrossum
Copy link
Member

Why does the Python 3 version not have __getattribute__? What difference in behavior is there?

@JelleZijlstra
Copy link
Member

$ python3.6 -c 'x = classmethod(lambda _: None); x.y = 1; print(x.y)'
1
$ python2.7 -c 'x = classmethod(lambda _: None); x.y = 1; print(x.y)'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AttributeError: 'classmethod' object has no attribute 'y'

@gvanrossum
Copy link
Member

OK, I'm still confused --- isn't that backwards?

@sproshev
Copy link
Contributor Author

Sorry, I was looking at classmethod.__dict__.keys() while writing stubs and forgot to inherit classmethod and staticmethod from the object in Python 2.

@gvanrossum gvanrossum merged commit 8c1690b into python:master Mar 29, 2017
@gvanrossum
Copy link
Member

Thanks, looks great now! Merged.

@gvanrossum
Copy link
Member

FWIW I'm not 100% happy with using function, which is a mypy internal hack, but we have to clean that up later, after fixing it in mypy (python/mypy#2765).

@sproshev sproshev deleted the sproshev/static-class-methods branch April 3, 2017 05:45
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.

3 participants