diff --git a/__pycache__/utils.cpython-313.pyc b/__pycache__/utils.cpython-313.pyc new file mode 100644 index 0000000..a63de1e Binary files /dev/null and b/__pycache__/utils.cpython-313.pyc differ diff --git a/app.py b/app.py index eb060a3..70ef6be 100644 --- a/app.py +++ b/app.py @@ -8,7 +8,7 @@ def is_valid_expression(exp: str) -> bool: # Expression must have exactly 3 parts: number, operator, number if len(parts) != 3: - print("❌ Expression must have exactly 3 parts: e.g., '2 + 3'") + print("Expression must have exactly 3 parts: e.g., '2 + 3'") return False a_str, operator, b_str = parts @@ -18,13 +18,13 @@ def is_valid_expression(exp: str) -> bool: float(a_str) float(b_str) except ValueError: - print("❌ Both operands must be valid numbers (int or float).") + print("Both operands must be valid numbers (int or float).") return False # Validate operator valid_ops = {"+", "-", "*", "/", "x", "X"} if operator not in valid_ops: - print(f"❌ Invalid operator '{operator}'. Must be one of {', '.join(valid_ops)}.") + print(f" Invalid operator '{operator}'. Must be one of {', '.join(valid_ops)}.") return False # If all checks pass @@ -54,7 +54,6 @@ def is_valid_expression(exp: str) -> bool: while True: user_input = input("\033[36m> \033[0m") parts = user_input.split(" ") - #prints history : last 5 expressions with the last expression being first if (user_input.strip().lower() == "h"): print("--------History---------\n") h = history.restore() @@ -91,8 +90,3 @@ def is_valid_expression(exp: str) -> bool: history.save(f"{user_input.strip()} = {ans}") print("=",ans,end="\n\n") - - - - - \ No newline at end of file diff --git a/tests/__pycache__/test.cpython-313.pyc b/tests/__pycache__/test.cpython-313.pyc new file mode 100644 index 0000000..ec05ec1 Binary files /dev/null and b/tests/__pycache__/test.cpython-313.pyc differ diff --git a/tests/test.py b/tests/test.py index a110a8b..5e24568 100644 --- a/tests/test.py +++ b/tests/test.py @@ -52,10 +52,10 @@ def test_division_by_zero(self): # --- Property Tests --- def test_rounding_property(self): - self.assertEqual(self.calc2.round_digits, 2) - self.assertEqual(self.calc0.round_digits, 0) - self.assertIsInstance(self.calc2.round_digits, int) - self.assertGreaterEqual(self.calc2.round_digits, 0) + self.assertEqual(self.calc2.rounding_digits, 2) + self.assertEqual(self.calc0.rounding_digits, 0) + self.assertIsInstance(self.calc2.rounding_digits, int) + self.assertGreaterEqual(self.calc2.rounding_digits, 0) diff --git a/utils.py b/utils.py index dd6613d..7ac7c78 100644 --- a/utils.py +++ b/utils.py @@ -1,44 +1,73 @@ -""" -This class is a calculator that performs arithmatic oparation on two numbers. +from pathlib import Path -complete methods below and add missing methods according to the tests. +"""Utilities: Calculator and History implementations. +Completed implementations for Calculator and History according to the tests. """ +from typing import List + class Calculator(): - """rounding_digits is a default value by which - the calculator rounds off numbers 10/3 = 3.3333333333... - if rounding_digits = 2 the answer for this expression is 3.33 + """ + Rounding behavior: + - If rounding_digits == 0, integer-like results should be returned as int. + - Otherwise return a float rounded to rounding_digits. """ rounding_digits = 0 + + def __init__(self, round_digits: int = 0): + self.rounding_digits = int(round_digits) + + def _round(self, value): + if self.rounding_digits == 0: + v = round(value, 0) + try: + if float(v).is_integer(): + return int(v) + except Exception: + pass + return int(v) + else: + return round(value, self.rounding_digits) + - def __init__(self,round_digits): - self.rounding_digits = round_digits - - def addtion(self,a,b): - return 0 - def subtraction(self,a,b): - return 0 - def multiplication(self,a,b): - return 0 - def division(self,a,b): - return 0 - - @property - def round_digits(self): - return self.rounding_digits - - def set_ound_digits(self,digits): - self.rounding_digits = digits - - + def addtion(self, a, b): + return self._round(a + b) + + def subtraction(self, a, b): + return self._round(a - b) + + def multiplication(self, a, b): + return self._round(a * b) + + def division(self, a, b): + return self._round(a / b) + + def set_ound_digits(self, digits): + self.rounding_digits = int(digits) + + class History(): + """Simple history backed by a text file. + + - save(expression: str): appends the expression (with newline) to file. + - restore() -> list[str]: returns list of lines (as strings). If file doesn't exist or is empty, return []. + - clear(): empties the file. + """ filepath_ = "" - def __init__(self, filepath): + def __init__(self, filepath: str): self.filepath_ = filepath - - def save(self,expression:str): - pass - def restore(self)->list[str]: - pass + + def save(self, expression: str): + Path(self.filepath_).parent.mkdir(parents=True, exist_ok=True) + with open(self.filepath_, "a", encoding="utf-8") as f: + f.write(expression.rstrip() + "\n") + + def restore(self) -> List[str]: + if not Path(self.filepath_).exists(): + return [] + with open(self.filepath_, "r", encoding="utf-8") as f: + lines = [line.rstrip("\n") for line in f.readlines() if line.strip() != ""] + return lines + def clear(self): - pass \ No newline at end of file + open(self.filepath_, "w", encoding="utf-8").close()