From 4502afad4fbffcb394967cc7f47de87381dd58a9 Mon Sep 17 00:00:00 2001 From: andygoblins Date: Sun, 9 Feb 2020 14:37:06 -0600 Subject: [PATCH 1/3] fix __eq__ in Split and Transaction Compare guids with .Equal() when comparing Split and Transaction instances. --- bindings/python/gnucash_core.py | 6 ++++++ bindings/python/tests/test_split.py | 5 +++++ bindings/python/tests/test_transaction.py | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/bindings/python/gnucash_core.py b/bindings/python/gnucash_core.py index c7a7901e41..8cab524177 100644 --- a/bindings/python/gnucash_core.py +++ b/bindings/python/gnucash_core.py @@ -434,6 +434,9 @@ class Transaction(GnuCashCoreClass): return self.do_lookup_create_oo_instance( gncInvoiceGetInvoiceFromTxn, Transaction ) + def __eq__(self, other): + return self.Equal(other, True, False, False, False) + def decorate_monetary_list_returning_function(orig_function): def new_function(self, *args): """decorate function that returns list of gnc_monetary to return tuples of GncCommodity and GncNumeric @@ -461,6 +464,9 @@ class Split(GnuCashCoreClass): """ _new_instance = 'xaccMallocSplit' + def __eq__(self, other): + return self.Equal(other, True, False, False) + class Account(GnuCashCoreClass): """A GnuCash Account. diff --git a/bindings/python/tests/test_split.py b/bindings/python/tests/test_split.py index f3da096a27..bbe37cc467 100644 --- a/bindings/python/tests/test_split.py +++ b/bindings/python/tests/test_split.py @@ -57,6 +57,11 @@ class TestSplit( SplitSession ): def test_equal(self): COPY = self.split self.assertTrue( self.split.Equal(COPY, True, False, False) ) + # test __eq__ implementation + TRANS = Transaction(self.book) + self.split.SetParent(TRANS) + self.assertTrue( self.split == TRANS.GetSplitList()[0] ) + self.assertTrue( self.split != Split(self.book) ) if __name__ == '__main__': main() diff --git a/bindings/python/tests/test_transaction.py b/bindings/python/tests/test_transaction.py index 86776db64c..373aa65d9d 100644 --- a/bindings/python/tests/test_transaction.py +++ b/bindings/python/tests/test_transaction.py @@ -44,6 +44,11 @@ class TestTransaction( TransactionSession ): def test_equal(self): TRANS = self.trans self.assertTrue( TRANS.Equal(self.trans, True, False, False, False) ) + # test __eq__ implementation + SPLIT = Split(self.book) + SPLIT.SetParent(TRANS) + self.assertTrue( self.trans == SPLIT.GetParent() ) + self.assertTrue( self.trans != Transaction(self.book) ) def test_clone(self): domain = "gnc.engine" From f1f450cedc6ed9d79bf45f1045fc933c403bd171 Mon Sep 17 00:00:00 2001 From: andygoblins Date: Sun, 9 Feb 2020 14:53:17 -0600 Subject: [PATCH 2/3] make Session a context manager --- .../python/example_scripts/simple_test.py | 152 +++++++++--------- bindings/python/gnucash_core.py | 9 ++ 2 files changed, 83 insertions(+), 78 deletions(-) diff --git a/bindings/python/example_scripts/simple_test.py b/bindings/python/example_scripts/simple_test.py index 9bc21789e6..b8a1bed02e 100644 --- a/bindings/python/example_scripts/simple_test.py +++ b/bindings/python/example_scripts/simple_test.py @@ -7,81 +7,77 @@ from gnucash import Session, Account, Transaction, Split, GncNumeric FILE_1 = "/tmp/example.gnucash" -session = Session("xml://%s" % FILE_1, is_new=True) - -book = session.book -root_acct = Account(book) -expenses_acct = Account(book) -savings_acct = Account(book) -opening_acct = Account(book) -trans1 = Transaction(book) -trans1.BeginEdit() -trans2 = Transaction(book) -trans2.BeginEdit() - -split1 = Split(book) -split3 = Split(book) -comm_table = book.get_table() -cad = comm_table.lookup("CURRENCY", "CAD") - -num1 = GncNumeric(4, 1) -num2 = GncNumeric(100, 1) - -#Set new root account -book.set_root_account(root_acct) - -#Set up root account and add sub-accounts -root_acct.SetName("Root") -root_acct.SetType(13) #ACCT_TYPE_ROOT = 13 -root_acct.append_child(expenses_acct) -root_acct.append_child(savings_acct) -root_acct.append_child(opening_acct) - -#Set up Expenses account -expenses_acct.SetCommodity(cad) -expenses_acct.SetName("Expenses") -expenses_acct.SetType(9) #ACCT_TYPE_EXPENSE = 9 - -#Set up Savings account -savings_acct.SetCommodity(cad) -savings_acct.SetName("Savings") -savings_acct.SetType(0) #ACCT_TYPE_BANK = 0 - -#Set up Opening Balance account -opening_acct.SetCommodity(cad) -opening_acct.SetName("Opening Balance") -opening_acct.SetType(10) #ACCT_TYPE_EQUITY = 10 - -split1.SetValue(num1) -split1.SetAccount(expenses_acct) -split1.SetParent(trans1) - -split3.SetValue(num2) -split3.SetAccount(savings_acct) -split3.SetParent(trans2) - -trans1.SetCurrency(cad) -trans1.SetDate(14, 3, 2006) -trans1.SetDescription("Groceries") - -trans2.SetCurrency(cad) -trans2.SetDate(7, 11, 1995) -trans2.SetDescription("Opening Savings Balance") - -split2 = Split(book) -split2.SetAccount(savings_acct) -split2.SetParent(trans1) -split2.SetValue(num1.neg()) - -split4 = Split(book) -split4.SetAccount(opening_acct) -split4.SetParent(trans2) -split4.SetValue(num2.neg()) - - -trans1.CommitEdit() -trans2.CommitEdit() - -session.save() -session.end() -session.destroy() +with Session("xml://%s" % FILE_1, is_new=True) as session: + + book = session.book + root_acct = Account(book) + expenses_acct = Account(book) + savings_acct = Account(book) + opening_acct = Account(book) + trans1 = Transaction(book) + trans1.BeginEdit() + trans2 = Transaction(book) + trans2.BeginEdit() + + split1 = Split(book) + split3 = Split(book) + comm_table = book.get_table() + cad = comm_table.lookup("CURRENCY", "CAD") + + num1 = GncNumeric(4, 1) + num2 = GncNumeric(100, 1) + + #Set new root account + book.set_root_account(root_acct) + + #Set up root account and add sub-accounts + root_acct.SetName("Root") + root_acct.SetType(13) #ACCT_TYPE_ROOT = 13 + root_acct.append_child(expenses_acct) + root_acct.append_child(savings_acct) + root_acct.append_child(opening_acct) + + #Set up Expenses account + expenses_acct.SetCommodity(cad) + expenses_acct.SetName("Expenses") + expenses_acct.SetType(9) #ACCT_TYPE_EXPENSE = 9 + + #Set up Savings account + savings_acct.SetCommodity(cad) + savings_acct.SetName("Savings") + savings_acct.SetType(0) #ACCT_TYPE_BANK = 0 + + #Set up Opening Balance account + opening_acct.SetCommodity(cad) + opening_acct.SetName("Opening Balance") + opening_acct.SetType(10) #ACCT_TYPE_EQUITY = 10 + + split1.SetValue(num1) + split1.SetAccount(expenses_acct) + split1.SetParent(trans1) + + split3.SetValue(num2) + split3.SetAccount(savings_acct) + split3.SetParent(trans2) + + trans1.SetCurrency(cad) + trans1.SetDate(14, 3, 2006) + trans1.SetDescription("Groceries") + + trans2.SetCurrency(cad) + trans2.SetDate(7, 11, 1995) + trans2.SetDescription("Opening Savings Balance") + + split2 = Split(book) + split2.SetAccount(savings_acct) + split2.SetParent(trans1) + split2.SetValue(num1.neg()) + + split4 = Split(book) + split4.SetAccount(opening_acct) + split4.SetParent(trans2) + split4.SetValue(num2.neg()) + + + trans1.CommitEdit() + trans2.CommitEdit() \ No newline at end of file diff --git a/bindings/python/gnucash_core.py b/bindings/python/gnucash_core.py index 8cab524177..915fe06383 100644 --- a/bindings/python/gnucash_core.py +++ b/bindings/python/gnucash_core.py @@ -117,6 +117,15 @@ class Session(GnuCashCoreClass): self.destroy() raise + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + # Roll back changes on exception by not calling save. Only works for XMl backend. + if not exc_type: + self.save() + self.end() + def raise_backend_errors(self, called_function="qof_session function"): """Raises a GnuCashBackendException if there are outstanding QOF_BACKEND errors. From 08af4ce9bd3046b14af407f7b7c603dbd888d6ee Mon Sep 17 00:00:00 2001 From: andygoblins Date: Sat, 22 Feb 2020 11:28:50 -0600 Subject: [PATCH 3/3] context manager examples --- .../python/example_scripts/simple_book.py | 16 +++++++------- .../python/example_scripts/simple_session.py | 21 +++++++------------ 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/bindings/python/example_scripts/simple_book.py b/bindings/python/example_scripts/simple_book.py index 9a6040b928..19ebb01865 100644 --- a/bindings/python/example_scripts/simple_book.py +++ b/bindings/python/example_scripts/simple_book.py @@ -11,15 +11,15 @@ from gnucash import Session uri = "xml:///tmp/simple_book.gnucash" print("uri:", uri) -ses = Session(uri, is_new=True) -book = ses.get_book() +with Session(uri, is_new=True) as ses: + book = ses.get_book() -#Call some methods that produce output to show that Book works -book.get_root_account().SetDescription("hello, book") -print("Book is saved:", not book.session_not_saved()) + #Call some methods that produce output to show that Book works + book.get_root_account().SetDescription("hello, book") + print("Book is saved:", not book.session_not_saved()) -print("saving...") -ses.save() + #As long as there's no exceptions, book is automatically saved + #when session ends. + print("saving...") print("Book is saved:", not book.session_not_saved()) -ses.end() diff --git a/bindings/python/example_scripts/simple_session.py b/bindings/python/example_scripts/simple_session.py index 3bd219c9c9..05da9487ba 100644 --- a/bindings/python/example_scripts/simple_session.py +++ b/bindings/python/example_scripts/simple_session.py @@ -19,18 +19,13 @@ except GnuCashBackendException as backend_exception: # create a new file, this requires a file type specification -session = Session("xml://%s" % FILE_2, is_new=True) -session.save() -session.end() -session.destroy() +with Session("xml://%s" % FILE_2, is_new=True) as session: + book = session.book + root = book.get_root_account() # open the new file, try to open it a second time, detect the lock -session = Session(FILE_2) -try: - session_2 = Session(FILE_2) -except GnuCashBackendException as backend_exception: - assert( ERR_BACKEND_LOCKED in backend_exception.errors ) -session.end() -session.destroy() - - +with Session(FILE_2) as session: + try: + session_2 = Session(FILE_2) + except GnuCashBackendException as backend_exception: + assert( ERR_BACKEND_LOCKED in backend_exception.errors )