Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit973e68f

Browse files
feat: addasdict() andto_json() methods to Gitlab Objects
Add an `asdict()` method that returns a dictionary representation copyof the Gitlab Object. This is a copy and changes made to it will haveno impact on the Gitlab Object.The `asdict()` method name was chosen as both the `dataclasses` and`attrs` libraries have an `asdict()` function which has the similarpurpose of creating a dictionary represenation of an object.Also add a `to_json()` method that returns a JSON stringrepresentation of the object.Closes:#1116
1 parent160ae82 commit973e68f

File tree

3 files changed

+96
-22
lines changed

3 files changed

+96
-22
lines changed

‎docs/api-usage.rst‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,38 @@ the value on the object is accepted:
214214
issue.my_super_awesome_feature_flag="random_value"
215215
issue.save()
216216
217+
You can get a dictionary representation copy of the Gitlab Object. Modifications made to
218+
the dictionary will have no impact on the GitLab Object.
219+
220+
* `asdict()` method. Returns a dictionary representation of the Gitlab object.
221+
* `attributes` property. Returns a dictionary representation of the Gitlab
222+
object. Also returns any relevant parent object attributes.
223+
224+
..note::
225+
226+
`attributes` returns the parent object attributes that are defined in
227+
`object._from_parent_attrs`. What this can mean is that for example a `ProjectIssue`
228+
object will have a `project_id` key in the dictionary returned from `attributes` but
229+
`asdict()` will not.
230+
231+
232+
..code-block::python
233+
234+
project= gl.projects.get(1)
235+
project_dict= project.asdict()
236+
237+
# Or a dictionary representation also containing some of the parent attributes
238+
issue= project.issues.get(1)
239+
attribute_dict= issue.attributes
240+
241+
You can get a JSON string represenation of the Gitlab Object. For example:
242+
243+
..code-block::python
244+
245+
project= gl.projects.get(1)
246+
print(project.to_json())
247+
# Use arguments supported by `json.dump()`
248+
print(project.to_json(sort_keys=True,indent=4))
217249
218250
Base types
219251
==========

‎gitlab/base.py‎

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
importcopy
1919
importimportlib
20+
importjson
2021
importpprint
2122
importtextwrap
2223
fromtypesimportModuleType
@@ -143,15 +144,26 @@ def __getattr__(self, name: str) -> Any:
143144
def__setattr__(self,name:str,value:Any)->None:
144145
self.__dict__["_updated_attrs"][name]=value
145146

147+
defasdict(self,*,with_parent_attrs:bool=False)->Dict[str,Any]:
148+
data= {}
149+
ifwith_parent_attrs:
150+
data.update(copy.deepcopy(self._parent_attrs))
151+
data.update(copy.deepcopy(self._attrs))
152+
data.update(copy.deepcopy(self._updated_attrs))
153+
returndata
154+
155+
@property
156+
defattributes(self)->Dict[str,Any]:
157+
returnself.asdict(with_parent_attrs=True)
158+
159+
defto_json(self,*,with_parent_attrs:bool=False,**kwargs:Any)->str:
160+
returnjson.dumps(self.asdict(with_parent_attrs=with_parent_attrs),**kwargs)
161+
146162
def__str__(self)->str:
147-
data=self._attrs.copy()
148-
data.update(self._updated_attrs)
149-
returnf"{type(self)} =>{data}"
163+
returnf"{type(self)} =>{self.asdict()}"
150164

151165
defpformat(self)->str:
152-
data=self._attrs.copy()
153-
data.update(self._updated_attrs)
154-
returnf"{type(self)} =>\n{pprint.pformat(data)}"
166+
returnf"{type(self)} =>\n{pprint.pformat(self.asdict())}"
155167

156168
defpprint(self)->None:
157169
print(self.pformat())
@@ -242,14 +254,6 @@ def encoded_id(self) -> Optional[Union[int, str]]:
242254
obj_id=gitlab.utils.EncodedId(obj_id)
243255
returnobj_id
244256

245-
@property
246-
defattributes(self)->Dict[str,Any]:
247-
data= {}
248-
data.update(copy.deepcopy(self._parent_attrs))
249-
data.update(copy.deepcopy(self._attrs))
250-
data.update(copy.deepcopy(self._updated_attrs))
251-
returndata
252-
253257

254258
classRESTObjectList:
255259
"""Generator object representing a list of RESTObject's.

‎tests/unit/test_base.py‎

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def fake_manager(fake_gitlab):
4848

4949
@pytest.fixture
5050
deffake_object(fake_manager):
51-
returnFakeObject(fake_manager, {"attr1": [1,2,3]})
51+
returnFakeObject(fake_manager, {"attr1":"foo","alist":[1,2,3]})
5252

5353

5454
classTestRESTManager:
@@ -313,22 +313,60 @@ def test_repr(self, fake_manager):
313313
assertrepr(obj)=="<FakeObject>"
314314

315315
deftest_attributes_get(self,fake_object):
316-
assertfake_object.attr1==[1,2,3]
316+
assertfake_object.attr1=="foo"
317317
result=fake_object.attributes
318-
assertresult== {"attr1": [1,2,3]}
318+
assertresult== {"attr1":"foo","alist":[1,2,3]}
319319

320320
deftest_attributes_shows_updates(self,fake_object):
321321
# Updated attribute value is reflected in `attributes`
322322
fake_object.attr1="hello"
323-
assertfake_object.attributes== {"attr1":"hello"}
323+
assertfake_object.attributes== {"attr1":"hello","alist": [1,2,3]}
324324
assertfake_object.attr1=="hello"
325325
# New attribute is in `attributes`
326326
fake_object.new_attrib="spam"
327-
assertfake_object.attributes== {"attr1":"hello","new_attrib":"spam"}
327+
assertfake_object.attributes== {
328+
"attr1":"hello",
329+
"new_attrib":"spam",
330+
"alist": [1,2,3],
331+
}
328332

329333
deftest_attributes_is_copy(self,fake_object):
330334
# Modifying the dictionary does not cause modifications to the object
331335
result=fake_object.attributes
332-
result["attr1"].append(10)
333-
assertresult== {"attr1": [1,2,3,10]}
334-
assertfake_object.attributes== {"attr1": [1,2,3]}
336+
result["alist"].append(10)
337+
assertresult== {"attr1":"foo","alist": [1,2,3,10]}
338+
assertfake_object.attributes== {"attr1":"foo","alist": [1,2,3]}
339+
340+
deftest_asdict(self,fake_object):
341+
assertfake_object.attr1=="foo"
342+
result=fake_object.asdict()
343+
assertresult== {"attr1":"foo","alist": [1,2,3]}
344+
345+
deftest_asdict_modify_dict_does_not_change_object(self,fake_object):
346+
result=fake_object.asdict()
347+
# Demonstrate modifying the dictionary does not modify the object
348+
result["attr1"]="testing"
349+
result["alist"].append(4)
350+
assertresult== {"attr1":"testing","alist": [1,2,3,4]}
351+
assertfake_object.attr1=="foo"
352+
assertfake_object.alist== [1,2,3]
353+
354+
deftest_asdict_modify_dict_does_not_change_object2(self,fake_object):
355+
# Modify attribute and then ensure modifying a list in the returned dict won't
356+
# modify the list in the object.
357+
fake_object.attr1= [9,7,8]
358+
assertfake_object.asdict()== {
359+
"attr1": [9,7,8],
360+
"alist": [1,2,3],
361+
}
362+
result=fake_object.asdict()
363+
result["attr1"].append(1)
364+
assertfake_object.asdict()== {
365+
"attr1": [9,7,8],
366+
"alist": [1,2,3],
367+
}
368+
369+
deftest_asdict_modify_object(self,fake_object):
370+
# asdict() returns the updated value
371+
fake_object.attr1="spam"
372+
assertfake_object.asdict()== {"attr1":"spam","alist": [1,2,3]}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp