Last active
April 26, 2024 05:19
-
-
Save clintval/6019589173e046116ba0931be7e1b575 to your computer and use it in GitHub Desktop.
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
def is_classmethod(method: FunctionType) -> bool: | |
"""Determine if a method is a classmethod or not by searching for a classmethod sentinel.""" | |
bound_to = getattr(method, "__self__", None) | |
if not isinstance(bound_to, type): | |
return False | |
name = method.__name__ | |
for clazz in bound_to.__mro__: | |
descriptor = vars(clazz).get(name) | |
if descriptor is not None: | |
return isinstance(descriptor, classmethod) | |
return False | |
def _patch_base_generic_alias_getattr_for_generic_classmethods() -> None: | |
def __getattr__(self: Any, name: str) -> Any: # type: ignore[misc] | |
"""A generic classmethod aware patch for __getattr__ of all base generic classes.""" | |
if is_classmethod(class_def := original_getattr(self, name)): | |
param_to_args = dict(zip(self.__origin__.__parameters__, self.__args__, strict=True)) | |
function = class_def.__func__ | |
return FunctionType( | |
function.__code__, | |
function.__globals__, | |
function.__name__, | |
function.__defaults__, | |
tuple( | |
CellType( | |
param_to_args.get(value, value) if isinstance(value, Hashable) else value | |
) | |
for value in map(attrgetter("cell_contents"), function.__closure__) | |
), | |
).__get__(class_def.__self__) | |
return class_def | |
if _BaseGenericAlias.__getattr__ is not __getattr__: | |
original_getattr = _BaseGenericAlias.__getattr__ | |
_BaseGenericAlias.__getattr__ = __getattr__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment