19
19
DISABLED_PREFIX = "DISABLED"
20
20
UNSTABLE_PREFIX = "UNSTABLE"
21
21
DISABLED_TEST_ISSUE_TITLE = re .compile (r"DISABLED\s*test_.+\s*\(.+\)" )
22
+ DISABLED_TEST_MULTI_ISSUE_TITLE = re .compile (r"DISABLED MULTIPLE" )
22
23
JOB_NAME_MAXSPLIT = 2
23
24
24
25
OWNER = "pytorch"
@@ -122,14 +123,108 @@ def filter_disable_issues(
122
123
if not title or not title .startswith (prefix ):
123
124
continue
124
125
125
- if DISABLED_TEST_ISSUE_TITLE .match (title ):
126
+ if DISABLED_TEST_ISSUE_TITLE .match (
127
+ title
128
+ ) or DISABLED_TEST_MULTI_ISSUE_TITLE .match (title ):
126
129
disable_test_issues .append (issue )
127
130
else :
128
131
disable_job_issues .append (issue )
129
132
130
133
return disable_test_issues , disable_job_issues
131
134
132
135
136
+ def get_disabled_tests (issues : List [Dict [str , Any ]]) -> Dict [str , Tuple ]:
137
+ def get_platforms_to_skip (body : str , prefix : str ) -> List [str ]:
138
+ # Empty list = all platforms should skip the test
139
+ platforms_to_skip = []
140
+ if body is not None :
141
+ for line in body .splitlines ():
142
+ line = line .lower ()
143
+ if line .startswith (prefix ):
144
+ platforms_to_skip .extend (
145
+ [x .strip () for x in line [len (prefix ) :].split ("," ) if x .strip ()]
146
+ )
147
+ return platforms_to_skip
148
+
149
+ disabled_tests = {}
150
+
151
+ def update_disabled_tests (
152
+ key : str , number : str , url : str , platforms_to_skip : List [str ]
153
+ ):
154
+ # merge the list of platforms to skip if the test is disabled by
155
+ # multiple issues. This results in some urls being wrong
156
+ if key not in disabled_tests :
157
+ disabled_tests [key ] = (number , url , platforms_to_skip )
158
+ else :
159
+ original_platforms = disabled_tests [key ][2 ]
160
+ if len (original_platforms ) == 0 or len (platforms_to_skip ) == 0 :
161
+ platforms = []
162
+ else :
163
+ platforms = sorted (set (original_platforms + platforms_to_skip ))
164
+ disabled_tests [key ] = (
165
+ number ,
166
+ url ,
167
+ platforms ,
168
+ )
169
+
170
+ test_name_regex = re .compile (r"(test_[a-zA-Z0-9-_\.]+)\s+\(([a-zA-Z0-9-_\.]+)\)" )
171
+
172
+ def parse_test_name (s : str ) -> Optional [str ]:
173
+ test_name_match = test_name_regex .match (s )
174
+ if test_name_match :
175
+ return f"{ test_name_match .group (1 )} ({ test_name_match .group (2 )} )"
176
+ return None
177
+
178
+ for issue in issues :
179
+ try :
180
+ url = issue ["url" ]
181
+ number = url .split ("/" )[- 1 ]
182
+ title = issue ["title" ].strip ()
183
+ body = issue ["body" ]
184
+
185
+ test_name = parse_test_name (title [len ("DISABLED" ) :].strip ())
186
+ if test_name is not None :
187
+ update_disabled_tests (
188
+ test_name , number , url , get_platforms_to_skip (body , "platforms:" )
189
+ )
190
+ elif DISABLED_TEST_MULTI_ISSUE_TITLE .match (title ):
191
+ # This is a multi-test issue
192
+ start = body .lower ().find ("disable the following tests:" )
193
+ # Format for disabling tests:
194
+ # Title: DISABLED MULTIPLE anything
195
+ # disable the following tests:
196
+ # ```
197
+ # test_name1 (test_suite1): mac, windows
198
+ # test_name2 (test_suite2): mac, windows
199
+ # ```
200
+ for line in body [start :].splitlines ()[2 :]:
201
+ if "```" in line :
202
+ break
203
+ split_by_colon = line .split (":" )
204
+
205
+ test_name = parse_test_name (split_by_colon [0 ].strip ())
206
+ if test_name is None :
207
+ continue
208
+ update_disabled_tests (
209
+ test_name ,
210
+ number ,
211
+ url ,
212
+ get_platforms_to_skip (
213
+ split_by_colon [1 ].strip ()
214
+ if len (split_by_colon ) > 1
215
+ else "" ,
216
+ "" ,
217
+ ),
218
+ )
219
+ else :
220
+ print (f"Unknown disable issue type: { title } " )
221
+ except Exception as e :
222
+ print (f"Failed to parse issue { issue ['url' ]} : { e } " )
223
+ continue
224
+
225
+ return disabled_tests
226
+
227
+
133
228
@lru_cache ()
134
229
def can_disable_jobs (owner : str , repo : str , username : str , token : str ) -> bool :
135
230
url = f"https://api.github.com/repos/{ owner } /{ repo } /collaborators/{ username } /permission"
@@ -146,38 +241,6 @@ def can_disable_jobs(owner: str, repo: str, username: str, token: str) -> bool:
146
241
return perm and perm .get ("permission" , "" ).lower () in PERMISSIONS_TO_DISABLE_JOBS
147
242
148
243
149
- def condense_disable_tests (
150
- disable_issues : List [Dict [str , Any ]],
151
- ) -> Dict [str , Tuple ]:
152
- disabled_test_from_issues = {}
153
- for item in disable_issues :
154
- issue_url = item ["url" ]
155
- issue_number = issue_url .split ("/" )[- 1 ]
156
-
157
- title = item ["title" ]
158
- test_name = title [len (DISABLED_PREFIX ) :].strip ()
159
-
160
- body = item ["body" ]
161
- platforms_to_skip = []
162
- key = "platforms:"
163
- # When the issue has no body, it is assumed that all platforms should skip the test
164
- if body is not None :
165
- for line in body .splitlines ():
166
- line = line .lower ()
167
- if line .startswith (key ):
168
- platforms_to_skip .extend (
169
- [x .strip () for x in line [len (key ) :].split ("," ) if x .strip ()]
170
- )
171
-
172
- disabled_test_from_issues [test_name ] = (
173
- issue_number ,
174
- issue_url ,
175
- platforms_to_skip ,
176
- )
177
-
178
- return disabled_test_from_issues
179
-
180
-
181
244
def condense_disable_jobs (
182
245
disable_issues : List [Any ],
183
246
owner : str ,
@@ -253,9 +316,7 @@ def main() -> None:
253
316
disable_test_issues , disable_job_issues = filter_disable_issues (disable_issues )
254
317
# Create the list of disabled tests taken into account the list of disabled issues
255
318
# and those that are not flaky anymore
256
- dump_json (
257
- condense_disable_tests (disable_test_issues ), "disabled-tests-condensed.json"
258
- )
319
+ dump_json (get_disabled_tests (disable_test_issues ), "disabled-tests-condensed.json" )
259
320
dump_json (
260
321
condense_disable_jobs (disable_job_issues , args .owner , args .repo , token ),
261
322
"disabled-jobs.json" ,
0 commit comments