diff options
author | John Wiegley <johnw@newartisans.com> | 2007-05-04 13:41:23 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-04-13 03:38:38 -0400 |
commit | 0528a1e49a82221e63039abc7f759a43f4d4ffc9 (patch) | |
tree | e433db931847f003aef895ea255a2c541057bd3f /src | |
parent | 96684b72ca367bfd4dbe2e45a9a66c56204eb533 (diff) | |
download | fork-ledger-0528a1e49a82221e63039abc7f759a43f4d4ffc9.tar.gz fork-ledger-0528a1e49a82221e63039abc7f759a43f4d4ffc9.tar.bz2 fork-ledger-0528a1e49a82221e63039abc7f759a43f4d4ffc9.zip |
Added boost::optional support for using with Boost.Python.
Diffstat (limited to 'src')
-rw-r--r-- | src/py_amount.cc | 19 | ||||
-rw-r--r-- | src/py_times.cc | 18 | ||||
-rw-r--r-- | src/pyutils.h | 74 |
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 |