gncOwnerCreatePaymentLotSecs is a bad design because it tries to fit two use 
cases. 

One,  in gncInvoiceApplyPayment, has a transaction already and passes it to 
gncOwnerCreatePaymentLotSecs. That's OK.

The other, in gnc_payment_ok_cb via gncOwnerApplyPayemtSecs, asks it to create 
a transaction and apply the payment to it, and passes in a Transaction** so 
that it can get the new transaction. That's bad. The fix is to remove the 
transaction-creation code from gncOwnerCreatePaymentLotSecs and change the 
Transaction** parameter to Transaction* in both gncOwnerCreatePaymentLotSecs 
and gncOwnerApplyPaymentSecs. gnc_payment_ok_cb (actually gnc_payment_ok_cb's 
controller function, but that's for a different rant) should create the 
transaction itself and pass it to gncOwnerApplyPayemtSecs.

While that will make gncOwnerCreatePaymentLotSecs wrappable, I think it's 
debatable that it should be wrapped: It's pretty clearly an implementation 
detail of applying a payment. Implementation details shouldn't be part of the 
public API.

Regards,
John Ralls


> On May 10, 2022, at 2:59 PM, Matteo Lasagni <laser...@gmail.com> wrote:
> 
> Thank you Derek, I understand what you mean.
> The point here is that I was not interested in the value returned through the 
> pointer,
> but only in making that function callable from Python.
> I was looking for a solution to automatically associate multiple invoices to 
> the same transaction,
> as it is possible with the GUI; this seemed to be the right way.
> Maybe there is a better solution for this specific goal.
> 
> However, I try to follow your suggestion to unref the return value or return 
> it in a tuple.
> Since I kept receiving always the following error, no matter how I change the 
> swig interface,
> I was only focusing on the input value (i.e., c input direction) quite 
> convinced the first step was
> to fix the conversion of a double pointer.
> 
> TypeError: in method 'gncOwnerCreatePaymentLotSecs', argument 2 of type 
> 'Transaction **'
> 
> 
> Best,
> Matteo
> 
> 
> 
> On Tue, 10 May 2022 at 23:37, Derek Atkins <de...@ihtfp.com 
> <mailto:de...@ihtfp.com>> wrote:
> More specifically...
> 
> The issue here is that there are multiple return values.  
> gncOwnerCreatePaymentLotSecs() is *RETURNING* both a GNCLot* and a
> Transaction*.  However, C doesn't allow you to do that, so the function
> returns the GNCLot* and assigns the Transaction* to the Transaction**
> argument as a second return value.
> 
> Your proposed wrapper here is wrong.
> 
> You can either write a wrapper that obtains the transaction and then
> unrefs it (returning only the Lot), or you can write a wrapper that
> obtains both values and returns the tuple (Lot, Txn) in Python -- assuming
> Python, like Scheme, allows that.
> 
> Most likely this is why the function wasn't wrapped before -- due to the
> complexities of the double return values.
> 
> -derek
> 
> On Tue, May 10, 2022 5:23 pm, Matteo Lasagni wrote:
> > If I can find a good solution, yes, I will put it in a pull request.
> >
> > I have tried to encapsulate Transaction* in a list, but of course it
> > doesn't work without touching swig definitions.
> > I am now trying to create a specific typemap for handling the double
> > pointer. I think this would be the cleanest solution.
> >
> > Alternatively, a quick and dirty workaround is to add a C wrapper in
> > gncOwner.c that expects Transaction* and passes Transaction** to
> > gncOwnerCreatePaymentLotSecs:
> >
> >
> > GNCLot *
> > gncOwnerCreatePaymentLotSecsPyHelper (const GncOwner *owner, Transaction
> > *txn, Account *posted_acc, Account *xfer_acc, gnc_numeric amount,
> > gnc_numeric exch, time64 date, const char *memo, const char *num)
> > {
> >     return gncOwnerCreatePaymentLotSecs(owner, &txn, posted_acc, xfer_acc,
> > amount, exch, date, memo, num);
> > }
> >
> >
> > regards,
> > Matteo
> >
> > On Tue, 10 May 2022 at 17:25, john <jra...@ceridwen.us 
> > <mailto:jra...@ceridwen.us>> wrote:
> >
> >>
> >>
> >> On May 10, 2022, at 1:53 AM, Matteo Lasagni <laser...@gmail.com 
> >> <mailto:laser...@gmail.com>> wrote:
> >>
> >> Thank you, John!
> >>
> >> I fixed it by adding the following into base-typemaps.i:
> >>
> >> %typemap(in) GList * {
> >>     $1 = NULL;
> >>     /* Check if is a list */
> >>     if (PyList_Check($input)) {
> >>         int i;
> >>         int size = PyList_Size($input);
> >>         for (i = size-1; i >= 0; i--) {
> >>             PyObject *o = PyList_GetItem($input, i);
> >>             $1 = g_list_prepend($1, o);
> >>         }
> >>     } else {
> >>         PyErr_SetString(PyExc_TypeError, "not a list");
> >>         return NULL;
> >>     }
> >> }
> >>
> >> I had overlooked the swig definition in engine.i, where there is a
> >> typemap
> >> (in) for GList, but then it is cleared right afterwards...
> >> I am not (yet) very familiar with swig :-)
> >>
> >> I have also noticed that CreatePaymentLotSecs does not work out of the
> >> box, as it expects **Transaction while only *Transaction is type mapped.
> >>
> >> I will test these changes then I will figure out how to share them with
> >> the developers.
> >>
> >>
> >> Matteo
> >>
> >>
> >> On Tue, 10 May 2022 at 02:32, John Ralls <jra...@ceridwen.us 
> >> <mailto:jra...@ceridwen.us>> wrote:
> >>
> >>>
> >>>
> >>> > On May 9, 2022, at 2:17 PM, Matteo Lasagni <laser...@gmail.com 
> >>> > <mailto:laser...@gmail.com>>
> >>> wrote:
> >>> >
> >>> > Hi,
> >>> > I am writing a python script to automatically associate a set of
> >>> > invoices to a single transaction.
> >>> > To this end, I am trying to use the function
> >>> AutoApplyPaymentsWithLots
> >>> > with no success:
> >>> >
> >>> >
> >>> > lots = [lot1, lot2, lotn, ..]
> >>> > owner.AutoApplyPaymentsWithLots(lots)
> >>> >
> >>> > This causes the following error:
> >>> >
> >>> > TypeError: in method 'gncOwnerAutoApplyPaymentsWithLots', argument 2
> >>> of
> >>> > type 'GList *'
> >>> >
> >>> > I have tried different solutions from passing different types of
> >>> python
> >>> > objects, to updating the swig typemap and also to modifying the
> >>> > auto-generated gnucash_core.c...nothing worked out so far.
> >>> > I could write an additional c-wrapper, but I am sure there is a more
> >>> > general solution.
> >>>
> >>> The fundamental problem is that there's only a Python out typemap for
> >>> GList, that is one that converts from a GList* to a python list.
> >>> Lacking an
> >>> in typemap the gncOwner.AutoApplyPaymentsWithLots python wrapper
> >>> expects an
> >>> already constructed and Swig-wrapped GList*.
> >>>
> >>> Regards,
> >>> John Ralls
> >>>
> >>>
> >>
> >> Nice. Would you put that in a pull request?
> >>
> >> There are two typemap(in) GList* in engine.i, but they're both for Guile
> >> (Scheme), not Python. 'scm' is the giveaway.
> >>
> >> If there's a way to implement an output pointer parameter in Python I
> >> don't know about it. You can pass in a container object and put the
> >> output
> >> Transaction* in the container, but that's both a bit of a hack and
> >> doesn't
> >> have the same meaning as Transaction** nor is it very pythonic. Nor, for
> >> that matter, is gncOwnerCreatePaymentLotSecs a very good design as it
> >> mixes
> >> responsibilities. Unfortunately there's a lot of that in GnuCash because
> >> most of it is written with a very narrow focus, in this case providing
> >> for
> >> the payments dialog.
> >>
> >> Regards,
> >> John Ralls
> >>
> >>
> >
> > --
> >
> > -------------
> > Matteo Lasagni
> >
> >
> > *"You can't connect the dots looking forward,you can only connect them
> > looking backwards"* [Steve Jobs]
> > _______________________________________________
> > gnucash-devel mailing list
> > gnucash-devel@gnucash.org <mailto:gnucash-devel@gnucash.org>
> > https://lists.gnucash.org/mailman/listinfo/gnucash-devel 
> > <https://lists.gnucash.org/mailman/listinfo/gnucash-devel>
> >
> 
> 
> -- 
>        Derek Atkins                 617-623-3745
>        de...@ihtfp.com <mailto:de...@ihtfp.com>             www.ihtfp.com 
> <http://www.ihtfp.com/>
>        Computer and Internet Security Consultant
> 
> 
> 
> -- 
> 
> -------------
> Matteo Lasagni
> 
> "You can't connect the dots looking forward,
> you can only connect them looking backwards" [Steve Jobs]

_______________________________________________
gnucash-devel mailing list
gnucash-devel@gnucash.org
https://lists.gnucash.org/mailman/listinfo/gnucash-devel

Reply via email to