mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Merge Christoph Holterman's 'python-gnc-numeric' into maint.
This commit is contained in:
commit
7fbbd6e745
@ -28,6 +28,8 @@
|
||||
# @author Jeff Green, ParIT Worker Co-operative <jeff@parit.ca>
|
||||
# @ingroup python_bindings
|
||||
|
||||
import operator
|
||||
|
||||
from enum import IntEnum
|
||||
from urllib.parse import urlparse
|
||||
|
||||
@ -426,7 +428,7 @@ class GncNumeric(GnuCashCoreClass):
|
||||
elif len(args) == 1:
|
||||
arg = args[0]
|
||||
if isinstance(arg, int):
|
||||
return gnc_numeric_create(arg ,1)
|
||||
return gnc_numeric_create(arg, 1)
|
||||
elif isinstance(arg, float):
|
||||
return double_to_gnc_numeric(arg, GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER)
|
||||
elif isinstance(arg, str):
|
||||
@ -434,8 +436,10 @@ class GncNumeric(GnuCashCoreClass):
|
||||
if not string_to_gnc_numeric(arg, instance):
|
||||
raise TypeError('Failed to convert to GncNumeric: ' + str(args))
|
||||
return instance
|
||||
elif isinstance(arg, GncNumeric):
|
||||
return arg.instance
|
||||
else:
|
||||
raise TypeError('Only single int/float/str allowed: ' + str(args))
|
||||
raise TypeError('Only single int/float/str/GncNumeric allowed: ' + str(args))
|
||||
elif len(args) == 2:
|
||||
if isinstance(args[0], int) and isinstance(args[1], int):
|
||||
return gnc_numeric_create(*args)
|
||||
@ -451,6 +455,133 @@ class GncNumeric(GnuCashCoreClass):
|
||||
else:
|
||||
raise TypeError('Required single int/float/str or two ints: ' + str(args))
|
||||
|
||||
# from https://docs.python.org/3/library/numbers.html#numbers.Integral
|
||||
# and https://github.com/python/cpython/blob/3.7/Lib/fractions.py
|
||||
|
||||
def _operator_fallbacks(monomorphic_operator, fallback_operator):
|
||||
"""fallbacks are not needed except for method name,
|
||||
keep for possible later use"""
|
||||
def forward(a, b):
|
||||
if isinstance(b, GncNumeric):
|
||||
return monomorphic_operator(a, b)
|
||||
if isinstance(b, (int, float)):
|
||||
return monomorphic_operator(a, GncNumeric(b))
|
||||
else:
|
||||
return NotImplemented
|
||||
forward.__name__ = '__' + fallback_operator.__name__ + '__'
|
||||
forward.__doc__ = monomorphic_operator.__doc__
|
||||
|
||||
def reverse(b, a):
|
||||
if isinstance(a, (GncNumeric, int, float)):
|
||||
return forward(b, a)
|
||||
else:
|
||||
return NotImplemented
|
||||
reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
|
||||
reverse.__doc__ = monomorphic_operator.__doc__
|
||||
|
||||
return forward, reverse
|
||||
|
||||
def _add(a, b):
|
||||
return a.add(b, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND)
|
||||
|
||||
def _sub(a, b):
|
||||
return a.sub(b, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND)
|
||||
|
||||
def _mul(a, b):
|
||||
return a.mul(b, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND)
|
||||
|
||||
def _div(a, b):
|
||||
return a.div(b, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND)
|
||||
|
||||
def _floordiv(a, b):
|
||||
return a.div(b, 1, GNC_HOW_RND_TRUNC)
|
||||
|
||||
__add__, __radd__ = _operator_fallbacks(_add, operator.add)
|
||||
__iadd__ = __add__
|
||||
__sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub)
|
||||
__isub__ = __sub__
|
||||
__mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
|
||||
__imul__ = __mul__
|
||||
__truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
|
||||
__itruediv__ = __truediv__
|
||||
__floordiv__, __rfloordiv__ = _operator_fallbacks(_floordiv, operator.floordiv)
|
||||
__ifloordiv__ = __floordiv__
|
||||
|
||||
# Comparisons derived from https://github.com/python/cpython/blob/3.7/Lib/fractions.py
|
||||
def _lt(a, b):
|
||||
return a.compare(b) == -1
|
||||
|
||||
def _gt(a, b):
|
||||
return a.compare(b) == 1
|
||||
|
||||
def _le(a, b):
|
||||
return a.compare(b) in (0,-1)
|
||||
|
||||
def _ge(a, b):
|
||||
return a.compare(b) in (0,1)
|
||||
|
||||
def _eq(a, b):
|
||||
return a.compare(b) == 0
|
||||
|
||||
def _richcmp(self, other, op):
|
||||
"""Helper for comparison operators, for internal use only.
|
||||
Implement comparison between a GncNumeric instance `self`,
|
||||
and either another GncNumeric instance, an int or a float
|
||||
`other`. If `other` is not an instance of that kind, return
|
||||
NotImplemented. `op` should be one of the six standard
|
||||
comparison operators. The comparisons are based on
|
||||
GncNumeric.compare().
|
||||
"""
|
||||
import math
|
||||
if isinstance(other, GncNumeric):
|
||||
return op(other)
|
||||
elif isinstance(other, (int, float)):
|
||||
return op(GncNumeric(other))
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
def __lt__(a, b):
|
||||
"""a < b"""
|
||||
return a._richcmp(b, a._lt)
|
||||
|
||||
def __gt__(a, b):
|
||||
"""a > b"""
|
||||
return a._richcmp(b, a._gt)
|
||||
|
||||
def __le__(a, b):
|
||||
"""a <= b"""
|
||||
return a._richcmp(b, a._le)
|
||||
|
||||
def __ge__(a, b):
|
||||
"""a >= b"""
|
||||
return a._richcmp(b, a._ge)
|
||||
|
||||
def __eq__(a, b):
|
||||
"""a == b"""
|
||||
return a._richcmp(b, a._eq)
|
||||
|
||||
def __bool__(a):
|
||||
"""a != 0"""
|
||||
return bool(a.num())
|
||||
|
||||
def __float__(self):
|
||||
return self.to_double()
|
||||
|
||||
def __int__(self):
|
||||
return int(self.to_double())
|
||||
|
||||
def __pos__(a):
|
||||
"""+a"""
|
||||
return GncNumeric(a.num(), a.denom())
|
||||
|
||||
def __neg__(a):
|
||||
"""-a"""
|
||||
return a.neg()
|
||||
|
||||
def __abs__(a):
|
||||
"""abs(a)"""
|
||||
return a.abs()
|
||||
|
||||
def to_fraction(self):
|
||||
from fractions import Fraction
|
||||
return Fraction(self.num(), self.denom())
|
||||
@ -673,7 +804,7 @@ from gnucash.gnucash_core_c import \
|
||||
# used for the how argument in arithmetic functions like GncNumeric.add
|
||||
from gnucash.gnucash_core_c import \
|
||||
GNC_HOW_DENOM_EXACT, GNC_HOW_DENOM_REDUCE, GNC_HOW_DENOM_LCD, \
|
||||
GNC_HOW_DENOM_FIXED
|
||||
GNC_HOW_DENOM_FIXED, GNC_HOW_DENOM_SIGFIG
|
||||
|
||||
# import account types
|
||||
from gnucash.gnucash_core_c import \
|
||||
@ -714,7 +845,8 @@ gncnumeric_dict = {
|
||||
'add_fixed' : GncNumeric,
|
||||
'sub_fixed' : GncNumeric,
|
||||
'convert' : GncNumeric,
|
||||
'reduce' : GncNumeric
|
||||
'reduce' : GncNumeric,
|
||||
'invert' : GncNumeric
|
||||
}
|
||||
methods_return_instance(GncNumeric, gncnumeric_dict)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user