1- """fancylog
2- ===============
3-
4- Wrapper around the standard logging module, with additional information.
5-
6- """
1+ """Wrapper around the standard logging module, with additional information."""
72
83import contextlib
94import logging
@@ -39,32 +34,51 @@ def start_logging(
3934 timestamp = True ,
4035 logger_name = None ,
4136):
42- """Prepares the log file, and then begins logging.
43-
44- :param output_dir: Directory to save the log file
45- :param package: What python package are we logging?
46- :param variables: List of objects whose attributes we want to log at the
47- beginning of the log file
48- :param verbose: If true, all info (i.e. 'DEBUG') is printed to
49- console. Else, only 'INFO' and above. Default: True
50- :param file_log_level: What level of logging to print to file.
51- Default: 'DEBUG'
52- :param filename: Filename for log file. Default: 'package.__name__'
53- :param log_header: Header for the log file, if the args are written'
54- :param multiprocessing_aware: Log from multiple processes. Default: True
55- :param write_header: Write a header for the log file. Default: True
56- :param write_git: Write information about the git repository.
57- Default: True
58- :param write_cli_args: Log the command-line arguments. Default: True
59- :param write_variables: Write the attributes of selected objects.
60- Default: True
61- :param log_to_file: If True, write a log file, otherwise just print to
62- terminal.
63- :param log_to_console: Print logs to the console or not: Default: True
64- :param timestamp: If True, add a timestamp to the filename
65- :param logger_name: If None, logger uses default logger. Otherwise,
66- logger name is set to `logger_name`.
67- :return: Path to the logging file#
37+ """Prepare the log file, and then begin logging.
38+
39+ Parameters
40+ ----------
41+ output_dir
42+ Directory to save the log file.
43+ package
44+ What Python package are we logging?
45+ variables
46+ List of objects whose attributes we want to log at the
47+ beginning of the log file.
48+ verbose
49+ If True, all info (i.e. 'DEBUG') is printed to console;
50+ else only 'INFO' and above. Default: True
51+ file_log_level
52+ What level of logging to print to file. Default: 'DEBUG'
53+ filename
54+ Filename for log file. Default: 'package.__name__'
55+ log_header
56+ Header for the log file, if the args are written.
57+ multiprocessing_aware
58+ Log from multiple processes. Default: True
59+ write_header
60+ Write a header for the log file. Default: True
61+ write_git
62+ Write information about the git repository. Default: True
63+ write_cli_args
64+ Log the command-line arguments. Default: True
65+ write_variables
66+ Write the attributes of selected objects. Default: True
67+ log_to_file
68+ If True, write a log file; otherwise just print to terminal.
69+ log_to_console
70+ Print logs to the console or not. Default: True
71+ timestamp
72+ If True, add a timestamp to the filename.
73+ logger_name
74+ If None, logger uses default logger; otherwise, logger
75+ name is set to `logger_name`.
76+
77+ Returns
78+ -------
79+ path
80+ Path to the logging file.
81+
6882 """
6983 output_dir = str (output_dir )
7084 print_log_level = "DEBUG" if verbose else "INFO"
@@ -107,6 +121,8 @@ def start_logging(
107121
108122
109123class LoggingHeader :
124+ """Manage and write the log header."""
125+
110126 def __init__ (
111127 self ,
112128 file ,
@@ -119,6 +135,10 @@ def __init__(
119135 write_variables = True ,
120136 log_header = None ,
121137 ):
138+ """Initialize LoggingHeader and write header to the log file.
139+
140+ See start_logging() for parameters.
141+ """
122142 self .program = program
123143
124144 with open (file , "w" , encoding = "utf-8" ) as self .file :
@@ -132,6 +152,17 @@ def __init__(
132152 self .write_variables (variable_objects )
133153
134154 def write_git_info (self , program_name , header = "GIT INFO" ):
155+ """Write information about the git repository state.
156+
157+ Parameters
158+ ----------
159+ program_name
160+ The name of the installed package, to
161+ locate and inspect its Git repository.
162+ header
163+ The section header to use. Default is "GIT INFO".
164+
165+ """
135166 self .write_separated_section_header (header )
136167 try :
137168 program_path = find_spec (program_name ).submodule_search_locations [
@@ -163,11 +194,27 @@ def write_git_info(self, program_name, header="GIT INFO"):
163194 )
164195
165196 def write_command_line_arguments (self , header = "COMMAND LINE ARGUMENTS" ):
197+ """Write the command-line arguments used to run the script.
198+
199+ Parameters
200+ ----------
201+ header
202+ Title of the section that will be written to the log file.
203+
204+ """
166205 self .write_separated_section_header (header )
167206 self .file .write (f"Command: { sys .argv [0 ]} \n " )
168207 self .file .write (f"Input arguments: { sys .argv [1 :]} " )
169208
170209 def write_variables (self , variable_objects ):
210+ """Write a section for variables with their values.
211+
212+ Parameters
213+ ----------
214+ variable_objects
215+ A list of python objects, the attributes of which will be written.
216+
217+ """
171218 self .write_separated_section_header ("VARIABLES" , bottom_separator = "\n " )
172219 if hasattr (variable_objects [0 ], "__dict__" ):
173220 self .write_variables_from_object_list (variable_objects )
@@ -176,10 +223,27 @@ def write_variables(self, variable_objects):
176223 self .write_separated_section_header ("LOGGING" )
177224
178225 def write_variables_from_slot_type_list (self , variable_objects ):
226+ """Write variables and their values from a namedtuple-like object.
227+
228+ Parameters
229+ ----------
230+ variable_objects
231+ An object with a `_asdict()` method (e.g., a namedtuple)
232+ containing variables to write.
233+
234+ """
179235 for attr , value in variable_objects ._asdict ().items ():
180236 self .file .write (f"{ attr } : { value } \n " )
181237
182238 def write_variables_from_object_list (self , variable_objects ):
239+ """Write attributes of each object in a list.
240+
241+ Parameters
242+ ----------
243+ variable_objects
244+ A list of objects whose attributes will be written to the file.
245+
246+ """
183247 for variable_object in variable_objects :
184248 self .file .write (f"\n { variable_object .__class__ .__name__ } :\n " )
185249 for attr , value in variable_object .__dict__ .items ():
@@ -188,6 +252,19 @@ def write_variables_from_object_list(self, variable_objects):
188252 self .file .write (f"{ attr } : { value } \n " )
189253
190254 def write_log_header (self , output_dir , log_header ):
255+ """Write the log header.
256+
257+ The header includes time, output directory,
258+ and current directory.
259+
260+ Parameters
261+ ----------
262+ output_dir
263+ The path to the output directory to include in the log.
264+ log_header
265+ Optional custom header text. If None, defaults to "LOG".
266+
267+ """
191268 if log_header is None :
192269 log_header = "LOG"
193270 self .write_separated_section_header (log_header , top_sep = False )
@@ -207,18 +284,53 @@ def write_separated_section_header(
207284 top_separator = "\n \n " ,
208285 bottom_separator = "\n \n " ,
209286 ):
287+ r"""Write a section header with optional top and bottom separators.
288+
289+ Parameters
290+ ----------
291+ section_header
292+ The section header text to write.
293+ top_sep
294+ Whether to write the top separator before the section header.
295+ bottom_sep
296+ Whether to write the bottom separator after the section header.
297+ top_separator
298+ The string to use as the top separator. Default: "\\n\\n"
299+ bottom_separator
300+ The string to use as the bottom separator. Default: "\\n\\n"
301+
302+ """
210303 if top_sep :
211304 self .write_separator (separator = top_separator )
212305 self .write_section_header (section_header )
213306 if bottom_sep :
214307 self .write_separator (separator = bottom_separator )
215308
216309 def write_separator (self , separator = "\n \n \n " ):
310+ r"""Write a separator string to the file.
311+
312+ Parameters
313+ ----------
314+ separator
315+ The separator string to write. Default: "\\n\\n\\n"
316+
317+ """
217318 self .file .write (separator )
218319
219320 def write_section_header (
220321 self , section_header , lateral_separator = "**************"
221322 ):
323+ """Write a section header framed by a lateral separator.
324+
325+ Parameters
326+ ----------
327+ section_header
328+ The section header text to write.
329+ lateral_separator
330+ The string used to frame the section header.
331+ Default: "**************"
332+
333+ """
222334 self .file .write (
223335 f"{ lateral_separator } { section_header } { lateral_separator } "
224336 )
@@ -231,15 +343,22 @@ def initialise_logger(
231343 log_to_console = True ,
232344 logger_name = None ,
233345):
234- """Sets up (possibly multiprocessing aware) logging.
235- :param filename: Where to save the logs to
236- :param print_level: What level of logging to print to console.
237- Default: 'INFO'
238- :param file_level: What level of logging to print to file.
239- Default: 'DEBUG'
240- :param log_to_console: Print logs to the console or not
241- :param logger_name: If None, logger uses default logger. Otherwise,
242- logger name is set to `logger_name`.
346+ """Set up (possibly multiprocessing aware) logging.
347+
348+ Parameters
349+ ----------
350+ filename
351+ Where to save the logs to.
352+ print_level
353+ What level of logging to print to console. Default: 'INFO'
354+ file_level
355+ What level of logging to print to file. Default: 'DEBUG'
356+ log_to_console
357+ Print logs to the console or not.
358+ logger_name
359+ If None, logger uses default logger. Otherwise, logger name
360+ is set to `logger_name`.
361+
243362 """
244363 if logger_name :
245364 logger = logging .getLogger (logger_name )
@@ -280,17 +399,23 @@ def setup_logging(
280399 log_to_console = True ,
281400 logger_name = None ,
282401):
283- """Sets up (possibly multiprocessing aware) logging.
284- :param filename: Where to save the logs to
285- :param print_level: What level of logging to print to console.
286- Default: 'INFO'
287- :param file_level: What level of logging to print to file.
288- Default: 'DEBUG'
289- :param multiprocessing_aware: Default: True
290- :param log_to_console: Print logs to the console or no.
291- Default: True
292- :param logger_name: If None, logger uses default logger. Otherwise,
293- logger name is set to `logger_name`.
402+ """Set up (possibly multiprocessing-aware) logging.
403+
404+ Parameters
405+ ----------
406+ filename
407+ Path to the file where logs will be saved.
408+ print_level
409+ Logging level for console output. Default is 'INFO'.
410+ file_level
411+ Logging level for file output. Default is 'DEBUG'.
412+ multiprocessing_aware
413+ If True, enables multiprocessing-safe logging. Default is True.
414+ log_to_console
415+ If True, logs will also be printed to the console. Default is True.
416+ logger_name
417+ Name of the logger to use. If None, the default logger is used.
418+
294419 """
295420 logger = initialise_logger (
296421 filename ,
@@ -328,8 +453,9 @@ def setup_logging(
328453
329454
330455def disable_logging ():
331- """Prevents any more logging. Saves remembering that logging.disable() with
456+ """Prevent any more logging.
457+
458+ Saves remembering that logging.disable() with
332459 no argument doesn't work.
333- :return:
334460 """
335461 logging .disable (2 ** 63 - 1 )
0 commit comments