summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/py_amount.cc19
-rw-r--r--src/py_times.cc18
-rw-r--r--src/pyutils.h74
3 files changed, 93 insertions, 18 deletions
diff --git a/src/py_amount.cc b/src/py_amount.cc
index 61e3e4b5..c4f476c3 100644
--- a/src/py_amount.cc
+++ b/src/py_amount.cc
@@ -1,7 +1,9 @@
#include "pyinterp.h"
+#include "pyutils.h"
#include "amount.h"
#include <boost/python/exception_translator.hpp>
+#include <boost/python/implicit.hpp>
namespace ledger {
@@ -21,6 +23,14 @@ amount_t py_round_2(const amount_t& amount) {
return amount.round();
}
+boost::optional<amount_t> py_value_1(const amount_t& amount,
+ const boost::optional<moment_t>& moment) {
+ return amount.value(moment);
+}
+boost::optional<amount_t> py_value_2(const amount_t& amount) {
+ return amount.value();
+}
+
#define EXC_TRANSLATOR(type) \
void exc_translate_ ## type(const type& err) { \
PyErr_SetString(PyExc_ArithmeticError, err.what()); \
@@ -161,7 +171,8 @@ void export_amount()
.def("in_place_unreduce", &amount_t::in_place_unreduce,
return_value_policy<reference_existing_object>())
- .def("value", &amount_t::value)
+ .def("value", py_value_1)
+ .def("value", py_value_2)
.def("sign", &amount_t::sign)
.def("__nonzero__", &amount_t::nonzero)
@@ -213,6 +224,12 @@ void export_amount()
.def("valid", &amount_t::valid)
;
+ python_optional<amount_t>();
+
+ implicitly_convertible<double, amount_t>();
+ implicitly_convertible<long, amount_t>();
+ implicitly_convertible<string, amount_t>();
+
#define EXC_TRANSLATE(type) \
register_exception_translator<type>(&exc_translate_ ## type);
diff --git a/src/py_times.cc b/src/py_times.cc
index 578d887b..f509e0d0 100644
--- a/src/py_times.cc
+++ b/src/py_times.cc
@@ -9,6 +9,8 @@
#include <Python.h>
#include <datetime.h>
+// jww (2007-05-04): Convert time duration objects to PyDelta
+
namespace ledger {
using namespace boost::python;
@@ -29,7 +31,7 @@ struct date_from_python
static void* convertible(PyObject* obj_ptr)
{
PyDateTime_IMPORT;
- if(PyDate_Check(obj_ptr) || PyDateTime_Check(obj_ptr)) return obj_ptr;
+ if (PyDate_Check(obj_ptr)) return obj_ptr;
return 0;
}
@@ -48,15 +50,13 @@ 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)
+ static PyObject* convert(const moment_t& moment)
{
PyDateTime_IMPORT;
date dte = moment.date();
- datetime::time_duration_type tod = moment.time_of_day();
+ moment_t::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);
@@ -81,19 +81,21 @@ struct datetime_from_python
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));
+ moment_t* moment = new moment_t(date(y,m,d),
+ moment_t::time_duration_type(h, min, s));
data->convertible = (void*)moment;
}
};
-typedef register_python_conversion<datetime, datetime_to_python, datetime_from_python>
+typedef register_python_conversion<moment_t, datetime_to_python, datetime_from_python>
datetime_python_conversion;
void export_times()
{
date_python_conversion();
datetime_python_conversion();
+
+ python_optional<moment_t>();
}
} // namespace ledger
diff --git a/src/pyutils.h b/src/pyutils.h
index 4ff33f8f..84a0db7e 100644
--- a/src/pyutils.h
+++ b/src/pyutils.h
@@ -1,22 +1,78 @@
#ifndef _PY_UTILS_H
#define _PY_UTILS_H
-template<class T, class TfromPy>
-struct ObjFromPy {
- ObjFromPy() {
+template <typename T, typename TfromPy>
+struct object_from_python
+{
+ object_from_python() {
boost::python::converter::registry::push_back
- (&TfromPy::convertible,
- &TfromPy::construct,
- boost::python::type_id<T>());
+ (&TfromPy::convertible, &TfromPy::construct,
+ boost::python::type_id<T>());
}
};
-template<class T, class TtoPy, class TfromPy>
-struct register_python_conversion {
+template <typename T, typename TtoPy, typename TfromPy>
+struct register_python_conversion
+{
register_python_conversion() {
boost::python::to_python_converter<T, TtoPy>();
- ObjFromPy<T, TfromPy>();
+ object_from_python<T, TfromPy>();
}
};
+template <typename T>
+struct python_optional : public boost::noncopyable
+{
+ struct optional_to_python
+ {
+ static PyObject * convert(const boost::optional<T>& value)
+ {
+ return (value ? boost::python::to_python_value<T>()(*value) :
+ boost::python::detail::none());
+ }
+ };
+
+ struct optional_from_python
+ {
+ static void * convertible(PyObject * source)
+ {
+ using namespace boost::python::converter;
+
+ if (source == Py_None)
+ return source;
+
+ const registration& converters(registered<T>::converters);
+
+ if (implicit_rvalue_convertible_from_python(source, converters)) {
+ rvalue_from_python_stage1_data data =
+ rvalue_from_python_stage1(source, converters);
+ return rvalue_from_python_stage2(source, data, converters);
+ }
+ return NULL;
+ }
+
+ static void construct(PyObject * source,
+ boost::python::converter::rvalue_from_python_stage1_data * data)
+ {
+ using namespace boost::python::converter;
+
+ void * const storage = ((rvalue_from_python_storage<T> *) data)->storage.bytes;
+
+ if (data->convertible == source) // == None
+ new (storage) boost::optional<T>(); // A Boost uninitialized value
+ else
+ new (storage) boost::optional<T>(*static_cast<T *>(data->convertible));
+
+ data->convertible = storage;
+ }
+ };
+
+ explicit python_optional() {
+ register_python_conversion<boost::optional<T>,
+ optional_to_python, optional_from_python>();
+ }
+};
+
+//boost::python::register_ptr_to_python< boost::shared_ptr<Base> >();
+
#endif // _PY_UTILS_H