@@ -495,64 +495,6 @@ def _transform_attrs(
495495
496496 return _Attributes (AttrsClass (attrs ), base_attrs , base_attr_map )
497497
498-
499- def _make_cached_property_getattr (cached_properties , original_getattr , cls ):
500- lines = [
501- # Wrapped to get `__class__` into closure cell for super()
502- # (It will be replaced with the newly constructed class after construction).
503- "def wrapper(_cls):" ,
504- " __class__ = _cls" ,
505- " def __getattr__(self, item, cached_properties=cached_properties, original_getattr=original_getattr, _cached_setattr_get=_cached_setattr_get):" ,
506- " func = cached_properties.get(item)" ,
507- " if func is not None:" ,
508- " cache = item + '_cache'" ,
509- " cached = _cls.__dict__[cache]" ,
510- " try:" ,
511- " return cached.__get__(self, _cls)" ,
512- " except AttributeError:" ,
513- " pass" ,
514- " result = func(self)" ,
515- " cached.__set__(self, result)" ,
516- " return result" ,
517- ]
518- if original_getattr is not None :
519- lines .append (
520- " return original_getattr(self, item)" ,
521- )
522- else :
523- lines .extend (
524- [
525- " try:" ,
526- " return super().__getattribute__(item)" ,
527- " except AttributeError:" ,
528- " if not hasattr(super(), '__getattr__'):" ,
529- " raise" ,
530- " return super().__getattr__(item)" ,
531- " original_error = f\" '{self.__class__.__name__}' object has no attribute '{item}'\" " ,
532- " raise AttributeError(original_error)" ,
533- ]
534- )
535-
536- lines .extend (
537- [
538- " return __getattr__" ,
539- "__getattr__ = wrapper(_cls)" ,
540- ]
541- )
542-
543- unique_filename = _generate_unique_filename (cls , "getattr" )
544-
545- glob = {
546- "cached_properties" : cached_properties ,
547- "_cached_setattr_get" : _OBJ_SETATTR .__get__ ,
548- "original_getattr" : original_getattr ,
549- }
550-
551- return _linecache_and_compile (
552- "\n " .join (lines ), unique_filename , glob , locals = {"_cls" : cls }
553- )["__getattr__" ]
554-
555-
556498def _make_cached_property_uncached (original_cached_property_func , cls ):
557499 """Make an ordinary :deco:`property` to replace a :deco:`cached_property`
558500
@@ -585,6 +527,7 @@ def _make_cached_property_uncached(original_cached_property_func, cls):
585527 annotation = inspect .signature (
586528 original_cached_property_func
587529 ).return_annotation
530+ name = original_cached_property_func .__name__
588531 if annotation is inspect .Parameter .empty :
589532 defline = f"def { name } (self):"
590533 elif isinstance (
@@ -601,7 +544,19 @@ def _make_cached_property_uncached(original_cached_property_func, cls):
601544 "@property" ,
602545 defline ,
603546 * doc_lines ,
604- " raise AttributeError('Use __getattr__ instead')" ,
547+ " for entry in type.__dict__['__mro__'].__get__(self.__class__):" ,
548+ f" if '{ name } _cache' in entry.__dict__:" ,
549+ f" descriptor = entry.__dict__['{ name } _cache']" ,
550+ " break" ,
551+ " else:" ,
552+ " raise AttributeError('No descriptor')" ,
553+ " try:" ,
554+ " return descriptor.__get__(self, self.__class__)" ,
555+ " except AttributeError:" ,
556+ " pass" ,
557+ " result = original_cached_property(self)" ,
558+ " descriptor.__set__(self, result)" ,
559+ " return result" ,
605560 ]
606561 unique_filename = _generate_unique_filename (
607562 cls , original_cached_property_func
@@ -992,10 +947,6 @@ def _create_slots_class(self):
992947 if original_getattr is not None :
993948 additional_closure_functions_to_update .append (original_getattr )
994949
995- cd ["__getattr__" ] = _make_cached_property_getattr (
996- cached_properties , original_getattr , self ._cls
997- )
998-
999950 # We only add the names of attributes that aren't inherited.
1000951 # Setting __slots__ to inherited attributes wastes memory.
1001952 slot_names = [name for name in names if name not in base_names ]
0 commit comments