mirror of
https://github.com/Wojtek242/pylg.git
synced 2024-12-23 15:14:39 +01:00
Release 1.2.0
This commit is contained in:
parent
142017c57f
commit
c29553985c
29
CHANGES.rst
Normal file
29
CHANGES.rst
Normal file
@ -0,0 +1,29 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
1.2.0
|
||||
-----
|
||||
|
||||
- Fixed bug that didn't preserve exception backtrace correctly.
|
||||
|
||||
- Function ``trace`` now automatically converts a message to a string.
|
||||
|
||||
- Added several new options that can now be set in
|
||||
``pylg_settings.py``, see the README for details.
|
||||
|
||||
- Improved dummy implementation for the case when PyLg is disabled.
|
||||
|
||||
- User settings provided in ``pylg_settings.py`` are now checked for
|
||||
errors. In the case of a failed import, PyLg will set all settings
|
||||
to defaults. In case of an invalid individual value, only the
|
||||
relevant setting will be reset to its default.
|
||||
|
||||
1.1.0
|
||||
-----
|
||||
|
||||
- PyLg can now be installed with pip.
|
||||
|
||||
1.0.0
|
||||
-----
|
||||
|
||||
- Initial PyLg version.
|
@ -1,2 +1,3 @@
|
||||
recursive-include pylg *.py
|
||||
include LICENSE.txt
|
||||
include CHANGES.rst
|
||||
|
117
README.rst
117
README.rst
@ -55,8 +55,9 @@ To automatically log function entry and exit use the
|
||||
Despite the name, this works for both functions and methods.
|
||||
|
||||
``@TraceFunction`` can take up to two optional arguments:
|
||||
- trace_args - if ``True``, input parameters will be logged.
|
||||
- trace_rv - if ``True``, the return value will be logged.
|
||||
|
||||
- ``trace_args`` - if ``True``, input parameters will be logged.
|
||||
- ``trace_rv`` - if ``True``, the return value will be logged.
|
||||
|
||||
The default values for these arguments are set in a global settings
|
||||
file.
|
||||
@ -73,7 +74,7 @@ These arguments have to specified explicitly by name. Some examples:
|
||||
def some_fuction():
|
||||
pass
|
||||
|
||||
@TraceFunction(trace_args = False, trace_args = False)
|
||||
@TraceFunction(trace_args = False, trace_rv = False)
|
||||
def some_fuction():
|
||||
pass
|
||||
|
||||
@ -88,38 +89,90 @@ User Settings
|
||||
-------------
|
||||
|
||||
The user can adjust several settings to suit their preferences. To do
|
||||
so, create a file named ``pylg_settings.py`` in the top-level
|
||||
directory and set any of the following variables to the desired values
|
||||
in order to override the defaults. The settings.py file in the project
|
||||
so, create a file named ``pylg_settings.py`` somewhere in your path
|
||||
and set any of the following variables to the desired values in order
|
||||
to override the defaults. The settings.py file in the project
|
||||
directory contains all the default settings and can be used as a
|
||||
template.
|
||||
|
||||
- PYLG_ENABLE (default = True) - enable/disable logs.
|
||||
- PYLG (default = 'pylg.log') - the log file name.
|
||||
- CLASS_NAME_RESOLUTION (default = False) - PyLg can also log the
|
||||
class name along with the method name if one exists. However, for
|
||||
this to work correctly the ``trace`` function cannot be called from
|
||||
functions that are not decorated by ``@TraceFunction`` which is why
|
||||
it is disabled by default.
|
||||
- DEFAULT_TRACE_ARGS (default = True) - the default value for
|
||||
``trace_args`` argument which can be passed to the ``@TraceFunction`
|
||||
decorator. If ``trace_args`` is ``True`` all parameters passed to
|
||||
the function will be logged. This can be overriden on an individual
|
||||
function basis.
|
||||
- DEFAULT_TRACE_RV (default = True) - the default value for trace_rv
|
||||
argument which can be passed to the ``@TraceFunction`` decorator. If
|
||||
``trace_rv`` is ``True`` the function's return value will be
|
||||
logged. This can be overriden on an individual function basis.
|
||||
- EXCEPTION_WARNING (default = True) - PyLg catches all exceptions in
|
||||
traced functions, logs them, and then re-raises them with the full
|
||||
backtrace. This setting determines whether it should also produce a
|
||||
warning for the user using the Python warning mechanism.
|
||||
- FILENAME_COLUMN_WIDTH (default = 32) - the column width reserved for
|
||||
the file name. Names that are too short will be padded with
|
||||
whitespace and names that are too long will be truncated.
|
||||
- FUNCTION_COLUMN_WIDTH (default = 32) - the column width reserved for
|
||||
the function name. Names that are too short will be padded with
|
||||
whitespace and names that are too long will be truncated.
|
||||
- ``PYLG_ENABLE`` (default = ``True``) - enable/disable PyLg.
|
||||
|
||||
- ``PYLG_FILE`` (default = ``'pylg.log'``) - the log file name.
|
||||
|
||||
- ``EXCEPTION_WARNING`` (default = ``True``) - if ``True``, PyLg will
|
||||
print a warning about every exception caught to stderr.
|
||||
|
||||
- ``EXCEPTION_EXIT`` (default = ``False``) - if ``True``, PyLg will
|
||||
force the program to exit (and not just raise ``SystemExit``)
|
||||
whenever an exception occurs. This will happen even if the exception
|
||||
would be handled at a later point.
|
||||
|
||||
- ``TRACE_TIME`` (default = ``TRUE``) - enable/disable time logging.
|
||||
|
||||
- ``TIME_FORMAT`` (default = ``"%Y-%m-%d %H:%M:%S.%f"``) - formatting
|
||||
for the time trace. For a full list of options, see
|
||||
https://docs.python.org/2/library/datetime.html#strftime-strptime-behavior.
|
||||
|
||||
- ``TRACE_FILENAME`` (default = ``True``) - enable/disable file name
|
||||
logging.
|
||||
|
||||
- ``FILENAME_COLUMN_WIDTH`` (default = ``20``) - the column width for
|
||||
the file name. If a name is too long, it will be truncated.
|
||||
|
||||
- ``TRACE_LINENO`` (default = ``True``) - enable/disable the logging
|
||||
of the line number from which the trace call was made. For entry and
|
||||
exit messages this logs the line in which the decorator is placed
|
||||
(which should be directly above the function itself).
|
||||
|
||||
- ``LINENO_WIDTH`` (default = ``4``) - the minimum number of digits to
|
||||
use to print the line number. If the number is too long, more digits
|
||||
will be used.
|
||||
|
||||
- ``TRACE_FUNCTION`` (default = ``True``) - enable/disable the logging
|
||||
of the function name from which the trace call was made. Entry/exit
|
||||
logs refer to the function they enter into and exit from.
|
||||
|
||||
- ``FUNCTION_COLUMN_WIDTH`` (default = ``32``) - the column width for
|
||||
the function name. If a name is too long, it will be truncated.
|
||||
|
||||
- ``CLASS_NAME_RESOLUTION`` (default = ``False``) - enable/disable
|
||||
class name resolution. Function names will be printed with their
|
||||
class names. IMPORTANT: If this setting is enabled, the trace
|
||||
function should ONLY be called from within functions that have the
|
||||
``@TraceFunction`` decorator OR outside of any function.
|
||||
|
||||
- ``TRACE_MESSAGE`` (default = ``True``) - enable/disable message
|
||||
logging.
|
||||
|
||||
- ``MESSAGE_WIDTH`` (default = ``0``) - the column width for the
|
||||
message. A width of zero means unlimited.
|
||||
|
||||
- ``MESSAGE_WRAP`` (default = ``True``) - if ``True``, PyLG will wrap
|
||||
the message to fit within the column width. Otherwise, the message
|
||||
will be truncated.
|
||||
|
||||
- ``MESSAGE_MARK_TRUNCATION`` (default = ``True``) - if ``True``,
|
||||
truncated message lines should have the last character replaced with
|
||||
``\``.
|
||||
|
||||
- ``TRACE_SELF`` (default = ``False``) - enable/disable logging of the
|
||||
``self`` function argument.
|
||||
|
||||
- ``COLLAPSE_LISTS`` (default = ``False``) - if ``True`` lists will be
|
||||
collapsed to ``[ len=x ]`` where ``x`` denotes the number of
|
||||
elements in the list.
|
||||
|
||||
- ``COLLAPSE_DICTS`` (default = ``False``) - if ``True`` dictionaries
|
||||
will be collapsed to ``{ len=x }`` where ``x`` denotes the number of
|
||||
elements in the dictionary.
|
||||
|
||||
- ``DEFAULT_TRACE_ARGS`` (default = ``True``) - the default setting
|
||||
for ``trace_args`` which determines whether TraceFunction should
|
||||
trace function parameters on entry.
|
||||
|
||||
- ``DEFAULT_TRACE_RV`` (default = ``True``) - the default setting for
|
||||
``trace_rv`` which determines whether TraceFunction should trace
|
||||
function return values on exit.
|
||||
|
||||
Under development
|
||||
-----------------
|
||||
|
@ -1,4 +1,4 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
# PyLg: module to facilitate and automate the process of writing runtime logs.
|
||||
# Copyright (C) 2017 Wojciech Kozlowski <wojciech.kozlowski@vivaldi.net>
|
||||
#
|
||||
@ -14,6 +14,11 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#-------------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
from .pylg import TraceFunction, trace
|
||||
from .loadSettings import PYLG_ENABLE
|
||||
|
||||
if PYLG_ENABLE:
|
||||
from .pylg import TraceFunction, trace
|
||||
else:
|
||||
from .dummy import TraceFunction, trace
|
||||
|
116
pylg/dummy.py
Normal file
116
pylg/dummy.py
Normal file
@ -0,0 +1,116 @@
|
||||
# -----------------------------------------------------------------------------
|
||||
# PyLg: module to facilitate and automate the process of writing runtime logs.
|
||||
# Copyright (C) 2017 Wojciech Kozlowski <wojciech.kozlowski@vivaldi.net>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
from functools import partial
|
||||
|
||||
|
||||
class TraceFunction(object):
|
||||
|
||||
""" Dummy implementation of TraceFunction.
|
||||
"""
|
||||
|
||||
def __get__(self, obj, objtype):
|
||||
|
||||
""" Support for instance functions.
|
||||
"""
|
||||
|
||||
return partial(self.__call__, obj)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
""" Constructor for dummy TraceFunction. Note that the behaviour is
|
||||
different depending on whether TraceFunction is passed any
|
||||
parameters. For details see the non-dummy implementation.
|
||||
"""
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Make sure this decorator is never called with no arguments.
|
||||
# ---------------------------------------------------------------------
|
||||
assert args or kwargs
|
||||
|
||||
if args:
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# The function init_function will verify the input.
|
||||
# -----------------------------------------------------------------
|
||||
self.init_function(*args, **kwargs)
|
||||
|
||||
if kwargs:
|
||||
|
||||
trace_args_str = 'trace_args'
|
||||
trace_rv_str = 'trace_rv'
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# If kwargs is non-empty, it should only contain trace_rv,
|
||||
# trace_args, or both and args should be empty. Assert all
|
||||
# this.
|
||||
# -----------------------------------------------------------------
|
||||
assert not args
|
||||
assert (len(kwargs) > 0) and (len(kwargs) <= 2)
|
||||
if len(kwargs) == 1:
|
||||
assert (trace_rv_str in kwargs) or (trace_args_str in kwargs)
|
||||
elif len(kwargs) == 2:
|
||||
assert (trace_rv_str in kwargs) and (trace_args_str in kwargs)
|
||||
|
||||
self.function = None
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
|
||||
""" The actual wrapper that is called when a call to a
|
||||
decorated function is made. It also handles extra
|
||||
initialisation when parameters are passed to
|
||||
TraceFunction.
|
||||
|
||||
:return: The return value of the decorated function.
|
||||
"""
|
||||
|
||||
if self.function is None:
|
||||
# -----------------------------------------------------------------
|
||||
# For an explanation of the logic here, see the non-dummy
|
||||
# implementations in pylg.py.
|
||||
# -----------------------------------------------------------------
|
||||
self.init_function(*args, **kwargs)
|
||||
return self
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# The actual decorating. The dummy implementation doesn't do anything.
|
||||
# ---------------------------------------------------------------------
|
||||
return self.function(*args, **kwargs)
|
||||
|
||||
def init_function(self, *args, **kwargs):
|
||||
|
||||
""" Function to initialise the TraceFunctionStruct kept by the
|
||||
decorator.
|
||||
"""
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# This function should only ever be called with one parameter
|
||||
# - the function to be decorated. These checks are done here,
|
||||
# rather than by the caller, as anything that calls this
|
||||
# function should also have been called with the decorated
|
||||
# function as its only parameter.
|
||||
# ---------------------------------------------------------------------
|
||||
assert not kwargs
|
||||
assert len(args) == 1
|
||||
assert callable(args[0])
|
||||
|
||||
self.function = args[0]
|
||||
|
||||
|
||||
def trace(message, function=None):
|
||||
pass
|
332
pylg/loadSettings.py
Normal file
332
pylg/loadSettings.py
Normal file
@ -0,0 +1,332 @@
|
||||
# -----------------------------------------------------------------------------
|
||||
# PyLg: module to facilitate and automate the process of writing runtime logs.
|
||||
# Copyright (C) 2017 Wojciech Kozlowski <wojciech.kozlowski@vivaldi.net>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
import traceback
|
||||
import warnings
|
||||
import inspect
|
||||
import sys
|
||||
import os
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Import all the defaults first.
|
||||
# -----------------------------------------------------------------------------
|
||||
from .settings import *
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# The filename of the user settings. It will be set once it can be
|
||||
# determined after loading the module.
|
||||
# -----------------------------------------------------------------------------
|
||||
PYLG_USER_FILE = None
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Attempt to load the module pylg_settings module. If successful, set
|
||||
# PYLG_USER_FILE to the module's path. By attempting an import rather
|
||||
# than checking if a file exists, we can handle the case of the user
|
||||
# having the settings file elsewhere in their path.
|
||||
# -----------------------------------------------------------------------------
|
||||
try:
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# We import the module itself to be able to determine its source
|
||||
# file before we import all the settings.
|
||||
# -------------------------------------------------------------------------
|
||||
import pylg_settings
|
||||
from pylg_settings import *
|
||||
PYLG_USER_FILE = inspect.getsourcefile(pylg_settings)
|
||||
|
||||
except ImportError:
|
||||
# -------------------------------------------------------------------------
|
||||
# The user settings don't exist. We assume the user is happy with
|
||||
# the defaults.
|
||||
# -------------------------------------------------------------------------
|
||||
pass
|
||||
|
||||
except (NameError, SyntaxError):
|
||||
|
||||
warnings.warn("There was a problem importing user settings")
|
||||
|
||||
sys.stderr.write("\n")
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
sys.stderr.write("\n")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Utility functions for sanity checking user settings. They raise an
|
||||
# ImportError if something is wrong.
|
||||
# -----------------------------------------------------------------------------
|
||||
def pylg_check_bool(value, name):
|
||||
|
||||
if not isinstance(value, bool):
|
||||
|
||||
warning_msg = ("Invalid type for " + name + " in " +
|
||||
PYLG_USER_FILE +
|
||||
" - should be bool, is type " +
|
||||
type(value).__name__)
|
||||
|
||||
warnings.warn(warning_msg)
|
||||
|
||||
raise ImportError
|
||||
|
||||
|
||||
def pylg_check_string(value, name):
|
||||
|
||||
if not isinstance(value, basestring):
|
||||
|
||||
warning_msg = ("Invalid type for " + name + " in " +
|
||||
PYLG_USER_FILE +
|
||||
" - should be a string, is type " +
|
||||
type(value).__name__)
|
||||
|
||||
warnings.warn(warning_msg)
|
||||
|
||||
raise ImportError
|
||||
|
||||
|
||||
def pylg_check_int(value, name):
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# We check for bool as well as bools are an instance of int, but
|
||||
# we don't want to let that go through.
|
||||
# -------------------------------------------------------------------------
|
||||
if not isinstance(value, int) or isinstance(value, bool):
|
||||
|
||||
warning_msg = ("Invalid type for " + name + " in " +
|
||||
PYLG_USER_FILE +
|
||||
" - should be int, is " +
|
||||
type(value).__name__)
|
||||
|
||||
warnings.warn(warning_msg)
|
||||
|
||||
raise ImportError
|
||||
|
||||
|
||||
def pylg_check_nonneg_int(value, name):
|
||||
|
||||
pylg_check_int(value, name)
|
||||
|
||||
if value < 0:
|
||||
|
||||
warning_msg = ("Invalid value for " + name + " in " +
|
||||
PYLG_USER_FILE +
|
||||
" - should be non-negative, is " +
|
||||
str(value))
|
||||
|
||||
warnings.warn(warning_msg)
|
||||
|
||||
raise ImportError
|
||||
|
||||
|
||||
def pylg_check_pos_int(value, name):
|
||||
|
||||
pylg_check_int(value, name)
|
||||
|
||||
if value <= 0:
|
||||
|
||||
warning_msg = ("Invalid value for " + name + " in " +
|
||||
PYLG_USER_FILE +
|
||||
" - should be positive, is " +
|
||||
str(value))
|
||||
|
||||
warnings.warn(warning_msg)
|
||||
|
||||
raise ImportError
|
||||
|
||||
|
||||
if PYLG_USER_FILE is not None:
|
||||
# -------------------------------------------------------------------------
|
||||
# If PYLG_USER_FILE is set, we have successfully imported user
|
||||
# settings. Nowe, we need to sanity check them. If anything is
|
||||
# wrong we reset the value to its default. At this stage a single
|
||||
# error should not affect any other settings.
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# PYLG_ENABLE - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(PYLG_ENABLE, "PYLG_ENABLE")
|
||||
except ImportError:
|
||||
from .settings import PYLG_ENABLE
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# PYLG_FILE - string
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_string(PYLG_FILE, "PYLG_FILE")
|
||||
except ImportError:
|
||||
from .settings import PYLG_FILE
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EXCEPTION_WARNING - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(EXCEPTION_WARNING, "EXCEPTION_WARNING")
|
||||
except ImportError:
|
||||
from .settings import EXCEPTION_WARNING
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# EXCEPTION_EXIT - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(EXCEPTION_EXIT, "EXCEPTION_EXIT")
|
||||
except ImportError:
|
||||
from .settings import EXCEPTION_EXIT
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# TRACE_TIME - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(TRACE_TIME, "TRACE_TIME")
|
||||
except ImportError:
|
||||
from .settings import TRACE_TIME
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# TIME_FORMAT - string
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_string(TIME_FORMAT, "TIME_FORMAT")
|
||||
except ImportError:
|
||||
from .settings import TIME_FORMAT
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# TRACE_FILENAME - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(TRACE_FILENAME, "TRACE_FILENAME")
|
||||
except ImportError:
|
||||
from .settings import TRACE_FILENAME
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# FILENAME_COLUMN_WIDTH - non-negative integer
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_pos_int(FILENAME_COLUMN_WIDTH, "FILENAME_COLUMN_WIDTH")
|
||||
except ImportError:
|
||||
from .settings import FILENAME_COLUMN_WIDTH
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# TRACE_LINENO - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(TRACE_LINENO, "TRACE_LINENO")
|
||||
except ImportError:
|
||||
from .settings import TRACE_LINENO
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# LINENO_WIDTH - non-negative integer
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_nonneg_int(LINENO_WIDTH, "LINENO_WIDTH")
|
||||
except ImportError:
|
||||
from .settings import LINENO_WIDTH
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# TRACE_FUNCTION - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(TRACE_FUNCTION, "TRACE_FUNCTION")
|
||||
except ImportError:
|
||||
from .settings import TRACE_FUNCTION
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# FUNCTION_COLUMN_WIDTH - non-negative integer
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_pos_int(FUNCTION_COLUMN_WIDTH, "FUNCTION_COLUMN_WIDTH")
|
||||
except ImportError:
|
||||
from .settings import FUNCTION_COLUMN_WIDTH
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# CLASS_NAME_RESOLUTION - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(CLASS_NAME_RESOLUTION, "CLASS_NAME_RESOLUTION")
|
||||
except ImportError:
|
||||
from .settings import CLASS_NAME_RESOLUTION
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# TRACE_MESSAGE - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(TRACE_MESSAGE, "TRACE_MESSAGE")
|
||||
except ImportError:
|
||||
from .settings import TRACE_MESSAGE
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# MESSAGE_WIDTH - non-negative integer - note 0 denotes unlimited
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_nonneg_int(MESSAGE_WIDTH, "MESSAGE_WIDTH")
|
||||
except ImportError:
|
||||
from .settings import MESSAGE_WIDTH
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# MESSAGE_WRAP - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(MESSAGE_WRAP, "MESSAGE_WRAP")
|
||||
except ImportError:
|
||||
from .settings import MESSAGE_WRAP
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# MESSAGE_MARK_TRUNCATION - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(MESSAGE_MARK_TRUNCATION, "MESSAGE_MARK_TRUNCATION")
|
||||
except ImportError:
|
||||
from .settings import MESSAGE_MARK_TRUNCATION
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# TRACE_SELF - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(TRACE_SELF, "TRACE_SELF")
|
||||
except ImportError:
|
||||
from .settings import TRACE_SELF
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# COLLAPSE_LISTS - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(COLLAPSE_LISTS, "COLLAPSE_LISTS")
|
||||
except ImportError:
|
||||
from .settings import COLLAPSE_LISTS
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# COLLAPSE_DICTS - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(COLLAPSE_DICTS, "COLLAPSE_DICTS")
|
||||
except ImportError:
|
||||
from .settings import COLLAPSE_DICTS
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# DEFAULT_TRACE_ARGS - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(DEFAULT_TRACE_ARGS, "DEFAULT_TRACE_ARGS")
|
||||
except ImportError:
|
||||
from .settings import DEFAULT_TRACE_ARGS
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# DEFAULT_TRACE_RV - bool
|
||||
# -------------------------------------------------------------------------
|
||||
try:
|
||||
pylg_check_bool(DEFAULT_TRACE_RV, "DEFAULT_TRACE_RV")
|
||||
except ImportError:
|
||||
from .settings import DEFAULT_TRACE_RV
|
309
pylg/pylg.py
309
pylg/pylg.py
@ -1,4 +1,4 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
# PyLg: module to facilitate and automate the process of writing runtime logs.
|
||||
# Copyright (C) 2017 Wojciech Kozlowski <wojciech.kozlowski@vivaldi.net>
|
||||
#
|
||||
@ -14,31 +14,22 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#-------------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
from datetime import datetime
|
||||
from functools import partial
|
||||
import traceback
|
||||
import warnings
|
||||
import textwrap
|
||||
import inspect
|
||||
import sys
|
||||
import os
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Load default settings.
|
||||
#-------------------------------------------------------------------------------
|
||||
from .settings import *
|
||||
# -----------------------------------------------------------------------------
|
||||
# Load settings.
|
||||
# -----------------------------------------------------------------------------
|
||||
from .loadSettings import *
|
||||
|
||||
try:
|
||||
#---------------------------------------------------------------------------
|
||||
# Load user settings.
|
||||
#---------------------------------------------------------------------------
|
||||
from pylg_settings import *
|
||||
|
||||
except ImportError:
|
||||
#---------------------------------------------------------------------------
|
||||
# User settings don't exist.
|
||||
#---------------------------------------------------------------------------
|
||||
pass
|
||||
|
||||
class ClassNameStack(object):
|
||||
|
||||
@ -67,13 +58,14 @@ class ClassNameStack(object):
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class PyLg(object):
|
||||
|
||||
""" Class to handle the log file.
|
||||
"""
|
||||
|
||||
wfile = None
|
||||
filename = PYLG
|
||||
filename = PYLG_FILE
|
||||
|
||||
@staticmethod
|
||||
def set_filename(new_filename):
|
||||
@ -104,6 +96,7 @@ class PyLg(object):
|
||||
str(datetime.now()) + " ===\n\n")
|
||||
|
||||
PyLg.wfile.write(string)
|
||||
PyLg.wfile.flush()
|
||||
|
||||
@staticmethod
|
||||
def close():
|
||||
@ -117,6 +110,7 @@ class PyLg(object):
|
||||
else:
|
||||
warnings.warn("PyLg wfile is not open - nothing to close")
|
||||
|
||||
|
||||
class TraceFunction(object):
|
||||
|
||||
""" Class that serves as a decorator to trace entry and exit from
|
||||
@ -129,13 +123,13 @@ class TraceFunction(object):
|
||||
""" Internal object to handle traced function properties.
|
||||
"""
|
||||
|
||||
function = None
|
||||
varnames = None
|
||||
defaults = None
|
||||
function = None
|
||||
varnames = None
|
||||
defaults = None
|
||||
|
||||
filename = None
|
||||
lineno = None
|
||||
classname = None
|
||||
filename = None
|
||||
lineno = None
|
||||
classname = None
|
||||
functionname = None
|
||||
|
||||
def __get__(self, obj, objtype):
|
||||
@ -152,31 +146,31 @@ class TraceFunction(object):
|
||||
parameters. For details see __call__ in this class.
|
||||
"""
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
# Make sure this decorator is never called with no arguments.
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
assert args or kwargs
|
||||
|
||||
if args:
|
||||
|
||||
self.trace_args = DEFAULT_TRACE_ARGS
|
||||
self.trace_rv = DEFAULT_TRACE_RV
|
||||
self.trace_rv = DEFAULT_TRACE_RV
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------
|
||||
# The function init_function will verify the input.
|
||||
#-------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------
|
||||
self.init_function(*args, **kwargs)
|
||||
|
||||
if kwargs:
|
||||
|
||||
trace_args_str = 'trace_args'
|
||||
trace_rv_str = 'trace_rv'
|
||||
trace_rv_str = 'trace_rv'
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------
|
||||
# If kwargs is non-empty, it should only contain trace_rv,
|
||||
# trace_args, or both and args should be empty. Assert all
|
||||
# this.
|
||||
#-------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------
|
||||
assert not args
|
||||
assert (len(kwargs) > 0) and (len(kwargs) <= 2)
|
||||
if len(kwargs) == 1:
|
||||
@ -206,7 +200,7 @@ class TraceFunction(object):
|
||||
:return: The return value of the decorated function.
|
||||
"""
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
# __call__ has to behave differently depending on whether the
|
||||
# decorator has been given any parameters. The reason for this
|
||||
# is as follows:
|
||||
@ -226,10 +220,10 @@ class TraceFunction(object):
|
||||
# the first case, the callable object is an instance of
|
||||
# TraceFunction, in the latter case the return value of
|
||||
# TraceFunction.__call__ is the callable object.
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
if self.function is None:
|
||||
#-------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------
|
||||
# If the decorator has been passed a parameter, __init__
|
||||
# will not define self.function and __call__ will be
|
||||
# called immediately after __init__ with the decorated
|
||||
@ -240,34 +234,29 @@ class TraceFunction(object):
|
||||
# object as the callable handle for the decorated
|
||||
# function. This if block should be hit only once at most
|
||||
# and only during initialisation.
|
||||
#-------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------
|
||||
self.init_function(*args, **kwargs)
|
||||
return self
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
# The actual decorating.
|
||||
#-----------------------------------------------------------------------
|
||||
if PYLG_ENABLE:
|
||||
# ---------------------------------------------------------------------
|
||||
ClassNameStack.insert(self.function.classname)
|
||||
self.trace_entry(*args, **kwargs)
|
||||
|
||||
ClassNameStack.insert(self.function.classname)
|
||||
self.trace_entry(*args, **kwargs)
|
||||
|
||||
try:
|
||||
rv = self.function.function(*args, **kwargs)
|
||||
except Exception as e:
|
||||
self.trace_exception(e)
|
||||
|
||||
exc_info = sys.exc_info()
|
||||
raise (exc_info[0], exc_info[1], exc_info[2])
|
||||
|
||||
self.trace_exit(rv)
|
||||
ClassNameStack.pop()
|
||||
|
||||
else:
|
||||
#-------------------------------------------------------------------
|
||||
# If PYLG is disabled, don't wrap anything.
|
||||
#-------------------------------------------------------------------
|
||||
try:
|
||||
rv = self.function.function(*args, **kwargs)
|
||||
except Exception as e:
|
||||
self.trace_exception(e)
|
||||
|
||||
if EXCEPTION_EXIT:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
os._exit(1)
|
||||
|
||||
raise
|
||||
|
||||
self.trace_exit(rv)
|
||||
ClassNameStack.pop()
|
||||
|
||||
return rv
|
||||
|
||||
@ -277,13 +266,13 @@ class TraceFunction(object):
|
||||
decorator.
|
||||
"""
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
# This function should only ever be called with one parameter
|
||||
# - the function to be decorated. These checks are done here,
|
||||
# rather than by the caller, as anything that calls this
|
||||
# function should also have been called with the decorated
|
||||
# function as its only parameter.
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
assert not kwargs
|
||||
assert len(args) == 1
|
||||
assert callable(args[0])
|
||||
@ -300,16 +289,16 @@ class TraceFunction(object):
|
||||
zip(argspec.args[-len(argspec.defaults):],
|
||||
argspec.defaults))
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
# init_function is called from either __init__ or __call__ and
|
||||
# we want the frame before that.
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
frames_back = 2
|
||||
caller_frame = inspect.stack()[frames_back]
|
||||
caller_frame = inspect.stack()[frames_back]
|
||||
|
||||
self.function.filename = os.path.basename(caller_frame[1])
|
||||
self.function.lineno = caller_frame[2]
|
||||
self.function.classname = caller_frame[3]
|
||||
self.function.filename = os.path.basename(caller_frame[1])
|
||||
self.function.lineno = caller_frame[2]
|
||||
self.function.classname = caller_frame[3]
|
||||
self.function.functionname = self.function.function.__name__
|
||||
|
||||
def trace_entry(self, *args, **kwargs):
|
||||
@ -319,9 +308,9 @@ class TraceFunction(object):
|
||||
trace.
|
||||
"""
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
# The ENTRY message.
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
msg = "-> ENTRY"
|
||||
if args or kwargs:
|
||||
msg += ": "
|
||||
@ -329,25 +318,30 @@ class TraceFunction(object):
|
||||
n_args = len(args)
|
||||
if self.trace_args:
|
||||
for arg in range(n_args):
|
||||
|
||||
if not TRACE_SELF and \
|
||||
self.function.varnames[arg] == "self":
|
||||
continue
|
||||
|
||||
msg += (self.function.varnames[arg] + " = " +
|
||||
str(args[arg]) + ", ")
|
||||
self.get_value_string(args[arg]) + ", ")
|
||||
|
||||
for name in self.function.varnames[n_args:]:
|
||||
msg += name + " = "
|
||||
if name in kwargs:
|
||||
msg += str(kwargs[name])
|
||||
value = kwargs[name]
|
||||
else:
|
||||
msg += str(self.function.defaults[name])
|
||||
msg += ", "
|
||||
value = self.function.defaults[name]
|
||||
msg += self.get_value_string(value) + ", "
|
||||
|
||||
msg = msg[:-2]
|
||||
|
||||
else:
|
||||
msg += "---"
|
||||
|
||||
trace(msg, function = self.function)
|
||||
trace(msg, function=self.function)
|
||||
|
||||
def trace_exit(self, rv = None):
|
||||
def trace_exit(self, rv=None):
|
||||
|
||||
""" Called on function exit to log the fact that a function has
|
||||
finished executing.
|
||||
@ -355,18 +349,18 @@ class TraceFunction(object):
|
||||
:param rv: The return value of the traced function.
|
||||
"""
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
# The EXIT message.
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
msg = "<- EXIT "
|
||||
if rv is not None:
|
||||
msg += ": "
|
||||
if self.trace_rv:
|
||||
msg += str(rv)
|
||||
msg += self.get_value_string(rv)
|
||||
else:
|
||||
msg += "---"
|
||||
|
||||
trace(msg, function = self.function)
|
||||
trace(msg, function=self.function)
|
||||
return
|
||||
|
||||
def trace_exception(self, exception):
|
||||
@ -376,9 +370,9 @@ class TraceFunction(object):
|
||||
:param exception: The raised exception.
|
||||
"""
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
# The EXIT message.
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
core_msg = type(exception).__name__ + " RAISED"
|
||||
msg = "<- EXIT : " + core_msg
|
||||
|
||||
@ -388,10 +382,29 @@ class TraceFunction(object):
|
||||
if EXCEPTION_WARNING:
|
||||
warnings.warn(core_msg, RuntimeWarning)
|
||||
|
||||
trace(msg, function = self.function)
|
||||
trace(msg, function=self.function)
|
||||
return
|
||||
|
||||
def trace(message, function = None):
|
||||
def get_value_string(self, value):
|
||||
|
||||
""" Convert value to a string for the log.
|
||||
"""
|
||||
|
||||
if isinstance(value, list) and COLLAPSE_LISTS:
|
||||
return self.collapse_list(value)
|
||||
elif isinstance(value, dict) and COLLAPSE_DICTS:
|
||||
return self.collapse_dict(value)
|
||||
else:
|
||||
return str(value)
|
||||
|
||||
def collapse_list(self, ll):
|
||||
return "[ len=" + str(len(ll)) + " ]"
|
||||
|
||||
def collapse_dict(self, dd):
|
||||
return "{ len=" + str(len(dd)) + " }"
|
||||
|
||||
|
||||
def trace(message, function=None):
|
||||
|
||||
""" Writes message to the log file. It will also log the time,
|
||||
filename, line number and function name.
|
||||
@ -401,48 +414,132 @@ def trace(message, function = None):
|
||||
TraceFunction.
|
||||
"""
|
||||
|
||||
if not PYLG_ENABLE:
|
||||
#-----------------------------------------------------------------------
|
||||
# Don't do anything if PYLG is disabled
|
||||
#-----------------------------------------------------------------------
|
||||
return
|
||||
|
||||
if function is None:
|
||||
#-----------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
# If there is no function object, we need to work out
|
||||
# where the trace call was made from.
|
||||
#-----------------------------------------------------------------------
|
||||
frames_back = 1
|
||||
caller_frame = inspect.stack()[frames_back]
|
||||
# ---------------------------------------------------------------------
|
||||
frames_back = 1
|
||||
caller_frame = inspect.stack()[frames_back]
|
||||
|
||||
filename = os.path.basename(caller_frame[1])
|
||||
lineno = caller_frame[2]
|
||||
filename = os.path.basename(caller_frame[1])
|
||||
lineno = caller_frame[2]
|
||||
functionname = caller_frame[3]
|
||||
|
||||
else:
|
||||
filename = function.filename
|
||||
lineno = function.lineno
|
||||
filename = function.filename
|
||||
lineno = function.lineno
|
||||
functionname = function.functionname
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------------
|
||||
# If CLASS_NAME_RESOLUTION is enabled, the top element of the
|
||||
# stack should be the class name of the function from which this
|
||||
# trace call is made. This cannot be policed so the user must make
|
||||
# sure this is the case by ensuring that trace is only called
|
||||
# outside of any function or from within functions that have the
|
||||
# @TraceFunction decorator.
|
||||
#---------------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------------
|
||||
classname = ClassNameStack.get()
|
||||
if classname is not None and classname != "<module>":
|
||||
functionname = classname + "." + functionname
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------------
|
||||
# Generate the string based on the settings.
|
||||
# -------------------------------------------------------------------------
|
||||
msg = ""
|
||||
|
||||
if TRACE_TIME:
|
||||
msg += datetime.now().strftime(TIME_FORMAT) + " "
|
||||
|
||||
if TRACE_FILENAME:
|
||||
msg += '{filename:{w}.{w}} '.format(filename=filename,
|
||||
w=FILENAME_COLUMN_WIDTH)
|
||||
|
||||
if TRACE_LINENO:
|
||||
msg += '{lineno:0{w}}: '.format(lineno=lineno, w=LINENO_WIDTH)
|
||||
|
||||
if TRACE_FUNCTION:
|
||||
msg += '{function:{w}.{w}} '.format(function=functionname,
|
||||
w=FUNCTION_COLUMN_WIDTH)
|
||||
|
||||
if TRACE_MESSAGE:
|
||||
|
||||
message = str(message)
|
||||
|
||||
if MESSAGE_WIDTH > 0:
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Get the length of the trace line so far
|
||||
# -----------------------------------------------------------------
|
||||
premsglen = len(msg)
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Wrap the text.
|
||||
# -----------------------------------------------------------------
|
||||
wrapped = textwrap.wrap(message, MESSAGE_WIDTH)
|
||||
|
||||
if wrapped:
|
||||
if MESSAGE_WRAP:
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Print the first line. It gets special treatment
|
||||
# as it doesn't need whitespace in front of it.
|
||||
# ---------------------------------------------------------
|
||||
msg += wrapped[0]
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Print the remaining lines. Append whitespace to
|
||||
# align it with the first line.
|
||||
# ---------------------------------------------------------
|
||||
for line in wrapped[1:]:
|
||||
msg += '\n' + '{:{w}}'.format('', w=premsglen) + line
|
||||
|
||||
else:
|
||||
# ---------------------------------------------------------
|
||||
# The message is not being wrapped.
|
||||
# ---------------------------------------------------------
|
||||
|
||||
if MESSAGE_MARK_TRUNCATION and wrapped[1:]:
|
||||
# -----------------------------------------------------
|
||||
# We want to mark truncated lines so we need
|
||||
# to determine if the line is being
|
||||
# truncated. If it is we replace the last
|
||||
# character with '\'.
|
||||
# -----------------------------------------------------
|
||||
|
||||
if MESSAGE_WIDTH > 1:
|
||||
wrapped = textwrap.wrap(wrapped[0],
|
||||
MESSAGE_WIDTH - 1)
|
||||
assert wrapped
|
||||
|
||||
msg += ('{m:{w}}'.format(m=wrapped[0],
|
||||
w=MESSAGE_WIDTH - 1) +
|
||||
'\\')
|
||||
|
||||
else:
|
||||
assert MESSAGE_WIDTH == 1
|
||||
msg += '\\'
|
||||
|
||||
else:
|
||||
# -----------------------------------------------------
|
||||
# Either the message is not being truncated or
|
||||
# MESSAGE_MARK_TRUNCATION is False.
|
||||
# -----------------------------------------------------
|
||||
msg += wrapped[0]
|
||||
|
||||
else:
|
||||
# -----------------------------------------------------------------
|
||||
# A MESSAGE_WIDTH of 0 denotes no limit.
|
||||
# -----------------------------------------------------------------
|
||||
assert MESSAGE_WIDTH == 0
|
||||
msg += message
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Terminate the log line with a newline.
|
||||
# -------------------------------------------------------------------------
|
||||
msg += "\n"
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Write the data to the log file.
|
||||
#---------------------------------------------------------------------------
|
||||
PyLg.write(str(datetime.now()) + " " +
|
||||
'{filename:{w}.{w}} '.format(filename = filename,
|
||||
w = FILENAME_COLUMN_WIDTH) +
|
||||
'{0:04d}: '.format(lineno) +
|
||||
'{function:{w}.{w}} '.format(function = functionname,
|
||||
w = FUNCTION_COLUMN_WIDTH) +
|
||||
message + "\n")
|
||||
# -------------------------------------------------------------------------
|
||||
PyLg.write(msg)
|
||||
|
144
pylg/settings.py
144
pylg/settings.py
@ -1,4 +1,4 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
# PyLg: module to facilitate and automate the process of writing runtime logs.
|
||||
# Copyright (C) 2017 Wojciech Kozlowski <wojciech.kozlowski@vivaldi.net>
|
||||
#
|
||||
@ -14,43 +14,129 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#-------------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
# Enable/disable PyLg.
|
||||
#-------------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
PYLG_ENABLE = True
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Log file.
|
||||
#-------------------------------------------------------------------------------
|
||||
PYLG = 'pylg.log'
|
||||
# -----------------------------------------------------------------------------
|
||||
# The log file name.
|
||||
# -----------------------------------------------------------------------------
|
||||
PYLG_FILE = 'pylg.log'
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Enable class name resolution. Function names will be printed with
|
||||
# their class names.
|
||||
# -----------------------------------------------------------------------------
|
||||
# If True, PyLg will print a warning about every exception caught to
|
||||
# stderr.
|
||||
# -----------------------------------------------------------------------------
|
||||
EXCEPTION_WARNING = True
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# If True, PyLg will force the program to exit (and not just raise
|
||||
# SystemExit) whenever an exception occurs. This will happen even if
|
||||
# the exception would be handled at a later point.
|
||||
# -----------------------------------------------------------------------------
|
||||
EXCEPTION_EXIT = False
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Enable/disable time logging.
|
||||
# -----------------------------------------------------------------------------
|
||||
TRACE_TIME = True
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Formatting for the time trace. For a full list of options, see
|
||||
# https://docs.python.org/2/library/datetime.html#strftime-strptime-behavior.
|
||||
# -----------------------------------------------------------------------------
|
||||
TIME_FORMAT = "%Y-%m-%d %H:%M:%S.%f"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Enable/disable file name logging.
|
||||
# -----------------------------------------------------------------------------
|
||||
TRACE_FILENAME = True
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# The column width for the file name. If a name is too long, it will
|
||||
# be truncated.
|
||||
# -----------------------------------------------------------------------------
|
||||
FILENAME_COLUMN_WIDTH = 20
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Enable/disable the logging of the line number from which the trace
|
||||
# call was made. For entry and exit messages this logs the line in
|
||||
# which the decorator is placed (which should be directly above the
|
||||
# function itself).
|
||||
# -----------------------------------------------------------------------------
|
||||
TRACE_LINENO = True
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# The minimum number of digits to use to print the line number. If the
|
||||
# number is too long, more digits will be used.
|
||||
# -----------------------------------------------------------------------------
|
||||
LINENO_WIDTH = 4
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Enable/disable the logging of the function name from which the trace
|
||||
# call was made. Entry/exit logs refer to the function they enter into
|
||||
# and exit from.
|
||||
# -----------------------------------------------------------------------------
|
||||
TRACE_FUNCTION = True
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# The column width for the function name. If a name is too long, it
|
||||
# will be truncated.
|
||||
# -----------------------------------------------------------------------------
|
||||
FUNCTION_COLUMN_WIDTH = 32
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Enable/disable class name resolution. Function names will be printed
|
||||
# with their class names.
|
||||
#
|
||||
# IMPORTANT: If this setting is enabled, the trace function should
|
||||
# ONLY be called from within functions that have the @TraceFunction
|
||||
# decorator OR outside of any function.
|
||||
#-------------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
CLASS_NAME_RESOLUTION = False
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# The default for whether TraceFunction should trace function
|
||||
# parameters and return values.
|
||||
#-------------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
# Enable/disable message logging.
|
||||
# -----------------------------------------------------------------------------
|
||||
TRACE_MESSAGE = True
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# The column width for the message. A width of zero means unlimited.
|
||||
# -----------------------------------------------------------------------------
|
||||
MESSAGE_WIDTH = 0
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# If True, PyLG will wrap the message to fit within the column
|
||||
# width. Otherwise, the message will be truncated.
|
||||
# -----------------------------------------------------------------------------
|
||||
MESSAGE_WRAP = True
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# If true, truncated message lines should have the last character
|
||||
# replaced with '\'.
|
||||
# -----------------------------------------------------------------------------
|
||||
MESSAGE_MARK_TRUNCATION = True
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Enable/disable logging of the 'self' function argument.
|
||||
# -----------------------------------------------------------------------------
|
||||
TRACE_SELF = False
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# If True lists/dictionaries will be collapsed to '[ len=x ]' and '{
|
||||
# len=x }' respectively, where x denotes the number of elements in the
|
||||
# collection.
|
||||
# -----------------------------------------------------------------------------
|
||||
COLLAPSE_LISTS = False
|
||||
COLLAPSE_DICTS = False
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# The default settings for 'trace_args' and 'trace_rv' which determine
|
||||
# whether TraceFunction should trace function parameters on entry and
|
||||
# return values on exit.
|
||||
# -----------------------------------------------------------------------------
|
||||
DEFAULT_TRACE_ARGS = True
|
||||
DEFAULT_TRACE_RV = True
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Whether to warn the user when an Exception has been raised in a
|
||||
# traced funcion.
|
||||
#-------------------------------------------------------------------------------
|
||||
EXCEPTION_WARNING = True
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# The column width for file and function names.
|
||||
#-------------------------------------------------------------------------------
|
||||
FILENAME_COLUMN_WIDTH = 32
|
||||
FUNCTION_COLUMN_WIDTH = 32
|
||||
DEFAULT_TRACE_RV = True
|
||||
|
18
setup.py
18
setup.py
@ -8,15 +8,15 @@ with open(path.join(pwd, 'README.rst'), encoding='utf-8') as f:
|
||||
long_description = f.read()
|
||||
|
||||
setup(
|
||||
name = 'PyLg',
|
||||
version = '1.1.0',
|
||||
description = 'Python module to facilitate and automate the process of writing runtime logs.',
|
||||
long_description = long_description,
|
||||
url = 'https://gitlab.wojciechkozlowski.eu/wojtek/PyLg',
|
||||
name='PyLg',
|
||||
version='1.2.0',
|
||||
description='Python module to facilitate and automate the process of writing runtime logs.',
|
||||
long_description=long_description,
|
||||
url='https://gitlab.wojciechkozlowski.eu/wojtek/PyLg',
|
||||
|
||||
author = 'Wojciech Kozlowski',
|
||||
author_email = 'wojciech.kozlowski@vivaldi.net',
|
||||
classifiers = [
|
||||
author='Wojciech Kozlowski',
|
||||
author_email='wojciech.kozlowski@vivaldi.net',
|
||||
classifiers=[
|
||||
'Development Status :: 3 - Alpha',
|
||||
'Intended Audience :: Developers',
|
||||
'Topic :: Software Development :: Debuggers',
|
||||
@ -26,7 +26,7 @@ setup(
|
||||
],
|
||||
|
||||
keywords='development log debug trace',
|
||||
include_package_data = True,
|
||||
include_package_data=True,
|
||||
|
||||
packages=["pylg"]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user