(cached_properties, original_getattr, cls)
| 505 | |
| 506 | |
| 507 | def _make_cached_property_getattr(cached_properties, original_getattr, cls): |
| 508 | lines = [ |
| 509 | # Wrapped to get `__class__` into closure cell for super() |
| 510 | # (It will be replaced with the newly constructed class after construction). |
| 511 | "def wrapper(_cls):", |
| 512 | " __class__ = _cls", |
| 513 | " def __getattr__(self, item, cached_properties=cached_properties, original_getattr=original_getattr, _cached_setattr_get=_cached_setattr_get):", |
| 514 | " func = cached_properties.get(item)", |
| 515 | " if func is not None:", |
| 516 | " result = func(self)", |
| 517 | " _setter = _cached_setattr_get(self)", |
| 518 | " _setter(item, result)", |
| 519 | " return result", |
| 520 | ] |
| 521 | if original_getattr is not None: |
| 522 | lines.append( |
| 523 | " return original_getattr(self, item)", |
| 524 | ) |
| 525 | else: |
| 526 | lines.extend( |
| 527 | [ |
| 528 | " try:", |
| 529 | " return super().__getattribute__(item)", |
| 530 | " except AttributeError:", |
| 531 | " if not hasattr(super(), '__getattr__'):", |
| 532 | " raise", |
| 533 | " return super().__getattr__(item)", |
| 534 | " original_error = f\"'{self.__class__.__name__}' object has no attribute '{item}'\"", |
| 535 | " raise AttributeError(original_error)", |
| 536 | ] |
| 537 | ) |
| 538 | |
| 539 | lines.extend( |
| 540 | [ |
| 541 | " return __getattr__", |
| 542 | "__getattr__ = wrapper(_cls)", |
| 543 | ] |
| 544 | ) |
| 545 | |
| 546 | unique_filename = _generate_unique_filename(cls, "getattr") |
| 547 | |
| 548 | glob = { |
| 549 | "cached_properties": cached_properties, |
| 550 | "_cached_setattr_get": _OBJ_SETATTR.__get__, |
| 551 | "original_getattr": original_getattr, |
| 552 | } |
| 553 | |
| 554 | return _linecache_and_compile( |
| 555 | "\n".join(lines), unique_filename, glob, locals={"_cls": cls} |
| 556 | )["__getattr__"] |
| 557 | |
| 558 | |
| 559 | def _frozen_setattrs(self, name, value): |
no test coverage detected