From 161de4e410c8b8fa94f2a5c39867b63f5aa7ecde Mon Sep 17 00:00:00 2001 From: "junie-eap[bot]" Date: Mon, 28 Apr 2025 12:20:22 +0000 Subject: [PATCH] chore(junie): bizarre behavior with torch module's Attribute Error Junie changes from the task: #4 --- test_descriptor.py | 16 ++++++++++++++++ test_fix.py | 22 ++++++++++++++++++++++ test_property_issue.py | 15 +++++++++++++++ torch/nn/modules/module.py | 12 ++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 test_descriptor.py create mode 100644 test_fix.py create mode 100644 test_property_issue.py diff --git a/test_descriptor.py b/test_descriptor.py new file mode 100644 index 0000000000000..89541f115805e --- /dev/null +++ b/test_descriptor.py @@ -0,0 +1,16 @@ +class Base: + def __getattr__(self, name): + print(f"Base.__getattr__({name})") + raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") + +class Derived(Base): + @property + def foo(self): + print("Derived.foo property") + return self.bar # This will raise AttributeError + +d = Derived() +try: + print(d.foo) +except AttributeError as e: + print(f"AttributeError: {e}") diff --git a/test_fix.py b/test_fix.py new file mode 100644 index 0000000000000..ae597bb19f127 --- /dev/null +++ b/test_fix.py @@ -0,0 +1,22 @@ +import torch + +class A(torch.nn.Module): + def __init__(self): + super().__init__() + + @property + def foo(self): + return self.bar # attr error + +a = A() +try: + print(a.foo) +except AttributeError as e: + print(f"AttributeError: {e}") + + # Verify that the error message mentions 'bar' and not 'foo' + error_message = str(e) + if "'bar'" in error_message: + print("Test PASSED: Error message correctly identifies the missing attribute 'bar'") + else: + print(f"Test FAILED: Error message does not mention 'bar': {error_message}") diff --git a/test_property_issue.py b/test_property_issue.py new file mode 100644 index 0000000000000..ec129e2bb7e03 --- /dev/null +++ b/test_property_issue.py @@ -0,0 +1,15 @@ +import torch + +class A(torch.nn.Module): + def __init__(self): + super().__init__() + + @property + def foo(self): + return self.bar # attr error + +a = A() +try: + print(a.foo) +except AttributeError as e: + print(f"AttributeError: {e}") diff --git a/torch/nn/modules/module.py b/torch/nn/modules/module.py index e10855f7c47ab..cdd4cdc71437e 100644 --- a/torch/nn/modules/module.py +++ b/torch/nn/modules/module.py @@ -1941,6 +1941,18 @@ def __getattr__(self, name: str) -> Union[Tensor, "Module"]: modules = self.__dict__["_modules"] if name in modules: return modules[name] + + # Check if the attribute exists as a property + # This handles the case where a property raises an AttributeError + property_obj = getattr(type(self), name, None) + if isinstance(property_obj, property): + # Re-raise the original AttributeError from the property + try: + return property_obj.__get__(self, type(self)) + except AttributeError as e: + # Re-raise the original AttributeError + raise e + raise AttributeError( f"'{type(self).__name__}' object has no attribute '{name}'" )