Skip to content

Commit f2ed5e5

Browse files
fix: results returned by attributes property to show updates
Previously the `attributes` method would show the original values in a Gitlab Object even if they had been updated. Correct this so that the updated value will be returned. Also use copy.deepcopy() to ensure that modifying the dictionary returned can not also modify the object.
1 parent 7220c55 commit f2ed5e5

File tree

2 files changed

+15
-19
lines changed

2 files changed

+15
-19
lines changed

gitlab/base.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ def __setattr__(self, name: str, value: Any) -> None:
146146
self.__dict__["_updated_attrs"][name] = value
147147

148148
def asdict(self) -> Dict[str, Any]:
149-
data = copy.deepcopy(self._attrs)
149+
data = {}
150+
data.update(copy.deepcopy(self._attrs))
150151
data.update(copy.deepcopy(self._updated_attrs))
151152
return data
152153

@@ -231,10 +232,10 @@ def encoded_id(self) -> Optional[Union[int, str]]:
231232

232233
@property
233234
def attributes(self) -> Dict[str, Any]:
234-
d = self.__dict__["_updated_attrs"].copy()
235-
d.update(self.__dict__["_attrs"])
236-
d.update(self.__dict__["_parent_attrs"])
237-
return d
235+
data = {}
236+
data.update(copy.deepcopy(self._parent_attrs))
237+
data.update(copy.deepcopy(self.asdict()))
238+
return data
238239

239240

240241
class RESTObjectList:

tests/unit/test_base.py

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -284,21 +284,20 @@ def test_attributes(self, fake_manager):
284284
result = fake_object.attributes
285285
assert result == {"attr1": [1, 2, 3]}
286286

287-
# Updated attribute value is not reflected in `attributes`
287+
# Updated attribute value is reflected in `attributes`
288288
fake_object.attr1 = "hello"
289-
assert fake_object.attributes == {"attr1": [1, 2, 3]}
289+
assert fake_object.attributes == {"attr1": "hello"}
290290
assert fake_object.attr1 == "hello"
291291
# New attribute is in `attributes`
292292
fake_object.new_attrib = "spam"
293-
assert fake_object.attributes == {"attr1": [1, 2, 3], "new_attrib": "spam"}
293+
assert fake_object.attributes == {"attr1": "hello", "new_attrib": "spam"}
294294

295-
# Modifying the dictionary can cause modification to the object :(
295+
# Modifying the dictionary does not cause modifications to the object
296+
fake_object = FakeObject(fake_manager, {"attr1": [1, 2, 3]})
296297
result = fake_object.attributes
297298
result["attr1"].append(10)
298-
assert result == {"attr1": [1, 2, 3, 10], "new_attrib": "spam"}
299-
assert fake_object.attributes == {"attr1": [1, 2, 3, 10], "new_attrib": "spam"}
300-
assert fake_object.attr1 == "hello"
301-
299+
assert result == {"attr1": [1, 2, 3, 10]}
300+
assert fake_object.attributes == {"attr1": [1, 2, 3]}
302301

303302
def test_asdict_vs_attributes(self, fake_manager):
304303
fake_object = FakeObject(fake_manager, {"attr1": "foo"})
@@ -310,10 +309,6 @@ def test_asdict_vs_attributes(self, fake_manager):
310309
assert fake_object.attributes == fake_object.asdict()
311310
fake_object.attr2 = "eggs"
312311
assert fake_object.attributes == fake_object.asdict()
313-
# Update attribute, return different result
312+
# Update attribute, return same result
314313
fake_object.attr1 = "hello"
315-
assert fake_object.attributes != fake_object.asdict()
316-
# asdict() returns the updated value
317-
assert fake_object.asdict() == {"attr1": "hello", "attr2": "eggs"}
318-
# `attributes` returns original value
319-
assert fake_object.attributes == {"attr1": "foo", "attr2": "eggs"}
314+
assert fake_object.attributes == fake_object.asdict()

0 commit comments

Comments
 (0)