Skip to content

Commit

Permalink
Merge pull request #43 from thomaseleff/v1.3.0
Browse files Browse the repository at this point in the history
v1.3.0
  • Loading branch information
thomaseleff authored Dec 6, 2024
2 parents 86e5807 + 408c5b7 commit a190258
Show file tree
Hide file tree
Showing 20 changed files with 190 additions and 104 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
__pycache__
/archive
.vscode
.pytensils
.venv
.pytest_cache
.coverage
testing.py
7 changes: 7 additions & 0 deletions pytensils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
""" pytensils
A Python package that provides general utility functions for managing
configuration, user-logging, directories and data-types as well as
a basic run-time profiler.
"""

import pytensils.config as config
import pytensils.logging as logging
import pytensils.utils as utils
Expand Down
55 changes: 38 additions & 17 deletions pytensils/config.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
"""
Information
---------------------------------------------------------------------
Name : config.py
Location : ~/
Description
---------------------------------------------------------------------
Contains the `class` methods for managing configuration.
"""
""" Configuration management """

from __future__ import annotations
import os
import json
import copy
Expand All @@ -21,6 +13,23 @@


class Handler():
""" A `class` that represents a configuration-handler.
Parameters
----------
path : `str`
Directory path to the folder that contains the `file_name` of the
'.json' config-file.
file_name : `str`
File name of the '.json' config-file.
create: `bool`
`True` or `False`, creates an empty log-file, `file_name`
within `path` when `True`.
Logging: `pytensils.logging.Handler`
An instance of the `pytensils.logging.Handler` class that allows
for native 'pretty' user-logging of all `ValidationError`
exceptions.
"""

def __init__(
self,
Expand Down Expand Up @@ -123,7 +132,8 @@ def __init__(
)

def read(self) -> dict:
""" Reads a '.json' config-file and returns the content as a `dict`.
""" Reads a '.json' config-file, updates the config data
and returns the content as a `dict`.
"""
with open(
os.path.join(
Expand Down Expand Up @@ -164,6 +174,9 @@ def read(self) -> dict:
)
)

# Update the config data
self.data = copy.deepcopy(dict_object)

return dict_object

except json.decoder.JSONDecodeError:
Expand Down Expand Up @@ -201,8 +214,7 @@ def read(self) -> dict:
)

def write(self):
""" Writes a '.json' config-file.
"""
""" Writes a '.json' config-file. """
with open(
os.path.join(
self.path,
Expand All @@ -218,17 +230,27 @@ def write(self):

def validate(
self,
dtypes: dict
dtypes: Union[dict, Handler],
) -> bool:
""" Validates the config-file data against the dtypes in `dtypes`.
Returns `True` when validation completes successfully.
Parameters
----------
dtypes : `dict`
dtypes : Union[`dict`, `pytensils.config.Handler`]
Dictionary object that contains the expected
configuration value dtypes.
"""
assert type(dtypes) in [dict, Handler], (
''.join([
'{dtypes} must be either a `dict` or an instance of',
' `pytensils.config.Handler`.'
])
)

# Parse the config data as a dictionary
if isinstance(dtypes, Handler):
dtypes = dtypes.to_dict()

# Validate instance
self._validate_instance(dict_object=dtypes, parameter='dtypes')
Expand All @@ -251,8 +273,7 @@ def validate(
return True

def to_dict(self) -> dict:
""" Returns a dictionary object of the config-file data.
"""
""" Returns a dictionary object of the config-file data. """
return copy.deepcopy(self.data)

def from_dict(
Expand Down
12 changes: 2 additions & 10 deletions pytensils/errors.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
"""
Information
---------------------------------------------------------------------
Name : errors.py
Location : ~/
Description
---------------------------------------------------------------------
Contains the `class` exceptions for all native `pytensils` errors and
all error accessor functions.
"""
""" errors """


class config:
""" A `class` that contains all config-related errors. """

# Exceptions
class OSError(OSError):
Expand Down
44 changes: 32 additions & 12 deletions pytensils/logging.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
"""
Information
---------------------------------------------------------------------
Name : logging.py
Location : ~/
Description
---------------------------------------------------------------------
Contains the `class` methods for 'pretty' user-logging.
"""
""" Pretty user-logging """

import os
import textwrap
Expand All @@ -31,16 +22,45 @@
# Setup CPython logging
pytensils = logging.getLogger('pytensils')
pytensils.setLevel(level=logging.DEBUG)

# Prevent propagation to the root logger to avoid duplicate messages
pytensils.propagate = False

# Setup a CPython logging stream handler
debugger = logging.StreamHandler()
debugger.setLevel(level=logging.DEBUG)
debugger.setFormatter(fmt=logging.Formatter('[DEBUG] %(message)s'))
pytensils.addHandler(hdlr=debugger)

# Add the handler if it does not currently exist
if not any(isinstance(h, logging.StreamHandler) for h in pytensils.handlers):
pytensils.addHandler(hdlr=debugger)

# Setup tabulate
tabulate.PRESERVE_WHITESPACE = True


class Handler():
""" A `class` that represents a logging-handler.
Parameters
----------
path : `str`
Directory path to the folder that contains the `file_name` of the
log-file.
file_name : `str`
File name of the log-file.
description : `str`
Information about the executed Python job run.
metadata : `dict`
Environment parameters to display as metadata about the executed
Python job run.
create: `bool`
`True` or `False`, creates an empty log-file, `file_name`
within `path` when `True`.
debug_console: `bool`
`True` or `False`, outputs the logging content to the console
output when `True` using `logging.debug()`.
"""

def __init__(
self,
Expand All @@ -51,7 +71,7 @@ def __init__(
create: bool = True,
debug_console: bool = False
):
""" Initializes an instance of the logger-handler class.
""" Initializes an instance of the logging-handler class.
Parameters
----------
Expand Down
13 changes: 2 additions & 11 deletions pytensils/profiler.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
"""
Information
---------------------------------------------------------------------
Name : profiler.py
Location : ~/
Description
---------------------------------------------------------------------
Contains utility functions for profiling functions.
"""
""" Run-time profiling """

import time
import datetime as dt
Expand All @@ -31,7 +22,7 @@ def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
t2 = time.time()
td = dt.timedelta(seconds=(t2-t1))
print("\n[INFO] Function {%s()} executed in %s hh:mm:ss" % (
print("\n[INFO] Function {%s()} executed in %s hh:mm:ss." % (
func.__name__,
td
)
Expand Down
18 changes: 8 additions & 10 deletions pytensils/utils.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
"""
Information
---------------------------------------------------------------------
Name : utils.py
Location : ~/
Description
---------------------------------------------------------------------
Contains utility functions for managing directories and data-types.
"""
""" Directory and data-type utilities """

import os
import ast
Expand Down Expand Up @@ -55,6 +46,7 @@ def generate_output_directory(
def as_type(
value: str,
return_dtype: Literal[
'none',
'str',
'int',
'float',
Expand Down Expand Up @@ -88,6 +80,12 @@ def as_type(
"""

try:
if (
return_dtype.strip().upper() == 'NONE'
and not ast.literal_eval(value)
):
return None

if return_dtype.strip().upper() == 'STR':
return str(value)

Expand Down
1 change: 0 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ description = A Python package that provides general utility functions for manag
long_description = file: README.md
long_description_content_type = text/markdown
author = Tom Eleff
author_email = [email protected]
url = https://github.com/thomaseleff/pytensils
project_urls =
Issues = https://github.com/thomaseleff/pytensils/issues
Expand Down
4 changes: 2 additions & 2 deletions tests/resources/closes-on-exception-filenotfounderror.log
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@

Generates close-on-exception content for `pytenstils.logging`
functionality.
Start time : 2024-07-08 18:33:26

Start time : 2024-12-06 18:04:46
10 changes: 5 additions & 5 deletions tests/resources/closes-on-exception-notimplementederror.log
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Generates close-on-exception content for `pytenstils.logging`
functionality.

Start time : 2024-07-08 18:33:26
Start time : 2024-12-06 18:04:46

--------------------------------------------------------------------------

Expand All @@ -27,9 +27,9 @@
--------

Run-time performance summary.

Start time : 18:33:26.617300
End time : 18:33:26.893199
Run time : 00:00:00.275899

Start time : 18:04:46.649282
End time : 18:04:46.847472
Run time : 00:00:00.198190

--------------------------------------------------------------------------
3 changes: 2 additions & 1 deletion tests/resources/closes-on-exception-oserror.log
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
Generates close-on-exception content for `pytenstils.logging`
functionality.

Start time : 2024-07-08 18:33:26
Start time : 2024-12-06 18:04:46

8 changes: 4 additions & 4 deletions tests/resources/closes-on-exception-success.log
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Generates close-on-exception content for `pytenstils.logging`
functionality.

Start time : 2024-07-08 18:33:25
Start time : 2024-12-06 18:04:45

--------------------------------------------------------------------------

Expand All @@ -13,8 +13,8 @@

Run-time performance summary.

Start time : 18:33:25.566032
End time : 18:33:25.737897
Run time : 00:00:00.171865
Start time : 18:04:45.812073
End time : 18:04:45.939506
Run time : 00:00:00.127433

--------------------------------------------------------------------------
2 changes: 1 addition & 1 deletion tests/resources/closes-on-exception-typeerror.log
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
Generates close-on-exception content for `pytenstils.logging`
functionality.

Start time : 2024-07-08 18:33:26
Start time : 2024-12-06 18:04:46
2 changes: 1 addition & 1 deletion tests/resources/closes-on-exception-validationerror.log
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
Generates close-on-exception content for `pytenstils.logging`
functionality.

Start time : 2024-07-08 18:33:26
Start time : 2024-12-06 18:04:46
10 changes: 5 additions & 5 deletions tests/resources/closes-on-exception.log
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Generates close-on-exception content for `pytenstils.logging`
functionality.

Start time : 2024-07-08 18:33:25
Start time : 2024-12-06 18:04:46

--------------------------------------------------------------------------

Expand All @@ -16,7 +16,7 @@
>>> ZeroDivisionError: division by zero

Filename : T:\Documents\Projects\[...]sils\tests\test_logging.py
Line Number : Line 329
Line Number : Line 361
Function : divide_by_zero()
Exception : ZeroDivisionError

Expand All @@ -27,8 +27,8 @@

Run-time performance summary.

Start time : 18:33:25.823342
End time : 18:33:26.211961
Run time : 00:00:00.388619
Start time : 18:04:46.014435
End time : 18:04:46.316471
Run time : 00:00:00.302036

--------------------------------------------------------------------------
Loading

0 comments on commit a190258

Please sign in to comment.