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

Commit644ef29

Browse files
chore: attempt to be more informative for missing attributes
A commonly reported issue from users on Gitter is that they get anAttributeError for an attribute that should be present. This is oftencaused due to the fact that they used the `list()` method to retrievethe object and objects retrieved this way often only have a subset ofthe full data.Add more details in the AttributeError message that explains thesituation to users. This will hopefully allow them to resolve theissue.Update the FAQ in the docs to add a section discussing the issue.Closes#1138
1 parent7ba5995 commit644ef29

File tree

4 files changed

+60
-4
lines changed

4 files changed

+60
-4
lines changed

‎docs/faq.rst‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ I cannot edit the merge request / issue I've just retrieved
1616
See the:ref:`merge requests example<merge_requests_examples>` and the
1717
:ref:`issues examples<issues_examples>`.
1818

19+
.. _attribute_error_list:
20+
21+
I get an ``AttributeError`` when accessing attributes of an object retrieved via a ``list()`` call.
22+
Fetching a list of objects, doesn’t always include all attributes in the
23+
objects. To retrieve an object with all attributes use a ``get()`` call.
24+
25+
Example with projects::
26+
27+
for projects in gl.projects.list():
28+
# Retrieve project object with all attributes
29+
project = gl.projects.get(project.id)
30+
1931
How can I clone the repository of a project?
2032
python-gitlab doesn't provide an API to clone a project. You have to use a
2133
git library or call the ``git`` command.

‎gitlab/base.py‎

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
]
3333

3434

35+
_URL_ATTRIBUTE_ERROR= (
36+
"https://python-gitlab.readthedocs.io/en/stable/faq.html#attribute-error-list"
37+
)
38+
39+
3540
classRESTObject(object):
3641
"""Represents an object built from server data.
3742
@@ -45,13 +50,20 @@ class RESTObject(object):
4550

4651
_id_attr:Optional[str]="id"
4752
_attrs:Dict[str,Any]
53+
_list_created_object:bool# Indicates if object was created from a list() action
4854
_module:ModuleType
4955
_parent_attrs:Dict[str,Any]
5056
_short_print_attr:Optional[str]=None
5157
_updated_attrs:Dict[str,Any]
5258
manager:"RESTManager"
5359

54-
def__init__(self,manager:"RESTManager",attrs:Dict[str,Any])->None:
60+
def__init__(
61+
self,
62+
manager:"RESTManager",
63+
attrs:Dict[str,Any],
64+
*,
65+
list_created_object:bool=False,
66+
)->None:
5567
ifnotisinstance(attrs,dict):
5668
raiseGitlabParsingError(
5769
"Attempted to initialize RESTObject with a non-dictionary value: "
@@ -64,6 +76,7 @@ def __init__(self, manager: "RESTManager", attrs: Dict[str, Any]) -> None:
6476
"_attrs":attrs,
6577
"_updated_attrs": {},
6678
"_module":importlib.import_module(self.__module__),
79+
"_list_created_object":list_created_object,
6780
}
6881
)
6982
self.__dict__["_parent_attrs"]=self.manager.parent_attrs
@@ -107,7 +120,16 @@ def __getattr__(self, name: str) -> Any:
107120
try:
108121
returnself.__dict__["_parent_attrs"][name]
109122
exceptKeyError:
110-
raiseAttributeError(name)
123+
message=name
124+
ifself._list_created_object:
125+
message= (
126+
f"Unable to find attribute{name!r}. This object "
127+
f"({self.__class__}) was created via a list() call and "
128+
f"only a subset of the data may be present. To ensure all "
129+
f"data is present get the object using a get(object.id) "
130+
f"call. See{_URL_ATTRIBUTE_ERROR} for details."
131+
)
132+
raiseAttributeError(message)
111133

112134
def__setattr__(self,name:str,value:Any)->None:
113135
self.__dict__["_updated_attrs"][name]=value
@@ -229,7 +251,7 @@ def __next__(self) -> RESTObject:
229251

230252
defnext(self)->RESTObject:
231253
data=self._list.next()
232-
returnself._obj_cls(self.manager,data)
254+
returnself._obj_cls(self.manager,data,list_created_object=True)
233255

234256
@property
235257
defcurrent_page(self)->int:

‎gitlab/mixins.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ def list(self, **kwargs: Any) -> Union[base.RESTObjectList, List[base.RESTObject
240240
assertself._obj_clsisnotNone
241241
obj=self.gitlab.http_list(path,**data)
242242
ifisinstance(obj,list):
243-
return [self._obj_cls(self,item)foriteminobj]
243+
return [self._obj_cls(self,item,list_created_object=True)foriteminobj]
244244
else:
245245
returnbase.RESTObjectList(self,self._obj_cls,obj)
246246

‎tests/unit/test_base.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,28 @@ def test_instantiate_non_dict(self, fake_gitlab, fake_manager):
9090
withpytest.raises(gitlab.exceptions.GitlabParsingError):
9191
FakeObject(fake_manager, ["a","list","fails"])
9292

93+
deftest_missing_attribute_does_not_raise_custom(self,fake_gitlab,fake_manager):
94+
"""Ensure a missing attribute does not raise our custom error message
95+
if the RESTObject was not created from a list"""
96+
obj=FakeObject(manager=fake_manager,attrs={"foo":"bar"})
97+
withpytest.raises(AttributeError)asexcinfo:
98+
obj.missing_attribute
99+
assertstr(excinfo.value)=="missing_attribute"
100+
assert"was created via a list()"notinstr(excinfo.value)
101+
assertbase._URL_ATTRIBUTE_ERRORnotinstr(excinfo.value)
102+
103+
deftest_missing_attribute_from_list_raises_custom(self,fake_gitlab,fake_manager):
104+
"""Ensure a missing attribute raises our custom error message if the
105+
RESTObject was created from a list"""
106+
obj=FakeObject(
107+
manager=fake_manager,attrs={"foo":"bar"},list_created_object=True
108+
)
109+
withpytest.raises(AttributeError)asexcinfo:
110+
obj.missing_attribute
111+
assert"missing_attribute"instr(excinfo.value)
112+
assert"was created via a list()"instr(excinfo.value)
113+
assertbase._URL_ATTRIBUTE_ERRORinstr(excinfo.value)
114+
93115
deftest_picklability(self,fake_manager):
94116
obj=FakeObject(fake_manager, {"foo":"bar"})
95117
original_obj_module=obj._module

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp