mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Use builtin SWIG conversions for glib types
Where possible in the Python SWIG code use the builtin SWIG conversion code over custom code. This ensures appropriate overflow/type checking. With this I have enabled GncNumeric from longs and tested for correct overflow handling. Note: This could be extended to GUILE but I am not familiar enought to safely enable this.
This commit is contained in:
@@ -294,7 +294,7 @@ class GncNumeric(GnuCashCoreClass):
|
||||
return gnc_numeric_zero()
|
||||
elif len(args) == 1:
|
||||
arg = args[0]
|
||||
if type(arg) == int:
|
||||
if type(arg) in (int, long):
|
||||
return gnc_numeric_create(arg ,1)
|
||||
elif type(arg) == float:
|
||||
return double_to_gnc_numeric(arg, GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER)
|
||||
|
||||
@@ -13,6 +13,7 @@ SET(test_python_bindings_DATA
|
||||
test_book.py
|
||||
test_business.py
|
||||
test_commodity.py
|
||||
test_numeric.py
|
||||
test_split.py
|
||||
test_transaction.py)
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ EXTRA_DIST = \
|
||||
test_account.py \
|
||||
test_book.py \
|
||||
test_split.py \
|
||||
test_commodity.py \
|
||||
test_numeric.py \
|
||||
test_transaction.py \
|
||||
test_business.py \
|
||||
CMakeLists.txt
|
||||
|
||||
106
bindings/python/tests/test_numeric.py
Normal file
106
bindings/python/tests/test_numeric.py
Normal file
@@ -0,0 +1,106 @@
|
||||
from unittest import TestCase, main
|
||||
|
||||
from gnucash import GncNumeric, GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED, \
|
||||
GNC_HOW_RND_NEVER, GNC_HOW_RND_FLOOR, GNC_HOW_RND_CEIL
|
||||
|
||||
class TestGncNumeric( TestCase ):
|
||||
def test_defaut(self):
|
||||
num = GncNumeric()
|
||||
self.assertEqual(str(num), "0/1")
|
||||
self.assertEqual(num.num(), 0)
|
||||
self.assertEqual(num.denom(), 1)
|
||||
|
||||
def test_from_num_denom(self):
|
||||
num = GncNumeric(1, 2)
|
||||
self.assertEqual(str(num), "1/2")
|
||||
self.assertEqual(num.num(), 1)
|
||||
self.assertEqual(num.denom(), 2)
|
||||
|
||||
def test_from_int(self):
|
||||
num = GncNumeric(3)
|
||||
self.assertEqual(str(num), "3/1")
|
||||
self.assertEqual(num.num(), 3)
|
||||
self.assertEqual(num.denom(), 1)
|
||||
|
||||
def test_from_long(self):
|
||||
num = GncNumeric(3L)
|
||||
self.assertEqual(str(num), "3/1")
|
||||
self.assertEqual(num.num(), 3)
|
||||
self.assertEqual(num.denom(), 1)
|
||||
|
||||
#One might think this would be an overflow error, but SWIG type-checks
|
||||
#it first and discovers that it's too big to be an int64_t.
|
||||
with self.assertRaises(TypeError):
|
||||
GncNumeric((2**64)+1)
|
||||
|
||||
def test_from_float(self):
|
||||
num = GncNumeric(3.1, 20, GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER)
|
||||
self.assertEqual(str(num), "62/20")
|
||||
self.assertEqual(num.num(), 62)
|
||||
self.assertEqual(num.denom(), 20)
|
||||
|
||||
num = GncNumeric(1/3.0, 10000000000, GNC_HOW_RND_FLOOR)
|
||||
self.assertEqual(str(num), "3333333333/10000000000")
|
||||
self.assertEqual(num.num(), 3333333333)
|
||||
self.assertEqual(num.denom(), 10000000000)
|
||||
|
||||
num = GncNumeric(1/3.0, 10000000000, GNC_HOW_RND_CEIL)
|
||||
self.assertEqual(str(num), "3333333334/10000000000")
|
||||
self.assertEqual(num.num(), 3333333334)
|
||||
self.assertEqual(num.denom(), 10000000000)
|
||||
|
||||
def test_from_float_auto(self):
|
||||
num = GncNumeric(3.1)
|
||||
self.assertEqual(str(num), "31/10")
|
||||
self.assertEqual(num.num(), 31)
|
||||
self.assertEqual(num.denom(), 10)
|
||||
|
||||
def test_from_instance(self):
|
||||
orig = GncNumeric(3)
|
||||
num = GncNumeric(instance=orig.instance)
|
||||
self.assertEqual(str(num), "3/1")
|
||||
self.assertEqual(num.num(), 3)
|
||||
self.assertEqual(num.denom(), 1)
|
||||
|
||||
def test_from_str(self):
|
||||
num = GncNumeric("3.1")
|
||||
self.assertEqual(str(num), "31/10")
|
||||
self.assertEqual(num.num(), 31)
|
||||
self.assertEqual(num.denom(), 10)
|
||||
|
||||
num = GncNumeric("1/3")
|
||||
self.assertEqual(str(num), "1/3")
|
||||
self.assertEqual(num.num(), 1)
|
||||
self.assertEqual(num.denom(), 3)
|
||||
|
||||
def test_to_str(self):
|
||||
num = GncNumeric("1000/3")
|
||||
self.assertEqual(str(num), "1000/3")
|
||||
|
||||
num = GncNumeric(1, 0)
|
||||
self.assertEqual(str(num), "1/0")
|
||||
|
||||
def test_to_double(self):
|
||||
for test_num in [0.0, 1.1, -1.1, 1/3.0]:
|
||||
self.assertEqual(GncNumeric(test_num).to_double(), test_num)
|
||||
|
||||
def test_to_fraction(self):
|
||||
fraction = GncNumeric("1000/3").to_fraction()
|
||||
self.assertEqual(fraction.numerator, 1000)
|
||||
self.assertEqual(fraction.denominator, 3)
|
||||
|
||||
def test_incorect_args(self):
|
||||
with self.assertRaises(TypeError):
|
||||
GncNumeric(1, 2, 3)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
GncNumeric("1", 2)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
GncNumeric(1.1, "round")
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
GncNumeric(complex(1, 1))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user