[PATCH] Switch to python 3

Julian Wollrath jwollrath at web.de
Fri Mar 16 03:49:14 EDT 2018


This switches swig to use python 3 specific features, switches the build
over to python 3 and adapts the tests accordingly.
---
 CMakeLists.txt                               |  6 +--
 bindings/python/__init__.py                  |  2 +-
 bindings/python/function_class.py            | 34 ++++++------
 bindings/python/gnucash_business.py          | 28 +++++-----
 bindings/python/gnucash_core.py              | 78 +++++++++++++---------------
 bindings/python/tests/runTests.py.in         |  7 +--
 bindings/python/tests/test_account.py        |  4 +-
 bindings/python/tests/test_numeric.py        |  6 ---
 bindings/python/tests/test_split.py          |  6 +--
 bindings/python/tests/test_transaction.py    | 40 +++++++-------
 common/cmake_modules/GncAddSwigCommand.cmake |  2 +-
 gnucash/python/gncmod-python.c               |  4 ++
 12 files changed, 103 insertions(+), 114 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 370a6d15f..c85bcf23c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -459,7 +459,7 @@ ENDIF (WITH_SQL)
 # ############################################################
 
 IF (WITH_PYTHON)
-  FIND_PACKAGE(PythonInterp)
+  FIND_PACKAGE(PythonInterp 3)
   IF (NOT PYTHONINTERP_FOUND)
     MESSAGE(SEND_ERROR "Python support enabled, but Python interpreter not found.")
   ENDIF()
@@ -468,14 +468,14 @@ IF (WITH_PYTHON)
     MESSAGE(SEND_ERROR "Found python version ${PYTHON_VERSION_STRING}, but it's too old. Need python >= 2.4.0")
   ENDIF()
 
-  FIND_PACKAGE(PythonLibs)
+  FIND_PACKAGE(PythonLibs 3)
   IF (NOT PYTHONLIBS_FOUND)
     MESSAGE(SEND_ERROR "Python support enabled, but Python libraries not found.")
   ENDIF()
 
   # Determine where to install the python libraries.
   EXECUTE_PROCESS(
-    COMMAND ${PYTHON_EXECUTABLE} -c "from distutils import sysconfig; print sysconfig.get_python_lib(prefix='${CMAKE_INSTALL_PREFIX}', plat_specific=True)"
+    COMMAND ${PYTHON_EXECUTABLE} -c "from distutils import sysconfig; print(sysconfig.get_python_lib(prefix='${CMAKE_INSTALL_PREFIX}', plat_specific=True))"
     RESULT_VARIABLE PYTHON_SYSCONFIG_RESULT
     OUTPUT_VARIABLE PYTHON_SYSCONFIG_OUTPUT
     ERROR_VARIABLE PYTHON_SYSCONFIG_ERROR
diff --git a/bindings/python/__init__.py b/bindings/python/__init__.py
index 3627eac47..1c874734e 100644
--- a/bindings/python/__init__.py
+++ b/bindings/python/__init__.py
@@ -3,7 +3,7 @@
 # >>> from gnucash import thingy
 # instead of
 # >>> from gnucash.gnucash_core import thingy
-from gnucash_core import *
+from gnucash.gnucash_core import *
 ##  @file
 #   @brief helper file for the importing of gnucash
 #   @author Mark Jenkins, ParIT Worker Co-operative <mark at parit.ca>
diff --git a/bindings/python/function_class.py b/bindings/python/function_class.py
index f628667a4..db159ff83 100644
--- a/bindings/python/function_class.py
+++ b/bindings/python/function_class.py
@@ -1,5 +1,5 @@
 # function_class.py -- Library for making python classes from a set
-#                      of functions. 
+#                      of functions.
 #
 # Copyright (C) 2008 ParIT Worker Co-operative <paritinfo at parit.ca>
 # This program is free software; you can redistribute it and/or
@@ -53,7 +53,7 @@ class ClassFromFunctions(object):
         # already exist with the same __instance value, or equivalent __instance
         # values, where this is desirable...
         return super(ClassFromFunctions, cls).__new__(cls)
-    
+
     def __init__(self, *args, **kargs):
         """Construct a new instance, using either the function
         self._module[self._new_instance] or using existing instance
@@ -89,7 +89,7 @@ class ClassFromFunctions(object):
             return getattr(self._module, function_name)(
                 self.instance,
                 *process_list_convert_to_instance(meth_func_args) )
-        
+
         setattr(cls, method_name, method_function)
         setattr(method_function, "__name__", method_name)
         return method_function
@@ -97,41 +97,41 @@ class ClassFromFunctions(object):
     @classmethod
     def ya_add_classmethod(cls, function_name, method_name):
         """Add the function, method_name to this class as a classmethod named name
-        
+
         Taken from function_class and slightly modified.
         """
         def method_function(self, *meth_func_args):
             return getattr(self._module, function_name)(
                 self,
                 *process_list_convert_to_instance(meth_func_args) )
-        
+
         setattr(cls, method_name, classmethod(method_function))
         setattr(method_function, "__name__", method_name)
-        return method_function    
+        return method_function
 
     @classmethod
     def ya_add_method(cls, function_name, method_name):
         """Add the function, method_name to this class as a method named name
-        
+
         Taken from function_class and slightly modified.
         """
         def method_function(self, *meth_func_args):
             return getattr(self._module, function_name)(
                 self,
                 *process_list_convert_to_instance(meth_func_args) )
-        
+
         setattr(cls, method_name, method_function)
         setattr(method_function, "__name__", method_name)
         return method_function
 
     @classmethod
     def add_methods_with_prefix(cls, prefix):
-        """Add a group of functions with the same prefix 
+        """Add a group of functions with the same prefix
         """
         for function_name, function_value, after_prefix in \
             extract_attributes_with_prefix(cls._module, prefix):
                 cls.add_method(function_name, after_prefix)
-    
+
     @classmethod
     def add_constructor_and_methods_with_prefix(cls, prefix, constructor):
         """Add a group of functions with the same prefix, and set the
@@ -160,7 +160,7 @@ def method_function_returns_instance(method_function, cls):
             return None
         else:
             return cls( **kargs )
-    
+
     return new_function
 
 def method_function_returns_instance_list(method_function, cls):
@@ -170,7 +170,7 @@ def method_function_returns_instance_list(method_function, cls):
     return new_function
 
 def methods_return_instance_lists(cls, function_dict):
-    for func_name, instance_name in function_dict.iteritems():
+    for func_name, instance_name in iter(function_dict.items()):
         setattr(cls, func_name,
                 method_function_returns_instance_list(
                 getattr(cls, func_name), instance_name))
@@ -186,7 +186,7 @@ def default_arguments_decorator(function, *args):
         new_argset.extend( args[ len(function_args): ] )
         return function( *new_argset )
     return new_function
-    
+
 def return_instance_if_value_has_it(value):
     """Return value.instance if value is an instance of ClassFromFunctions,
     else return value
@@ -212,16 +212,16 @@ def extract_attributes_with_prefix(obj, prefix):
     the attribute name, the attribute value, and the text that appears
     after the prefix in the name
     """
-    for attr_name, attr_value in obj.__dict__.iteritems():
+    for attr_name, attr_value in iter(obj.__dict__.items()):
         if attr_name.startswith(prefix):
             after_prefix = attr_name[ len(prefix): ]
             yield attr_name, attr_value, after_prefix
 
 def methods_return_instance(cls, function_dict):
     """Iterates through a dictionary of function name strings and instance names
-    and sets the function to return the associated instance 
+    and sets the function to return the associated instance
     """
-    for func_name, instance_name in function_dict.iteritems():
-        setattr(cls, func_name, 
+    for func_name, instance_name in iter(function_dict.items()):
+        setattr(cls, func_name,
             method_function_returns_instance( getattr(cls, func_name), instance_name))
 
diff --git a/bindings/python/gnucash_business.py b/bindings/python/gnucash_business.py
index 8d3850f07..f2e47e677 100644
--- a/bindings/python/gnucash_business.py
+++ b/bindings/python/gnucash_business.py
@@ -26,18 +26,18 @@
 #   @author Jeff Green,   ParIT Worker Co-operative <jeff at parit.ca>
 #   @ingroup python_bindings
 
-import gnucash_core_c
+import gnucash.gnucash_core_c as gnucash_core_c
 
-from function_class import \
+from gnucash.function_class import \
      ClassFromFunctions, extract_attributes_with_prefix, \
      default_arguments_decorator, method_function_returns_instance, \
      methods_return_instance, methods_return_instance_lists
 
-from gnucash_core import \
+from gnucash.gnucash_core import \
      GnuCashCoreClass, GncNumeric, GncCommodity, Transaction, \
      Split, Book, GncLot, Account, GUID
 
-from gnucash_core_c import GNC_OWNER_CUSTOMER, GNC_OWNER_JOB, \
+from gnucash.gnucash_core_c import GNC_OWNER_CUSTOMER, GNC_OWNER_JOB, \
     GNC_OWNER_EMPLOYEE, GNC_OWNER_VENDOR, \
     GNC_PAYMENT_CASH, GNC_PAYMENT_CARD, \
     GNC_DISC_PRETAX, GNC_DISC_SAMETIME, GNC_DISC_POSTTAX, \
@@ -66,7 +66,7 @@ class GnuCashBusinessEntity(GnuCashCoreClass):
             GnuCashCoreClass.__init__(self, instance=instance)
 
 class Customer(GnuCashBusinessEntity): pass
-                         
+
 class Employee(GnuCashBusinessEntity): pass
 
 class Vendor(GnuCashBusinessEntity): pass
@@ -88,10 +88,10 @@ class Job(GnuCashBusinessEntity):
             if name != None:
                 self.SetName(name)
         else:
-            GnuCashCoreClass.__init__(self, instance=instance)    
+            GnuCashCoreClass.__init__(self, instance=instance)
 
 class Address(GnuCashCoreClass): pass
-    
+
 class BillTerm(GnuCashCoreClass): pass
 
 class TaxTable(GnuCashCoreClass):
@@ -111,14 +111,14 @@ class TaxTable(GnuCashCoreClass):
 class TaxTableEntry(GnuCashCoreClass):
     def __init__(self, account=None, percent=True, amount=None, instance=None):
         """TaxTableEntry constructor
-        
+
         You must provide an account, or be initizing this with an existing
         swig proxy object via the instance keyword argument.
-        
+
         You may also optionally set the percent keyword argument to False to get
         a fixed value instead of percentage based tax (which is the default, or
         when percent=True).
-        
+
         The tax will be zero percent or zero unless you set the amount keyword
         argument to a GncNumeric value as well.
         """
@@ -138,7 +138,7 @@ class TaxTableEntry(GnuCashCoreClass):
             if amount != None:
                 self.SetAmount(amount)
         else:
-            GnuCashCoreClass.__init__(self, instance=instance)        
+            GnuCashCoreClass.__init__(self, instance=instance)
 
 class Invoice(GnuCashCoreClass):
     def __init__(self, book=None, id=None, currency=None, owner=None,
@@ -191,7 +191,7 @@ def decorate_to_return_instance_instead_of_owner(dec_function):
 class Entry(GnuCashCoreClass):
     def __init__(self, book=None, invoice=None, date=None, instance=None):
         """Invoice Entry constructor
-        
+
         You must provide a book or be initizing this with an existing
         swig proxy object via the instance keyword argument.
 
@@ -217,7 +217,7 @@ class Entry(GnuCashCoreClass):
             if invoice != None:
                 invoice.AddEntry(self)
         else:
-            GnuCashCoreClass.__init__(self, instance=instance)    
+            GnuCashCoreClass.__init__(self, instance=instance)
 
     def test_type(self, invoice):
         if invoice.GetTypeString() == "Invoice" and self.GetInvoice() == None:
@@ -370,7 +370,7 @@ entry_dict = {
                  'GetInvoice': Invoice,
                  'GetBill': Invoice
              }
-methods_return_instance(Entry, entry_dict)             
+methods_return_instance(Entry, entry_dict)
 Entry.decorate_functions(
     decorate_to_return_instance_instead_of_owner,
     'GetBillTo' )
diff --git a/bindings/python/gnucash_core.py b/bindings/python/gnucash_core.py
index fe86958ae..cce02035b 100644
--- a/bindings/python/gnucash_core.py
+++ b/bindings/python/gnucash_core.py
@@ -28,15 +28,15 @@
 #  @author Jeff Green,   ParIT Worker Co-operative <jeff at parit.ca>
 #  @ingroup python_bindings
 
-import gnucash_core_c
+import gnucash.gnucash_core_c as gnucash_core_c
 
-from function_class import \
+from gnucash.function_class import \
      ClassFromFunctions, extract_attributes_with_prefix, \
      default_arguments_decorator, method_function_returns_instance, \
      methods_return_instance, process_list_convert_to_instance, \
      method_function_returns_instance_list, methods_return_instance_lists
 
-from gnucash_core_c import gncInvoiceLookup, gncInvoiceGetInvoiceFromTxn, \
+from gnucash.gnucash_core_c import gncInvoiceLookup, gncInvoiceGetInvoiceFromTxn, \
     gncInvoiceGetInvoiceFromLot, gncEntryLookup, gncInvoiceLookup, \
     gncCustomerLookup, gncVendorLookup, gncJobLookup, gncEmployeeLookup, \
     gncTaxTableLookup, gncTaxTableLookupByName, gnc_search_invoice_on_id, \
@@ -112,7 +112,7 @@ class Session(GnuCashCoreClass):
                 # More background: https://bugzilla.gnome.org/show_bug.cgi?id=726891
                 if book_uri[:3] != "xml" or not is_new:
                     self.load()
-            except GnuCashBackendException, backend_exception:
+            except GnuCashBackendException as backend_exception:
                 self.end()
                 self.destroy()
                 raise
@@ -174,75 +174,75 @@ class Book(GnuCashCoreClass):
     get_table -- Returns a commodity lookup table, of type GncCommodityTable
     """
     def InvoiceLookup(self, guid):
-        from gnucash_business import Invoice
+        from gnucash.gnucash_business import Invoice
         return self.do_lookup_create_oo_instance(
             gncInvoiceLookup, Invoice, guid.get_instance() )
 
     def EntryLookup(self, guid):
-        from gnucash_business import Entry
+        from gnucash.gnucash_business import Entry
         return self.do_lookup_create_oo_instance(
             gncEntryLookup, Entry, guid.get_instance() )
 
     def CustomerLookup(self, guid):
-        from gnucash_business import Customer
+        from gnucash.gnucash_business import Customer
         return self.do_lookup_create_oo_instance(
             gncCustomerLookup, Customer, guid.get_instance())
 
     def JobLookup(self, guid):
-        from gnucash_business import Job
+        from gnucash.gnucash_business import Job
         return self.do_lookup_create_oo_instance(
             gncJobLookup, Job, guid.get_instance() )
 
     def VendorLookup(self, guid):
-        from gnucash_business import Vendor
+        from gnucash.gnucash_business import Vendor
         return self.do_lookup_create_oo_instance(
             gncVendorLookup, Vendor, guid.get_instance() )
 
     def EmployeeLookup(self, guid):
-        from gnucash_business import Employee
+        from gnucash.gnucash_business import Employee
         return self.do_lookup_create_oo_instance(
             gncEmployeeLookup, Employee, guid.get_instance() )
 
     def TaxTableLookup(self, guid):
-        from gnucash_business import TaxTable
+        from gnucash.gnucash_business import TaxTable
         return self.do_lookup_create_oo_instance(
             gncTaxTableLookup, TaxTable, guid.get_instance() )
 
     def TaxTableLookupByName(self, name):
-        from gnucash_business import TaxTable
+        from gnucash.gnucash_business import TaxTable
         return self.do_lookup_create_oo_instance(
             gncTaxTableLookupByName, TaxTable, name)
 
     def TaxTableGetTables(self):
-        from gnucash_business import TaxTable
+        from gnucash.gnucash_business import TaxTable
         return [ TaxTable(instance=item) for item in gncTaxTableGetTables(self.instance) ]
 
     def BillLookupByID(self, id):
-        from gnucash_business import Bill
+        from gnucash.gnucash_business import Bill
         return self.do_lookup_create_oo_instance(
             gnc_search_bill_on_id, Bill, id)
 
     def InvoiceLookupByID(self, id):
-        from gnucash_business import Invoice
+        from gnucash.gnucash_business import Invoice
         return self.do_lookup_create_oo_instance(
             gnc_search_invoice_on_id, Invoice, id)
 
     def CustomerLookupByID(self, id):
-        from gnucash_business import Customer
+        from gnucash.gnucash_business import Customer
         return self.do_lookup_create_oo_instance(
             gnc_search_customer_on_id, Customer, id)
 
     def VendorLookupByID(self, id):
-        from gnucash_business import Vendor
+        from gnucash.gnucash_business import Vendor
         return self.do_lookup_create_oo_instance(
             gnc_search_vendor_on_id, Vendor, id)
-            
+
     def InvoiceNextID(self, customer):
-      ''' Return the next invoice ID. 
+      ''' Return the next invoice ID.
       This works but I'm not entirely happy with it.  FIX ME'''
       from gnucash.gnucash_core_c import gncInvoiceNextID
       return gncInvoiceNextID(self.get_instance(),customer.GetEndOwner().get_instance()[1])
-      
+
     def BillNextID(self, vendor):
       ''' Return the next Bill ID. '''
       from gnucash.gnucash_core_c import gncInvoiceNextID
@@ -294,11 +294,11 @@ class GncNumeric(GnuCashCoreClass):
             return gnc_numeric_zero()
         elif len(args) == 1:
             arg = args[0]
-            if type(arg) in (int, long):
+            if isinstance(arg, int):
                 return gnc_numeric_create(arg ,1)
-            elif type(arg) == float:
+            elif isinstance(arg, float):
                 return double_to_gnc_numeric(arg, GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER)
-            elif type(arg) == str:
+            elif isinstance(arg, str):
                 instance = gnc_numeric_zero()
                 if not string_to_gnc_numeric(arg, instance):
                     raise TypeError('Failed to convert to GncNumeric: ' + str(args))
@@ -306,17 +306,17 @@ class GncNumeric(GnuCashCoreClass):
             else:
                 raise TypeError('Only single int/float/str allowed: ' + str(args))
         elif len(args) == 2:
-            if type(args[0]) == int and type(args[1]) == int:
+            if isinstance(args[0], int) and isinstance(args[1], int):
                 return gnc_numeric_create(*args)
             else:
                 raise TypeError('Only two ints allowed: ' + str(args))
         elif len(args) == 3:
-            if type(args[0]) == float \
-                and type(args[1]) in (int, long) \
+            if isinstance(args[0], float) \
+                and isinstance(args[1], int) \
                 and type(args[2]) == type(GNC_HOW_DENOM_FIXED):
                 return double_to_gnc_numeric(*args)
             else:
-                raise TypeError('Only (float, int/long, GNC_HOW_RND_*) allowed: ' + str(args))
+                raise TypeError('Only (float, int, GNC_HOW_RND_*) allowed: ' + str(args))
         else:
             raise TypeError('Required single int/float/str or two ints: ' + str(args))
 
@@ -324,14 +324,10 @@ class GncNumeric(GnuCashCoreClass):
         from fractions import Fraction
         return Fraction(self.num(), self.denom())
 
-    def __unicode__(self):
+    def __str__(self):
         """Returns a human readable numeric value string as UTF8."""
         return gnc_numeric_to_string(self.instance)
 
-    def __str__(self):
-        """returns a human readable numeric value string as bytes."""
-        return unicode(self).encode('utf-8')
-
 class GncPrice(GnuCashCoreClass):
     '''
     Each priceEach price in the database represents an "instantaneous"
@@ -411,7 +407,7 @@ class GncCommodityNamespace(GnuCashCoreClass):
 
 class GncLot(GnuCashCoreClass):
     def GetInvoiceFromLot(self):
-        from gnucash_business import Invoice
+        from gnucash.gnucash_business import Invoice
         return self.do_lookup_create_oo_instance(
             gncInvoiceGetInvoiceFromLot, Invoice )
 
@@ -434,7 +430,7 @@ class Transaction(GnuCashCoreClass):
         return self.GetSplitList().pop(n)
 
     def GetInvoiceFromTxn(self):
-        from gnucash_business import Transaction
+        from gnucash.gnucash_business import Transaction
         return self.do_lookup_create_oo_instance(
             gncInvoiceGetInvoiceFromTxn, Transaction )
 
@@ -587,7 +583,7 @@ methods_return_instance_lists(
     GncCommodityTable, { 'get_namespaces_list': GncCommodityNamespace,
                          'get_commodities': GncCommodity,
                          'get_quotable_commodities': GncCommodity,
-                         
+
                        } )
 setattr(GncCommodityTable, 'get_namespaces', getattr(GncCommodityTable, '_get_namespaces_py'))
 
@@ -632,7 +628,7 @@ trans_dict =    {
                     'GetCurrency': GncCommodity,
                     'GetGUID': GUID
                 }
- 
+
 methods_return_instance(Transaction, trans_dict)
 methods_return_instance_lists(
     Transaction, { 'GetSplitList': Split,
@@ -738,18 +734,18 @@ class GUIDString(GnuCashCoreClass):
 GUIDString.add_constructor_and_methods_with_prefix('string_', 'to_guid')
 
 #Query
-from gnucash_core_c import \
+from gnucash.gnucash_core_c import \
     QOF_QUERY_AND, \
     QOF_QUERY_OR, \
     QOF_QUERY_NAND, \
     QOF_QUERY_NOR, \
     QOF_QUERY_XOR
 
-from gnucash_core_c import \
+from gnucash.gnucash_core_c import \
     QOF_STRING_MATCH_NORMAL, \
     QOF_STRING_MATCH_CASEINSENSITIVE
 
-from gnucash_core_c import \
+from gnucash.gnucash_core_c import \
     QOF_COMPARE_LT, \
     QOF_COMPARE_LTE, \
     QOF_COMPARE_EQUAL, \
@@ -757,10 +753,10 @@ from gnucash_core_c import \
     QOF_COMPARE_GTE, \
     QOF_COMPARE_NEQ
 
-from gnucash_core_c import \
+from gnucash.gnucash_core_c import \
     INVOICE_TYPE
 
-from gnucash_core_c import \
+from gnucash.gnucash_core_c import \
     INVOICE_IS_PAID
 
 class Query(GnuCashCoreClass):
diff --git a/bindings/python/tests/runTests.py.in b/bindings/python/tests/runTests.py.in
index 6028c8185..38c0d8d1c 100755
--- a/bindings/python/tests/runTests.py.in
+++ b/bindings/python/tests/runTests.py.in
@@ -5,8 +5,6 @@ import os
 
 os.environ["GNC_UNINSTALLED"] = "1"
 
-from test import test_support
-
 from test_book import TestBook
 from test_account import TestAccount
 from test_split import TestSplit
@@ -15,8 +13,5 @@ from test_business import TestBusiness
 from test_commodity import TestCommodity, TestCommodityNamespace
 from test_numeric import TestGncNumeric
 
-def test_main():
-    test_support.run_unittest(TestBook, TestAccount, TestSplit, TestTransaction, TestBusiness, TestCommodity, TestCommodityNamespace, TestGncNumeric)
-
 if __name__ == '__main__':
-    test_main()
+    unittest.main()
diff --git a/bindings/python/tests/test_account.py b/bindings/python/tests/test_account.py
index 9478f3750..2ee636a7a 100644
--- a/bindings/python/tests/test_account.py
+++ b/bindings/python/tests/test_account.py
@@ -13,9 +13,9 @@ class AccountSession( BookSession ):
 class TestAccount( AccountSession ):
     def test_name(self):
         NAME = "Money"
-        self.assertEquals( '', self.account.GetName() )
+        self.assertEqual( '', self.account.GetName() )
         self.account.SetName(NAME)
-        self.assertEquals( NAME, self.account.GetName() )
+        self.assertEqual( NAME, self.account.GetName() )
 
     def test_split(self):
         SPLIT = Split(self.book)
diff --git a/bindings/python/tests/test_numeric.py b/bindings/python/tests/test_numeric.py
index 86217c66d..4ca39f7c7 100644
--- a/bindings/python/tests/test_numeric.py
+++ b/bindings/python/tests/test_numeric.py
@@ -22,12 +22,6 @@ class TestGncNumeric( TestCase ):
         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)
-
         with self.assertRaises(Exception) as context:
             GncNumeric((2**64)+1)
 
diff --git a/bindings/python/tests/test_split.py b/bindings/python/tests/test_split.py
index ccc67de50..f3da096a2 100644
--- a/bindings/python/tests/test_split.py
+++ b/bindings/python/tests/test_split.py
@@ -17,9 +17,9 @@ class SplitSession( BookSession ):
 class TestSplit( SplitSession ):
     def test_memo(self):
         MEMO = "cookie monster"
-        self.assertEquals( '', self.split.GetMemo() )
+        self.assertEqual( '', self.split.GetMemo() )
         self.split.SetMemo(MEMO)
-        self.assertEquals( MEMO, self.split.GetMemo() )
+        self.assertEqual( MEMO, self.split.GetMemo() )
 
     def test_account(self):
         ACCT = Account(self.book)
@@ -49,7 +49,7 @@ class TestSplit( SplitSession ):
         self.split.SetParent(TRANS)
         TRANS.SetCurrency(self.currency)
         TRANS.SetDescription("Foo")
-        self.assertEquals( TRANS.GetDescription(), self.split.GetParent().GetDescription() )
+        self.assertEqual( TRANS.GetDescription(), self.split.GetParent().GetDescription() )
 
         g_log_remove_handler(domain2, hdlr2)
         g_log_remove_handler(domain1, hdlr1)
diff --git a/bindings/python/tests/test_transaction.py b/bindings/python/tests/test_transaction.py
index 66994104f..86776db64 100644
--- a/bindings/python/tests/test_transaction.py
+++ b/bindings/python/tests/test_transaction.py
@@ -73,13 +73,13 @@ class TestTransaction( TransactionSession ):
         self.assertFalse( self.trans.IsOpen() )
 
     def test_rollback(self):
-        self.assertEquals( '', self.trans.GetDescription() )
+        self.assertEqual( '', self.trans.GetDescription() )
         self.trans.BeginEdit()
         DESC = 'Food'
         self.trans.SetDescription(DESC)
-        self.assertEquals( DESC, self.trans.GetDescription() )
-        self.trans.RollbackEdit() 
-        self.assertEquals( '', self.trans.GetDescription() )
+        self.assertEqual( DESC, self.trans.GetDescription() )
+        self.trans.RollbackEdit()
+        self.assertEqual( '', self.trans.GetDescription() )
 
     def test_findsplit(self):
         ACCT = Account(self.book)
@@ -87,51 +87,51 @@ class TestTransaction( TransactionSession ):
         self.split.SetAccount( ACCT )
         SPLIT = self.trans.FindSplitByAccount( ACCT )
         self.assertTrue( SPLIT.Equal(self.split, True, False, False) )
-    
+
     def test_getsplit(self):
         SPLIT = self.trans.GetSplit(0)
         self.assertTrue( SPLIT.Equal(self.split, True, False, False) )
-        
+
     def test_getsplitindex(self):
-        self.assertEquals( 0, self.trans.GetSplitIndex(self.split) )
+        self.assertEqual( 0, self.trans.GetSplitIndex(self.split) )
 
     def test_countsplits(self):
-        self.assertEquals( 1, self.trans.CountSplits() )
+        self.assertEqual( 1, self.trans.CountSplits() )
 
     def test_readonly(self):
-        self.assertEquals( None, self.trans.GetReadOnly() )
+        self.assertEqual( None, self.trans.GetReadOnly() )
         REASON = 'none'
         self.trans.SetReadOnly(REASON)
-        self.assertEquals( REASON, self.trans.GetReadOnly() )
+        self.assertEqual( REASON, self.trans.GetReadOnly() )
         self.trans.ClearReadOnly()
-        self.assertEquals( None, self.trans.GetReadOnly() )
+        self.assertEqual( None, self.trans.GetReadOnly() )
 
     def test_txntype(self):
-        self.assertEquals( '\x00', self.trans.GetTxnType() )
+        self.assertEqual( '\x00', self.trans.GetTxnType() )
         TYPE = 'I'
         self.trans.SetTxnType(TYPE)
-        self.assertEquals( TYPE, self.trans.GetTxnType() )
+        self.assertEqual( TYPE, self.trans.GetTxnType() )
         TYPE = 'P'
         self.trans.SetTxnType(TYPE)
-        self.assertEquals( TYPE, self.trans.GetTxnType() )
+        self.assertEqual( TYPE, self.trans.GetTxnType() )
 
     def test_num(self):
         NUM = '5'
-        self.assertEquals( '', self.trans.GetNum() )
+        self.assertEqual( '', self.trans.GetNum() )
         self.trans.SetNum(NUM)
-        self.assertEquals( NUM, self.trans.GetNum() )
+        self.assertEqual( NUM, self.trans.GetNum() )
 
     def test_description(self):
         DESCR = 'Groceries'
-        self.assertEquals( '', self.trans.GetDescription() )
+        self.assertEqual( '', self.trans.GetDescription() )
         self.trans.SetDescription(DESCR)
-        self.assertEquals( DESCR, self.trans.GetDescription() )
+        self.assertEqual( DESCR, self.trans.GetDescription() )
 
     def test_notes(self):
         NOTE = 'For dinner party'
-        self.assertEquals( None, self.trans.GetNotes() )
+        self.assertEqual( None, self.trans.GetNotes() )
         self.trans.SetNotes(NOTE)
-        self.assertEquals( NOTE, self.trans.GetNotes() )
+        self.assertEqual( NOTE, self.trans.GetNotes() )
 
 if __name__ == '__main__':
     main()
diff --git a/common/cmake_modules/GncAddSwigCommand.cmake b/common/cmake_modules/GncAddSwigCommand.cmake
index 1fc143027..c6de5de03 100644
--- a/common/cmake_modules/GncAddSwigCommand.cmake
+++ b/common/cmake_modules/GncAddSwigCommand.cmake
@@ -75,7 +75,7 @@ macro (gnc_add_swig_python_command _target _out_var _py_out_var _output _py_outp
 
     if (GENERATE_SWIG_WRAPPERS)
         set (DEFAULT_SWIG_PYTHON_FLAGS
-            -python
+            -python -py3
             -Wall -Werror
             ${SWIG_ARGS}
         )
diff --git a/gnucash/python/gncmod-python.c b/gnucash/python/gncmod-python.c
index 24d4dc58f..19350d467 100644
--- a/gnucash/python/gncmod-python.c
+++ b/gnucash/python/gncmod-python.c
@@ -73,7 +73,11 @@ libgncmod_python_gnc_module_init(int refcount)
     */
     FILE *fp;
     gchar *pkgdatadir, *init_filename;
+#if PY_VERSION_HEX >= 0x03000000
+    wchar_t* argv = NULL;
+#else
     char* argv = "";
+#endif
     Py_Initialize();
     PySys_SetArgv(0, &argv);
 #if PY_VERSION_HEX >= 0x03000000
-- 
2.16.2



More information about the gnucash-devel mailing list