From 346e5c4f167654dd76c70dcefa168196a540df46 Mon Sep 17 00:00:00 2001 From: Catherine Date: Fri, 26 Jul 2024 00:25:04 +0000 Subject: [PATCH] support.lazy: make `__bool__` work. `if lazy_obj:` didn't work with e.g. `str` because `str.__bool__()` does not exist. --- software/glasgow/support/lazy.py | 54 +++++++++++++++++++------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/software/glasgow/support/lazy.py b/software/glasgow/support/lazy.py index f181b9d87..92ace058d 100644 --- a/software/glasgow/support/lazy.py +++ b/software/glasgow/support/lazy.py @@ -33,6 +33,13 @@ def __delattr__(self, attr): self._force_() delattr(self._object_, attr) + def __bool__(self): + self._force_() + if self._object_: + return True + else: + return False + def __repr__(self): if self._thunk_: rep = repr(self._thunk_) @@ -40,28 +47,33 @@ def __repr__(self): rep = repr(self._object_) return f"" - @classmethod - def _define_special_(cls, name): + +def define_specials(): + def define_special(name): def forward(self, *args, **kwargs): self._force_() return getattr(self._object_, name)(*args, **kwargs) forward.__name__ = name - setattr(cls, name, forward) - -# See https://docs.python.org/3/reference/datamodel.html#special-lookup -_specials = [ - "__str__", "__bytes__", "__format__", "__lt__", "__le__", "__eq__", "__ne__", "__gt__", - "__ge__", "__hash__", "__bool__", "__dir__", "__call__", "__len__", "__length_hint__", - "__getitem__", "__setitem__", "__delitem__", "__iter__", "__reversed__", "__contains__", - "__add__", "__sub__", "__mul__", "__matmul__", "__truediv__", "__floordiv__", "__mod__", - "__divmod__", "__pow__", "__lshift__", "__rshift__", "__and__", "__xor__", "__or__", - "__radd__", "__rsub__", "__rmul__", "__rmatmul__", "__rtruediv__", "__rfloordiv__", "__rmod__", - "__rdivmod__", "__rpow__", "__rlshift__", "__rrshift__", "__rand__", "__rxor__", "__ror__", - "__iadd__", "__isub__", "__imul__", "__imatmul__", "__itruediv__", "__ifloordiv__", "__imod__", - "__ipow__", "__ilshift__", "__irshift__", "__iand__", "__ixor__", "__ior__", "__neg__", - "__pos__", "__abs__", "__invert__", "__complex__", "__int__", "__float__", "__index__", - "__round__", "__trunc__", "__floor__", "__ceil__", "__enter__", "__exit__", "__await__", - "__aiter__", "__anext__", "__aenter__", "__aexit__" -] -for special in _specials: - lazy._define_special_(special) + setattr(lazy, name, forward) + + # See https://docs.python.org/3/reference/datamodel.html#special-lookup + # Note that the loop body has to be in a separate function because of local variable scoping. + for name in [ + "__str__", "__bytes__", "__format__", "__lt__", "__le__", "__eq__", "__ne__", "__gt__", + "__ge__", "__hash__", "__dir__", "__call__", "__len__", "__length_hint__", + "__getitem__", "__setitem__", "__delitem__", "__iter__", "__reversed__", "__contains__", + "__add__", "__sub__", "__mul__", "__matmul__", "__truediv__", "__floordiv__", "__mod__", + "__divmod__", "__pow__", "__lshift__", "__rshift__", "__and__", "__xor__", "__or__", + "__radd__", "__rsub__", "__rmul__", "__rmatmul__", "__rtruediv__", "__rfloordiv__", "__rmod__", + "__rdivmod__", "__rpow__", "__rlshift__", "__rrshift__", "__rand__", "__rxor__", "__ror__", + "__iadd__", "__isub__", "__imul__", "__imatmul__", "__itruediv__", "__ifloordiv__", "__imod__", + "__ipow__", "__ilshift__", "__irshift__", "__iand__", "__ixor__", "__ior__", "__neg__", + "__pos__", "__abs__", "__invert__", "__complex__", "__int__", "__float__", "__index__", + "__round__", "__trunc__", "__floor__", "__ceil__", "__enter__", "__exit__", "__await__", + "__aiter__", "__anext__", "__aenter__", "__aexit__" + ]: + define_special(name) + + +define_specials() +del define_specials