Skip to content

Commit

Permalink
Merge pull request #12 from JordanWelsman/0.4-bugfixes
Browse files Browse the repository at this point in the history
Merging now.
  • Loading branch information
JordanWelsman authored Feb 18, 2023
2 parents df25946 + 20ee75b commit c6449ec
Show file tree
Hide file tree
Showing 17 changed files with 202 additions and 41 deletions.
2 changes: 1 addition & 1 deletion jutl/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Dunder attributes
__version__ = "0.4.0"
__version__ = "0.4.1"
__author__ = "Jordan Welsman"
__license__ = "MIT"
__copyright__ = "Copyright 2020 Jordan Welsman"
Empty file added jutl/datastructures/__init__.py
Empty file.
10 changes: 10 additions & 0 deletions jutl/exceptions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Import submodule files so
# classes and functions are usable at
# 'from jutl.exceptions import _' level.
from .emptypipeline import *
from .invalidformatting import *
from .missinginput import *

# Only show functions specified in
# submodule files to the outside world.
__all__ = emptypipeline.__all__, invalidformatting.__all__, missinginput.__all__
8 changes: 8 additions & 0 deletions jutl/exceptions/emptypipeline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Module imports

# External class visibility
__all__ = ['EmptyPipelineError']

class EmptyPipelineError(Exception):
def __init__(self, message):
self.message = message
8 changes: 8 additions & 0 deletions jutl/exceptions/invalidformatting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Module imports

# External class visibility
__all__ = ['InvalidFormattingError']

class InvalidFormattingError(Exception):
def __init__(self, message):
self.message = message
8 changes: 8 additions & 0 deletions jutl/exceptions/missinginput.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Module imports

# External class visibility
__all__ = ['MissingInputError']

class MissingInputError(Exception):
def __init__(self, message):
self.message = message
16 changes: 13 additions & 3 deletions jutl/formatting/utils.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
from .color import Text, Background
from .text import Typography, Reset
from jutl.exceptions import InvalidFormattingError

__all__ = ['apply', 'test']

def apply(text: str, text_color: str = None, background_color: str = None, typography: str = None) -> str:
formatting = ""

if text_color is not None:
formatting += Text.colors[text_color.upper()] if text_color.upper() in Text.colors else ''
if text_color.upper() in Text.colors:
formatting += Text.colors[text_color.upper()]
else:
raise InvalidFormattingError(f"Color not found: {text_color}")
if background_color is not None:
formatting += Background.colors[background_color.upper()] if background_color.upper() in Background.colors else ''
if background_color.upper() in Background.colors:
formatting += Background.colors[background_color.upper()]
else:
raise InvalidFormattingError(f"Color not found: {background_color}")
if typography is not None:
formatting += Typography.types[typography.upper()] if typography.upper() in Typography.types else ''
if typography.upper() in Typography.types:
formatting += Typography.types[typography.upper()]
else:
raise InvalidFormattingError(f"Type not found: {typography}")
return formatting + text + Reset.types['ALL']

def test():
Expand Down
7 changes: 6 additions & 1 deletion jutl/pipelining/datapipeline.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Module imports
from jutl.pipelining.instructionpipeline import InstructionPipeline
from jutl.exceptions import EmptyPipelineError, MissingInputError

# External class visibility
__all__ = ['DataPipeline']
Expand Down Expand Up @@ -33,12 +34,16 @@ def __call__(self, *data):
with passed data.
"""
results: list = []
if len(data) < 1:
raise MissingInputError("No input data passed to data pipeline.")
if len(self.functions) < 1:
raise EmptyPipelineError("No functions added to data pipeline.")
for datum in data:
match type(datum).__name__:
case "int" | "float":
for function in self.functions:
datum = function(datum)
results.append(datum)
case other:
print(f"Data type ({other}) is not supported.")
raise TypeError(f"Unknown data type passed to instruction pipeline: {other}.")
return results
10 changes: 7 additions & 3 deletions jutl/pipelining/instructionpipeline.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Module imports
from jutl.exceptions import EmptyPipelineError, MissingInputError

# External class visibility
__all__ = ['InstructionPipeline']
Expand Down Expand Up @@ -31,21 +32,24 @@ def __repr__(self) -> str:
else:
return f"InstructionPipeline({self.name})"

def __call__(self, data: None) -> None:
def __call__(self, data = None) -> None:
"""
Executes the pipeline
with passed data.
"""
if data is None:
raise MissingInputError("No input data passed to instruction pipeline.")
if len(self.functions) < 1:
return data
raise EmptyPipelineError("No functions added to instruction pipeline.")
else:
match type(data).__name__:
case "int" | "float":
for function in self.functions:
data = function(data)
case other:
print(f"Data type ({other}) is not supported.")
raise TypeError(f"Unknown data type passed to instruction pipeline: {other}.")
return data


def __len__(self) -> int:
"""
Expand Down
45 changes: 30 additions & 15 deletions jutl/timers/stopwatch.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Module imports
from jutl.formatting import apply
from time import time

# External class visibility
Expand Down Expand Up @@ -35,15 +36,18 @@ def __repr__(self) -> str:
else:
return f"Stopwatch({self.name}, {round(self.total_time, 2)}s)"

def __call__(self):
def __call__(self, color: str = None):
"""
Tells the interpreter what to
do when an object of this
class is called directly.
"""
if self.lap_times:
for n, time in enumerate(self.lap_times):
print(f"Lap {n+1}: {round(time, 2)}s")
if color:
print(apply(text=f"Lap {n+1}: {round(time, 2)}s", text_color=color))
else:
print(f"Lap {n+1}: {round(time, 2)}s")
else:
print("There are no lap times.")

Expand Down Expand Up @@ -129,19 +133,22 @@ def __truediv__(self, other) -> float:
return self.total_time / other.total_time


def start(self):
def start(self, message: str = None, color: str = None):
"""
Starts the stopwatch by
initializing an object attribute.
Starts the stopwatch and
optionally prints a message.
"""
self._start_time = time()
if message:
print(apply(text=message, text_color=color) if color else print(message))


def lap(self, lap_time: float = None):
def lap(self, lap_time: float = None, message: str = None, color: str = None):
"""
Adds the current time to the lap time
list and records the time since the
start or time of the last recorded lap.
Adds the current time to the lap
time list, records the time since
the start or time of the last recorded
lap, and optionally prints a message.
"""
if lap_time:
self._laps.append(lap_time)
Expand All @@ -151,16 +158,21 @@ def lap(self, lap_time: float = None):
self.lap_times.append(self._calculate_time(self._start_time, self._laps[-1]))
else:
self.lap_times.append(self._calculate_time(self._laps[-2], self._laps[-1]))
if message:
print(apply(text=message, text_color=color) if color else print(message))


def stop(self):
def stop(self, message: str = None, color: str = None):
"""
Stops the stopwatch and calculates
the total time passed.
Stops the stopwatch, calculates
the total time passed, and
optionally prints a message.
"""
self._stop_time = time()
self.total_time = self._calculate_time(self._start_time, self._stop_time)
self.lap(self._stop_time)
self.lap(self._stop_time) # add final lap time and calculate lap difference
if message:
print(apply(text=message, text_color=color) if color else print(text=message))


def _calculate_time(self, time1: float, time2: float) -> float:
Expand All @@ -170,12 +182,15 @@ def _calculate_time(self, time1: float, time2: float) -> float:
return time2 - time1


def reset(self):
def reset(self, message: str = None, color: str = None):
"""
Resets all stopwatch attributes.
Resets all stopwatch attributes
and optionally prints a message.
"""
self._start_time = None
self._stop_time = None
self.total_time = None
self._laps.clear()
self.lap_times.clear()
if message:
print(apply(text=message, text_color=color) if color else print(text=message))
46 changes: 32 additions & 14 deletions jutl/timers/timer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Module imports
from jutl.formatting import apply
from time import time, sleep

# External class visibility
Expand Down Expand Up @@ -35,14 +36,17 @@ def __repr__(self) -> str:
else:
return f"Timer({self.name}, {round(self.total_time, 2)}s)"

def __call__(self):
def __call__(self, color: str = None):
"""
Tells the interpreter what to
do when an object of this
class is called directly.
"""
if self.total_time:
print(f"{self.name} total time: {round(self.total_time, 2)}s")
if color:
print(apply(text=f"{self.name} total time: {round(self.total_time, 2)}s", text_color=color))
else:
print(f"{self.name} total time: {round(self.total_time, 2)}s")
else:
print("There is no recorded time.")

Expand Down Expand Up @@ -125,42 +129,53 @@ def __truediv__(self, other) -> float:
return self.total_time / other.total_time


def start(self):
def start(self, message: str = None, color: str = None):
"""
Starts the timer by
initializing an object attribute.
Starts the timer and
optionally prints a message.
"""
self._start_time = time()
if message:
print(apply(text=message, text_color=color) if color else print(message))


def pause(self, duration: float = None):
def pause(self, duration: float = None, message: str = None, color: str = None):
"""
Pauses the timer.
Pauses the timer and
optionally prints a message.
"""
self._pause_time = time()
if duration:
sleep(duration)
if message:
print(apply(text=message, text_color=color) if color else print(text=message))


def resume(self):
def resume(self, message: str = None, color: str = None):
"""
Resumes the timer.
Resumes the timer and
optionally prints a message.
"""
if self._paused_time:
self._paused_time += self._calculate_time(self._pause_time, time())
else:
self._paused_time = self._calculate_time(self._pause_time, time())
if message:
print(apply(text=message, text_color=color) if color else print(text=message))


def stop(self):
def stop(self, message: str = None, color: str = None):
"""
Stops the timer and calculates
the total time passed.
Stops the timer, calculates
the total time passed, and
optionally prints a message.
"""
if self._pause_time and not self._paused_time: # if stopped while paused
self.resume()
self._stop_time = time()
self.total_time = self._calculate_time(self._start_time, self._stop_time)
if message:
print(apply(text=message, text_color=color) if color else print(text=message))


def _calculate_time(self, time1: float, time2: float) -> float:
Expand All @@ -170,12 +185,15 @@ def _calculate_time(self, time1: float, time2: float) -> float:
return time2 - time1


def reset(self):
def reset(self, message: str = None, color: str = None):
"""
Resets all timer attributes.
Resets all timer attributes
and optionally prints a message.
"""
self._start_time = None
self._pause_time = None
self._paused_time = None
self._stop_time = None
self.total_time = None
if message:
print(apply(text=message, text_color=color) if color else print(text=message))
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Arguments
git_name = "jutils"
pypi_name = "jutl"
version = "0.4.0" # update __init__.py
version = "0.4.1" # update __init__.py
python_version = ">=3.10"

# Long description from README.md
Expand All @@ -17,6 +17,7 @@
'calculators/*',
'converters/*',
'cryptography/*',
'datastructures/*',
'formatting/*',
'language/*',
'logic/*',
Expand Down
12 changes: 12 additions & 0 deletions test/exceptions/test_emptypipeline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#jutils/test/exceptions/test_emptypipeline.py
from jutl.exceptions import EmptyPipelineError

test_message = "Test message"
def func():
raise EmptyPipelineError(test_message)

class TestException():
def test_message(self):
"Tests if the exception message is correct."
exception = EmptyPipelineError(test_message)
assert exception.message == test_message
12 changes: 12 additions & 0 deletions test/exceptions/test_invalidformatting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#jutils/test/exceptions/test_invalidformatting.py
from jutl.exceptions import InvalidFormattingError

test_message = "Test message"
def func():
raise InvalidFormattingError(test_message)

class TestException():
def test_message(self):
"Tests if the exception message is correct."
exception = InvalidFormattingError(test_message)
assert exception.message == test_message
Loading

0 comments on commit c6449ec

Please sign in to comment.