Python bindings: patch, documentation, examples
David Osguthorpe
david.osguthorpe at gmail.com
Sat May 10 03:22:45 EDT 2014
Interestingly one of the extensions Im using gets the budget - as you say
its not available in current bindings - dont know about Future Transactions
- to get the budget needed some fixups to swig bindings
Ive attached my 2 extension scripts plus the binding patches ( this is to
2.6 version)
The budget extensions require re-running swig so you would need to build
gnucash - although it would be possible to access the budget using ctypes
without recompilation
Theres a little script showing usage of budget functions
Ill leave the pyguile/schemepy for now
David
On Fri, May 9, 2014 at 11:06 PM, Marc Shapiro <marcnshap at gmail.com> wrote:
> On 05/09/2014 06:37 PM, David Osguthorpe wrote:
>
>> On Thu, May 08, 2014 at 11:47:34PM -0700, mshapiro wrote:
>>
>>> David Osguthorpe wrote
>>>
>>>> I have a very hacky implementation in gnucash to call python from guile
>>>> and
>>>> return results to guile - I found existing libraries to do both
>>>> (no updates to gnucash required - just a user prototype.scm file)
>>>>
>>> Can you post what libraries you used, where you got them, how to use them
>>> and your prototype.scm file. Also, any pointers to useful documentation
>>> for
>>> using the Python bindings would be greatly appreciated. I am primarily
>>> interested (at the moment) in accessing budgeting information and future
>>> transactions, as well as accounts, since I would like to do more
>>> forecasting
>>> than the standard reports provide.
>>>
>>> it is really hacky - and I still had crashes when attempting to create
>> real reports
>> so its very, very alpha
>> but if you wish to pursue it here are the details
>>
> I have the feeling that I will be better off to just write a standalone
> python script. This is not really a problem. A program to do forecasting
> can be done outside gnucash just fine. Except that I still need to find a
> way to access the future transactions and the budget information. I
> haven't seen either of these in any of the example reports for the python
> bindings. Does anyone know of any info on how to use the python bindings
> to access these?
>
> note this does not use any of the python bindings - as far as I can tell
>> they only work for
>> non-gui standalone scripts - well its the only Ive used them
>> - you would write a script to access your gnucash database (xml or SQL)
>> and use any python
>> modules to format the data for a new report completely outside of gnucash
>> for the moment I would say you would be better just writing command line
>> scripts
>> using the python bindings to generate HTML or whatever reports
>>
>> here are some details
>>
>> 1. you need pyguile - a module for calling guile version of scheme from
>> python
>> - unfortunately the available source has not been udpated for years so
>> needed quite
>> a bit of patching to build (I run under macports on OSX mainly)
>> - one patch I did have to add was the ability to return so called SCM
>> (scheme) objects
>> back to guile
>>
>> 2. you need schemepy - which has a module for calling python from guile
>> version of scheme
>> - again the available source has not been udpated for years so needed
>> some patching to get running
>>
>> Then you have the prototype.scm (simply not bothered to change name)
>> which sets up
>> to call python where you could write your report.
>>
>>
>> My initial goal was to write reports in python - Im primarily writing in
>> this now
>> and although I had tried scheme for a multiple stock price scatter plot
>> report every time I went
>> back trying to re-think in scheme was a pain
>>
> I tried to write my report in scheme, and I can't really say that I
> failed. Just that I never got it finished. I took the Balance Sheet , the
> Budget Report and the Future Transactions Report and tried to put them
> together. I was able to successfully combine all of the required options
> so that they can be input on a singe screen. Then it simply runs the
> Balance Sheet. If I could figure out how to access the future transactions
> and budgeting data and update the accounts on the Balance Sheet before
> displaying them then I would be all set. But, so far, I have not been able
> to wrap my head around that much scheme. As a co-worker says of LISP (he
> uses it in AutoCad) I find myself Lost In Stupid Parenthesis. It makes my
> head hurt.
>
> The major problem I ran across is that when analysing the GUI report
>> system in gnucash
>> I discovered it was not done in pure gtk but some of the gui is actually
>> written in scheme
>> by calling gtk gunctions via swig wrapped functions involving gtk
>> - to directly call python reports would need re-writing most of this GUI
>> scheme stuff using
>> the python gtk library - not difficult but seemed like a lot of work
>> I had hoped to find a report function where I could plugin in a call to
>> python so could then
>> do the report in python (python has the ctypes module which allows
>> calling C functions
>> in arbitrary C shared libraries such as gnucash uses) - pygtk allows
>> direct use of gtk functions
>> in python
>> I did this around 2.4.7 and am looking to review it now at 2.6.3
>>
>> from that analysis as far as I could tell the final report result is an
>> html text string which is
>> written to a file - again these components using scheme coding
>>
>>
>> If you really want the files let me know
>>
> Yes. If you can post the files, or links to them, then I will have them
> if I decide to try and go down that route. If not, well, it won't hurt to
> have them and maybe it can help someone else.
>
> as you have discovered there isnt much documentation of the python
>> bindings
>>
> Yes. If I had proper documentation then I would have just written the
> standalone report and been done with it. As it stands, I have no actual
> proof that the bindings will give me access to the budgeting and future
> transactions. That may never have been included in them, but since no one
> actually seems to have documented what is, or is not, included (let alone
> how to use it) it makes it kind of difficult.
>
> Marc
>
>
> _______________________________________________
> gnucash-devel mailing list
> gnucash-devel at gnucash.org
> https://lists.gnucash.org/mailman/listinfo/gnucash-devel
>
-------------- next part --------------
--- src/base-typemaps.i.orig 2013-12-28 11:46:49.000000000 -0800
+++ src/base-typemaps.i 2014-01-26 12:57:22.000000000 -0800
@@ -161,8 +161,12 @@
}
}
-%typemap(out) GList *, CommodityList *, SplitList *, AccountList *, LotList *,
- MonetaryList *, PriceList *, EntryList * {
+/*
+ * move specific type lists into separate functions
+ * leaving a single generic GList function
+ */
+
+%typemap(out) GList * {
guint i;
gpointer data;
PyObject *list = PyList_New(0);
@@ -197,11 +201,107 @@
PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p__gncJob, 0));
else if (GNC_IS_TAXTABLE(data))
PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p__gncTaxTable, 0));
- else if ($1_descriptor == $descriptor(MonetaryList *))
- PyList_Append(list, SWIG_NewPointerObj(data, $descriptor(gnc_monetary *), 0));
+ else if (GNC_IS_BUDGET(data))
+ PyList_Append(list, SWIG_NewPointerObj(data, $descriptor(GncBudget *), 0));
else
PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p_void, 0));
}
$result = list;
}
+
+%typemap(out) EntryList * {
+ guint i;
+ gpointer data;
+ PyObject *list = PyList_New(0);
+ for (i = 0; i < g_list_length($1); i++)
+ {
+ data = g_list_nth_data($1, i);
+ PyList_Append(list, SWIG_NewPointerObj(data, $descriptor(Entry *), 0));
+ }
+ $result = list;
+}
+
+%typemap(out) PriceList * {
+ guint i;
+ gpointer data;
+ PyObject *list = PyList_New(0);
+ for (i = 0; i < g_list_length($1); i++)
+ {
+ data = g_list_nth_data($1, i);
+ PyList_Append(list, SWIG_NewPointerObj(data, $descriptor(GNCPrice *), 0));
+ }
+ $result = list;
+}
+
+%typemap(out) LotList * {
+ guint i;
+ gpointer data;
+ PyObject *list = PyList_New(0);
+ for (i = 0; i < g_list_length($1); i++)
+ {
+ data = g_list_nth_data($1, i);
+ PyList_Append(list, SWIG_NewPointerObj(data, $descriptor(GNCLot *), 0));
+ }
+ $result = list;
+}
+
+%typemap(out) AccountList * {
+ guint i;
+ gpointer data;
+ PyObject *list = PyList_New(0);
+ for (i = 0; i < g_list_length($1); i++)
+ {
+ data = g_list_nth_data($1, i);
+ PyList_Append(list, SWIG_NewPointerObj(data, $descriptor(Account *), 0));
+ }
+ $result = list;
+}
+
+%typemap(out) SplitList * {
+ guint i;
+ gpointer data;
+ PyObject *list = PyList_New(0);
+ for (i = 0; i < g_list_length($1); i++)
+ {
+ data = g_list_nth_data($1, i);
+ PyList_Append(list, SWIG_NewPointerObj(data, $descriptor(Split *), 0));
+ }
+ $result = list;
+}
+
+%typemap(out) CommodityList * {
+ guint i;
+ gpointer data;
+ PyObject *list = PyList_New(0);
+ for (i = 0; i < g_list_length($1); i++)
+ {
+ data = g_list_nth_data($1, i);
+ PyList_Append(list, SWIG_NewPointerObj(data, $descriptor(gnc_commodity *), 0));
+ }
+ $result = list;
+}
+
+%typemap(out) MonetaryList * {
+ guint i;
+ gpointer data;
+ PyObject *list = PyList_New(0);
+ for (i = 0; i < g_list_length($1); i++)
+ {
+ data = g_list_nth_data($1, i);
+ PyList_Append(list, SWIG_NewPointerObj(data, $descriptor(gnc_monetary *), 0));
+ }
+ $result = list;
+}
+
+%typemap(out) GncTaxTableEntryList * {
+ guint i;
+ gpointer data;
+ PyObject *list = PyList_New(0);
+ for (i = 0; i < g_list_length($1); i++)
+ {
+ data = g_list_nth_data($1, i);
+ PyList_Append(list, SWIG_NewPointerObj(data, $descriptor(GncTaxTableEntry *), 0));
+ }
+ $result = list;
+}
#endif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: gnucash_ext.py
Type: text/x-python-script
Size: 13562 bytes
Desc: not available
URL: <http://lists.gnucash.org/pipermail/gnucash-devel/attachments/20140510/c55ead73/attachment-0003.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: gnucash_ctypes.py
Type: text/x-python-script
Size: 12007 bytes
Desc: not available
URL: <http://lists.gnucash.org/pipermail/gnucash-devel/attachments/20140510/c55ead73/attachment-0004.bin>
-------------- next part --------------
--- src/optional/python-bindings/Makefile.am.orig 2013-12-28 11:46:50.000000000 -0800
+++ src/optional/python-bindings/Makefile.am 2014-01-07 18:27:27.000000000 -0800
@@ -1,6 +1,6 @@
SUBDIRS = . tests
-SWIG_FILES = gnucash_core.i timespec.i
+SWIG_FILES = gnucash_core.i timespec.i gdate.i
pkgpyexec_DATA = \
__init__.py \
--- src/optional/python-bindings/gnucash_core.i.orig 2013-12-28 11:46:50.000000000 -0800
+++ src/optional/python-bindings/gnucash_core.i 2014-01-08 15:59:40.000000000 -0800
@@ -82,6 +82,8 @@
#include "app-utils/gnc-prefs-utils.h"
%}
+%include <gdate.i>
+
%include <timespec.i>
%include <base-typemaps.i>
--- src/optional/python-bindings/gdate.i.orig 2014-01-08 16:47:56.000000000 -0800
+++ src/optional/python-bindings/gdate.i 2014-01-08 16:46:28.000000000 -0800
@@ -0,0 +1,76 @@
+/*
+ * gdate.i -- SWIG interface file for type translation of GDate types
+ *
+ */
+
+
+// well cant include this
+//%include "/opt/local/include/glib-2.0/glib/gdate.h"
+
+// but this starts getting there
+
+// this is a dummy definition
+// this tells swig we have this class but nothing is known about it
+// note that if we map these to python types on input/output python
+// never needs to know about GDate internals
+struct GDate { };
+
+%extend GDate {
+ GDate() {
+ return g_date_new();
+ }
+ ~GDate() {
+ g_date_free($self);
+ }
+}
+
+// A typemap for converting python dates to GDate in functions that
+// require GDate as an argument
+// not clear any functions in gnucash pass GDate objects - always pointers to objects
+%typemap(in) GDate {
+ PyDateTime_IMPORT;
+ g_date_set_day(&($1),PyDateTime_GET_DAY($input));
+ g_date_set_month(&($1),PyDateTime_GET_MONTH($input));
+ g_date_set_year(&($1),PyDateTime_GET_YEAR($input));
+}
+
+//
+// need to fix for julian dates??
+// dont think so - looks like GDate interconverts between dmy and julian
+// depending on how called
+// issue with this is what about freeing GDates??
+// use the freearg typemap
+%typemap(in) GDate * (GDate *ts) {
+ PyDateTime_IMPORT;
+ ts = g_date_new_dmy(PyDateTime_GET_DAY($input),
+ PyDateTime_GET_MONTH($input),
+ PyDateTime_GET_YEAR($input) );
+ $1 = ts;
+}
+
+%typemap(freearg) GDate * {
+ g_date_free($1);
+}
+
+// A typemap for converting GDate values returned from functions to
+// python dates.
+// need to fix for julian dates??
+// dont think so - looks like GDate interconverts between dmy and julian
+// depending on how called
+%typemap(out) GDate * {
+ int year, month, day;
+ PyDateTime_IMPORT;
+ day = g_date_get_day($1);
+ month = g_date_get_month($1);
+ year = g_date_get_year($1);
+ $result = PyDate_FromDate(year, month, day);
+}
+
+%typemap(out) GDate {
+ int year, month, day;
+ PyDateTime_IMPORT;
+ day = g_date_get_day(&($1));
+ month = g_date_get_month(&($1));
+ year = g_date_get_year(&($1));
+ $result = PyDate_FromDate(year, month, day);
+}
-------------- next part --------------
--- src/optional/python-bindings/Makefile.in.orig.save 2013-12-28 11:47:34.000000000 -0800
+++ src/optional/python-bindings/Makefile.in 2014-01-07 18:42:36.000000000 -0800
@@ -1016,7 +1016,7 @@
@BUILDING_FROM_SCM_TRUE at gnucash_core.c: $(SWIG_FILES) ${top_srcdir}/src/base-typemaps.i ${top_srcdir}/src/engine/engine-common.i $(_gnucash_core_c_includes)
- at BUILDING_FROM_SCM_TRUE@ swig -python -Wall -Werror \
+ at BUILDING_FROM_SCM_TRUE@ /opt/local/bin/swig -python -Wall -Werror \
@BUILDING_FROM_SCM_TRUE@ -I$(top_srcdir)/src -I$(top_srcdir)/src/engine \
@BUILDING_FROM_SCM_TRUE@ -I$(top_srcdir)/src/app-utils -I${top_srcdir}/src/libqof/qof \
@BUILDING_FROM_SCM_TRUE@ -o $@ $<
--- src/optional/python-bindings/gnucash_core.i.orig 2013-04-20 14:07:10.000000000 -0700
+++ src/optional/python-bindings/gnucash_core.i 2014-01-07 15:41:48.000000000 -0800
@@ -74,6 +74,8 @@
#include "gncTaxTable.h"
#include "gncIDSearch.h"
#include "engine/gnc-pricedb.h"
+#include "Recurrence.h"
+#include "engine/gnc-budget.h"
%}
%include <timespec.i>
@@ -194,6 +196,10 @@
%include <gncTaxTable.h>
%include <gncIDSearch.h>
+// Budget include
+%include "Recurrence.h"
+%include <gnc-budget.h>
+
// Commodity prices includes and stuff
%include <gnc-pricedb.h>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: add_budget.py
Type: text/x-python-script
Size: 11096 bytes
Desc: not available
URL: <http://lists.gnucash.org/pipermail/gnucash-devel/attachments/20140510/c55ead73/attachment-0005.bin>
More information about the gnucash-devel
mailing list