Skip to content

Commit

Permalink
Set ImportError attributes using _instance_setattr
Browse files Browse the repository at this point in the history
Subclasses in the wild write `@property` functions that shadow the
attributes. Since they are getter only, the builtin attribute setting
fails with an `AttributeError`:

```
======================================================================
ERROR: test_set_path_attr_on_import_error_subclass_with_property_sets_attr (__main__.ExceptionTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "library/builtins_test.py", line 4968, in test_set_path_attr_on_import_error_subclass_with_property_sets_attr
    c = C("a path")
  File "library/builtins.py", line 1037, in __init__
    self.path = path
AttributeError: can't set attribute
```

If we use `_instance_setattr`, this works.

This may be a more general problem since CPython does all this stuff in
C and our builtins are all in Python, but I am not sure how to approach
that yet.
  • Loading branch information
tekknolagi committed Feb 21, 2024
1 parent cd9b613 commit 9be7cba
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
4 changes: 2 additions & 2 deletions library/builtins.py
Original file line number Diff line number Diff line change
Expand Up @@ -1031,8 +1031,8 @@ def __init__(self, *args, name=None, path=None):
self.args = args
if len(args) == 1:
self.msg = args[0]
self.name = name
self.path = path
_instance_setattr(self, "name", name)
_instance_setattr(self, "path", path)

def __reduce__(self):
_unimplemented()
Expand Down
26 changes: 26 additions & 0 deletions library/builtins_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4944,6 +4944,32 @@ def test_system_exit_with_value_sets_code(self):
exc = SystemExit(1111)
self.assertEqual(exc.code, 1111)

def test_set_name_attr_on_import_error_subclass_with_property_sets_attr(self):
class C(ModuleNotFoundError):
# Modeled after PackageNotFoundError in
# importlib_metadata/__init__.py
@property
def name(self):
(name,) = self.args
return name

c = C("a name")
self.assertEqual(c.name, "a name")
self.assertEqual(c.path, None)

def test_set_path_attr_on_import_error_subclass_with_property_sets_attr(self):
class C(ModuleNotFoundError):
# Modeled after PackageNotFoundError in
# importlib_metadata/__init__.py
@property
def path(self):
(path,) = self.args
return path

c = C("a path")
self.assertEqual(c.name, None)
self.assertEqual(c.path, "a path")


class EvalTests(unittest.TestCase):
def test_globals_none_accesses_function_globals(self):
Expand Down

0 comments on commit 9be7cba

Please sign in to comment.