Created
February 17, 2020 16:37
-
-
Save MattOates/c14089385ab433311a072e63b2bb6a51 to your computer and use it in GitHub Desktop.
The general problem is that mypy doesn't really understand that a descriptor on an attribute is going to have the return value of __get__ not __call__/__init__
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from enum import Enum | |
from typing import Type, Any | |
Sentinels = Enum("Sentinels", "NO_INIT") | |
class attr_descriptor: | |
def __init__(self, default=Sentinels.NO_INIT): | |
self.default = default | |
def __set_name__(self, owner, name): | |
self.owner = owner | |
self.name = name | |
if hasattr(owner, "__annotations__"): | |
self.value_type = owner.__annotations__.get(name, None) | |
self.value_type = Sentinels.NO_INIT | |
def __get__(self, instance: 'BaseClass', typevar: Type['BaseClass']) -> Any: | |
if instance is None: | |
return self | |
if self.name in instance.__dict__: | |
return instance.__dict__[self.name] | |
if self.default != Sentinels.NO_INIT: | |
return self.default | |
if self.value_type != Sentinels.NO_INIT: | |
return self.value_type() | |
return None | |
class BaseClass: | |
thing: int = attr_descriptor(default=10) | |
def __init__(self, thing): | |
if thing: | |
self.thing = thing | |
BaseClass(thing=2) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment