r19294 - gnucash/trunk/src/optional/python-bindings - Bug #622523 - Python bindings are crash prone when linked to guile

Geert Janssens gjanssens at code.gnucash.org
Fri Jun 25 07:06:29 EDT 2010


Author: gjanssens
Date: 2010-06-25 07:06:29 -0400 (Fri, 25 Jun 2010)
New Revision: 19294
Trac: http://svn.gnucash.org/trac/changeset/19294

Added:
   gnucash/trunk/src/optional/python-bindings/example_scripts/simple_business_create.py
   gnucash/trunk/src/optional/python-bindings/example_scripts/simple_invoice_insert.py
Modified:
   gnucash/trunk/src/optional/python-bindings/Makefile.am
   gnucash/trunk/src/optional/python-bindings/gnucash_business.py
   gnucash/trunk/src/optional/python-bindings/gnucash_core.i
   gnucash/trunk/src/optional/python-bindings/gnucash_core.py
Log:
Bug #622523 - Python bindings are crash prone when linked to guile

Modified: gnucash/trunk/src/optional/python-bindings/Makefile.am
===================================================================
--- gnucash/trunk/src/optional/python-bindings/Makefile.am	2010-06-25 09:53:10 UTC (rev 19293)
+++ gnucash/trunk/src/optional/python-bindings/Makefile.am	2010-06-25 11:06:29 UTC (rev 19294)
@@ -53,6 +53,8 @@
   example_scripts/simple_book.py \
   example_scripts/simple_session.py \
   example_scripts/simple_test.py \
+  example_scripts/simple_business_create.py \
+  example_scripts/simple_invoice_insert.py \
   glib.i
 
 MAINTAINERCLEANFILES = gnucash-core.c

Added: gnucash/trunk/src/optional/python-bindings/example_scripts/simple_business_create.py
===================================================================
--- gnucash/trunk/src/optional/python-bindings/example_scripts/simple_business_create.py	                        (rev 0)
+++ gnucash/trunk/src/optional/python-bindings/example_scripts/simple_business_create.py	2010-06-25 11:06:29 UTC (rev 19294)
@@ -0,0 +1,152 @@
+#!/usr/bin/env python
+
+# simple_business_create.py -- Set up a set of books for business feature use
+#
+# Copyright (C) 2010 ParIT Worker Co-operative <transparency at parit.ca>
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, contact:
+# Free Software Foundation           Voice:  +1-617-542-5942
+# 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+# Boston, MA  02110-1301,  USA       gnu at gnu.org
+#
+# @author Mark Jenkins, ParIT Worker Co-operative <mark at parit.ca>
+
+# Creates a new book file (or *overwrites* an existing one) that has elements
+# in it for business use -- intended as a demonstration program.
+# Syntax:
+# gnucash-env python simple_business_create.py \
+#                       sqlite3:///home/blah/blah.gnucash
+#
+# Specificically, this sets up a simple tree, creates a customer, job,
+# employee and vendor, creates an unposted invoice for each,
+# and posts the customer invoice with a few entries and a tax table.
+#
+# You may also want to look at simple_invoice_insert.py
+
+from os.path import abspath
+from sys import argv
+import datetime
+from datetime import timedelta
+from gnucash import Session, Account, GncNumeric
+from gnucash.gnucash_business import Customer, Employee, Vendor, Job, \
+    Address, Invoice, Entry, TaxTable, TaxTableEntry, GNC_AMT_TYPE_PERCENT, \
+    GNC_DISC_PRETAX    
+from gnucash.gnucash_core_c import \
+    ACCT_TYPE_ASSET, ACCT_TYPE_RECEIVABLE, ACCT_TYPE_INCOME, \
+    GNC_OWNER_CUSTOMER, ACCT_TYPE_LIABILITY
+
+
+s = Session(argv[1], True)
+# this seems to make a difference in more complex cases
+s.save()
+
+book = s.book
+root = book.get_root_account()
+commod_table = book.get_table()
+CAD = commod_table.lookup('CURRENCY', 'CAD')
+
+a = Account(book)
+root.append_child(a)
+a.SetName('Assets')
+a.SetType(ACCT_TYPE_ASSET)
+a.SetCommodity(CAD)
+
+a2 = Account(book)
+a.append_child(a2)
+a2.SetName('Recievables')
+a2.SetType(ACCT_TYPE_RECEIVABLE)
+a2.SetCommodity(CAD)
+
+a3 = Account(book)
+root.append_child(a3)
+a3.SetName('Income')
+a3.SetType(ACCT_TYPE_INCOME)
+a3.SetCommodity(CAD)
+
+a4 = Account(book)
+root.append_child(a4)
+a4.SetName('Liabilities')
+a4.SetType(ACCT_TYPE_LIABILITY)
+a4.SetCommodity(CAD)
+
+a5 = Account(book)
+a4.append_child(a5)
+a5.SetName('Tax payable')
+a5.SetType(ACCT_TYPE_LIABILITY)
+a5.SetCommodity(CAD)
+
+a6 = Account(book)
+a.append_child(a6)
+a6.SetName('Bank')
+a6.SetType(ACCT_TYPE_ASSET)
+a6.SetCommodity(CAD)
+
+# name isn't required, ID and currency are
+new_customer = Customer(book, "1", CAD, "Bill & Bob Industries")
+
+# not required, but a good idea because the GUI insists on basic address info
+address = new_customer.GetAddr()
+address.SetName("Bill & Bob")
+address.SetAddr1("201 Nowhere street")
+
+new_employee = Employee(book, "2", CAD, "Reliable employee")
+
+new_vendor = Vendor(book, "3", CAD, "Dependable vendor")
+
+new_job = Job(book, "4", new_vendor, "Good clean, fun")
+
+# 7% tax
+tax_table = TaxTable(book, "good tax",
+                     TaxTableEntry(a5, True, GncNumeric(700000, 100000) ) )
+
+
+invoice_customer = Invoice(book, "5", CAD, new_customer)
+customer_extract = invoice_customer.GetOwner()
+assert( isinstance(customer_extract, Customer) )
+assert( customer_extract.GetName() == new_customer.GetName() )
+
+invoice_employee = Invoice(book, "6", CAD, new_employee)
+employee_extract = invoice_employee.GetOwner()
+assert( isinstance(employee_extract, Employee) )
+assert( employee_extract.GetName() == new_employee.GetName() )
+
+invoice_vendor = Invoice(book, "7", CAD, new_vendor)
+vendor_extract = invoice_vendor.GetOwner()
+assert( isinstance(vendor_extract, Vendor) )
+assert( vendor_extract.GetName() == new_vendor.GetName() )
+
+invoice_job = Invoice(book, "8", CAD, new_job)
+job_extract = invoice_job.GetOwner()
+assert( isinstance(job_extract, Job) )
+assert( job_extract.GetName() == new_job.GetName() )
+
+
+invoice_entry = Entry(book, invoice_customer)
+invoice_entry.SetInvTaxTable(tax_table)
+invoice_entry.SetInvTaxIncluded(False)
+invoice_entry.SetDescription("excelent product")
+invoice_entry.SetQuantity( GncNumeric(1) )
+invoice_entry.SetInvAccount(a3)
+invoice_entry.SetInvPrice(GncNumeric(1) )
+
+invoice_customer.PostToAccount(a2, datetime.date.today(), datetime.date.today(),
+                               "the memo", True)
+
+new_customer.ApplyPayment(None, a2, a6, GncNumeric(100,100),
+                          GncNumeric(1), datetime.date.today(), "", "")
+
+new_customer.ApplyPayment(invoice_customer, a2, a6, GncNumeric(7,100),
+                          GncNumeric(1), datetime.date.today(), "", "")
+s.save()
+
+s.end()

Added: gnucash/trunk/src/optional/python-bindings/example_scripts/simple_invoice_insert.py
===================================================================
--- gnucash/trunk/src/optional/python-bindings/example_scripts/simple_invoice_insert.py	                        (rev 0)
+++ gnucash/trunk/src/optional/python-bindings/example_scripts/simple_invoice_insert.py	2010-06-25 11:06:29 UTC (rev 19294)
@@ -0,0 +1,112 @@
+#!/usr/bin/env python
+
+# simple_invoice_insert.py -- Add an invoice to a set of books
+#
+# Copyright (C) 2010 ParIT Worker Co-operative <transparency at parit.ca>
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, contact:
+# Free Software Foundation           Voice:  +1-617-542-5942
+# 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+# Boston, MA  02110-1301,  USA       gnu at gnu.org
+#
+# @author Mark Jenkins, ParIT Worker Co-operative <mark at parit.ca>
+
+# Opens a GnuCash book file and adds an invoice to it for a particular
+# customer (by GUID) with a specific ID and value 
+#
+# The account tree and tax tables are assumed to be the same as the ones
+# created in simple_business_create.py, but you can edit that to adapt
+# this to become an invoice imported for your own books
+#
+# Syntax:
+# gnucash-env python simple_invoice_insert.py \
+#          sqlite3:///home/blah/blah.gnucash
+#          dda2ec8e3e63c7715097f852851d6b22 1001 'The Goods' 201.43 
+
+from gnucash import Session, GUID, GncNumeric
+from gnucash.gnucash_business import Customer, Invoice, Entry
+from gnucash.gnucash_core_c import string_to_guid
+from os.path import abspath
+from sys import argv
+from decimal import Decimal
+import datetime
+
+def gnc_numeric_from_decimal(decimal_value):
+    sign, digits, exponent = decimal_value.as_tuple()
+
+    # convert decimal digits to a fractional numerator
+    # equivlent to
+    # numerator = int(''.join(digits))
+    # but without the wated conversion to string and back,
+    # this is probably the same algorithm int() uses
+    numerator = 0
+    TEN = int(Decimal(0).radix()) # this is always 10
+    numerator_place_value = 1
+    # add each digit to the final value multiplied by the place value
+    # from least significant to most sigificant
+    for i in xrange(len(digits)-1,-1,-1):
+        numerator += digits[i] * numerator_place_value
+        numerator_place_value *= TEN
+
+    if decimal_value.is_signed():
+        numerator = -numerator
+
+    # if the exponent is negative, we use it to set the denominator
+    if exponent < 0 :
+        denominator = TEN ** (-exponent)
+    # if the exponent isn't negative, we bump up the numerator
+    # and set the denominator to 1
+    else:
+        numerator *= TEN ** exponent
+        denominator = 1
+
+    return GncNumeric(numerator, denominator)
+
+
+s = Session(argv[1], False)
+# this seems to make a difference in more complex cases
+s.save()
+
+book = s.book
+root = book.get_root_account()
+commod_table = book.get_table()
+CAD = commod_table.lookup('CURRENCY', 'CAD')
+
+my_customer_guid = GUID()
+result = string_to_guid(argv[2], my_customer_guid.get_instance())
+assert( result )
+my_customer = book.CustomerLookup(my_customer_guid)
+assert( my_customer != None )
+assert( isinstance(my_customer, Customer) )
+
+assets = root.lookup_by_name("Assets")
+recievables = assets.lookup_by_name("Recievables")
+income = root.lookup_by_name("Income")
+
+invoice = Invoice(book, argv[3], CAD, my_customer )
+description = argv[4]
+invoice_value = gnc_numeric_from_decimal(Decimal(argv[5]))
+tax_table = book.TaxTableLookupByName('good tax')
+invoice_entry = Entry(book, invoice)
+invoice_entry.SetInvTaxTable(tax_table)
+invoice_entry.SetInvTaxIncluded(False)
+invoice_entry.SetDescription(description)
+invoice_entry.SetQuantity( GncNumeric(1) )
+invoice_entry.SetInvAccount(income)
+invoice_entry.SetInvPrice(invoice_value)
+
+invoice.PostToAccount(recievables, datetime.date.today(), datetime.date.today(),
+                      "", True)
+
+s.save()
+s.end()

Modified: gnucash/trunk/src/optional/python-bindings/gnucash_business.py
===================================================================
--- gnucash/trunk/src/optional/python-bindings/gnucash_business.py	2010-06-25 09:53:10 UTC (rev 19293)
+++ gnucash/trunk/src/optional/python-bindings/gnucash_business.py	2010-06-25 11:06:29 UTC (rev 19294)
@@ -1,7 +1,7 @@
 # gnucash_business.py -- High level python wrapper classes for the business
 #                        parts of GnuCash
 #
-# Copyright (C) 2008 ParIT Worker Co-operative <paritinfo at parit.ca>
+# Copyright (C) 2008,2010 ParIT Worker Co-operative <paritinfo at parit.ca>
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License as
 # published by the Free Software Foundation; either version 2 of
@@ -30,18 +30,204 @@
 
 from gnucash_core import \
      GnuCashCoreClass, GncNumeric, GncCommodity, Transaction, \
-     Split, Book
+     Split, Book, GncLot, Account
 
-class Customer(GnuCashCoreClass): pass
+from gnucash_core_c import GNC_OWNER_CUSTOMER, GNC_OWNER_JOB, \
+    GNC_OWNER_EMPLOYEE, GNC_OWNER_VENDOR, gncOwnerApplyPayment, \
+    GNC_PAYMENT_CASH, GNC_PAYMENT_CARD, \
+    GNC_DISC_PRETAX, GNC_DISC_SAMETIME, GNC_DISC_POSTTAX, \
+    GNC_TAXINCLUDED_YES, GNC_TAXINCLUDED_NO, GNC_TAXINCLUDED_USEGLOBAL, \
+    GNC_AMT_TYPE_VALUE, GNC_AMT_TYPE_PERCENT
 
-class Employee(GnuCashCoreClass): pass
+import datetime
 
-class Vendor(GnuCashCoreClass): pass
+class GnuCashBusinessEntity(GnuCashCoreClass):
+    def __init__(self, book=None, id=None, currency=None, name=None,
+                 instance=None):
+        if instance == None:
+            if book==None or id==None or currency==None:
+                raise Exception(
+                    "you must call GnuCashBusinessEntity.__init__ "
+                    "with either a book, id, and currency, or an existing "
+                    "low level swig proxy in the argument instance")
+            GnuCashCoreClass.__init__(self, book)
+            self.SetID(id)
+            self.SetCurrency(currency)
+            if name != None:
+                self.SetName(name)
+        else:
+            GnuCashCoreClass.__init__(self, instance=instance)
 
+    def ApplyPayment(self, invoice, posted_acc, xfer_acc, amount,
+                     exch, date, memo, num):
+        if invoice != None:
+            invoice = invoice.get_instance()
+        trans = gncOwnerApplyPayment(
+            self.get_instance(), invoice, posted_acc.get_instance(),
+            xfer_acc.get_instance(), amount.get_instance(),
+            exch.get_instance(), date, memo, num)
+        if trans != None:
+            trans = Transaction(instance=trans)
+        return trans
+            
+
+class Customer(GnuCashBusinessEntity): pass
+                         
+class Employee(GnuCashBusinessEntity):
+    def SetName(self, name):
+        self.GetAddr().SetName(name)
+    
+    def GetName(self):
+        return self.GetAddr().GetName()
+
+class Vendor(GnuCashBusinessEntity): pass
+
+class Job(GnuCashBusinessEntity):
+    # override the superclass contructor, as Job doesn't require
+    # a currency but it does require an owner
+    def __init__(self, book=None, id=None, owner=None, name=None,
+                 instance=None):
+        if instance == None:
+            if book==None or id==None or owner==None:
+                raise Exception(
+                    "you must call Job.__init__ "
+                    "with either a book, id, and owner or an existing "
+                    "low level swig proxy in the argument instance")
+            GnuCashCoreClass.__init__(self, book)
+            self.SetID(id)
+            self.SetOwner(owner)
+            if name != None:
+                self.SetName(name)
+        else:
+            GnuCashCoreClass.__init__(self, instance=instance)    
+
 class Address(GnuCashCoreClass): pass
     
 class BillTerm(GnuCashCoreClass): pass
 
+class TaxTable(GnuCashCoreClass):
+    def __init__(self, book=None, name=None, first_entry=None, instance=None):
+        if instance == None:
+            if book==None or name==None or first_entry==None:
+                raise Exception(
+                    "you must call TaxTable.__init__  with either a "
+                    "book, name, and first_entry, or an existing "
+                    "low level swig proxy in the argument instance")
+            GnuCashCoreClass.__init__(self, book)
+            self.SetName(name)
+            self.AddEntry(first_entry)
+        else:
+            GnuCashCoreClass.__init__(self, instance=instance)
+
+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.
+        """
+
+        if instance == None:
+            if account==None:
+                raise Exception(
+                    "you must call TaxTableEntry.__init__  with either a "
+                    "account or an existing "
+                    "low level swig proxy in the argument instance")
+            GnuCashCoreClass.__init__(self)
+            self.SetAccount(account)
+            if percent:
+                self.SetType(GNC_AMT_TYPE_PERCENT)
+            else:
+                self.SetType(GNC_AMT_TYPE_VALUE)
+            if amount != None:
+                self.SetAmount(amount)
+        else:
+            GnuCashCoreClass.__init__(self, instance=instance)        
+
+class Invoice(GnuCashCoreClass):
+    def __init__(self, book=None, id=None, currency=None, owner=None,
+                 date_opened=None, instance=None):
+        """Invoice Contstructor
+
+        You must provide a book, id, currency and owner
+        (Customer, Job, Employee, Vendor) or an existing swig proxy object
+        in the keyword argument instance.
+
+        Optionally, you may provide a date the invoice is opened on
+        (datetime.date or datetime.datetime), otherwise today's date is used.
+        """
+        if instance == None:
+            if book==None or id==None or currency==None or owner==None:
+                raise Exception(
+                    "you must call Invoice.__init__ "
+                    "with either a book, id, currency and owner, or an existing"
+                    "low level swig proxy in the argument instance")
+            GnuCashCoreClass.__init__(self, book)
+            self.SetID(id)
+            self.SetCurrency(currency)
+            self.SetOwner(owner)
+            if date_opened == None:
+                date_opened = datetime.date.today()
+            self.SetDateOpened(date_opened)
+        else:
+            GnuCashCoreClass.__init__(self, instance=instance)
+
+class Bill(Invoice):
+    pass
+
+def decorate_to_return_instance_instead_of_owner(dec_function):
+    def new_get_owner_function(self):
+        (owner_type, instance) = dec_function(self)
+        if owner_type == GNC_OWNER_CUSTOMER:
+            return Customer(instance=instance)
+        elif owner_type == GNC_OWNER_JOB:
+            return Job(instance=instance)
+        elif owner_type == GNC_OWNER_EMPLOYEE:
+            return Employee(instance=instance)
+        elif owner_type == GNC_OWNER_VENDOR:
+            return Vendor(instance=instance)
+        else:
+            return None
+    return new_get_owner_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.
+
+        The optional invoice argument can be set to a Bill or Invoice
+        that you would like to associate the entry with. You might as well
+        assign one now, as an Entry can't exist without one, but you can
+        always use Invoice.AddEntry or Bill.AddEntry later on.
+
+        By default, the entry will be set to today's date unless you
+        override with the date argument.
+        """
+        if instance == None:
+            if book==None:
+                raise Exception(
+                    "you must call Entry.__init__  with either a "
+                    "book or an existing "
+                    "low level swig proxy in the argument instance")
+            GnuCashCoreClass.__init__(self, book)
+
+            if date == None:
+                date = datetime.date.today()
+            self.SetDate(date)
+            if invoice != None:
+                invoice.AddEntry(self)
+        else:
+            GnuCashCoreClass.__init__(self, instance=instance)    
+
 # Customer
 Customer.add_constructor_and_methods_with_prefix('gncCustomer', 'Create')
 
@@ -51,7 +237,8 @@
                     'GetDiscount' : GncNumeric,
                     'GetCredit' : GncNumeric,
                     'GetTerms' : BillTerm,
-                    'GetCurrency' : GncCommodity
+                    'GetCurrency' : GncCommodity,
+                    'GetTaxTable': TaxTable,
                 }
 methods_return_instance(Customer, customer_dict)
 
@@ -73,10 +260,17 @@
 vendor_dict =   {
                     'GetAddr' : Address,
                     'GetTerms' : BillTerm,
-                    'GetCurrency' : GncCommodity
+                    'GetCurrency' : GncCommodity,
+                    'GetTaxTable': TaxTable,
                 }
 methods_return_instance(Vendor, vendor_dict)
 
+# Job
+Job.add_constructor_and_methods_with_prefix('gncJob', 'Create')
+Job.decorate_functions(
+    decorate_to_return_instance_instead_of_owner,
+    'GetOwner')
+
 # Address
 Address.add_constructor_and_methods_with_prefix('gncAddress', 'Create')
 
@@ -90,3 +284,68 @@
                     'ReturnChild' : BillTerm
                 }
 methods_return_instance(BillTerm, billterm_dict)
+
+# TaxTable
+TaxTable.add_constructor_and_methods_with_prefix('gncTaxTable', 'Create')
+
+taxtable_dict = {
+                    'GetParent': TaxTable,
+                }
+methods_return_instance(TaxTable, taxtable_dict)
+
+# TaxTableEntry
+TaxTableEntry.add_constructor_and_methods_with_prefix(
+    'gncTaxTableEntry', 'Create')
+
+taxtableentry_dict = {
+                         'GetAccount': Account,
+                         'GetAmount': GncNumeric,
+                     }
+
+# Invoice
+Invoice.add_constructor_and_methods_with_prefix('gncInvoice', 'Create')
+
+# Bill
+Bill.add_methods_with_prefix('gncBill')
+
+invoice_dict = {
+                   'GetTerms': BillTerm,
+                   'GetCurrency': GncCommodity,
+                   'GetToChargeAmount': GncNumeric,
+                   'GetPostedLot': GncLot,
+                   'GetPostedTxn': Transaction,
+                   'GetPostedAcc': Account,
+                   'GetTotal': GncNumeric,
+                   'GetTotalOf': GncNumeric,
+                   'GetTotalSubtotal': GncNumeric,
+                   'GetTotalTax': GncNumeric,
+                   'PostToAccount': Transaction,
+                   'GetBook': Book,
+               }
+methods_return_instance(Invoice, invoice_dict)
+Invoice.decorate_functions(
+    decorate_to_return_instance_instead_of_owner,
+    'GetOwner', 'GetBillTo')
+
+# Entry
+Entry.add_constructor_and_methods_with_prefix('gncEntry', 'Create')
+
+entry_dict = {
+                 'GetQuantity': GncNumeric,
+                 'GetInvAccount': Account,
+                 'GetInvPrice': GncNumeric,
+                 'GetInvDiscount': GncNumeric,
+                 'GetInvTaxTable': TaxTable,
+                 'GetBillAccount': Account,
+                 'GetBillPrice': GncNumeric,
+                 'GetBillTaxTable': TaxTable,
+                 'Copy': Entry,
+                 'ReturnValue': GncNumeric,
+                 'ReturnDiscountValue': GncNumeric,
+                 'ReturnTaxValue': GncNumeric,
+                 'GetInvoice': Invoice,
+                 'GetBill': Invoice
+             }
+Entry.decorate_functions(
+    decorate_to_return_instance_instead_of_owner,
+    'GetBillTo' )

Modified: gnucash/trunk/src/optional/python-bindings/gnucash_core.i
===================================================================
--- gnucash/trunk/src/optional/python-bindings/gnucash_core.i	2010-06-25 09:53:10 UTC (rev 19293)
+++ gnucash/trunk/src/optional/python-bindings/gnucash_core.i	2010-06-25 11:06:29 UTC (rev 19294)
@@ -53,6 +53,11 @@
 #include "gncVendor.h"
 #include "gncAddress.h"
 #include "gncBillTerm.h"
+#include "gncOwner.h"
+#include "gncInvoice.h"
+#include "gncJob.h"
+#include "gncEntry.h"
+#include "gncTaxTable.h"
 %}
 
 %include <timespec.i>
@@ -86,6 +91,79 @@
 
 %include <gnc-commodity.h>
 
+%include <gncOwner.h>
+
+%typemap(out) GncOwner * {
+    GncOwnerType owner_type = gncOwnerGetType($1);
+    PyObject * owner_tuple = PyTuple_New(2);
+    PyTuple_SetItem(owner_tuple, 0, PyInt_FromLong( (long) owner_type ) );
+    PyObject * swig_wrapper_object;
+    if (owner_type == GNC_OWNER_CUSTOMER ){
+        swig_wrapper_object = SWIG_NewPointerObj(
+	    gncOwnerGetCustomer($1), $descriptor(GncCustomer *), 0);
+    }
+    else if (owner_type == GNC_OWNER_JOB){
+        swig_wrapper_object = SWIG_NewPointerObj(
+	    gncOwnerGetJob($1), $descriptor(GncJob *), 0);
+    }
+    else if (owner_type == GNC_OWNER_VENDOR){
+        swig_wrapper_object = SWIG_NewPointerObj(
+	    gncOwnerGetVendor($1), $descriptor(GncVendor *), 0);
+    }
+    else if (owner_type == GNC_OWNER_EMPLOYEE){
+        swig_wrapper_object = SWIG_NewPointerObj(
+	    gncOwnerGetEmployee($1), $descriptor(GncEmployee *), 0);
+    }
+    else {
+        swig_wrapper_object = Py_None;
+	Py_INCREF(Py_None);
+    }
+    PyTuple_SetItem(owner_tuple, 1, swig_wrapper_object);
+    $result = owner_tuple;
+}
+
+
+%typemap(in) GncOwner * {
+    GncOwner * temp_owner = gncOwnerCreate();
+    void * pointer_to_real_thing;
+    if ((SWIG_ConvertPtr($input, &pointer_to_real_thing,
+                         $descriptor(GncCustomer *),
+                         SWIG_POINTER_EXCEPTION)) == 0){
+        gncOwnerInitCustomer(temp_owner, (GncCustomer *)pointer_to_real_thing);
+        $1 = temp_owner;
+    }
+    else if ((SWIG_ConvertPtr($input, &pointer_to_real_thing,
+                         $descriptor(GncJob *),
+                         SWIG_POINTER_EXCEPTION)) == 0){
+        gncOwnerInitJob(temp_owner, (GncJob *)pointer_to_real_thing);
+        $1 = temp_owner;
+    }
+    else if ((SWIG_ConvertPtr($input, &pointer_to_real_thing,
+                         $descriptor(GncVendor *),
+                         SWIG_POINTER_EXCEPTION)) == 0){
+        gncOwnerInitVendor(temp_owner, (GncVendor *)pointer_to_real_thing);
+        $1 = temp_owner;
+    }
+    else if ((SWIG_ConvertPtr($input, &pointer_to_real_thing,
+                         $descriptor(GncEmployee *),
+                         SWIG_POINTER_EXCEPTION)) == 0){
+        gncOwnerInitEmployee(temp_owner, (GncEmployee *)pointer_to_real_thing);
+        $1 = temp_owner;
+    }
+    else {
+	PyErr_SetString(
+	    PyExc_ValueError,
+	    "Python object passed to function with GncOwner * argument "
+	    "couldn't be converted back to pointer of that type");
+        return NULL;
+    }
+}
+
+%typemap(freearg) GncOwner * {
+    gncOwnerDestroy($1);
+}
+
+
 %include <gnc-lot.h>
 
 //business-core includes
@@ -94,6 +172,10 @@
 %include <gncVendor.h>
 %include <gncAddress.h>
 %include <gncBillTerm.h>
+%include <gncInvoice.h>
+%include <gncJob.h>
+%include <gncEntry.h>
+%include <gncTaxTable.h>
 
 %init %{
 

Modified: gnucash/trunk/src/optional/python-bindings/gnucash_core.py
===================================================================
--- gnucash/trunk/src/optional/python-bindings/gnucash_core.py	2010-06-25 09:53:10 UTC (rev 19293)
+++ gnucash/trunk/src/optional/python-bindings/gnucash_core.py	2010-06-25 11:06:29 UTC (rev 19294)
@@ -28,9 +28,22 @@
      default_arguments_decorator, method_function_returns_instance, \
      methods_return_instance
 
+from gnucash_core_c import gncInvoiceLookup, gncInvoiceGetInvoiceFromTxn, \
+    gncInvoiceGetInvoiceFromLot, gncEntryLookup, gncInvoiceLookup, \
+    gncCustomerLookup, gncVendorLookup, gncJobLookup, gncEmployeeLookup, \
+    gncTaxTableLookup, gncTaxTableLookupByName
+    
+
 class GnuCashCoreClass(ClassFromFunctions):
     _module = gnucash_core_c
 
+    def do_lookup_create_oo_instance(self, lookup_function, cls, *args):
+        thing = lookup_function(self.get_instance(), *args)
+        if thing != None:
+            thing = cls(instance=thing)
+        return thing
+
+
 class GnuCashBackendException(Exception):
     def __init__(self, msg, errors):
         Exception.__init__(self, msg)
@@ -135,8 +148,46 @@
     get_root_account -- Returns the root level Account
     get_table -- Returns a commodity lookup table, of type GncCommodityTable
     """
-    pass
+    def InvoiceLookup(self, guid):
+        from gnucash_business import Invoice
+        return self.do_lookup_create_oo_instance(
+            gncInvoiceLookup, Invoice, guid.get_instance() )
 
+    def EntryLookup(self, guid):
+        from gnucash_business import Entr
+        return self.do_lookup_create_oo_instance(
+            gncEntryLookup, Entry, guid.get_instance() )
+
+    def CustomerLookup(self, guid):
+        from 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
+        return self.do_lookup_create_oo_instance(
+            gncJobLookup, Job, guid.get_instance() )
+
+    def VendorLookup(self, guid):
+        from 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
+        return self.do_lookup_create_oo_instance(
+            gncEmployeeLookup, Employee, guid.get_instance() )
+
+    def TaxTableLookup(self, guid):
+        from 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
+        return self.do_lookup_create_oo_instance(
+            gncTaxTableLookupByName, TaxTable, name)
+
 class GncNumeric(GnuCashCoreClass):
     """Object used by GnuCash to store all numbers. Always consists of a
     numerator and denominator.
@@ -170,7 +221,10 @@
     pass
 
 class GncLot(GnuCashCoreClass):
-    pass
+    def GetInvoiceFromLot(self):
+        from gnucash_business import Invoice
+        return self.do_lookup_create_oo_instance(
+            gncInvoiceGetInvoiceFromLot, Invoice )
 
 class Transaction(GnuCashCoreClass):
     """A GnuCash Transaction
@@ -182,6 +236,11 @@
     def GetNthSplit(self, n):
         return self.GetSplitList().pop(n)
 
+    def GetInvoiceFromTxn(self):
+        from gnucash_business import Transaction
+        return self.do_lookup_create_oo_instance(
+            gncInvoiceGetInvoiceFromTxn, Transaction )
+
 class Split(GnuCashCoreClass):
     """A GnuCash Split
 



More information about the gnucash-changes mailing list