1
1
#!/usr/bin/env python3
2
+ # pylint: disable=missing-module-docstring
2
3
3
4
import logging
4
5
import argparse
@@ -39,11 +40,14 @@ def __init__(self, tracker_filename: str = None):
39
40
trackers = {}
40
41
if tracker_filename :
41
42
try :
43
+ # pylint: disable-next=logging-fstring-interpolation
42
44
logging .info (f"Parsing tracker file: { tracker_filename } " )
43
45
tree = ET .parse (tracker_filename )
44
46
except FileNotFoundError as e :
47
+ # pylint: disable-next=raise-missing-from,broad-exception-raised
45
48
raise Exception (f"{ e .strerror } : '{ e .filename } '" )
46
49
except ET .ParseError as e :
50
+ # pylint: disable-next=raise-missing-from,broad-exception-raised
47
51
raise Exception (f"Error parsing '{ tracker_filename } ': { e .msg } " )
48
52
49
53
for tracker in tree .getroot ():
@@ -53,11 +57,13 @@ def __init__(self, tracker_filename: str = None):
53
57
name = tracker .find ("name" ).text
54
58
regex = tracker .find ("regex" ).text
55
59
except AttributeError :
60
+ # pylint: disable-next=raise-missing-from,broad-exception-raised
56
61
raise Exception (
57
62
f"Error parsing '{ tracker_filename } ': not a tracker XML file"
58
63
)
59
64
trackers [name ] = regex
60
65
66
+ # pylint: disable-next=logging-fstring-interpolation
61
67
logging .info (f"Found { len (trackers .keys ())} tracker definition(s)" )
62
68
63
69
self .trackers = trackers
@@ -145,10 +151,13 @@ def get_message_header(self) -> str:
145
151
if os .getenv ("GITHUB_ACTION" ):
146
152
msg = "::error" if self .severe else "::warning"
147
153
if self .file :
154
+ # pylint: disable-next=consider-using-f-string
148
155
msg += " file={}" .format (self .file )
149
156
if self .line :
157
+ # pylint: disable-next=consider-using-f-string
150
158
msg += ",line={}" .format (self .line )
151
159
if self .end_line :
160
+ # pylint: disable-next=consider-using-f-string
152
161
msg += ",endLine={}" .format (self .end_line )
153
162
154
163
return msg + "::"
@@ -214,6 +223,7 @@ def __init__(
214
223
regex_rules : RegexRules ,
215
224
):
216
225
if pr_number and not os .getenv ("GH_TOKEN" ):
226
+ # pylint: disable-next=broad-exception-raised
217
227
raise Exception (
218
228
"GitHub API key not set. Please set it in 'GH_TOKEN' environment variable."
219
229
)
@@ -239,14 +249,18 @@ def get_bugzilla_api(self) -> bugzilla.Bugzilla:
239
249
240
250
uri = os .getenv ("BUGZILLA_URI" , DEFAULT_BUGZILLA_URI )
241
251
try :
252
+ # pylint: disable-next=logging-fstring-interpolation
242
253
logging .info (f"Initializing Bugzilla API at '{ uri } '" )
243
254
bzapi = bugzilla .Bugzilla (uri , api_key = api_key )
255
+ # pylint: disable-next=unused-variable
244
256
except requests .exceptions .ConnectionError as e :
257
+ # pylint: disable-next=raise-missing-from
245
258
raise ConnectionError (f"Cannot connect to the Bugzilla API at '{ uri } '" )
246
259
247
260
try :
248
261
assert bzapi .logged_in , f"Cannot log into the Bugzilla API at '{ uri } '"
249
262
except xmlrpc .client .Fault as f :
263
+ # pylint: disable-next=raise-missing-from,broad-exception-raised
250
264
raise Exception (
251
265
f"Cannot log in to the Bugzilla API at '{ uri } ': { f .faultString } "
252
266
)
@@ -277,12 +291,16 @@ def get_modified_files_for_pkg(
277
291
pkg_files .append (f )
278
292
279
293
if logging .getLogger ().isEnabledFor (logging .DEBUG ):
294
+ # pylint: disable-next=use-implicit-booleaness-not-len
280
295
if len (pkg_files ):
296
+ # pylint: disable-next=logging-not-lazy
281
297
logging .debug (
282
298
f"Found { len (pkg_files )} file(s) in package { pkg_name } :\n "
283
299
+ "\n " .join (pkg_files )
284
300
)
301
+ # pylint: disable-next=use-implicit-booleaness-not-len
285
302
if len (pkg_chlogs ):
303
+ # pylint: disable-next=logging-not-lazy
286
304
logging .debug (
287
305
f"Found { len (pkg_chlogs )} changelog(s) in package { pkg_name } :\n "
288
306
+ "\n " .join (pkg_chlogs )
@@ -312,8 +330,10 @@ def get_pkg_index(self, files: list[str]) -> dict[str, list[str]]:
312
330
313
331
try :
314
332
pkg_names = os .listdir (packages_dir )
333
+ # pylint: disable-next=logging-fstring-interpolation
315
334
logging .debug (f"Found { len (pkg_names )} package(s) in 'rel-eng/packages'" )
316
335
except FileNotFoundError :
336
+ # pylint: disable-next=raise-missing-from,broad-exception-raised
317
337
raise Exception (
318
338
"Not an Uyuni repository. Consider using '--uyuni-dir' option."
319
339
)
@@ -330,6 +350,7 @@ def get_pkg_index(self, files: list[str]) -> dict[str, list[str]]:
330
350
.rstrip ()
331
351
.split (maxsplit = 1 )[1 ]
332
352
)
353
+ # pylint: disable-next=logging-fstring-interpolation
333
354
logging .debug (f"Indexing package { pkg_name } in path { pkg_path } " )
334
355
335
356
# Get the list of modified files and changelog files for the package
@@ -375,6 +396,7 @@ def get_pr_trackers(
375
396
assert pr_number
376
397
assert git_repo
377
398
399
+ # pylint: disable-next=logging-fstring-interpolation
378
400
logging .info (f"Requesting information for PR#{ pr_number } at '{ git_repo } '" )
379
401
380
402
pr_path = f"repos/{ git_repo } /pulls/{ pr_number } "
@@ -383,10 +405,12 @@ def get_pr_trackers(
383
405
)
384
406
title_and_commits = stream .read ()
385
407
if stream .close ():
408
+ # pylint: disable-next=broad-exception-raised
386
409
raise Exception (
387
410
"An error occurred when getting the PR information from the GitHub API."
388
411
)
389
412
413
+ # pylint: disable-next=logging-fstring-interpolation
390
414
logging .debug (
391
415
f"Retrieved title and commit messages for PR#{ pr_number } :\n { title_and_commits } "
392
416
)
@@ -409,6 +433,7 @@ def validate_chlog_entry(
409
433
# Test spacing (ignored in version strings)
410
434
# Test to check if a match overlaps with a version string
411
435
overlaps = (
436
+ # pylint: disable-next=unnecessary-lambda-assignment
412
437
lambda ver_str , match : ver_str .start () <= match .start ()
413
438
and ver_str .end () >= match .end ()
414
439
)
@@ -455,12 +480,14 @@ def get_entry_obj(self, buffer: list[str], file: str, line_no: int) -> Entry:
455
480
def validate_chlog_file (self , file : str ) -> tuple [list [Issue ], list [Entry ]]:
456
481
"""Validate a single changelog file"""
457
482
483
+ # pylint: disable-next=logging-fstring-interpolation
458
484
logging .debug (f"Validating changelog file: { file } " )
459
485
file_path = os .path .join (self .uyuni_root , file )
460
486
461
487
if os .path .getsize (file_path ) == 0 :
462
488
return ([Issue (IssueType .EMPTY_CHLOG , file )], [])
463
489
490
+ # pylint: disable-next=unspecified-encoding
464
491
f = open (file_path , "r" )
465
492
issues = []
466
493
entries = []
@@ -520,6 +547,7 @@ def validate_chlog_file(self, file: str) -> tuple[list[Issue], list[Entry]]:
520
547
# EOF
521
548
if entry_buf :
522
549
# Validate and append the last entry
550
+ # pylint: disable-next=undefined-loop-variable
523
551
entry = self .get_entry_obj (entry_buf , file , line_no + 1 )
524
552
issues .extend (self .validate_chlog_entry (entry , entries ))
525
553
entries .append (entry )
@@ -532,9 +560,11 @@ def validate_bsc(self, entry: Entry) -> list[Issue]:
532
560
issues = []
533
561
# 'bnc' is the name of the tracker as defined in the trackers file
534
562
if "bnc" in entry .trackers :
563
+ # pylint: disable-next=unused-variable
535
564
for tracker , bug_id in entry .trackers ["bnc" ]:
536
565
try :
537
566
bug = self .bzapi .getbug (bug_id )
567
+ # pylint: disable-next=logging-fstring-interpolation
538
568
logging .debug (f"Bug #{ bug_id } belongs to product '{ bug .product } '" )
539
569
540
570
if not bug .product .startswith ("SUSE Manager" ):
@@ -629,6 +659,7 @@ def validate_trackers(self, entries: list[Entry]) -> list[Issue]:
629
659
# changelog entry are also mentioned in the PR
630
660
if pr_validation :
631
661
for t in trackers :
662
+ # pylint: disable-next=possibly-used-before-assignment
632
663
if kind not in pr_trackers or t not in pr_trackers [kind ]:
633
664
# Tracker not mentioned in the PR
634
665
issues .append (
@@ -763,14 +794,18 @@ def main():
763
794
764
795
try :
765
796
logging .debug ("Initializing the validator" )
797
+ # pylint: disable-next=invalid-name
766
798
regexRules = RegexRules (args .tracker_file )
767
799
validator = ChangelogValidator (
768
800
args .uyuni_dir , args .git_repo , args .pr_number , args .line_length , regexRules
769
801
)
770
802
803
+ # pylint: disable-next=logging-fstring-interpolation
771
804
logging .debug (f"Validating { len (args .files )} file(s)" )
772
805
issues = validator .validate (args .files )
806
+ # pylint: disable-next=logging-fstring-interpolation
773
807
logging .debug (f"Validation finished with { len (issues )} issue(s)" )
808
+ # pylint: disable-next=broad-exception-caught
774
809
except Exception as e :
775
810
print (e , file = sys .stderr )
776
811
return 2
@@ -782,6 +817,7 @@ def main():
782
817
return 0
783
818
784
819
logging .info (
820
+ # pylint: disable-next=logging-format-interpolation,consider-using-f-string
785
821
"Changelog test {} with {} issue(s):" .format (
786
822
"failed" if is_fail else "passed" , len (issues )
787
823
)
@@ -794,6 +830,7 @@ def main():
794
830
if is_fail :
795
831
print ()
796
832
print (
833
+ # pylint: disable-next=consider-using-f-string
797
834
"{}See https://github.com/uyuni-project/uyuni/wiki/Contributing for a guide to writing changelogs." .format (
798
835
"::notice::" if is_gh_action else ""
799
836
)
0 commit comments