Source code for log

# -*- coding: utf-8 -*-
"""
:Purpose:   This is a small class module designed as a central log file
            creator.

            The calling program is responsible for passing the proper
            arguments to create the log file header. For example::

                (printheader=True, headertext='some,header,text,here')

            It is suggested to initialise the :class:`~Log` class
            at program startup, with the ``printheader`` parameter
            set to ``True``. This is safe because if the log file
            already exists, the header will not be re-created. However,
            if the log file does not exist, it will be created with a
            header, using the value of the ``headertext`` parameter.

:Platform:  Linux/Windows | Python 3.6+
:Developer: J Berendt
:Email:     support@s3dev.uk

:Comments:  n/a

:Example:

    To use the :class:`~Log` class in your project::

        >>> from utils4.log import Log

        >> header = 'COMMENT,TYPE,VAL,UNIT'
        >> logger = Log(filepath='/tmp/testlog.log',
                        printheader=True,
                        headertext=header)
        >> logger.write(text='Most cows can jump over the moon,Fact,94.2,pct')

"""

import getpass
import os
import socket
from datetime import datetime as dt


[docs] class Log: """This is a small and simple log file creator/writer class. The calling program is responsible for passing the proper arguments to create the log file header. For example:: (printheader=True, headertext='some,header,text,here') On class instantiation, validation is performed to determine if the log file exists. If the log file does not exist, a header is required before writing to the log file. These parameters can be passed to the class on instantiation, and will be ignored if the log file already exists. Args: filepath (str): Full path to the log file. autofill (bool, optional): Automatically populate ``datetime.now()``, host and username values, to each log entry. Defaults to True. printheader (bool, optional): Print a log file header using the text passed into the ``headertext`` parameter. Defaults to False. .. note:: The header will only be written if the log file does not exist. headertext (str, optional): String of delimited column labels to be written as the header. Defaults to ''. sep (str, optional): Separator to be used in the log file. This separator is used when writing the autofill values. Defaults to ','. :File Validation: On class instantiation, tests are performed to ensure the log file is being populated in a logical way. * If ``printheader`` is ``False``, and the log file does not exist, the user is notified. * If ``printheader`` is ``True``, yet ``headertext`` is blank, the user is instructed to pass header text. * If ``printheader`` is ``True``, yet the log file already exists, the header will not be written. :Example: To use the :class:`~Log` class in your project:: >>> from utils4.log import Log >>> header = 'COMMENT,TYPE,VAL,UNIT' >>> logger = Log(filepath='/tmp/testlog.log', printheader=True, headertext=header) >>> logger.write(text='Most cows can jump over the moon,Fact,94.2,pct') """
[docs] def __init__(self, filepath, autofill=True, printheader=False, headertext='', sep=','): """Log class initialiser.""" self._filepath = filepath self._autofill = autofill self._printheader = printheader self._headertext = headertext self._sep = sep self._host = socket.gethostname() self._user = getpass.getuser() self._autotext = '' self._setup()
[docs] def write(self, text: str): """Write text to the log file defined at instantiation. Args: text (str): Delimited text string to be written to the log. Note: If ``autofill`` is ``True``, the datetime, host and username values **will be populated automatically**; these do *not* need to be passed into the ``text`` argument. :Design: If the ``autofill`` argument is ``True``, the current datetime, host and username values are written (in that order), ahead of the text string provided to the ``text`` argument. The ``sep`` parameter (defined at instantiation), is used to separate these auto-populated fields. :Example: To write to the log file:: >>> from utils4.log import Log >>> logger = Log(filepath='/tmp/testlog.log, autofill=True) >>> logger.write(text='Just adding some random text to my log') """ try: if text: auto_text = f'{dt.now()}{self._sep}{self._autotext}' if self._autofill else '' with open(self._filepath, 'a', encoding='utf-8') as f: f.write(auto_text) f.write(text) f.write('\n') except Exception as err: # pragma: nocover print(err)
[docs] def write_blank_line(self): """Write a blank line to the log file. Note: The ``autofill`` information is **not** written. This is a true blank line, created by writing the system's native line separator character(s)to the log. :Example: To write a blank line to the log file:: >>> from utils4.log import Log >>> logger = Log(filepath='/tmp/testlog.log', autofill=True) >>> logger.write_blank_line() """ try: with open(self._filepath, 'a', encoding='utf-8') as f: f.write('\n') except Exception as err: # pragma: nocover print(err)
def _setup(self): """Setup tasks performed on class instantiation. :Tasks: - Create the log file. - Write the header. :Validation: - If the log file does not exist, ensure a header is requested. - If the header is requested, ensure the header text is provided. Raised: UserWarning: If either of the validation criteria are not met. """ self._autotext = (f'{self._host}{self._sep}{self._user}{self._sep}' if self._autofill else '') # Verify the logfile does not exists, ensure a header is requested. if (not self._printheader) & (not os.path.exists(self._filepath)): raise UserWarning('Header expected, log does not already exist.\n' '- Log file does not exist, therefore a header must be requested,\n' ' as the header is written at the time of log file creation.\n') # Verify header text is populated, if print header is requested. if self._printheader & (not self._headertext): raise UserWarning('Header requested, but header text not received.\n' '- The printheader argument is True, however the headertext string\n' ' is blank. A headertext string must also be supplied.\n') # Write the header if 1) requested, 2) header text provided and 3) log file does not exist. if all([self._printheader, self._headertext, not os.path.exists(self._filepath)]): with open(self._filepath, 'w', encoding='utf-8') as f: f.write(self._headertext) f.write('\n')