Skip to content

Commit b839f1d

Browse files
committed
Add docstring linting and update docstrings.
1 parent be60b5c commit b839f1d

File tree

4 files changed

+222
-85
lines changed

4 files changed

+222
-85
lines changed

fancylog/fancylog.py

Lines changed: 181 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
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

83
import contextlib
94
import 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,10 +121,12 @@ def start_logging(
107121

108122

109123
class LoggingHeader:
124+
"""Manage and write the log header."""
125+
110126
def __init__(
111127
self,
112128
file,
113-
program,
129+
program, # TODO: should this be called package?
114130
variable_objects,
115131
output_dir,
116132
write_header=True,
@@ -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

330455
def 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

Comments
 (0)