diff --git a/src/moneyx/core.py b/src/moneyx/core.py index fb53761..69a795b 100644 --- a/src/moneyx/core.py +++ b/src/moneyx/core.py @@ -444,7 +444,12 @@ def from_json(cls: Type[T], json_str: str) -> T: return from_json(cls, json_str) - def _validate_precision(self, amount: Decimal, currency: Currency, rounding_mode: RoundingModeStr) -> None: + def _validate_precision( + self, + amount: Decimal, + currency: Currency, + rounding_mode: RoundingModeStr, + ) -> None: """ Validate that the amount has the correct precision for the currency. diff --git a/tests/test_edge_cases.py b/tests/test_edge_cases.py index a5d0331..f62514f 100644 --- a/tests/test_edge_cases.py +++ b/tests/test_edge_cases.py @@ -83,34 +83,69 @@ def test_half_odd_rounding(self): def test_special_decimal_cases(self): """Test special cases for decimal rounding.""" # Test already correctly rounded values - assert apply_rounding(Decimal("2.00"), RoundingMode.HALF_UP, 2) == Decimal("2.00") + assert apply_rounding(Decimal("2.00"), RoundingMode.HALF_UP, 2) == Decimal( + "2.00", + ) assert apply_rounding(Decimal("2"), RoundingMode.HALF_UP, 0) == Decimal("2") - + # Test special cases with non-int exponents (NaN, Infinity) - we just want to ensure no errors # and proper handling - these should fall back to 0 decimal places as a safe default try: special_decimal = Decimal("NaN") - result = apply_rounding(special_decimal, RoundingMode.HALF_UP, 2) + # Just call the function without assigning to a variable we don't use + apply_rounding(special_decimal, RoundingMode.HALF_UP, 2) # We don't need to assert the exact result, just that it handled the case except Exception: pytest.fail("apply_rounding should handle special Decimal values") - + def test_half_towards_zero_rounding(self): """Test the HALF_TOWARDS_ZERO rounding mode.""" # Test with exactly 0.5 - should round towards zero - assert apply_rounding(Decimal("2.5"), RoundingMode.HALF_TOWARDS_ZERO, 0) == Decimal("2") - assert apply_rounding(Decimal("-2.5"), RoundingMode.HALF_TOWARDS_ZERO, 0) == Decimal("-2") - + assert apply_rounding( + Decimal("2.5"), + RoundingMode.HALF_TOWARDS_ZERO, + 0, + ) == Decimal("2") + assert apply_rounding( + Decimal("-2.5"), + RoundingMode.HALF_TOWARDS_ZERO, + 0, + ) == Decimal("-2") + # Test with non-half values - should use HALF_UP - assert apply_rounding(Decimal("2.4"), RoundingMode.HALF_TOWARDS_ZERO, 0) == Decimal("2") - assert apply_rounding(Decimal("2.6"), RoundingMode.HALF_TOWARDS_ZERO, 0) == Decimal("3") - + assert apply_rounding( + Decimal("2.4"), + RoundingMode.HALF_TOWARDS_ZERO, + 0, + ) == Decimal("2") + assert apply_rounding( + Decimal("2.6"), + RoundingMode.HALF_TOWARDS_ZERO, + 0, + ) == Decimal("3") + def test_half_away_from_zero_rounding(self): """Test the HALF_AWAY_FROM_ZERO rounding mode.""" # Test with exactly 0.5 - should round away from zero - assert apply_rounding(Decimal("2.5"), RoundingMode.HALF_AWAY_FROM_ZERO, 0) == Decimal("3") - assert apply_rounding(Decimal("-2.5"), RoundingMode.HALF_AWAY_FROM_ZERO, 0) == Decimal("-3") - + assert apply_rounding( + Decimal("2.5"), + RoundingMode.HALF_AWAY_FROM_ZERO, + 0, + ) == Decimal("3") + assert apply_rounding( + Decimal("-2.5"), + RoundingMode.HALF_AWAY_FROM_ZERO, + 0, + ) == Decimal("-3") + # Test with non-half values - should use HALF_UP - assert apply_rounding(Decimal("2.4"), RoundingMode.HALF_AWAY_FROM_ZERO, 0) == Decimal("2") - assert apply_rounding(Decimal("2.6"), RoundingMode.HALF_AWAY_FROM_ZERO, 0) == Decimal("3") + assert apply_rounding( + Decimal("2.4"), + RoundingMode.HALF_AWAY_FROM_ZERO, + 0, + ) == Decimal("2") + assert apply_rounding( + Decimal("2.6"), + RoundingMode.HALF_AWAY_FROM_ZERO, + 0, + ) == Decimal("3") diff --git a/tests/test_missing_coverage.py b/tests/test_missing_coverage.py index 40e4677..3193e8c 100644 --- a/tests/test_missing_coverage.py +++ b/tests/test_missing_coverage.py @@ -7,8 +7,8 @@ from moneyx import Money from moneyx.bulk import bulk_add, bulk_allocate, bulk_multiply, bulk_with_tax from moneyx.exceptions import SerializationError -from moneyx.serialization import from_dict, from_json, to_json from moneyx.rounding import RoundingMode +from moneyx.serialization import from_dict, from_json, to_json class TestComparisons: @@ -357,24 +357,24 @@ def test_distribute_remainder_negative(self): m = Money("10.00", "USD") amounts = [Decimal("3.33"), Decimal("3.33"), Decimal("3.34")] unit = Decimal("0.01") - + # Call the internal method directly with is_positive=False m._distribute_remainder(amounts, 0, False, unit) - + # Check that the amount was decreased by the unit assert amounts[0] == Decimal("3.32") assert amounts[1] == Decimal("3.33") assert amounts[2] == Decimal("3.34") - + def test_distribute_remainder_positive(self): """Test distributing positive remainders to amounts.""" m = Money("10.00", "USD") amounts = [Decimal("3.33"), Decimal("3.33"), Decimal("3.33")] unit = Decimal("0.01") - + # Call the internal method directly with is_positive=True m._distribute_remainder(amounts, 0, True, unit) - + # Check that the amount was increased by the unit assert amounts[0] == Decimal("3.34") assert amounts[1] == Decimal("3.33") @@ -383,28 +383,30 @@ def test_distribute_remainder_positive(self): class TestValidatePrecision: """Test the _validate_precision method directly to increase coverage.""" - + def test_non_int_exponent_handling(self): """Test _validate_precision with non-integer exponents.""" from decimal import Decimal + from moneyx.core import Money - from moneyx.rounding import RoundingMode - + m = Money("10.00", "USD") - + # Create a Decimal with a non-int exponent # We'll mock a non-int exponent by adding a patch class MockDecimal(Decimal): def as_tuple(self): result = super().as_tuple() + # Return an object with a non-int exponent attribute class Tuple: def __init__(self, sign, digits, exponent): self.sign = sign self.digits = digits self.exponent = "n" # Non-int exponent + return Tuple(result.sign, result.digits, "n") - + # Test the method directly amount = MockDecimal("123.456") m._validate_precision(amount, m.currency, RoundingMode.HALF_UP) diff --git a/tests/test_serialization.py b/tests/test_serialization.py index 5cd5111..976574e 100644 --- a/tests/test_serialization.py +++ b/tests/test_serialization.py @@ -62,13 +62,20 @@ def test_from_dict_invalid_types(self): # Test with invalid currency type with pytest.raises(SerializationError) as exc_info: - data = {"amount": "10.00", "currency": 123} # Integer is not a valid currency + data = { + "amount": "10.00", + "currency": 123, + } # Integer is not a valid currency from_dict(Money, data) assert "Currency code must be string" in str(exc_info.value) # Test with invalid rounding type with pytest.raises(SerializationError) as exc_info: - data = {"amount": "10.00", "currency": "USD", "rounding": 123} # Integer is not valid rounding + data = { + "amount": "10.00", + "currency": "USD", + "rounding": 123, + } # Integer is not valid rounding from_dict(Money, data) assert "Rounding mode must be string" in str(exc_info.value) @@ -189,17 +196,17 @@ def test_money_from_json_method(self): def test_from_dict_money_creation_error(self): """Test from_dict error handling for Money creation failure.""" from moneyx.exceptions import SerializationError - + # This will fail when creating the Money object because "XYZ" is not a valid currency with pytest.raises(SerializationError) as exc_info: data = {"amount": "10.00", "currency": "XYZ", "rounding": "HALF_UP"} from_dict(Money, data) assert "Failed to create Money object" in str(exc_info.value) - + def test_invalid_rounding_mode(self): """Test from_dict with invalid rounding mode.""" from moneyx.exceptions import SerializationError - + with pytest.raises(SerializationError) as exc_info: data = {"amount": "10.00", "currency": "USD", "rounding": "INVALID_MODE"} from_dict(Money, data)