Last active
March 10, 2021 07:59
-
-
Save linw1995/e160910d2d30e0498309f6a7ecc80c72 to your computer and use it in GitHub Desktop.
MustSetProperty -- descriptor that raises exception if its value is None.
This file contains hidden or 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 typing import Any, Generic, Optional, TypeVar, Union, overload | |
| T = TypeVar("T") | |
| class UnsetError(Exception): | |
| pass | |
| class MustSetProperty(Generic[T]): | |
| def __set_name__(self, owner: Any, name: str): | |
| """ | |
| Customized names -- Descriptor HowTo Guide | |
| https://docs.python.org/3/howto/descriptor.html#customized-names | |
| """ | |
| self.public_name = name | |
| self.private_name = f"__must_set_{name}" | |
| @overload | |
| def __get__(self, obj: None, objtype: Any) -> "MustSetProperty[T]": | |
| pass | |
| @overload | |
| def __get__(self, obj: Any, objtype: Any) -> T: | |
| pass | |
| def __get__(self, obj: Any, objtype: Any) -> Union["MustSetProperty[T]", T]: | |
| if obj is None: | |
| return self | |
| if (value := getattr(obj, self.private_name, None)) is None: | |
| raise UnsetError(f"{self.public_name} is missing") | |
| return value | |
| def __set__(self, obj: Any, value: Optional[T]): | |
| setattr(obj, self.private_name, value) | |
| class Bar: | |
| name = MustSetProperty[str]() | |
| assert isinstance(Bar.name, MustSetProperty) | |
| bar = Bar() | |
| try: | |
| bar.name # raise UnsetError | |
| except UnsetError: | |
| print("accesing error") | |
| bar.name = "bar" | |
| print(bar.name) # accesing OK | |
| bar.name = None # set None | |
| try: | |
| bar.name # raise UnsetError | |
| except UnsetError: | |
| print("accesing error") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment