Skip to content

Commit

Permalink
Merge pull request #64 from python-thread/feature/verbosity-setting
Browse files Browse the repository at this point in the history
Feature: verbosity setting
  • Loading branch information
caffeine-addictt authored Mar 12, 2024
2 parents 669bc5b + 0e87ae8 commit 5e31ddb
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 5 deletions.
11 changes: 7 additions & 4 deletions src/thread/thread.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ def wrapper(

except SystemExit:
self.status = 'Killed'
print('KILLED ident: %s' % self.ident)
if Settings.VERBOSITY > 'quiet':
print('KILLED ident: %s' % self.ident)
return

return wrapper
Expand Down Expand Up @@ -532,8 +533,9 @@ def start(self) -> None:
# Handle abrupt exit
def service_shutdown(signum, frame):
if Settings.GRACEFUL_EXIT_ENABLED:
print('\nCaught signal %d' % signum)
print('Gracefully killing active threads')
if Settings.VERBOSITY > 'quiet':
print('\nCaught signal %d' % signum)
print('Gracefully killing active threads')

for thread in Threads:
if isinstance(thread, Thread):
Expand All @@ -545,7 +547,8 @@ def service_shutdown(signum, frame):
):
pass
except Exception:
print('Failed to kill ident: %d' % thread.ident or 0)
if Settings.VERBOSITY > 'quiet':
print('Failed to kill ident: %d' % thread.ident or 0)
sys.exit(0)


Expand Down
1 change: 1 addition & 0 deletions src/thread/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
from .config import Settings

from . import (
config,
algorithm,
)
143 changes: 142 additions & 1 deletion src/thread/utils/config.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,155 @@
from typing import Any, Callable, Literal, Union

_Verbosity_Num = Literal[0, 1, 2]
_Verbosity_Enum = Literal['quiet', 'normal', 'verbose']
VerbosityLevel = Union[_Verbosity_Num, _Verbosity_Enum]
VerbosityMapping: dict[_Verbosity_Enum, _Verbosity_Num] = {
'quiet': 0,
'normal': 1,
'verbose': 2,
}


class Verbosity:
"""
# Verbosity
Can be instantiated with and compared against a number or an enum.
"""

level_number: _Verbosity_Num
level_string: _Verbosity_Enum

def __init__(self, level: VerbosityLevel) -> None:
"""
Initializes the verbosity object.
Parameters
----------
:param level: The level of verbosity. Can be a number or an enum.
Raises
------
ValueError: If the level is not a valid number or enum.
ValueError: If the level is not of a valid type.
"""
if isinstance(level, str):
if level not in VerbosityMapping.keys():
raise ValueError('Invalid verbosity level')
self.level_string = level
self.level_number = VerbosityMapping[level]
elif isinstance(level, int):
if level not in VerbosityMapping.values():
raise ValueError('Invalid verbosity level')
self.level_number = level
self.level_string = list(VerbosityMapping.keys())[level]
else:
raise ValueError(f'{type(level)} is not a valid verbosity level')

def __str__(self) -> str:
return self.level_string

def __eq__(self, other: Any) -> bool:
try:
return self._compare(other, lambda a, b: a == b)
except ValueError:
return False

def __lt__(self, other: Any) -> bool:
return self._compare(other, lambda a, b: a < b)

def __le__(self, other: Any) -> bool:
return self._compare(other, lambda a, b: a <= b)

def __gt__(self, other: Any) -> bool:
return self._compare(other, lambda a, b: a > b)

def __ge__(self, other: Any) -> bool:
return self._compare(other, lambda a, b: a >= b)

def __ne__(self, other: Any) -> bool:
return not self.__eq__(other)

def _compare(
self, other: Any, operator: Callable[[VerbosityLevel, Any], bool]
) -> bool:
if isinstance(other, Verbosity):
return operator(self.level_number, other.level_number)
if isinstance(other, int):
return operator(self.level_number, other)
if isinstance(other, str):
if Verbosity.is_valid_level(other):
return operator(self.level_number, VerbosityMapping[other])
return operator(self.level_string, other)
raise ValueError('Cannot compare Verbosity with other types')

@staticmethod
def is_valid_level(level: Any) -> bool:
"""
Determines whether the given level is a valid verbosity level.
Parameters
----------
:param level: The level to check.
Returns
-------
:returns: True if the level is a valid verbosity level, False otherwise.
"""
if isinstance(level, int):
return level in VerbosityMapping.values()
if isinstance(level, str):
return level in VerbosityMapping.keys()
return False


class Settings:
"""
# Settings
`Non Instantiable`
"""

# Verbosity
VerbosityLevel = VerbosityLevel
VERBOSITY: Verbosity = Verbosity(1)

# Graceful Exit
GRACEFUL_EXIT_ENABLED: bool = True

def __init__(self):
raise NotImplementedError('This class is not instantiable')

@staticmethod
def set_graceful_exit(enabled: bool = True):
def set_graceful_exit(enabled: bool = True) -> None:
"""
Enables/Disables graceful exiting.
Parameters
----------
:param enabled: True to enable graceful exit, False otherwise.
Returns
-------
:returns: None
"""
Settings.GRACEFUL_EXIT_ENABLED = enabled

@staticmethod
def set_verbosity(verbosity: VerbosityLevel = 'normal') -> None:
"""
Sets the verbosity level.
Parameters
----------
:param verbosity: The level of verbosity. Can be a number or an enum.
Returns
-------
:returns: None
Raises
------
ValueError: If the level is not a valid number or enum.
ValueError: If the level is not of a valid type.
"""
Settings.VERBOSITY = Verbosity(verbosity)
66 changes: 66 additions & 0 deletions tests/test_verbosity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import pytest
from src.thread.utils.config import Verbosity


# >>>>>>>>>> General Use <<<<<<<<<< #
def test_eqTrue():
assert Verbosity(0) == 0
assert Verbosity(0) == 'quiet'
assert Verbosity(1) == 'normal'
assert Verbosity(1) == Verbosity(1)


def test_neTrue():
assert Verbosity(0) != 1
assert Verbosity(0) != 'normal'
assert Verbosity(1) != 'quiet'
assert Verbosity(1) != Verbosity(0)


def test_ltTrue():
assert Verbosity(0) < 1
assert Verbosity(0) < 'normal'
assert Verbosity(1) < 'verbose'
assert Verbosity(1) < Verbosity(2)


def test_leTrue():
assert Verbosity(0) <= 1
assert Verbosity(0) <= 'normal'
assert Verbosity(1) <= 'verbose'
assert Verbosity(1) <= Verbosity(2)


def test_gtTrue():
assert Verbosity(1) > 0
assert Verbosity(1) > 'quiet'
assert Verbosity(2) > 'normal'
assert Verbosity(2) > Verbosity(1)


def test_geTrue():
assert Verbosity(1) >= 0
assert Verbosity(1) >= 'quiet'
assert Verbosity(2) >= 'normal'
assert Verbosity(2) >= Verbosity(1)


# >>>>>>>>>> Raising <<<<<<<<<< #
def test_ltRaise():
with pytest.raises(ValueError):
Verbosity(0) < Exception()


def test_leRaise():
with pytest.raises(ValueError):
Verbosity(0) <= Exception()


def test_gtRaise():
with pytest.raises(ValueError):
Verbosity(1) > Exception()


def test_geRaise():
with pytest.raises(ValueError):
Verbosity(1) >= Exception()

0 comments on commit 5e31ddb

Please sign in to comment.