77"""
88
99import argparse
10+ import enum
1011import json
12+ import logging
1113import os
1214import sys
1315import time
2123from . import lib50
2224
2325
26+ LOGGER = logging .getLogger (__name__ )
27+
28+
29+ class LogLevel (enum .IntEnum ):
30+ """Log levels aligned with check50."""
31+ DEBUG = logging .DEBUG
32+ INFO = logging .INFO
33+ WARNING = logging .WARNING
34+ ERROR = logging .ERROR
35+
36+
37+ class ColoredFormatter (logging .Formatter ):
38+ """Colored log formatter aligned with check50."""
39+ COLORS = {
40+ "ERROR" : "red" ,
41+ "WARNING" : "yellow" ,
42+ "DEBUG" : "cyan" ,
43+ "INFO" : "magenta" ,
44+ }
45+
46+ def __init__ (self , fmt , use_color = True ):
47+ super ().__init__ (fmt = fmt )
48+ self .use_color = use_color
49+
50+ def format (self , record ):
51+ msg = super ().format (record )
52+ return msg if not self .use_color else termcolor .colored (
53+ msg , getattr (record , "color" , self .COLORS .get (record .levelname ))
54+ )
55+
56+
57+ def setup_logging (level ):
58+ """
59+ Setup logging system aligned with check50.
60+
61+ Args:
62+ level: Log level string (debug, info, warning, error)
63+ """
64+ for logger in (logging .getLogger ("lib50" ), LOGGER ):
65+ logger .setLevel (level .upper ())
66+ handler = logging .StreamHandler (sys .stderr )
67+ handler .setFormatter (
68+ ColoredFormatter ("(%(levelname)s) %(message)s" , use_color = sys .stderr .isatty ())
69+ )
70+ logger .addHandler (handler )
71+
72+
2473def main ():
2574 """Main entry point for bootcs CLI."""
2675 parser = argparse .ArgumentParser (
@@ -36,7 +85,14 @@ def main():
3685 check_parser .add_argument ("slug" , help = "The check slug (e.g., cs50/mario-less)" )
3786 check_parser .add_argument ("-o" , "--output" , choices = ["ansi" , "json" ], default = "ansi" ,
3887 help = "Output format (default: ansi)" )
39- check_parser .add_argument ("--log" , action = "store_true" , help = "Show detailed log" )
88+ check_parser .add_argument ("--log" , action = "store_true" , help = "Show detailed log (deprecated, use --log-level info)" )
89+ check_parser .add_argument ("--log-level" ,
90+ action = "store" ,
91+ choices = [level .name .lower () for level in LogLevel ],
92+ type = str .lower ,
93+ help = "warning: displays usage warnings.\n "
94+ "info: adds all commands run and log messages.\n "
95+ "debug: adds output of all commands run." )
4096 check_parser .add_argument ("--target" , action = "append" , metavar = "check" ,
4197 help = "Run only the specified check(s)" )
4298 check_parser .add_argument ("-L" , "--language" ,
@@ -175,6 +231,21 @@ def run_check(args):
175231 slug = args .slug
176232 force_update = getattr (args , 'update' , False )
177233
234+ # Dev mode implies log level "info" if not overwritten (like check50)
235+ if args .dev :
236+ if not args .log_level :
237+ args .log_level = "info"
238+
239+ # Setup logging
240+ if not args .log_level :
241+ args .log_level = "warning"
242+ setup_logging (args .log_level )
243+
244+ # Legacy --log flag support
245+ if args .log and not args .log_level :
246+ args .log_level = "info"
247+ setup_logging (args .log_level )
248+
178249 # Parse slug (MVP: only 2-part format)
179250 course_slug , stage_slug = parse_slug (slug )
180251
@@ -195,6 +266,12 @@ def run_check(args):
195266 termcolor .cprint ("Use --dev to specify a checks directory for development." , "yellow" , file = sys .stderr )
196267 return 1
197268
269+ # Debug info in dev mode
270+ if args .dev :
271+ LOGGER .info (f"Dev mode enabled" )
272+ LOGGER .info (f"Check directory: { check_dir } " )
273+ LOGGER .info (f"Language: { language } " )
274+
198275 # Set internal state
199276 internal .check_dir = check_dir
200277 internal .slug = slug
@@ -211,6 +288,11 @@ def run_check(args):
211288 termcolor .cprint (f"Error: Checks file '{ config ['checks' ]} ' not found in { check_dir } " , "red" , file = sys .stderr )
212289 return 1
213290
291+ # Dev mode: show config details
292+ if args .dev :
293+ LOGGER .info (f"Config file: { config .get ('checks' , '__init__.py' )} " )
294+ LOGGER .info (f"Files pattern: { config .get ('files' , [])} " )
295+
214296 # Get list of files to include
215297 cwd = Path .cwd ()
216298 try :
0 commit comments