From fc6f4beb5b5e2dd310e919c1bf18c83106f4702d Mon Sep 17 00:00:00 2001 From: Chris Rink Date: Fri, 22 Nov 2024 13:43:44 -0500 Subject: [PATCH 1/2] Fix a bug where integer results of integer division were returned as fractions --- CHANGELOG.md | 1 + src/basilisp/lang/runtime.py | 3 ++- tests/basilisp/runtime_test.py | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e2803a82..f9478aa5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Fix a bug where tags in data readers were resolved as Vars within syntax quotes, rather than using standard data readers rules (#1129) * Fix a bug where `keyword` and `symbol` functions did not treat string arguments as potentially namespaced (#1131) * Fix a bug where `condp` would throw an exception if a result expression was `nil` (#1137) + * Fix a bug where integer division which resulted in an integer would return a `fractions.Fraction` (#1140) ## [v0.3.2] ### Added diff --git a/src/basilisp/lang/runtime.py b/src/basilisp/lang/runtime.py index c4f575cda..16f6df6ed 100644 --- a/src/basilisp/lang/runtime.py +++ b/src/basilisp/lang/runtime.py @@ -1655,7 +1655,8 @@ def divide(x: LispNumber, y: LispNumber) -> LispNumber: @divide.register(int) def _divide_ints(x: int, y: LispNumber) -> LispNumber: if isinstance(y, int): - return Fraction(x, y) + frac = Fraction(x, y) + return frac.numerator if frac.is_integer() else frac return x / y diff --git a/tests/basilisp/runtime_test.py b/tests/basilisp/runtime_test.py index f736b5fda..311551768 100644 --- a/tests/basilisp/runtime_test.py +++ b/tests/basilisp/runtime_test.py @@ -1,3 +1,4 @@ +import fractions import platform import sys from decimal import Decimal @@ -599,6 +600,23 @@ def test_not_equals(v1, v2): assert not runtime.equals(v2, v1) +@pytest.mark.parametrize( + "v1,v2,expected_result,result_type", + [ + (3, 3, 1, int), + (3, 1, 3, int), + (3, 1.001, 3 / 1.001, float), + (3000, 1000, 3, int), + (3000, 1001, fractions.Fraction(3000, 1001), fractions.Fraction), + (3001, 1000, fractions.Fraction(3001, 1000), fractions.Fraction), + ], +) +def test_divide(v1, v2, expected_result, result_type): + result = runtime.divide(v1, v2) + assert result == expected_result + assert isinstance(result, result_type) + + def test_pop_thread_bindings(): with pytest.raises(runtime.RuntimeException): runtime.pop_thread_bindings() From 01f06373167b0156409700a8b27274719a5f8b3d Mon Sep 17 00:00:00 2001 From: Chris Rink Date: Fri, 22 Nov 2024 13:45:37 -0500 Subject: [PATCH 2/2] Fix --- src/basilisp/lang/runtime.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/basilisp/lang/runtime.py b/src/basilisp/lang/runtime.py index 16f6df6ed..c05067ad7 100644 --- a/src/basilisp/lang/runtime.py +++ b/src/basilisp/lang/runtime.py @@ -1656,7 +1656,8 @@ def divide(x: LispNumber, y: LispNumber) -> LispNumber: def _divide_ints(x: int, y: LispNumber) -> LispNumber: if isinstance(y, int): frac = Fraction(x, y) - return frac.numerator if frac.is_integer() else frac + # fractions.Fraction.is_integer() wasn't added until 3.12 + return frac.numerator if frac.denominator == 1 else frac return x / y