2727import argparse
2828import re
2929import unicodedata
30+ import logging
3031from pathlib import Path
3132from importlib .metadata import version , PackageNotFoundError
3233
@@ -167,7 +168,7 @@ def spell_check_words(spell_checker: SpellChecker, words: list[str]):
167168
168169
169170def find_misspellings (
170- spell : SpellChecker , line : str , verbose : bool = False
171+ spell : SpellChecker , line : str , logger : logging . Logger
171172) -> list [str ]:
172173 """Find misspellings in a line of text."""
173174
@@ -177,23 +178,16 @@ def find_misspellings(
177178
178179 for word in words :
179180 if not (word .lower () in spell or word in spell ):
180- print (f"Misspelled word: { word } \n " if verbose else "" , end = " " )
181+ logger . info (f"Misspelled word: { word } " )
181182 mistakes .append (word )
182183 return mistakes
183184
184185
185- def remove_contractions (word : str , verbose : bool = False ):
186+ def remove_contractions (word : str , logger : logging . Logger ):
186187 """Remove contractions from the word."""
187188 for contraction in CONTRACTIONS :
188189 if word .endswith (contraction ):
189- print (
190- (
191- f" Contraction: { word } -> { word [: - len (contraction )]} \n "
192- if verbose
193- else ""
194- ),
195- end = "" ,
196- )
190+ logger .info (f"Contraction: { word } -> { word [: - len (contraction )]} " )
197191 return word [: - len (contraction )]
198192 return word
199193
@@ -209,25 +203,25 @@ def remove_prefix(word: str, prefixes: list[str]):
209203def spell_check_comment (
210204 spell : SpellChecker ,
211205 c : comment_parser .common .Comment ,
206+ logger : logging .Logger ,
212207 prefixes : list [str ] = None ,
213- output_lvl = 2 ,
214208) -> list [str ]:
215209 """Check comment and return list of identified issues if any."""
216210
217- print (f"Line { c .line_number ()} : { c } \n " if output_lvl > 1 else "" , end = " " )
211+ logger . info (f"Line { c .line_number ()} : { c } " )
218212
219213 line = c .text ()
220214 if "https://" in line or "http://" in line :
221215 line = url_remove .remove_urls (line )
222- print (f" Removed URLs: { line } \n " if output_lvl > 1 else "" , end = " " )
216+ logger . debug (f" Removed URLs: { line } " )
223217
224- bad_words = find_misspellings (spell , line , verbose = output_lvl > 1 )
218+ bad_words = find_misspellings (spell , line , logger )
225219
226220 mistakes = []
227221 for error_word in bad_words :
228- print (f" Error: { error_word } \n " if output_lvl > 1 else "" , end = " " )
222+ logger . debug (f" Error: { error_word } " )
229223
230- error_word = remove_contractions (error_word , output_lvl > 1 )
224+ error_word = remove_contractions (error_word , logger )
231225
232226 prefixes = prefixes or []
233227 error_word = remove_prefix (error_word , prefixes )
@@ -237,14 +231,9 @@ def spell_check_comment(
237231
238232 # Try splitting camel case words and checking each sub-word
239233 sub_words = split_camel_case (error_word )
240- print (
241- (
242- f" Trying splitting camel case word: { error_word } \n "
243- + f" Sub-words: { sub_words } \n "
244- if output_lvl > 1
245- else ""
246- ),
247- end = "" ,
234+ logger .debug (
235+ f" Trying splitting camel case word: { error_word } \n "
236+ + f" Sub-words: { sub_words } \n "
248237 )
249238
250239 if len (sub_words ) > 1 and spell_check_words (spell , sub_words ):
@@ -257,16 +246,18 @@ def spell_check_comment(
257246
258247
259248def spell_check_file (
260- filename , spell_checker , mime_type = "" , output_lvl = 1 , prefixes = None
249+ filename : str ,
250+ spell_checker : SpellChecker ,
251+ logger : logging .Logger ,
252+ mime_type : str = "" ,
253+ prefixes = None ,
261254):
262255 """Check spelling in ``filename``."""
263256
264257 if len (mime_type ) == 0 :
265258 mime_type = get_mime_type (filename )
266259
267- print (
268- f"spell_check_file: { filename } , { mime_type } \n " if output_lvl > 0 else "" , end = ""
269- )
260+ logger .info (f"spell_check_file: { filename } , { mime_type } " )
270261
271262 # Returns a list of comment_parser.parsers.common.Comments
272263 if mime_type == "text/plain" :
@@ -275,37 +266,32 @@ def spell_check_file(
275266 try :
276267 clist = comment_parser .extract_comments (filename , mime = mime_type )
277268 except TypeError :
278- print (f"Parser failed, skipping file { filename } " )
269+ logger . error (f"Parser failed, skipping file { filename } " )
279270 return []
280271
281272 bad_words = []
282273 line_count = 0
283274
284275 for c in clist :
285- mistakes = spell_check_comment (
286- spell_checker , c , prefixes = prefixes , output_lvl = output_lvl
287- )
276+ mistakes = spell_check_comment (spell_checker , c , logger , prefixes = prefixes )
288277 if len (mistakes ) > 0 :
289- if output_lvl > 0 :
290- print (f"\n Line number { c .line_number ()} " )
291- if output_lvl > 0 :
292- print (c .text ())
278+ logger .info (f"\n Line number { c .line_number ()} " )
279+ logger .info (c .text ())
293280 for m in mistakes :
294- print (f" { m } " if output_lvl >= 0 else " " )
281+ logger . info (f" { m } " )
295282 bad_words .append ([m , filename , c .line_number ()])
296283 line_count = line_count + 1
297284
298285 bad_words = sorted (bad_words )
299286
300- if output_lvl > 1 :
301- print ("\n Results" )
302- for x in bad_words :
303- print (x )
287+ logger .info ("Results" )
288+ for x in bad_words :
289+ logger .info (x )
304290
305291 return bad_words , line_count
306292
307293
308- def exclude_check (name , exclude_list ):
294+ def exclude_check (name : str , exclude_list : list [ str ] = None ):
309295 """Return True if ``name`` matches any of the regular expressions listed in
310296 ``exclude_list``."""
311297 if exclude_list is None :
@@ -317,7 +303,7 @@ def exclude_check(name, exclude_list):
317303 return False
318304
319305
320- def skip_check (name , skip_list ):
306+ def skip_check (name : str , skip_list : list [ str ] = None ):
321307 """Return True if ``name`` matches any of the glob pattern listed in
322308 ``skip_list``."""
323309 if skip_list is None :
@@ -451,34 +437,15 @@ def parse_args():
451437 return args
452438
453439
454- def add_dict (enchant_dict , filename , verbose = False ):
455- """Update ``enchant_dict`` spell checking dictionary with the words listed
456- in ``filename`` (one word per line)."""
457- print (f"Additional dictionary: { filename } " if verbose else "" , end = "" )
458-
459- with open (filename , encoding = "utf-8" ) as f :
460- lines = f .read ().splitlines ()
461-
462- # You better not have more than 1 word in a line
463- for wrd in lines :
464- if not wrd .replace ("'" , "" ).isidentifier ():
465- print (
466- "Warning: adding word with non-alphanumeric characters to dictionary:" ,
467- wrd ,
468- )
469- if not enchant_dict .check (wrd ):
470- enchant_dict .add (wrd )
471-
472-
473- def build_dictionary_list (args ):
440+ def build_dictionary_list (args , logger ):
474441 """build a list of dictionaries to use for spell checking."""
475442 dict_list = []
476443 initial_dct = Path (__file__ ).parent / "additional_dictionary.txt"
477444
478445 if initial_dct .exists ():
479446 dict_list .append (initial_dct )
480447 else :
481- print ( "Warning: initial dictionary not found." , initial_dct )
448+ logger . warning ( f"Initial dictionary not found: { initial_dct } " )
482449
483450 if not isinstance (args .dict , list ):
484451 return dict_list
@@ -491,24 +458,17 @@ def build_dictionary_list(args):
491458 return dict_list
492459
493460
494- def add_bibtex_words (spell , bibtex_files , verbose = False ):
461+ def add_bibtex_words (
462+ spell : SpellChecker , bibtex_files : list = None , logger : logging .Logger = None
463+ ):
495464 """Add words from bibtex files to the spell checker."""
496- for bibtex_file in bibtex_files :
497- print (f"Loading bibtex file: { bibtex_file } \n " if verbose else "" , end = "" )
498- bibtex_loader .add_bibtex (spell , bibtex_file , verbose = verbose )
499465
466+ if list is None :
467+ return
500468
501- def get_output_lvl (args ):
502- """Set the amount of debugging messages to print."""
503- output_lvl = 1
504- if args .brief :
505- output_lvl = 0
506- else :
507- if args .verbose :
508- output_lvl = 2
509- if args .miss :
510- output_lvl = - 1
511- return output_lvl
469+ for bibtex_file in bibtex_files :
470+ logger .info (f"Loading bibtex file: { bibtex_file } " )
471+ bibtex_loader .add_bibtex (spell , bibtex_file , logger )
512472
513473
514474def output_results (args , bad_words ):
@@ -539,18 +499,49 @@ def output_results(args, bad_words):
539499 print (f"\n { len (bad_words )} misspellings found" )
540500
541501
502+ def setup_logger (name , args ):
503+ """Sets up a logger that outputs to the console."""
504+
505+ level = logging .INFO
506+ if args .verbose :
507+ level = logging .DEBUG
508+ if args .miss :
509+ level = logging .ERROR
510+ if args .brief :
511+ level = logging .WARNING
512+
513+ logger = logging .getLogger (name )
514+ logger .setLevel (level )
515+
516+ # Create a console handler
517+ ch = logging .StreamHandler ()
518+ ch .setLevel (level )
519+
520+ # Create a formatter
521+ formatter = logging .Formatter (
522+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
523+ )
524+
525+ # Add formatter to ch
526+ ch .setFormatter (formatter )
527+
528+ # Add ch to logger
529+ logger .addHandler (ch )
530+
531+ return logger
532+
533+
542534def main ():
543535 """comment_spell_check main function."""
544536 args = parse_args ()
537+ logger = setup_logger ("comment_spell_check" , args )
545538
546- output_lvl = get_output_lvl (args )
539+ dict_list = build_dictionary_list (args , logger )
547540
548- dict_list = build_dictionary_list (args )
549-
550- spell = create_checker .create_checker (dict_list , output_lvl > 1 )
541+ spell = create_checker .create_checker (dict_list , logger )
551542
552543 if args .bibtex :
553- add_bibtex_words (spell , args .bibtex , verbose = output_lvl > 1 )
544+ add_bibtex_words (spell , args .bibtex , logger )
554545
555546 file_list = []
556547 if len (args .filenames ):
@@ -564,23 +555,14 @@ def main():
564555
565556 suffixes = [* set (args .suffix )] # remove duplicates
566557
567- print (
568- (
569- f"Prefixes: { prefixes } \n Suffixes: { suffixes } \n "
570- if any ([args .brief , output_lvl >= 0 ])
571- else ""
572- ),
573- end = "" ,
574- )
558+ logger .info ("Prefixes: %s\n Suffixes: %s" , prefixes , suffixes )
575559
576- file_count = 0
577- line_count = 0
560+ counts = [0 , 0 ]
578561
579562 #
580563 # Spell check the files
581564 #
582565 for f in file_list :
583- print (f"\n Checking { f } \n " if not args .miss else "" , end = "" )
584566
585567 # If f is a directory, recursively check for files in it.
586568 if os .path .isdir (f ):
@@ -589,54 +571,47 @@ def main():
589571 for s in suffixes :
590572 dir_entries = dir_entries + glob .glob (f + "/**/*" + s , recursive = True )
591573
592- print (dir_entries if output_lvl > 0 else "" , end = "" )
574+ logger . info (dir_entries )
593575
594576 # spell check the files found in f
595577 for x in dir_entries :
596578 if exclude_check (x , args .exclude ) or skip_check (x , args .skip ):
597- print ( f" \n Excluding { x } \n " if not args . miss else "" , end = "" )
579+ logger . info ( "Excluding %s" , x )
598580 continue
599581
600- print ( f" \n Checking { x } \n " if not args . miss else "" , end = "" )
582+ logger . info ( "Checking %s" , x )
601583 result , lc = spell_check_file (
602584 x ,
603585 spell ,
586+ logger ,
604587 args .mime_type ,
605- output_lvl = output_lvl ,
606588 prefixes = prefixes ,
607589 )
608590 bad_words = sorted (bad_words + result )
609- file_count = file_count + 1
610- line_count = line_count + lc
591+ counts [ 0 ] = counts [ 0 ] + 1
592+ counts [ 1 ] = counts [ 1 ] + lc
611593
612594 else :
613595 # f is a file
614596 if exclude_check (f , args .exclude ) or skip_check (f , args .skip ):
615- print ( f" \n Excluding { x } \n " if not args . miss else "" , end = "" )
597+ logger . info ( "Excluding %s" , f )
616598 continue
617599
618600 # f is a file, so spell check it
619601 result , lc = spell_check_file (
620602 f ,
621603 spell ,
604+ logger ,
622605 args .mime_type ,
623- output_lvl = output_lvl ,
624606 prefixes = prefixes ,
625607 )
626608 bad_words = sorted (bad_words + result )
627- file_count = file_count + 1
628- line_count = line_count + lc
609+ counts [ 0 ] = counts [ 0 ] + 1
610+ counts [ 1 ] = counts [ 1 ] + lc
629611
630612 output_results (args , bad_words )
631613
632- print (
633- (
634- f"{ file_count } files checked, { line_count } lines checked\n "
635- if not args .miss
636- else ""
637- ),
638- end = "" ,
639- )
614+ logger .info ("%s files checked, %s lines checked" , counts [0 ], counts [1 ])
640615
641616 sys .exit (len (bad_words ))
642617
0 commit comments