@@ -101,47 +101,43 @@ def __setstate__(self, state: Dict[str, Any]) -> None:
101101self .__dict__ ["_module" ]= importlib .import_module (module_name )
102102
103103def __getattr__ (self ,name :str )-> Any :
104- try :
104+ if name in self . __dict__ [ "_updated_attrs" ] :
105105return self .__dict__ ["_updated_attrs" ][name ]
106- except KeyError :
107- try :
108- value = self .__dict__ ["_attrs" ][name ]
109-
110- # If the value is a list, we copy it in the _updated_attrs dict
111- # because we are not able to detect changes made on the object
112- # (append, insert, pop, ...). Without forcing the attr
113- # creation __setattr__ is never called, the list never ends up
114- # in the _updated_attrs dict, and the update() and save()
115- # method never push the new data to the server.
116- # See https://github.com/python-gitlab/python-gitlab/issues/306
117- #
118- # note: _parent_attrs will only store simple values (int) so we
119- # don't make this check in the next except block.
120- if isinstance (value ,list ):
121- self .__dict__ ["_updated_attrs" ][name ]= value [:]
122- return self .__dict__ ["_updated_attrs" ][name ]
123-
124- return value
125-
126- except KeyError :
127- try :
128- return self .__dict__ ["_parent_attrs" ][name ]
129- except KeyError as exc :
130- message = (
131- f"{ type (self ).__name__ !r} object has no attribute{ name !r} "
132- )
133- if self ._created_from_list :
134- message = (
135- f"{ message } \n \n "
136- + textwrap .fill (
137- f"{ self .__class__ !r} was created via a list() call and "
138- f"only a subset of the data may be present. To ensure "
139- f"all data is present get the object using a "
140- f"get(object.id) call. For more details, see:"
141- )
142- + f"\n \n { _URL_ATTRIBUTE_ERROR } "
143- )
144- raise AttributeError (message )from exc
106+
107+ if name in self .__dict__ ["_attrs" ]:
108+ value = self .__dict__ ["_attrs" ][name ]
109+ # If the value is a list, we copy it in the _updated_attrs dict
110+ # because we are not able to detect changes made on the object
111+ # (append, insert, pop, ...). Without forcing the attr
112+ # creation __setattr__ is never called, the list never ends up
113+ # in the _updated_attrs dict, and the update() and save()
114+ # method never push the new data to the server.
115+ # See https://github.com/python-gitlab/python-gitlab/issues/306
116+ #
117+ # note: _parent_attrs will only store simple values (int) so we
118+ # don't make this check in the next block.
119+ if isinstance (value ,list ):
120+ self .__dict__ ["_updated_attrs" ][name ]= value [:]
121+ return self .__dict__ ["_updated_attrs" ][name ]
122+
123+ return value
124+
125+ if name in self .__dict__ ["_parent_attrs" ]:
126+ return self .__dict__ ["_parent_attrs" ][name ]
127+
128+ message = f"{ type (self ).__name__ !r} object has no attribute{ name !r} "
129+ if self ._created_from_list :
130+ message = (
131+ f"{ message } \n \n "
132+ + textwrap .fill (
133+ f"{ self .__class__ !r} was created via a list() call and "
134+ f"only a subset of the data may be present. To ensure "
135+ f"all data is present get the object using a "
136+ f"get(object.id) call. For more details, see:"
137+ )
138+ + f"\n \n { _URL_ATTRIBUTE_ERROR } "
139+ )
140+ raise AttributeError (message )
145141
146142def __setattr__ (self ,name :str ,value :Any )-> None :
147143self .__dict__ ["_updated_attrs" ][name ]= value