From f229f9ac8e6e38a230b5a7c8ef4883b708fa2ad9 Mon Sep 17 00:00:00 2001 From: Phil Longstaff Date: Sat, 5 Sep 2009 00:11:31 +0000 Subject: [PATCH] Python bindings patches by Mark Jenkins. python_GetNthChild_remove.patch remove the redundant GetNthChild code, gnc_account_nth_child supported python_more_GUID.patch Improve support for GUID python_better_commodity.patch * Removed custom __init__ from GncCommodity, not only is it wrong but the one from GnuCashCoreClass is just fine. * Supported the get_table method For Book * Removed support for direct instantiation of GncCommodityTable. (via gnc_commodity_table_new() ). Only methods and not the constructor function are added to the class now. Python binding users can access a GncCommodityTable instance via Book.get_table() and have no need to use gnc_commodity_table_new(), which the apis advise is for internal use only. python_GncLot.patch * included gnc-lot.h in gnucash_core.i again * Made GncLot class use superclass __init__, it doesn't need its own. python_more_documentation.patch Documentation strings for many classes, which can be viewed in source and with python's help() mechanism. python_business_module_load.patch load the business module, not the business module specific backend python_example_scripts.py example scripts improved, new one added. This new script originally came from this post: http://lists.gnucash.org/pipermail/gnucash-devel/2008-July/023618.html python_authors_update.patch added Legal Aid Manitoba to credit line for Mark Jenkins git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18291 57a11ea4-9604-0410-9ed3-97b8803252fd --- AUTHORS | 2 +- .../example_scripts/simple_session.py | 8 +- .../example_scripts/simple_test.py | 41 +++--- src/optional/python-bindings/gnucash_core.i | 4 +- src/optional/python-bindings/gnucash_core.py | 122 +++++++++++++++--- 5 files changed, 134 insertions(+), 43 deletions(-) diff --git a/AUTHORS b/AUTHORS index ed1121d23e..c39f271135 100644 --- a/AUTHORS +++ b/AUTHORS @@ -174,7 +174,7 @@ Péter Hosszú Hungarian translation Edward J. Huff Date handling in reports, quarterly option Tomokazu Iwashita Japanese translation of xea David Jafferian Delete account query code. -Mark Jenkins Python bindings, with grant funding from Assiniboine Credit Union (http://assiniboine.mb.ca/) +Mark Jenkins Python bindings, with grant funding from Assiniboine Credit Union (http://assiniboine.mb.ca/) and Legal Aid Manitoba (http://www.legalaid.mb.ca/) Miquel Jordana Vilamitjana Spanish translation of manual Prakash Kailasa for gnome build fixes Alexey Kakunin quickfill patch for Cyrillic diff --git a/src/optional/python-bindings/example_scripts/simple_session.py b/src/optional/python-bindings/example_scripts/simple_session.py index 5ee1a53e9f..c4a9512cb6 100644 --- a/src/optional/python-bindings/example_scripts/simple_session.py +++ b/src/optional/python-bindings/example_scripts/simple_session.py @@ -10,21 +10,21 @@ FILE_2 = "/tmp/example_file.xac" # open a file that isn't there, detect the error session = None try: - session = Session("file:%s" % FILE_1) + session = Session("xml:%s" % FILE_1) except GnuCashBackendException, backend_exception: assert( ERR_FILEIO_FILE_NOT_FOUND in backend_exception.errors) # create a new file -session = Session("file:%s" % FILE_2, True) +session = Session("xml:%s" % FILE_2, True) session.save() session.end() session.destroy() # open the new file, try to open it a second time, detect the lock -session = Session("file:%s" % FILE_2) +session = Session("xml:%s" % FILE_2) try: - session_2 = Session("file:%s" % FILE_2) + session_2 = Session("xml:%s" % FILE_2) except GnuCashBackendException, backend_exception: assert( ERR_BACKEND_LOCKED in backend_exception.errors ) session.end() diff --git a/src/optional/python-bindings/example_scripts/simple_test.py b/src/optional/python-bindings/example_scripts/simple_test.py index 1bf8a2ec8a..70310dd8fc 100644 --- a/src/optional/python-bindings/example_scripts/simple_test.py +++ b/src/optional/python-bindings/example_scripts/simple_test.py @@ -1,25 +1,26 @@ #!/usr/bin/env python # Creates a basic set of accounts and a couple of transactions -import gnucash +from gnucash import Session, Account, Transaction, Split, GncNumeric -FILE_1 = "/tmp/example.xac" +FILE_1 = "/tmp/example.gnucash" -session = None -session = gnucash.Session("file:%s" % FILE_1, True) +session = Session("xml:%s" % FILE_1, True) book = session.book -root_acct = gnucash.Account(book) -expenses_acct = gnucash.Account(book) -savings_acct = gnucash.Account(book) -opening_acct = gnucash.Account(book) -trans1 = gnucash.Transaction(book) -trans2 = gnucash.Transaction(book) -split1 = gnucash.Split(book) -split3 = gnucash.Split(book) -comm = gnucash.GncCommodity(book, "Canadian Dollars", "CURRENCY", "CAD", None, 100) -num1 = gnucash.GncNumeric(4, 1) -num2 = gnucash.GncNumeric(100, 1) +root_acct = Account(book) +expenses_acct = Account(book) +savings_acct = Account(book) +opening_acct = Account(book) +trans1 = Transaction(book) +trans2 = Transaction(book) +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) @@ -32,17 +33,17 @@ root_acct.append_child(savings_acct) root_acct.append_child(opening_acct) #Set up Expenses account -expenses_acct.SetCommodity(comm) +expenses_acct.SetCommodity(cad) expenses_acct.SetName("Expenses") expenses_acct.SetType(9) #ACCT_TYPE_EXPENSE = 9 #Set up Savings account -savings_acct.SetCommodity(comm) +savings_acct.SetCommodity(cad) savings_acct.SetName("Savings") savings_acct.SetType(0) #ACCT_TYPE_BANK = 0 #Set up Opening Balance account -opening_acct.SetCommodity(comm) +opening_acct.SetCommodity(cad) opening_acct.SetName("Opening Balance") opening_acct.SetType(10) #ACCT_TYPE_EQUITY = 10 @@ -54,10 +55,10 @@ split3.SetValue(num2) split3.SetAccount(savings_acct) split3.SetParent(trans2) -trans1.SetCurrency(comm) +trans1.SetCurrency(cad) trans1.SetDescription("Groceries") -trans2.SetCurrency(comm) +trans2.SetCurrency(cad) trans2.SetDescription("Opening Savings Balance") split2 = split1.GetOtherSplit() diff --git a/src/optional/python-bindings/gnucash_core.i b/src/optional/python-bindings/gnucash_core.i index 0a10633c40..1dded93b3e 100644 --- a/src/optional/python-bindings/gnucash_core.i +++ b/src/optional/python-bindings/gnucash_core.i @@ -79,7 +79,7 @@ %include -/* %include */ +%include //business-core includes %include @@ -93,6 +93,6 @@ g_type_init(); scm_init_guile(); gnc_module_load("gnucash/engine", 0); -gnc_module_load("gnucash/business-core-file", 0); +gnc_module_load("gnucash/business-core", 0); %} diff --git a/src/optional/python-bindings/gnucash_core.py b/src/optional/python-bindings/gnucash_core.py index 10fa31a2b4..4684e8d775 100644 --- a/src/optional/python-bindings/gnucash_core.py +++ b/src/optional/python-bindings/gnucash_core.py @@ -37,6 +37,18 @@ class GnuCashBackendException(Exception): self.errors = errors class Session(GnuCashCoreClass): + """A GnuCash book editing session + + To commit changes to the session you may need to call save, + (this is allways the case with the file backend). + + When you're down with a session you may need to call end() + + Every Session has a Book in the book attribute, which you'll definetely + be interested in, as every GnuCash entity (Transaction, Split, Vendor, + Invoice..) is associated with a particular book where it is stored. + """ + def __init__(self, book_uri=None, is_new=False): """A convienent contructor that allows you to specify a book URI, begin the session, and load the book. @@ -104,10 +116,37 @@ class Session(GnuCashCoreClass): return return_value return new_function -class Book(GnuCashCoreClass): pass +class Book(GnuCashCoreClass): + """A Book encapsulates all of the GnuCash data, it is the place where + all GnuCash entities (Transaction, Split, Vendor, Invoice...), are + stored. You'll notice that all of the constructors for those entities + need a book to be associated with. + + The most common way to get a book is through the book property in the + Session class, that is, create a session that connects to some storage, + such as through 'my_session = Session('file:my_books.xac')', and access + the book via the book property, 'my_session.book' + + If you would like to create a Book without any backing storage, call the + Book constructor wihout any parameters, 'Book()'. You can later merge + such a book into a book with actual store by using merge_init. + + Methods of interest + get_root_account -- Returns the root level Account + get_table -- Returns a commodity lookup table, of type GncCommodityTable + """ + pass class GncNumeric(GnuCashCoreClass): - def __init__(self, num=0, denom=0, **kargs): + """Object used by GnuCash to store all numbers. Always consists of a + numerator and denominator. + """ + + def __init__(self, num=0, denom=1, **kargs): + """Constructor that allows you to set the numerator and denominator or + leave them blank with a default value of 0 (not a good idea since there + is currently no way to alter the value after instantiation) + """ GnuCashCoreClass.__init__(self, num, denom, **kargs) #if INSTANCE_ARG in kargs: # GnuCashCoreClass.__init__(**kargs) @@ -115,28 +154,60 @@ class GncNumeric(GnuCashCoreClass): # self.set_denom(denom) # currently undefined # self.set_num(num) # currently undefined -class GncCommodity(GnuCashCoreClass): - def __init__(self, book, name=None, namespace=None, mnemonic=None, cusip=None, fraction=1, **kargs): - GnuCashCoreClass.__init__(self, book, name, namespace, mnemonic, cusip, fraction, **kargs) +class GncCommodity(GnuCashCoreClass): pass -class GncCommodityTable(GnuCashCoreClass): pass +class GncCommodityTable(GnuCashCoreClass): + """A CommodityTable provides a way to store and lookup commoditys. + Commoditys are primarily currencies, but other tradable things such as + stocks, mutual funds, and material substances are posible. + + Users of this library should not create thier own CommodityTable, instead + the get_table method from the Book class should be used. + + This table is automatically populated with the GnuCash default commodity's + which includes most of the world's currencies. + """ + pass class GncLot(GnuCashCoreClass): - def __init__(self, book, **kargs): - GnuCashCoreClass.__init__(self, book, **kargs) + pass class Transaction(GnuCashCoreClass): + """A GnuCash Transaction + + Consists of at least one (generally two) splits to represent a transaction + between two accounts. + """ _new_instance = 'xaccMallocTransaction' def GetNthSplit(self, n): return self.GetSplitList().pop(n) class Split(GnuCashCoreClass): + """A GnuCash Split + + The most basic representation of a movement of currency from one account to + another. + """ _new_instance = 'xaccMallocSplit' class Account(GnuCashCoreClass): + """A GnuCash Account. + + A fundamental entity in accounting, an Account provides representation + for a financial object, such as a BANK account, an ASSET (like a building), + a LIABILITY (such as a bank loan), a summary of some type of EXPENSE, or + a summary of some source of INCOME. + + The words in upper case are the constants that GnuCash and this library uses + to describe account type. Here is the full list: + BANK, CASH, CREDIT, ASSET, LIABILITY, STOCK, MUTUAL + CURRENCY, INCOME, EXPENSE, EQUITY, RECEIVABLE, PAYABLE, + CHECKING, SAVINGS, MONEYMRKT, CREDITLINE + + These are not strings, they are attributes you can import from this + module + """ _new_instance = 'xaccMallocAccount' - def GetNthChild(self, n): - return self.get_children().pop(n) class GUID(GnuCashCoreClass): _new_instance = 'guid_new_return' @@ -165,9 +236,13 @@ for error_name, error_value, error_name_after_prefix in \ Book.add_constructor_and_methods_with_prefix('qof_book_', 'new') Book.add_method('gnc_book_get_root_account', 'get_root_account') Book.add_method('gnc_book_set_root_account', 'set_root_account') +Book.add_method('gnc_commodity_table_get_table', 'get_table') #Functions that return Account Book.get_root_account = method_function_returns_instance( Book.get_root_account, Account ) +#Functions that return GncCommodityTable +Book.get_table = method_function_returns_instance( + Book.get_table, GncCommodityTable ) # GncNumeric GncNumeric.add_constructor_and_methods_with_prefix('gnc_numeric_', 'create') @@ -198,8 +273,7 @@ GncCommodity.clone = method_function_returns_instance( GncCommodity.clone, GncCommodity ) # GncCommodityTable -GncCommodityTable.add_constructor_and_methods_with_prefix('gnc_commodity_table_', 'get_table') - +GncCommodityTable.add_methods_with_prefix('gnc_commodity_table_') commoditytable_dict = { 'lookup' : GncCommodity, 'lookup_unique' : GncCommodity, @@ -224,6 +298,7 @@ methods_return_instance(GncLot, gnclot_dict) # Transaction Transaction.add_methods_with_prefix('xaccTrans') +Transaction.add_method('gncTransGetGUID', 'GetGUID'); trans_dict = { 'GetSplit': Split, @@ -237,12 +312,14 @@ trans_dict = { 'GetAccountAmount': GncNumeric, 'GetAccountConvRate': GncNumeric, 'GetAccountBalance': GncNumeric, - 'GetCurrency': GncCommodity + 'GetCurrency': GncCommodity, + 'GetGUID': GUID } methods_return_instance(Transaction, trans_dict) # Split Split.add_methods_with_prefix('xaccSplit') +Split.add_method('gncSplitGetGUID', 'GetGUID'); split_dict = { 'GetBook': Book, @@ -259,7 +336,8 @@ split_dict = { 'GetClearedBalance': GncNumeric, 'GetReconciledBalance': GncNumeric, 'VoidFormerAmount': GncNumeric, - 'VoidFormerValue': GncNumeric + 'VoidFormerValue': GncNumeric, + 'GetGUID': GUID } methods_return_instance(Split, split_dict) @@ -269,6 +347,7 @@ Split.parent = property( Split.GetParent, Split.SetParent ) # Account Account.add_methods_with_prefix('xaccAccount') Account.add_methods_with_prefix('gnc_account_') +Account.add_method('gncAccountGetGUID', 'GetGUID'); account_dict = { 'get_book' : Book, @@ -278,7 +357,6 @@ account_dict = { 'nth_child' : Account, 'lookup_by_name' : Account, 'lookup_by_full_name' : Account, - 'GetNthChild' : Account, 'FindTransByDesc' : Transaction, 'FindSplitByDesc' : Split, 'get_start_balance' : GncNumeric, @@ -298,7 +376,8 @@ account_dict = { 'GetProjectedMinimumBalanceInCurrency' : GncNumeric, 'GetBalanceAsOfDateInCurrency' : GncNumeric, 'GetBalanceChangeForPeriod' : GncNumeric, - 'GetCommodity' : GncCommodity + 'GetCommodity' : GncCommodity, + 'GetGUID': GUID } methods_return_instance(Account, account_dict) @@ -306,4 +385,15 @@ Account.name = property( Account.GetName, Account.SetName ) #GUID GUID.add_methods_with_prefix('guid_') +GUID.add_method('xaccAccountLookup', 'AccountLookup') +GUID.add_method('xaccTransLookup', 'TransLookup') +GUID.add_method('xaccSplitLookup', 'SplitLookup') +guid_dict = { + 'copy' : GUID, + 'TransLookup': Transaction, + 'AccountLookup': Account, + 'SplitLookup': Split + } +methods_return_instance(GUID, guid_dict) +