gnucash maint: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Sun Mar 20 15:34:19 EDT 2022


Updated	 via  https://github.com/Gnucash/gnucash/commit/7fbbd6e7 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/6a015c87 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/567df27c (commit)
	from  https://github.com/Gnucash/gnucash/commit/859b5720 (commit)



commit 7fbbd6e74593f67fd7ca122d5eb6e071807663c1
Merge: 859b57203 6a015c874
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun Mar 20 12:26:42 2022 -0700

    Merge Christoph Holterman's 'python-gnc-numeric' into maint.


commit 6a015c87448b2ab405e12e543d1805c315bd8094
Author: Christoph Holtermann <mail at c-holtermann.net>
Date:   Sat Mar 19 15:57:57 2022 +0100

    make GncNumeric.invert() return GncNumeric

diff --git a/bindings/python/gnucash_core.py b/bindings/python/gnucash_core.py
index 784b71478..c688097f4 100644
--- a/bindings/python/gnucash_core.py
+++ b/bindings/python/gnucash_core.py
@@ -845,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)
 

commit 567df27cc79f423c76d552bb202634ebc1c7e18d
Author: Christoph Holtermann <mail at c-holtermann.net>
Date:   Sat Mar 19 13:10:20 2022 +0100

    Implement some comparisons and arithmetics for GncNumeric
    
    Derive some numeric comparisons and arithmetics from Fraction
    class
    https://github.com/python/cpython/blob/3.7/Lib/fractions.py
    and general information from
    https://docs.python.org/3/library/numbers.html#numbers.Integral
    
    These methods are bound closer to the gnucash-C-api than those
    from the fraction class.
    
    This is not the full set of comparisons and arithmetics, needs
    to be extended. It would be good to extend tests to cover this.

diff --git a/bindings/python/gnucash_core.py b/bindings/python/gnucash_core.py
index 5147f7ae3..784b71478 100644
--- a/bindings/python/gnucash_core.py
+++ b/bindings/python/gnucash_core.py
@@ -28,6 +28,8 @@
 #  @author Jeff Green,   ParIT Worker Co-operative <jeff at 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 \



Summary of changes:
 bindings/python/gnucash_core.py | 140 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 136 insertions(+), 4 deletions(-)



More information about the gnucash-changes mailing list