mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-11 09:28:27 -04:00
Stop JSONModel hiding attribute errors
`__getattr__` is called whenever an attribute error is raised. This means that if something deep inside a property on a model raised an attribute error, that error would be caught by `__getattr__`, which would then raise an exception that looked like the property itself didn’t exist. Very confusing. The solution seems to be to override `__getattribute__` instead, which handles _all_ attributes, not just those that aren’t explicitly defined. We then only intervene if the desired attribute is one of the `ALLOWED_PROPERTIES`, otherwise falling through to the built in methods of the underlying `object`.
This commit is contained in:
@@ -21,12 +21,27 @@ class JSONModel():
|
||||
def __eq__(self, other):
|
||||
return self.id == other.id
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr in self.ALLOWED_PROPERTIES:
|
||||
return self._dict[attr]
|
||||
raise AttributeError('`{}` is not a {} attribute'.format(
|
||||
attr,
|
||||
self.__class__.__name__.lower(),
|
||||
def __getattribute__(self, attr):
|
||||
|
||||
try:
|
||||
return super().__getattribute__(attr)
|
||||
except AttributeError as e:
|
||||
# Re-raise any `AttributeError`s that are not directly on
|
||||
# this object because they indicate an underlying exception
|
||||
# that we don’t want to swallow
|
||||
if str(e) != "'{}' object has no attribute '{}'".format(
|
||||
self.__class__.__name__, attr
|
||||
):
|
||||
raise e
|
||||
|
||||
if attr in super().__getattribute__('ALLOWED_PROPERTIES'):
|
||||
return super().__getattribute__('_dict')[attr]
|
||||
|
||||
raise AttributeError((
|
||||
"'{}' object has no attribute '{}' and '{}' is not a field "
|
||||
"in the underlying JSON"
|
||||
).format(
|
||||
self.__class__.__name__, attr, attr
|
||||
))
|
||||
|
||||
def _get_by_id(self, things, id):
|
||||
|
||||
Reference in New Issue
Block a user