@@ -243,8 +243,52 @@ def log_handler(self, msg):
243243 self .check_response (response , "/update_workflow_status" )
244244
245245
246- class DefaultFormatter (_logging .Formatter ):
246+ # Helper functions for logging
247+ def format_dict (dict_like , omit_keys = None , omit_values = None ):
248+ from snakemake .io import Namedlist
249+
250+ omit_keys = omit_keys or []
251+ omit_values = omit_values or []
252+
253+ if isinstance (dict_like , Namedlist ):
254+ items = dict_like .items ()
255+ elif isinstance (dict_like , dict ):
256+ items = dict_like .items ()
257+ else :
258+ raise ValueError (
259+ "bug: format_dict applied to something neither a dict nor a Namedlist"
260+ )
261+ return ", " .join (
262+ f"{ name } ={ value } "
263+ for name , value in items
264+ if name not in omit_keys and value not in omit_values
265+ )
266+
267+
268+ format_resources = partial (format_dict , omit_keys = {"_cores" , "_nodes" })
269+ format_wildcards = format_dict
270+
247271
272+ def format_resource_names (resources , omit_resources = "_cores _nodes" .split ()):
273+ return ", " .join (name for name in resources if name not in omit_resources )
274+
275+
276+ def format_percentage (done , total ):
277+ """Format percentage from given fraction while avoiding superfluous precision."""
278+ if done == total :
279+ return "100%"
280+ if done == 0 :
281+ return "0%"
282+ precision = 0
283+ fraction = done / total
284+ fmt_precision = "{{:.{}%}}" .format
285+ fmt = lambda fraction : fmt_precision (precision ).format (fraction )
286+ while fmt (fraction ) == "100%" or fmt (fraction ) == "0%" :
287+ precision += 1
288+ return fmt (fraction )
289+
290+
291+ class DefaultFormatter (_logging .Formatter ):
248292 def __init__ (self , printreason = False , show_failed_logs = False , printshellcmds = False ):
249293 self .printreason = printreason
250294 self .show_failed_logs = show_failed_logs
@@ -256,7 +300,9 @@ def format(self, record):
256300 Override format method to format Snakemake-specific log messages.
257301 """
258302 msg = record .msg
259- level = msg .get ("level" , "INFO" ) # Default to "INFO" if level not in message
303+ level = msg .get (
304+ "level" , "INFO"
305+ ).lower () # Default to "INFO" if level not in message
260306
261307 # Call specific handlers based on the log level
262308 if level == "info" :
@@ -360,7 +406,7 @@ def format_progress(self, msg):
360406 """Format for progress log."""
361407 done = msg ["done" ]
362408 total = msg ["total" ]
363- return f"{ done } of { total } steps ({ self . _format_percentage (done , total )} ) done"
409+ return f"{ done } of { total } steps ({ format_percentage (done , total )} ) done"
364410
365411 def format_job_finished (self , msg ):
366412 """Format for job_finished log."""
@@ -501,20 +547,6 @@ def timestamp(self):
501547 """Helper method to format the timestamp."""
502548 return f"[{ time .asctime ()} ]"
503549
504- def _format_percentage (self , done , total ):
505- """Helper method to format percentage."""
506- if done == total :
507- return "100%"
508- if done == 0 :
509- return "0%"
510- precision = 0
511- fraction = done / total
512- fmt_precision = "{{:.{}%}}" .format
513- fmt = lambda fraction : fmt_precision (precision ).format (fraction )
514- while fmt (fraction ) == "100%" or fmt (fraction ) == "0%" :
515- precision += 1
516- return fmt (fraction )
517-
518550
519551def show_logs (logs ):
520552 """Helper method to show logs."""
@@ -540,50 +572,6 @@ def show_logs(logs):
540572 yield "=" * max_len
541573
542574
543- def format_dict (dict_like , omit_keys = None , omit_values = None ):
544- from snakemake .io import Namedlist
545-
546- omit_keys = omit_keys or []
547- omit_values = omit_values or []
548-
549- if isinstance (dict_like , Namedlist ):
550- items = dict_like .items ()
551- elif isinstance (dict_like , dict ):
552- items = dict_like .items ()
553- else :
554- raise ValueError (
555- "bug: format_dict applied to something neither a dict nor a Namedlist"
556- )
557- return ", " .join (
558- f"{ name } ={ value } "
559- for name , value in items
560- if name not in omit_keys and value not in omit_values
561- )
562-
563-
564- format_resources = partial (format_dict , omit_keys = {"_cores" , "_nodes" })
565- format_wildcards = format_dict
566-
567-
568- def format_resource_names (resources , omit_resources = "_cores _nodes" .split ()):
569- return ", " .join (name for name in resources if name not in omit_resources )
570-
571-
572- def format_percentage (done , total ):
573- """Format percentage from given fraction while avoiding superfluous precision."""
574- if done == total :
575- return "100%"
576- if done == 0 :
577- return "0%"
578- precision = 0
579- fraction = done / total
580- fmt_precision = "{{:.{}%}}" .format
581- fmt = lambda fraction : fmt_precision (precision ).format (fraction )
582- while fmt (fraction ) == "100%" or fmt (fraction ) == "0%" :
583- precision += 1
584- return fmt (fraction )
585-
586-
587575class DefaultFilter :
588576 def __init__ (
589577 self ,
@@ -688,7 +676,6 @@ def emit(self, record):
688676 """
689677 with self ._output_lock :
690678 try :
691-
692679 level = record .msg .get ("level" , "INFO" ).lower ()
693680
694681 if level == "job_info" :
@@ -736,20 +723,14 @@ def decorate(self, record, message):
736723
737724
738725class Logger :
739-
740726 def __init__ (self ):
741727 from snakemake_interface_executor_plugins .settings import ExecMode
742728
743729 self .logger = _logging .getLogger (__name__ )
744730 self .stream_handler = None
745- self .printshellcmds = False
746- self .printreason = False
747731 self .debug_dag = False
748- self .quiet = set ()
749732 self .logfile = None
750- self .last_msg_was_job_info = False
751733 self .mode = ExecMode .DEFAULT
752- self .show_failed_logs = False
753734 self .logfile_handler = None
754735 self .dryrun = False
755736 self .level = 0
@@ -774,6 +755,7 @@ def setup_logfile(self):
774755 self .logfile_handler .setFormatter (self .default_formatter )
775756 self .logfile_handler .addFilter (self .default_filter )
776757 self .logfile_handler .setLevel (self .level )
758+ self .logfile_handler .name = "DefaultLogFileHandler"
777759 self .logger .addHandler (self .logfile_handler )
778760
779761 def cleanup (self ):
@@ -825,9 +807,7 @@ def handler(self, msg):
825807 "resources_info" : _logging .WARNING ,
826808 "host" : _logging .INFO ,
827809 "job_stats" : _logging .WARNING ,
828- }.get (
829- custom_level , _logging .INFO
830- ) # Default to INFO if not recognized
810+ }.get (custom_level , _logging .INFO ) # Default to INFO if not recognized
831811
832812 record = self .logger .makeRecord (
833813 name = self .logger .name ,
@@ -922,6 +902,7 @@ def get_logfile(self):
922902
923903logger = Logger ()
924904
905+
925906def setup_logger (
926907 handler = [],
927908 quiet = False ,
@@ -936,18 +917,20 @@ def setup_logger(
936917 dryrun = False ,
937918):
938919 from snakemake .settings .types import Quietness
920+ from snakemake_interface_executor_plugins .settings import ExecMode
939921
940922 if mode is None :
941923 mode = get_default_exec_mode ()
942924
943925 if quiet is None :
944- # not quiet at all
945926 quiet = set ()
927+
946928 elif isinstance (quiet , bool ):
947929 if quiet :
948930 quiet = {Quietness .PROGRESS , Quietness .RULES }
949931 else :
950932 quiet = set ()
933+
951934 elif not isinstance (quiet , set ):
952935 raise ValueError (
953936 "Unsupported value provided for quiet mode (either bool, None or set allowed)."
@@ -958,6 +941,7 @@ def setup_logger(
958941 stream = sys .stdout if stdout else sys .stderr ,
959942 mode = mode ,
960943 )
944+ stream_handler .name = "DefaultStreamHandler"
961945 formatter = DefaultFormatter (
962946 printreason = printreason ,
963947 show_failed_logs = show_failed_logs ,
@@ -966,8 +950,13 @@ def setup_logger(
966950 filter = DefaultFilter (quiet = quiet , debug_dag = debug_dag )
967951 logger .default_formatter = formatter
968952 logger .default_filter = filter
969- logger .set_stream_handler (stream_handler )
970- logger .set_level (_logging .DEBUG if debug else _logging .INFO )
953+
954+ if mode == ExecMode .SUBPROCESS :
955+ logger .set_stream_handler (_logging .NullHandler ())
956+ else :
957+ logger .set_stream_handler (stream_handler )
958+ logger .set_level (_logging .DEBUG if debug else _logging .INFO )
959+
971960 logger .quiet = quiet
972961 logger .printshellcmds = printshellcmds
973962 logger .printreason = printreason
0 commit comments