Added code for converting ledger::string and boost::date_time to their
respective Python counterparts.
This commit is contained in:
parent
93096b77f3
commit
96684b72ca
11 changed files with 504 additions and 25 deletions
11
Makefile.am
11
Makefile.am
|
|
@ -95,6 +95,8 @@ libpyledger_la_CPPFLAGS = $(libledger_la_CPPFLAGS)
|
|||
libpyledger_la_LDFLAGS = -release 3.0
|
||||
|
||||
libpyledger_la_SOURCES = \
|
||||
src/py_utils.cc \
|
||||
src/py_times.cc \
|
||||
src/py_amount.cc
|
||||
|
||||
|
||||
|
|
@ -168,7 +170,11 @@ CLEANFILES += ledger.so
|
|||
clean-local:
|
||||
rm -fr build
|
||||
|
||||
ledger_so_SOURCES = src/pyledger.cc src/py_amount.cc
|
||||
ledger_so_SOURCES = \
|
||||
src/pyledger.cc \
|
||||
src/py_utils.cc \
|
||||
src/py_times.cc \
|
||||
src/py_amount.cc
|
||||
ledger_so_DEPENDENCIES = libledger.la gdtoa/libgdtoa.la libpyledger.la
|
||||
|
||||
PYLIBS = pyledger ledger gdtoa gmp boost_date_time \
|
||||
|
|
@ -184,9 +190,6 @@ if HAVE_LIBOFX
|
|||
PYLIBS += ofx
|
||||
endif
|
||||
|
||||
PYLEDGER_SRC = src/pyledger.cc \
|
||||
src/py_amount.cc
|
||||
|
||||
ledger.so: $(ledger_so_SOURCES) $(ledger_so_DEPENDENCIES)
|
||||
CFLAGS="$(CPPFLAGS) -I$(srcdir) $(libledger_la_CPPFLAGS)" \
|
||||
LDFLAGS="$(LDFLAGS) -L. -L.libs -Lgdtoa -Lgdtoa/.libs" \
|
||||
|
|
|
|||
65
Makefile.in
65
Makefile.in
|
|
@ -118,7 +118,8 @@ libledger_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
|
|||
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libledger_la_CXXFLAGS) \
|
||||
$(CXXFLAGS) $(libledger_la_LDFLAGS) $(LDFLAGS) -o $@
|
||||
libpyledger_la_LIBADD =
|
||||
am_libpyledger_la_OBJECTS = libpyledger_la-py_amount.lo
|
||||
am_libpyledger_la_OBJECTS = libpyledger_la-py_utils.lo \
|
||||
libpyledger_la-py_times.lo libpyledger_la-py_amount.lo
|
||||
libpyledger_la_OBJECTS = $(am_libpyledger_la_OBJECTS)
|
||||
libpyledger_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
|
||||
|
|
@ -147,8 +148,10 @@ ledger_DEPENDENCIES = $(LIBOBJS) libledger.la gdtoa/libgdtoa.la \
|
|||
ledger_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
--mode=link $(CXXLD) $(ledger_CXXFLAGS) $(CXXFLAGS) \
|
||||
$(ledger_LDFLAGS) $(LDFLAGS) -o $@
|
||||
am__ledger_so_SOURCES_DIST = src/pyledger.cc src/py_amount.cc
|
||||
am__ledger_so_SOURCES_DIST = src/pyledger.cc src/py_utils.cc \
|
||||
src/py_times.cc src/py_amount.cc
|
||||
@HAVE_BOOST_PYTHON_TRUE@am_ledger_so_OBJECTS = pyledger.$(OBJEXT) \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ py_utils.$(OBJEXT) py_times.$(OBJEXT) \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ py_amount.$(OBJEXT)
|
||||
ledger_so_OBJECTS = $(am_ledger_so_OBJECTS)
|
||||
ledger_so_LDADD = $(LDADD)
|
||||
|
|
@ -374,6 +377,8 @@ libledger_la_SOURCES = src/session.cc src/journal.cc src/amount.cc \
|
|||
libpyledger_la_CPPFLAGS = $(libledger_la_CPPFLAGS)
|
||||
libpyledger_la_LDFLAGS = -release 3.0
|
||||
libpyledger_la_SOURCES = \
|
||||
src/py_utils.cc \
|
||||
src/py_times.cc \
|
||||
src/py_amount.cc
|
||||
|
||||
pkginclude_HEADERS = \
|
||||
|
|
@ -425,16 +430,18 @@ info_TEXINFOS = docs/ledger.texi
|
|||
|
||||
######################################################################
|
||||
dist_lisp_LISP = lisp/ledger.el lisp/timeclock.el
|
||||
@HAVE_BOOST_PYTHON_TRUE@ledger_so_SOURCES = src/pyledger.cc src/py_amount.cc
|
||||
@HAVE_BOOST_PYTHON_TRUE@ledger_so_SOURCES = \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ src/pyledger.cc \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ src/py_utils.cc \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ src/py_times.cc \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ src/py_amount.cc
|
||||
|
||||
@HAVE_BOOST_PYTHON_TRUE@ledger_so_DEPENDENCIES = libledger.la gdtoa/libgdtoa.la libpyledger.la
|
||||
@HAVE_BOOST_PYTHON_TRUE@PYLIBS = pyledger ledger gdtoa gmp \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ boost_date_time boost_signals \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ boost_filesystem boost_regex \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ boost_python $(am__append_15) \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ $(am__append_16) $(am__append_17)
|
||||
@HAVE_BOOST_PYTHON_TRUE@PYLEDGER_SRC = src/pyledger.cc \
|
||||
@HAVE_BOOST_PYTHON_TRUE@ src/py_amount.cc
|
||||
|
||||
nodist_UnitTests_SOURCES = tests/UnitTests.cc \
|
||||
\
|
||||
tests/numerics/BasicAmount.cc \
|
||||
|
|
@ -628,7 +635,11 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-xmlparse.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libledger_la-xpath.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpyledger_la-py_amount.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpyledger_la-py_times.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpyledger_la-py_utils.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/py_amount.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/py_times.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/py_utils.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pyledger.Po@am__quote@
|
||||
|
||||
.cc.o:
|
||||
|
|
@ -841,6 +852,20 @@ libledger_la-pyinterp.lo: src/pyinterp.cc
|
|||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libledger_la_CPPFLAGS) $(CPPFLAGS) $(libledger_la_CXXFLAGS) $(CXXFLAGS) -c -o libledger_la-pyinterp.lo `test -f 'src/pyinterp.cc' || echo '$(srcdir)/'`src/pyinterp.cc
|
||||
|
||||
libpyledger_la-py_utils.lo: src/py_utils.cc
|
||||
@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpyledger_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libpyledger_la-py_utils.lo -MD -MP -MF $(DEPDIR)/libpyledger_la-py_utils.Tpo -c -o libpyledger_la-py_utils.lo `test -f 'src/py_utils.cc' || echo '$(srcdir)/'`src/py_utils.cc
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libpyledger_la-py_utils.Tpo $(DEPDIR)/libpyledger_la-py_utils.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/py_utils.cc' object='libpyledger_la-py_utils.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpyledger_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libpyledger_la-py_utils.lo `test -f 'src/py_utils.cc' || echo '$(srcdir)/'`src/py_utils.cc
|
||||
|
||||
libpyledger_la-py_times.lo: src/py_times.cc
|
||||
@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpyledger_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libpyledger_la-py_times.lo -MD -MP -MF $(DEPDIR)/libpyledger_la-py_times.Tpo -c -o libpyledger_la-py_times.lo `test -f 'src/py_times.cc' || echo '$(srcdir)/'`src/py_times.cc
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libpyledger_la-py_times.Tpo $(DEPDIR)/libpyledger_la-py_times.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/py_times.cc' object='libpyledger_la-py_times.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpyledger_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libpyledger_la-py_times.lo `test -f 'src/py_times.cc' || echo '$(srcdir)/'`src/py_times.cc
|
||||
|
||||
libpyledger_la-py_amount.lo: src/py_amount.cc
|
||||
@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpyledger_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libpyledger_la-py_amount.lo -MD -MP -MF $(DEPDIR)/libpyledger_la-py_amount.Tpo -c -o libpyledger_la-py_amount.lo `test -f 'src/py_amount.cc' || echo '$(srcdir)/'`src/py_amount.cc
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libpyledger_la-py_amount.Tpo $(DEPDIR)/libpyledger_la-py_amount.Plo
|
||||
|
|
@ -960,6 +985,34 @@ pyledger.obj: src/pyledger.cc
|
|||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o pyledger.obj `if test -f 'src/pyledger.cc'; then $(CYGPATH_W) 'src/pyledger.cc'; else $(CYGPATH_W) '$(srcdir)/src/pyledger.cc'; fi`
|
||||
|
||||
py_utils.o: src/py_utils.cc
|
||||
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT py_utils.o -MD -MP -MF $(DEPDIR)/py_utils.Tpo -c -o py_utils.o `test -f 'src/py_utils.cc' || echo '$(srcdir)/'`src/py_utils.cc
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/py_utils.Tpo $(DEPDIR)/py_utils.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/py_utils.cc' object='py_utils.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o py_utils.o `test -f 'src/py_utils.cc' || echo '$(srcdir)/'`src/py_utils.cc
|
||||
|
||||
py_utils.obj: src/py_utils.cc
|
||||
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT py_utils.obj -MD -MP -MF $(DEPDIR)/py_utils.Tpo -c -o py_utils.obj `if test -f 'src/py_utils.cc'; then $(CYGPATH_W) 'src/py_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/py_utils.cc'; fi`
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/py_utils.Tpo $(DEPDIR)/py_utils.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/py_utils.cc' object='py_utils.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o py_utils.obj `if test -f 'src/py_utils.cc'; then $(CYGPATH_W) 'src/py_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/py_utils.cc'; fi`
|
||||
|
||||
py_times.o: src/py_times.cc
|
||||
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT py_times.o -MD -MP -MF $(DEPDIR)/py_times.Tpo -c -o py_times.o `test -f 'src/py_times.cc' || echo '$(srcdir)/'`src/py_times.cc
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/py_times.Tpo $(DEPDIR)/py_times.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/py_times.cc' object='py_times.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o py_times.o `test -f 'src/py_times.cc' || echo '$(srcdir)/'`src/py_times.cc
|
||||
|
||||
py_times.obj: src/py_times.cc
|
||||
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT py_times.obj -MD -MP -MF $(DEPDIR)/py_times.Tpo -c -o py_times.obj `if test -f 'src/py_times.cc'; then $(CYGPATH_W) 'src/py_times.cc'; else $(CYGPATH_W) '$(srcdir)/src/py_times.cc'; fi`
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/py_times.Tpo $(DEPDIR)/py_times.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/py_times.cc' object='py_times.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o py_times.obj `if test -f 'src/py_times.cc'; then $(CYGPATH_W) 'src/py_times.cc'; else $(CYGPATH_W) '$(srcdir)/src/py_times.cc'; fi`
|
||||
|
||||
py_amount.o: src/py_amount.cc
|
||||
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT py_amount.o -MD -MP -MF $(DEPDIR)/py_amount.Tpo -c -o py_amount.o `test -f 'src/py_amount.cc' || echo '$(srcdir)/'`src/py_amount.cc
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/py_amount.Tpo $(DEPDIR)/py_amount.Po
|
||||
|
|
|
|||
16
acprep
16
acprep
|
|
@ -57,10 +57,12 @@ while [ -n "$1" ]; do
|
|||
case "$1" in
|
||||
--debug)
|
||||
SWITCHES="$SWITCHES --enable-debug"
|
||||
if [ -f /usr/local/lib/libstlportstlg.a ]; then
|
||||
CPPFLAGS="-I/usr/local/include/stlport -D_STLP_DEBUG $CPPFLAGS"
|
||||
#LDFLAGS="-lstlportstlg $LDFLAGS"
|
||||
fi
|
||||
#if [ -f /usr/local/lib/libstlportstlg.a ]; then
|
||||
# SWITCHES="$SWITCHES --enable-stlportg"
|
||||
# CPPFLAGS="-D_STLP_DEBUG $CPPFLAGS"
|
||||
# CPPFLAGS="-I/usr/local/include/stlport $CPPFLAGS"
|
||||
# LIBS="$LIBS -lstlportstlg"
|
||||
#fi
|
||||
CXXFLAGS="$CXXFLAGS -g" ;;
|
||||
|
||||
--prof | --perf)
|
||||
|
|
@ -69,8 +71,8 @@ while [ -n "$1" ]; do
|
|||
--python)
|
||||
if [ -d "$PYTHON_HOME" ]; then
|
||||
SWITCHES="$SWITCHES --enable-python"
|
||||
INCDIRS="$INCDIRS -I$PYTHON_HOME/include/python2.5"
|
||||
LIBDIRS="$LIBDIRS -L$PYTHON_HOME/lib/python2.5/config"
|
||||
CPPFLAGS="$CPPFLAGS -I$PYTHON_HOME/include/python2.5"
|
||||
LDFLAGS="$LDFLAGS -L$PYTHON_HOME/lib/python2.5/config"
|
||||
fi ;;
|
||||
|
||||
--opt)
|
||||
|
|
@ -103,4 +105,4 @@ fi
|
|||
|
||||
"$HERE/configure" --srcdir="$HERE" \
|
||||
CPPFLAGS="$CPPFLAGS" CXXFLAGS="$CXXFLAGS $local_cxxflags" \
|
||||
LDFLAGS="$LDFLAGS" $SWITCHES "$@"
|
||||
LDFLAGS="$LDFLAGS" LIBS="$LIBS" $SWITCHES "$@"
|
||||
|
|
|
|||
3
src/TODO
Normal file
3
src/TODO
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
- Add tracing code for functions that records call count and total
|
||||
time spent, as well as average time per call. This would implement
|
||||
selective profiling.
|
||||
99
src/py_times.cc
Normal file
99
src/py_times.cc
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
#include "pyinterp.h"
|
||||
#include "pyutils.h"
|
||||
|
||||
#include <boost/cast.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/to_python_converter.hpp>
|
||||
|
||||
#include <Python.h>
|
||||
#include <datetime.h>
|
||||
|
||||
namespace ledger {
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
typedef boost::gregorian::date date;
|
||||
|
||||
struct date_to_python
|
||||
{
|
||||
static PyObject* convert(const date& dte)
|
||||
{
|
||||
PyDateTime_IMPORT;
|
||||
return PyDate_FromDate(dte.year(), dte.month(), dte.day());
|
||||
}
|
||||
};
|
||||
|
||||
struct date_from_python
|
||||
{
|
||||
static void* convertible(PyObject* obj_ptr)
|
||||
{
|
||||
PyDateTime_IMPORT;
|
||||
if(PyDate_Check(obj_ptr) || PyDateTime_Check(obj_ptr)) return obj_ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void construct(PyObject* obj_ptr, converter::rvalue_from_python_stage1_data* data)
|
||||
{
|
||||
PyDateTime_IMPORT;
|
||||
int y = PyDateTime_GET_YEAR(obj_ptr);
|
||||
int m = PyDateTime_GET_MONTH(obj_ptr);
|
||||
int d = PyDateTime_GET_DAY(obj_ptr);
|
||||
date* dte = new date(y,m,d);
|
||||
data->convertible = (void*)dte;
|
||||
}
|
||||
};
|
||||
|
||||
typedef register_python_conversion<date, date_to_python, date_from_python>
|
||||
date_python_conversion;
|
||||
|
||||
|
||||
typedef boost::posix_time::ptime datetime;
|
||||
|
||||
struct datetime_to_python
|
||||
{
|
||||
static PyObject* convert(const datetime& moment)
|
||||
{
|
||||
PyDateTime_IMPORT;
|
||||
date dte = moment.date();
|
||||
datetime::time_duration_type tod = moment.time_of_day();
|
||||
return PyDateTime_FromDateAndTime(dte.year(), dte.month(), dte.day(),
|
||||
tod.hours(), tod.minutes(), tod.seconds(),
|
||||
tod.total_microseconds() % 1000000);
|
||||
}
|
||||
};
|
||||
|
||||
struct datetime_from_python
|
||||
{
|
||||
static void* convertible(PyObject* obj_ptr)
|
||||
{
|
||||
PyDateTime_IMPORT;
|
||||
if(PyDateTime_Check(obj_ptr)) return obj_ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void construct(PyObject* obj_ptr, converter::rvalue_from_python_stage1_data* data)
|
||||
{
|
||||
PyDateTime_IMPORT;
|
||||
int y = PyDateTime_GET_YEAR(obj_ptr);
|
||||
int m = PyDateTime_GET_MONTH(obj_ptr);
|
||||
int d = PyDateTime_GET_DAY(obj_ptr);
|
||||
int h = PyDateTime_DATE_GET_HOUR(obj_ptr);
|
||||
int min = PyDateTime_DATE_GET_MINUTE(obj_ptr);
|
||||
int s = PyDateTime_DATE_GET_SECOND(obj_ptr);
|
||||
datetime* moment = new datetime(date(y,m,d),
|
||||
datetime::time_duration_type(h, min, s));
|
||||
data->convertible = (void*)moment;
|
||||
}
|
||||
};
|
||||
|
||||
typedef register_python_conversion<datetime, datetime_to_python, datetime_from_python>
|
||||
datetime_python_conversion;
|
||||
|
||||
void export_times()
|
||||
{
|
||||
date_python_conversion();
|
||||
datetime_python_conversion();
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
46
src/py_utils.cc
Normal file
46
src/py_utils.cc
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#include "pyinterp.h"
|
||||
#include "pyutils.h"
|
||||
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/to_python_converter.hpp>
|
||||
|
||||
namespace ledger {
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
struct string_to_python
|
||||
{
|
||||
static PyObject* convert(const string& str)
|
||||
{
|
||||
return incref(object(*boost::polymorphic_downcast<const std::string *>(&str)).ptr());
|
||||
}
|
||||
};
|
||||
|
||||
struct string_from_python
|
||||
{
|
||||
static void* convertible(PyObject* obj_ptr)
|
||||
{
|
||||
if (!PyString_Check(obj_ptr)) return 0;
|
||||
return obj_ptr;
|
||||
}
|
||||
|
||||
static void construct(PyObject* obj_ptr, converter::rvalue_from_python_stage1_data* data)
|
||||
{
|
||||
const char* value = PyString_AsString(obj_ptr);
|
||||
if (value == 0) throw_error_already_set();
|
||||
void* storage = ((converter::rvalue_from_python_storage<string>*) data)->storage.bytes;
|
||||
new (storage) string(value);
|
||||
data->convertible = storage;
|
||||
}
|
||||
};
|
||||
|
||||
typedef register_python_conversion<string, string_to_python, string_from_python>
|
||||
string_python_conversion;
|
||||
|
||||
void export_utils()
|
||||
{
|
||||
string_python_conversion();
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
@ -4,6 +4,8 @@ using namespace boost::python;
|
|||
|
||||
namespace ledger {
|
||||
|
||||
void export_utils();
|
||||
void export_times();
|
||||
void export_amount();
|
||||
#if 0
|
||||
void export_balance();
|
||||
|
|
@ -19,6 +21,8 @@ void export_valexpr();
|
|||
|
||||
void initialize_for_python()
|
||||
{
|
||||
export_utils();
|
||||
export_times();
|
||||
export_amount();
|
||||
#if 0
|
||||
export_balance();
|
||||
|
|
|
|||
22
src/pyutils.h
Normal file
22
src/pyutils.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef _PY_UTILS_H
|
||||
#define _PY_UTILS_H
|
||||
|
||||
template<class T, class TfromPy>
|
||||
struct ObjFromPy {
|
||||
ObjFromPy() {
|
||||
boost::python::converter::registry::push_back
|
||||
(&TfromPy::convertible,
|
||||
&TfromPy::construct,
|
||||
boost::python::type_id<T>());
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, class TtoPy, class TfromPy>
|
||||
struct register_python_conversion {
|
||||
register_python_conversion() {
|
||||
boost::python::to_python_converter<T, TtoPy>();
|
||||
ObjFromPy<T, TfromPy>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _PY_UTILS_H
|
||||
250
src/tuples.hpp
Normal file
250
src/tuples.hpp
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
// Copyright 2004-2007 Roman Yakovenko.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef TUPLES_HPP_16_JAN_2007
|
||||
#define TUPLES_HPP_16_JAN_2007
|
||||
|
||||
#include "boost/python.hpp"
|
||||
#include "boost/tuple/tuple.hpp"
|
||||
#include "boost/python/object.hpp" //len function
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/mpl/next.hpp>
|
||||
|
||||
/**
|
||||
* Converts boost::tuples::tuple<...> to\from Python tuple
|
||||
*
|
||||
* The conversion is done "on-the-fly", you should only register the conversion
|
||||
* with your tuple classes.
|
||||
* For example:
|
||||
*
|
||||
* typedef boost::tuples::tuple< int, double, std::string > triplet;
|
||||
* boost::python::register_tuple< triplet >();
|
||||
*
|
||||
* That's all. After this point conversion to\from next types will be handled
|
||||
* by Boost.Python library:
|
||||
*
|
||||
* triplet
|
||||
* triplet& ( return type only )
|
||||
* const triplet
|
||||
* const triplet&
|
||||
*
|
||||
* Implementation description.
|
||||
* The conversion uses Boost.Python custom r-value converters. r-value converters
|
||||
* is very powerful and undocumented feature of the library. The only documentation
|
||||
* we have is http://boost.org/libs/python/doc/v2/faq.html#custom_string .
|
||||
*
|
||||
* The conversion consists from two parts: "to" and "from".
|
||||
*
|
||||
* "To" conversion
|
||||
* The "to" part is pretty easy and well documented ( http://docs.python.org/api/api.html ).
|
||||
* You should use Python C API to create an instance of a class and than you
|
||||
* initialize the relevant members of the instance.
|
||||
*
|
||||
* "From" conversion
|
||||
* Lets start from analyzing one of the use case Boost.Python library have to
|
||||
* deal with:
|
||||
*
|
||||
* void do_smth( const triplet& arg ){...}
|
||||
*
|
||||
* In order to allow calling this function from Python, the library should keep
|
||||
* parameter "arg" alive until the function returns. In other words, the library
|
||||
* should provide instances life-time management. The provided interface is not
|
||||
* ideal and could be improved. You have to implement two functions:
|
||||
*
|
||||
* void* convertible( PyObject* obj )
|
||||
* Checks whether the "obj" could be converted to an instance of the desired
|
||||
* class. If true, the function should return "obj", otherwise NULL
|
||||
*
|
||||
* void construct( PyObject* obj, converter::rvalue_from_python_stage1_data* data)
|
||||
* Constructs the instance of the desired class. This function will be called
|
||||
* if and only if "convertible" function returned true. The first argument
|
||||
* is Python object, which was passed as parameter to "convertible" function.
|
||||
* The second object is some kind of memory allocator for one object. Basically
|
||||
* it keeps a memory chunk. You will use the memory for object allocation.
|
||||
*
|
||||
* For some unclear for me reason, the library implements "C style Inheritance"
|
||||
* ( http://www.embedded.com/97/fe29712.htm ). So, in order to create new
|
||||
* object in the storage you have to cast to the "right" class:
|
||||
*
|
||||
* typedef converter::rvalue_from_python_storage<your_type_t> storage_t;
|
||||
* storage_t* the_storage = reinterpret_cast<storage_t*>( data );
|
||||
* void* memory_chunk = the_storage->storage.bytes;
|
||||
*
|
||||
* "memory_chunk" points to the memory, where the instance will be allocated.
|
||||
*
|
||||
* In order to create object at specific location, you should use placement new
|
||||
* operator:
|
||||
*
|
||||
* your_type_t* instance = new (memory_chunk) your_type_t();
|
||||
*
|
||||
* Now, you can continue to initialize the instance.
|
||||
*
|
||||
* instance->set_xyz = read xyz from obj
|
||||
*
|
||||
* If "your_type_t" constructor requires some arguments, "read" the Python
|
||||
* object before you call the constructor:
|
||||
*
|
||||
* xyz_type xyz = read xyz from obj
|
||||
* your_type_t* instance = new (memory_chunk) your_type_t(xyz);
|
||||
*
|
||||
* Hint:
|
||||
* In most case you don't really need\have to work with C Python API. Let
|
||||
* Boost.Python library to do some work for you!
|
||||
*
|
||||
**/
|
||||
|
||||
namespace boost{ namespace python{
|
||||
|
||||
namespace details{
|
||||
|
||||
//Small helper function, introduced to allow short syntax for index incrementing
|
||||
template< int index>
|
||||
typename mpl::next< mpl::int_< index > >::type increment_index(){
|
||||
typedef typename mpl::next< mpl::int_< index > >::type next_index_type;
|
||||
return next_index_type();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template< class TTuple >
|
||||
struct to_py_tuple{
|
||||
|
||||
typedef mpl::int_< tuples::length< TTuple >::value > length_type;
|
||||
|
||||
static PyObject* convert(const TTuple& c_tuple){
|
||||
list values;
|
||||
//add all c_tuple items to "values" list
|
||||
convert_impl( c_tuple, values, mpl::int_< 0 >(), length_type() );
|
||||
//create Python tuple from the list
|
||||
return incref( python::tuple( values ).ptr() );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template< int index, int length >
|
||||
static void
|
||||
convert_impl( const TTuple &c_tuple, list& values, mpl::int_< index >, mpl::int_< length > ) {
|
||||
values.append( c_tuple.template get< index >() );
|
||||
convert_impl( c_tuple, values, details::increment_index<index>(), length_type() );
|
||||
}
|
||||
|
||||
template< int length >
|
||||
static void
|
||||
convert_impl( const TTuple&, list& values, mpl::int_< length >, mpl::int_< length >)
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template< class TTuple>
|
||||
struct from_py_sequence{
|
||||
|
||||
typedef TTuple tuple_type;
|
||||
|
||||
typedef mpl::int_< tuples::length< TTuple >::value > length_type;
|
||||
|
||||
static void*
|
||||
convertible(PyObject* py_obj){
|
||||
|
||||
if( !PySequence_Check( py_obj ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !PyObject_HasAttrString( py_obj, "__len__" ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
python::object py_sequence( handle<>( borrowed( py_obj ) ) );
|
||||
|
||||
if( tuples::length< TTuple >::value != len( py_sequence ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( convertible_impl( py_sequence, mpl::int_< 0 >(), length_type() ) ){
|
||||
return py_obj;
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
construct( PyObject* py_obj, converter::rvalue_from_python_stage1_data* data){
|
||||
typedef converter::rvalue_from_python_storage<TTuple> storage_t;
|
||||
storage_t* the_storage = reinterpret_cast<storage_t*>( data );
|
||||
void* memory_chunk = the_storage->storage.bytes;
|
||||
TTuple* c_tuple = new (memory_chunk) TTuple();
|
||||
data->convertible = memory_chunk;
|
||||
|
||||
python::object py_sequence( handle<>( borrowed( py_obj ) ) );
|
||||
construct_impl( py_sequence, *c_tuple, mpl::int_< 0 >(), length_type() );
|
||||
}
|
||||
|
||||
static TTuple to_c_tuple( PyObject* py_obj ){
|
||||
if( !convertible( py_obj ) ){
|
||||
throw std::runtime_error( "Unable to construct boost::tuples::tuple from Python object!" );
|
||||
}
|
||||
TTuple c_tuple;
|
||||
python::object py_sequence( handle<>( borrowed( py_obj ) ) );
|
||||
construct_impl( py_sequence, c_tuple, mpl::int_< 0 >(), length_type() );
|
||||
return c_tuple;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template< int index, int length >
|
||||
static bool
|
||||
convertible_impl( const python::object& py_sequence, mpl::int_< index >, mpl::int_< length > ){
|
||||
|
||||
typedef typename tuples::element< index, TTuple>::type element_type;
|
||||
|
||||
object element = py_sequence[index];
|
||||
extract<element_type> type_checker( element );
|
||||
if( !type_checker.check() ){
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
return convertible_impl( py_sequence, details::increment_index<index>(), length_type() );
|
||||
}
|
||||
}
|
||||
|
||||
template< int length >
|
||||
static bool
|
||||
convertible_impl( const python::object& py_sequence, mpl::int_< length >, mpl::int_< length > ){
|
||||
return true;
|
||||
}
|
||||
|
||||
template< int index, int length >
|
||||
static void
|
||||
construct_impl( const python::object& py_sequence, TTuple& c_tuple, mpl::int_< index >, mpl::int_< length > ){
|
||||
|
||||
typedef typename tuples::element< index, TTuple>::type element_type;
|
||||
|
||||
object element = py_sequence[index];
|
||||
c_tuple.template get< index >() = extract<element_type>( element );
|
||||
|
||||
construct_impl( py_sequence, c_tuple, details::increment_index<index>(), length_type() );
|
||||
}
|
||||
|
||||
template< int length >
|
||||
static void
|
||||
construct_impl( const python::object& py_sequence, TTuple& c_tuple, mpl::int_< length >, mpl::int_< length > )
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
template< class TTuple>
|
||||
void register_tuple(){
|
||||
|
||||
to_python_converter< TTuple, to_py_tuple<TTuple> >();
|
||||
|
||||
converter::registry::push_back( &from_py_sequence<TTuple>::convertible
|
||||
, &from_py_sequence<TTuple>::construct
|
||||
, type_id<TTuple>() );
|
||||
};
|
||||
|
||||
} } //boost::python
|
||||
|
||||
#endif//TUPLES_HPP_16_JAN_2007
|
||||
|
|
@ -353,7 +353,6 @@ void report_memory(std::ostream& out, bool report_all)
|
|||
}
|
||||
}
|
||||
|
||||
#if ! defined(USE_BOOST_PYTHON)
|
||||
|
||||
string::string() : std::string() {
|
||||
TRACE_CTOR(string, "");
|
||||
|
|
@ -389,8 +388,6 @@ string::~string() {
|
|||
TRACE_DTOR(string);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // VERIFY_ON
|
||||
|
|
|
|||
10
src/utils.h
10
src/utils.h
|
|
@ -36,7 +36,7 @@
|
|||
namespace ledger {
|
||||
using namespace boost;
|
||||
|
||||
#if defined(VERIFY_ON) && ! defined(USE_BOOST_PYTHON)
|
||||
#if defined(VERIFY_ON)
|
||||
class string;
|
||||
#else
|
||||
typedef std::string string;
|
||||
|
|
@ -115,8 +115,10 @@ void trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size);
|
|||
|
||||
void report_memory(std::ostream& out, bool report_all = false);
|
||||
|
||||
#if ! defined(USE_BOOST_PYTHON)
|
||||
|
||||
/**
|
||||
* This string type is a wrapper around std::string that allows us to
|
||||
* trace constructor and destructor calls.
|
||||
*/
|
||||
class string : public std::string
|
||||
{
|
||||
public:
|
||||
|
|
@ -177,8 +179,6 @@ inline bool operator!=(const char* __lhs, const string& __rhs)
|
|||
inline bool operator!=(const string& __lhs, const char* __rhs)
|
||||
{ return __lhs.compare(__rhs) != 0; }
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#else // ! VERIFY_ON
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue