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

Commit909aa9a

Browse files
authored
Merge pull request#1352 from JohnVillalovos/jlvillal/fix_mro
fix: add a check to ensure the MRO is correct
2 parentsdde01c7 +0357c37 commit909aa9a

File tree

6 files changed

+127
-5
lines changed

6 files changed

+127
-5
lines changed

‎gitlab/tests/objects/test_mro.py‎

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
"""
2+
Ensure objects defined in gitlab.v4.objects have REST* as last item in class
3+
definition
4+
5+
Original notes by John L. Villalovos
6+
7+
An example of an incorrect definition:
8+
class ProjectPipeline(RESTObject, RefreshMixin, ObjectDeleteMixin):
9+
^^^^^^^^^^ This should be at the end.
10+
11+
Correct way would be:
12+
class ProjectPipeline(RefreshMixin, ObjectDeleteMixin, RESTObject):
13+
Correctly at the end ^^^^^^^^^^
14+
15+
16+
Why this is an issue:
17+
18+
When we do type-checking for gitlab/mixins.py we make RESTObject or
19+
RESTManager the base class for the mixins
20+
21+
Here is how our classes look when type-checking:
22+
23+
class RESTObject(object):
24+
def __init__(self, manager: "RESTManager", attrs: Dict[str, Any]) -> None:
25+
...
26+
27+
class Mixin(RESTObject):
28+
...
29+
30+
# Wrong ordering here
31+
class Wrongv4Object(RESTObject, RefreshMixin):
32+
...
33+
34+
If we actually ran this in Python we would get the following error:
35+
class Wrongv4Object(RESTObject, Mixin):
36+
TypeError: Cannot create a consistent method resolution
37+
order (MRO) for bases RESTObject, Mixin
38+
39+
When we are type-checking it fails to understand the class Wrongv4Object
40+
and thus we can't type check it correctly.
41+
42+
Almost all classes in gitlab/v4/objects/*py were already correct before this
43+
check was added.
44+
"""
45+
importinspect
46+
47+
importpytest
48+
49+
importgitlab.v4.objects
50+
51+
52+
deftest_show_issue():
53+
"""Test case to demonstrate the TypeError that occurs"""
54+
55+
classRESTObject(object):
56+
def__init__(self,manager:str,attrs:int)->None:
57+
...
58+
59+
classMixin(RESTObject):
60+
...
61+
62+
withpytest.raises(TypeError)asexc_info:
63+
# Wrong ordering here
64+
classWrongv4Object(RESTObject,Mixin):
65+
...
66+
67+
# The error message in the exception should be:
68+
# TypeError: Cannot create a consistent method resolution
69+
# order (MRO) for bases RESTObject, Mixin
70+
71+
# Make sure the exception string contains "MRO"
72+
assert"MRO"inexc_info.exconly()
73+
74+
# Correctly ordered class, no exception
75+
classCorrectv4Object(Mixin,RESTObject):
76+
...
77+
78+
79+
deftest_mros():
80+
"""Ensure objects defined in gitlab.v4.objects have REST* as last item in
81+
class definition.
82+
83+
We do this as we need to ensure the MRO (Method Resolution Order) is
84+
correct.
85+
"""
86+
87+
failed_messages= []
88+
formodule_name,module_valueininspect.getmembers(gitlab.v4.objects):
89+
ifnotinspect.ismodule(module_value):
90+
# We only care about the modules
91+
continue
92+
# Iterate through all the classes in our module
93+
forclass_name,class_valueininspect.getmembers(module_value):
94+
ifnotinspect.isclass(class_value):
95+
continue
96+
97+
# Ignore imported classes from gitlab.base
98+
ifclass_value.__module__=="gitlab.base":
99+
continue
100+
101+
mro=class_value.mro()
102+
103+
# We only check classes which have a 'gitlab.base' class in their MRO
104+
has_base=False
105+
forcount,objinenumerate(mro,start=1):
106+
ifobj.__module__=="gitlab.base":
107+
has_base=True
108+
base_classname=obj.__name__
109+
ifhas_base:
110+
filename=inspect.getfile(class_value)
111+
# NOTE(jlvillal): The very last item 'mro[-1]' is always going
112+
# to be 'object'. That is why we are checking 'mro[-2]'.
113+
ifmro[-2].__module__!="gitlab.base":
114+
failed_messages.append(
115+
(
116+
f"class definition for{class_name!r} in file{filename!r} "
117+
f"must have{base_classname!r} as the last class in the "
118+
f"class definition"
119+
)
120+
)
121+
failed_msg="\n".join(failed_messages)
122+
assertnotfailed_messages,failed_msg

‎gitlab/v4/objects/commits.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ class ProjectCommitCommentManager(ListMixin, CreateMixin, RESTManager):
159159
)
160160

161161

162-
classProjectCommitStatus(RESTObject,RefreshMixin):
162+
classProjectCommitStatus(RefreshMixin,RESTObject):
163163
pass
164164

165165

‎gitlab/v4/objects/deployments.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
]
99

1010

11-
classProjectDeployment(RESTObject,SaveMixin):
11+
classProjectDeployment(SaveMixin,RESTObject):
1212
pass
1313

1414

‎gitlab/v4/objects/jobs.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
]
1111

1212

13-
classProjectJob(RESTObject,RefreshMixin):
13+
classProjectJob(RefreshMixin,RESTObject):
1414
@cli.register_custom_action("ProjectJob")
1515
@exc.on_http_error(exc.GitlabJobCancelError)
1616
defcancel(self,**kwargs):

‎gitlab/v4/objects/pipelines.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
]
3131

3232

33-
classProjectPipeline(RESTObject,RefreshMixin,ObjectDeleteMixin):
33+
classProjectPipeline(RefreshMixin,ObjectDeleteMixin,RESTObject):
3434
_managers= (
3535
("jobs","ProjectPipelineJobManager"),
3636
("bridges","ProjectPipelineBridgeManager"),

‎gitlab/v4/objects/releases.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class ProjectReleaseManager(NoUpdateMixin, RESTManager):
2424
)
2525

2626

27-
classProjectReleaseLink(RESTObject,ObjectDeleteMixin,SaveMixin):
27+
classProjectReleaseLink(ObjectDeleteMixin,SaveMixin,RESTObject):
2828
pass
2929

3030

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp