diff options
-rw-r--r-- | Makefile.am | 52 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | README | 12 | ||||
-rwxr-xr-x | acprep | 10 | ||||
-rw-r--r-- | amount.cc | 165 | ||||
-rw-r--r-- | balance.cc | 191 | ||||
-rw-r--r-- | binary.cc | 27 | ||||
-rw-r--r-- | config.cc | 150 | ||||
-rw-r--r-- | configure.in | 40 | ||||
-rw-r--r-- | datetime.cc | 79 | ||||
-rw-r--r-- | derive.cc | 27 | ||||
-rw-r--r-- | emacs.cc | 23 | ||||
-rw-r--r-- | format.cc | 117 | ||||
-rw-r--r-- | format.h | 41 | ||||
-rw-r--r-- | gnucash.cc | 19 | ||||
-rw-r--r-- | journal.cc | 366 | ||||
-rw-r--r-- | ledger.texi | 47 | ||||
-rw-r--r-- | main.cc | 30 | ||||
-rw-r--r-- | main.py | 373 | ||||
-rw-r--r-- | ofx.cc | 19 | ||||
-rw-r--r-- | option.cc | 91 | ||||
-rw-r--r-- | parser.cc | 48 | ||||
-rw-r--r-- | py_eval.cc | 163 | ||||
-rw-r--r-- | py_eval.h | 75 | ||||
-rw-r--r-- | pyfstream.h | 146 | ||||
-rw-r--r-- | pyledger.cc | 9 | ||||
-rw-r--r-- | pyledger.h | 16 | ||||
-rw-r--r-- | qif.cc | 19 | ||||
-rw-r--r-- | reconcile.cc | 20 | ||||
-rwxr-xr-x | setup.py | 30 | ||||
-rw-r--r-- | textual.cc | 27 | ||||
-rwxr-xr-x | timeclock | 461 | ||||
-rw-r--r-- | timeclock.el | 46 | ||||
-rw-r--r-- | valexpr.cc | 136 | ||||
-rw-r--r-- | valexpr.h | 1 | ||||
-rw-r--r-- | value.cc | 270 | ||||
-rw-r--r-- | walk.cc | 305 | ||||
-rw-r--r-- | xml.cc | 30 |
38 files changed, 37 insertions, 3648 deletions
diff --git a/Makefile.am b/Makefile.am index f2f59760..d20eb0ce 100644 --- a/Makefile.am +++ b/Makefile.am @@ -33,10 +33,6 @@ if HAVE_LIBOFX libledger_la_CXXFLAGS += -DHAVE_LIBOFX=1 libledger_la_SOURCES += ofx.cc endif -if HAVE_BOOST_PYTHON -libledger_la_CXXFLAGS += -DUSE_BOOST_PYTHON=1 -libledger_la_SOURCES += py_eval.cc -endif if DEBUG libledger_la_CXXFLAGS += -DDEBUG_LEVEL=4 libledger_la_SOURCES += debug.cc @@ -61,8 +57,6 @@ pkginclude_HEADERS = \ mask.h \ option.h \ parser.h \ - py_eval.h \ - pyledger.h \ qif.h \ quotes.h \ reconcile.h \ @@ -79,12 +73,7 @@ pkginclude_HEADERS = \ bin_PROGRAMS = ledger ledger_CXXFLAGS = ledger_SOURCES = main.cc -if HAVE_BOOST_PYTHON -ledger_CXXFLAGS += -DUSE_BOOST_PYTHON=1 -ledger_LDADD = $(LIBOBJS) libledger.la -lboost_python -lpython$(PYTHON_VERSION) -else ledger_LDADD = $(LIBOBJS) libledger.la -endif if HAVE_EXPAT ledger_CXXFLAGS += -DHAVE_EXPAT=1 ledger_LDADD += -lexpat @@ -106,48 +95,11 @@ info_TEXINFOS = ledger.texi ###################################################################### -if HAVE_BOOST_PYTHON - -noinst_PROGRAMS = ledger.so - -if HAVE_EXPAT -HAVE_EXPAT_VALUE = true -else -HAVE_EXPAT_VALUE = false -endif -if HAVE_XMLPARSE -HAVE_XMLPARSE_VALUE = true -else -HAVE_XMLPARSE_VALUE = false -endif -if HAVE_LIBOFX -HAVE_LIBOFX_VALUE = true -else -HAVE_LIBOFX_VALUE = false -endif - -ledger.so: py_eval.cc libledger.la - CFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS) -L. -L.libs" \ - HAVE_EXPAT="$(HAVE_EXPAT_VALUE)" \ - HAVE_XMLPARSE="$(HAVE_XMLPARSE_VALUE)" \ - HAVE_LIBOFX="$(HAVE_LIBOFX_VALUE)" \ - python setup.py build --build-lib=. - -install-exec-hook: - CFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS) -L. -L.libs" \ - HAVE_EXPAT="$(HAVE_EXPAT_VALUE)" \ - HAVE_XMLPARSE="$(HAVE_XMLPARSE_VALUE)" \ - HAVE_LIBOFX="$(HAVE_LIBOFX_VALUE)" \ - python setup.py install --prefix=$(prefix) - -endif - all-clean: maintainer-clean rm -fr *~ .*~ .\#* *.html *.info *.pdf *.a *.so *.o *.lo *.la \ - *.elc *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.pyc \ + *.elc *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr \ .gdb_history gmon.out h out TAGS ledger valexpr .deps \ .libs build AUTHORS COPYING INSTALL Makefile acconf.h \ acconf.h.in aclocal.m4 autom4te config.guess config.sub \ configure depcomp install-sh libtool ltconfig ltmain.sh \ - missing stamp texinfo.tex Makefile.in mkinstalldirs \ - py-compile + missing stamp texinfo.tex Makefile.in mkinstalldirs @@ -84,6 +84,10 @@ - Added a new value expression regexp command: C// compare against transaction amount's commodity symbol +- Added a new "csv" command, for outputting results in CSV format. + +- Completely removed Python integration. + * 2.4 - Both "-$100.00" and "$-100.00" are now equivalent amounts. @@ -71,15 +71,3 @@ join the Ledger mailing list at the following Web address: You can also find help at the #ledger channel on the IRC server irc.freenode.net. - - -Building Ledger as a Python Module -================================== - -If you have Python 2.2 or higher installed, and Boost.Python, then -Ledger can also be built as a Python module if --enable-python is -passed to the configure script. This means you can interact with your -Ledger data from Python, making it easier to write custom reports. - -This feature is mostly undocumented in version 2.0, although main.py -gives a working example. @@ -12,17 +12,14 @@ else fi autoconf -INCDIRS="-I/sw/include -I/usr/local/include/boost-1_33 -I/usr/include/httpd/xml -I/usr/include/python2.3" +INCDIRS="-I/sw/include -I/usr/local/include/boost-1_33 -I/usr/include/httpd/xml" #INCDIRS="$INCDIRS -I/sw/include/libofx" INCDIRS="$INCDIRS -Wno-long-double" -LIBDIRS="-L/sw/lib -L/usr/local/lib -L/usr/lib/python2.3/config" +LIBDIRS="-L/sw/lib -L/usr/local/lib" if [ "$1" = "--debug" ]; then ./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" CXXFLAGS="-g" \ --enable-debug -elif [ "$1" = "--debug-python" ]; then - ./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" CXXFLAGS="-g" \ - --enable-debug --enable-python elif [ "$1" = "--opt" ]; then ./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \ CXXFLAGS="-fomit-frame-pointer -O3 -mcpu=7450 -fPIC" @@ -31,8 +28,7 @@ elif [ "$1" = "--flat-opt" ]; then CXXFLAGS="-fomit-frame-pointer -O3 -mcpu=7450" elif [ "$1" = "--safe-opt" ]; then ./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \ - CXXFLAGS="-fomit-frame-pointer -O3 -mcpu=7450 -fPIC -DDEBUG_LEVEL=1" \ - --enable-python + CXXFLAGS="-fomit-frame-pointer -O3 -mcpu=7450 -fPIC -DDEBUG_LEVEL=1" elif [ "$1" = "--perf" ]; then ./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" CXXFLAGS="-g -pg" fi @@ -1245,168 +1245,3 @@ amount_t commodity_t::value(const std::time_t moment) } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> -#include <Python.h> - -using namespace boost::python; -using namespace ledger; - -void py_parse_1(amount_t& amount, const std::string& str, - unsigned short flags) { - amount.parse(str, flags); -} -void py_parse_2(amount_t& amount, const std::string& str) { - amount.parse(str); -} - -struct commodity_updater_wrap : public commodity_t::updater_t -{ - PyObject * self; - commodity_updater_wrap(PyObject * self_) : self(self_) {} - - virtual void operator()(commodity_t& commodity, - const std::time_t moment, - const std::time_t date, - const std::time_t last, - amount_t& price) { - call_method<void>(self, "__call__", commodity, moment, date, last, price); - } -}; - -commodity_t * py_find_commodity_1(const std::string& symbol) -{ - return commodity_t::find_commodity(symbol); -} - -commodity_t * py_find_commodity_2(const std::string& symbol, bool auto_create) -{ - return commodity_t::find_commodity(symbol, auto_create); -} - -#define EXC_TRANSLATOR(type) \ - void exc_translate_ ## type(const type& err) { \ - PyErr_SetString(PyExc_RuntimeError, err.what()); \ - } - -EXC_TRANSLATOR(amount_error) - -void export_amount() -{ - scope().attr("AMOUNT_PARSE_NO_MIGRATE") = AMOUNT_PARSE_NO_MIGRATE; - scope().attr("AMOUNT_PARSE_NO_REDUCE") = AMOUNT_PARSE_NO_REDUCE; - - class_< amount_t > ("Amount") - .def(init<amount_t>()) - .def(init<std::string>()) - .def(init<char *>()) - .def(init<bool>()) - .def(init<long>()) - .def(init<unsigned long>()) - .def(init<double>()) - - .def("commodity", &amount_t::commodity, - return_value_policy<reference_existing_object>()) - .def("set_commodity", &amount_t::set_commodity) - .def("clear_commodity", &amount_t::clear_commodity) - .def("quantity_string", &amount_t::quantity_string) - - .def(self += self) - .def(self += long()) - .def(self + self) - .def(self + long()) - .def(self -= self) - .def(self -= long()) - .def(self - self) - .def(self - long()) - .def(self *= self) - .def(self *= long()) - .def(self * self) - .def(self * long()) - .def(self /= self) - .def(self /= long()) - .def(self / self) - .def(self / long()) - .def(- self) - - .def(self < self) - .def(self < long()) - .def(self <= self) - .def(self <= long()) - .def(self > self) - .def(self > long()) - .def(self >= self) - .def(self >= long()) - .def(self == self) - .def(self == long()) - .def(self != self) - .def(self != long()) - .def(! self) - - .def(self_ns::int_(self)) - .def(self_ns::float_(self)) - .def(self_ns::str(self)) - .def(abs(self)) - - .def("negate", &amount_t::negate) - .def("parse", py_parse_1) - .def("parse", py_parse_2) - .def("reduce", &amount_t::reduce) - .def("valid", &amount_t::valid) - ; - - class_< commodity_t::updater_t, commodity_updater_wrap, boost::noncopyable > - ("Updater") - ; - - scope().attr("COMMODITY_STYLE_DEFAULTS") = COMMODITY_STYLE_DEFAULTS; - scope().attr("COMMODITY_STYLE_SUFFIXED") = COMMODITY_STYLE_SUFFIXED; - scope().attr("COMMODITY_STYLE_SEPARATED") = COMMODITY_STYLE_SEPARATED; - scope().attr("COMMODITY_STYLE_EUROPEAN") = COMMODITY_STYLE_EUROPEAN; - scope().attr("COMMODITY_STYLE_THOUSANDS") = COMMODITY_STYLE_THOUSANDS; - scope().attr("COMMODITY_STYLE_NOMARKET") = COMMODITY_STYLE_NOMARKET; - scope().attr("COMMODITY_STYLE_VARIABLE") = COMMODITY_STYLE_VARIABLE; - - class_< commodity_t > ("Commodity") - .def(init<std::string, optional<unsigned int, unsigned int> >()) - - .def_readonly("symbol", &commodity_t::symbol) - .def("set_symbol", &commodity_t::set_symbol) - .def_readwrite("name", &commodity_t::name) - .def_readwrite("note", &commodity_t::name) - .def_readwrite("precision", &commodity_t::precision) - .def_readwrite("flags", &commodity_t::flags) - .def_readwrite("ident", &commodity_t::ident) - .def_readwrite("updater", &commodity_t::updater) - .add_property("smaller", - make_getter(&commodity_t::smaller, - return_value_policy<reference_existing_object>())) - .add_property("larger", - make_getter(&commodity_t::larger, - return_value_policy<reference_existing_object>())) - - .def(self_ns::str(self)) - - .def("add_price", &commodity_t::add_price) - .def("remove_price", &commodity_t::remove_price) - .def("value", &commodity_t::value) - - .def("valid", &commodity_t::valid) - ; - - def("add_commodity", &commodity_t::add_commodity); - def("remove_commodity", &commodity_t::remove_commodity); - def("find_commodity", py_find_commodity_1, - return_value_policy<reference_existing_object>()); - def("find_commodity", py_find_commodity_2, - return_value_policy<reference_existing_object>()); - -#define EXC_TRANSLATE(type) \ - register_exception_translator<type>(&exc_translate_ ## type); - - EXC_TRANSLATE(amount_error); -} - -#endif // USE_BOOST_PYTHON @@ -86,194 +86,3 @@ void balance_t::write(std::ostream& out, } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -unsigned int balance_len(balance_t& bal) -{ - return bal.amounts.size(); -} - -amount_t balance_getitem(balance_t& bal, int i) -{ - std::size_t len = bal.amounts.size(); - - if (abs(i) >= len) { - PyErr_SetString(PyExc_IndexError, "Index out of range"); - throw_error_already_set(); - } - - int x = i < 0 ? len + i : i; - amounts_map::iterator elem = bal.amounts.begin(); - while (--x >= 0) - elem++; - - return (*elem).second; -} - -unsigned int balance_pair_len(balance_pair_t& bal_pair) -{ - return balance_len(bal_pair.quantity); -} - -amount_t balance_pair_getitem(balance_pair_t& bal_pair, int i) -{ - return balance_getitem(bal_pair.quantity, i); -} - -void export_balance() -{ - class_< balance_t > ("Balance") - .def(init<balance_t>()) - .def(init<amount_t>()) - .def(init<long>()) - .def(init<unsigned long>()) - .def(init<double>()) - - .def(self += self) - .def(self += other<amount_t>()) - .def(self += long()) - .def(self + self) - .def(self + other<amount_t>()) - .def(self + long()) - .def(self -= self) - .def(self -= other<amount_t>()) - .def(self -= long()) - .def(self - self) - .def(self - other<amount_t>()) - .def(self - long()) - .def(self *= self) - .def(self *= other<amount_t>()) - .def(self *= long()) - .def(self * self) - .def(self * other<amount_t>()) - .def(self * long()) - .def(self /= self) - .def(self /= other<amount_t>()) - .def(self /= long()) - .def(self / self) - .def(self / other<amount_t>()) - .def(self / long()) - .def(- self) - - .def(self < self) - .def(self < other<amount_t>()) - .def(self < long()) - .def(self <= self) - .def(self <= other<amount_t>()) - .def(self <= long()) - .def(self > self) - .def(self > other<amount_t>()) - .def(self > long()) - .def(self >= self) - .def(self >= other<amount_t>()) - .def(self >= long()) - .def(self == self) - .def(self == other<amount_t>()) - .def(self == long()) - .def(self != self) - .def(self != other<amount_t>()) - .def(self != long()) - .def(! self) - - .def(abs(self)) - .def(self_ns::str(self)) - - .def("__len__", balance_len) - .def("__getitem__", balance_getitem) - - .def("negate", &balance_t::negate) - .def("amount", &balance_t::amount) - .def("value", &balance_t::value) - .def("write", &balance_t::write) - .def("valid", &balance_t::valid) - ; - - class_< balance_pair_t > ("BalancePair") - .def(init<balance_pair_t>()) - .def(init<balance_t>()) - .def(init<amount_t>()) - .def(init<long>()) - .def(init<unsigned long>()) - .def(init<double>()) - - .def(self += self) - .def(self += other<balance_t>()) - .def(self += other<amount_t>()) - .def(self += long()) - .def(self + self) - .def(self + other<balance_t>()) - .def(self + other<amount_t>()) - .def(self + long()) - .def(self -= self) - .def(self -= other<balance_t>()) - .def(self -= other<amount_t>()) - .def(self -= long()) - .def(self - self) - .def(self - other<balance_t>()) - .def(self - other<amount_t>()) - .def(self - long()) - .def(self *= self) - .def(self *= other<balance_t>()) - .def(self *= other<amount_t>()) - .def(self *= long()) - .def(self * self) - .def(self * other<balance_t>()) - .def(self * other<amount_t>()) - .def(self * long()) - .def(self /= self) - .def(self /= other<balance_t>()) - .def(self /= other<amount_t>()) - .def(self /= long()) - .def(self / self) - .def(self / other<balance_t>()) - .def(self / other<amount_t>()) - .def(self / long()) - .def(- self) - - .def(self < self) - .def(self < other<balance_t>()) - .def(self < other<amount_t>()) - .def(self < long()) - .def(self <= self) - .def(self <= other<balance_t>()) - .def(self <= other<amount_t>()) - .def(self <= long()) - .def(self > self) - .def(self > other<balance_t>()) - .def(self > other<amount_t>()) - .def(self > long()) - .def(self >= self) - .def(self >= other<balance_t>()) - .def(self >= other<amount_t>()) - .def(self >= long()) - .def(self == self) - .def(self == other<balance_t>()) - .def(self == other<amount_t>()) - .def(self == long()) - .def(self != self) - .def(self != other<balance_t>()) - .def(self != other<amount_t>()) - .def(self != long()) - .def(! self) - - .def(abs(self)) - .def(self_ns::str(self)) - - .def("__len__", balance_pair_len) - .def("__getitem__", balance_pair_getitem) - - .def("negate", &balance_pair_t::negate) - .def("amount", &balance_pair_t::amount) - .def("value", &balance_pair_t::value) - .def("write", &balance_pair_t::write) - .def("valid", &balance_pair_t::valid) - ; -} - -#endif // USE_BOOST_PYTHON @@ -795,30 +795,3 @@ void write_binary_journal(std::ostream& out, journal_t * journal) } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(binary_parse_overloads, - binary_parser_t::parse, 2, 4) - -void py_write_binary_journal(const std::string& path, journal_t * journal) -{ - std::ofstream out(path.c_str()); - write_binary_journal(out, journal); -} - -void export_binary() { - class_< binary_parser_t, bases<parser_t> > ("BinaryParser") - .def("test", &binary_parser_t::test) - .def("parse", &binary_parser_t::parse, binary_parse_overloads()) - ; - - def("write_binary_journal", py_write_binary_journal); -} - -#endif // USE_BOOST_PYTHON @@ -5,9 +5,6 @@ #include "quotes.h" #include "valexpr.h" #include "walk.h" -#ifdef USE_BOOST_PYTHON -#include "py_eval.h" -#endif #include <fstream> #include <ctime> @@ -43,12 +40,7 @@ void config_t::reset() write_hdr_format = "%d %Y%C%P\n"; write_xact_format = " %-34W %12o%n\n"; equity_format = "\n%D %Y%C%P\n%/ %-34W %12t\n"; -#ifndef USE_BOOST_PYTHON prices_format = "%[%Y/%m/%d %H:%M:%S %Z] %-10A %12t %12T\n"; -#else - prices_format = ("%[%Y/%m/%d %H:%M:%S %Z] %-8A " - "%10t %10(@vmin(t)) %10(@vmax(t)) %12T\n"); -#endif pricesdb_format = "P %[%Y/%m/%d %H:%M:%S] %A %t\n"; predicate = ""; @@ -444,9 +436,6 @@ static void show_version(std::ostream& out) This program is made available under the terms of the BSD Public License.\n\ See LICENSE file included with the distribution for details and disclaimer.\n"; out << "\n(modules: gmp, pcre"; -#ifdef USE_BOOST_PYTHON - out << ", python"; -#endif #if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE) out << ", xml"; #endif @@ -523,12 +512,6 @@ Commodity reporting:\n\ -V, --market report last known market value\n\ -g, --performance report gain/loss for each displayed transaction\n\ -G, --gain report net gain/loss\n\n"; -#ifdef USE_BOOST_PYTHON - out - << "Python support:\n\ - --import MODULE on startup, import the given Python MODULE\n\ - --import-stdin on start, read Python code from standard input\n\n"; -#endif out << "Commands:\n\ balance [REGEXP]... show balance totals for matching accounts\n\ @@ -547,9 +530,6 @@ Use -H to see all the help text on one page, or:\n\ --help-calc calculation options\n\ --help-disp display options\n\ --help-comm commodity options\n"; -#ifdef USE_BOOST_PYTHON - out << " --help-python Python options\n"; -#endif out << "\nBasic options:\n\ -h, --help display this help text\n\ -v, --version show version information\n\ @@ -635,15 +615,6 @@ void option_comm_help(std::ostream& out) -G, --gain report net gain/loss\n"; } -#ifdef USE_BOOST_PYTHON -void option_python_help(std::ostream& out) -{ - out << "Python support options:\n\ - --import MODULE on startup, import the given Python MODULE\n\ - --import-stdin on start, read Python code from standard input\n\n"; -} -#endif - ////////////////////////////////////////////////////////////////////// // // Basic options @@ -673,13 +644,6 @@ OPT_BEGIN(help_comm, "") { throw 0; } OPT_END(help_comm); -#ifdef USE_BOOST_PYTHON -OPT_BEGIN(help_python, "") { - option_python_help(std::cout); - throw 0; -} OPT_END(help_python); -#endif - OPT_BEGIN(version, "v") { show_version(std::cout); throw 0; @@ -1076,118 +1040,4 @@ OPT_BEGIN(percentage, "%") { config->total_expr_template = "^#&{100.0%}*(#/^#)"; } OPT_END(percentage); -#ifdef USE_BOOST_PYTHON - -////////////////////////////////////////////////////////////////////// -// -// Python support - -OPT_BEGIN(import, ":") { - python_eval(std::string("import ") + optarg, PY_EVAL_STMT); -} OPT_END(import); - -OPT_BEGIN(import_stdin, "") { - python_eval(std::cin, PY_EVAL_MULTI); -} OPT_END(import_stdin); - -#endif // USE_BOOST_PYTHON - } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> -#include <boost/python/detail/api_placeholder.hpp> - -using namespace boost::python; -using namespace ledger; - -void py_process_options(config_t& config, const std::string& command, - list args) -{ - strings_list strs; - - int l = len(args); - for (int i = 0; i < l; i++) - strs.push_back(std::string(extract<char *>(args[i]))); - - config.process_options(command, strs.begin(), strs.end()); -} - -void add_other_option_handlers(const std::list<option_t>& other); - -void py_add_config_option_handlers() -{ - add_other_option_handlers(config_options); -} - -void py_option_help() -{ - option_help(std::cout); -} - -void export_config() -{ - class_< config_t > ("Config") - .def_readwrite("init_file", &config_t::init_file) - .def_readwrite("data_file", &config_t::data_file) - .def_readwrite("cache_file", &config_t::cache_file) - .def_readwrite("price_db", &config_t::price_db) - .def_readwrite("output_file", &config_t::output_file) - .def_readwrite("account", &config_t::account) - .def_readwrite("predicate", &config_t::predicate) - .def_readwrite("display_predicate", &config_t::display_predicate) - .def_readwrite("report_period", &config_t::report_period) - .def_readwrite("report_period_sort", &config_t::report_period_sort) - .def_readwrite("format_string", &config_t::format_string) - .def_readwrite("balance_format", &config_t::balance_format) - .def_readwrite("register_format", &config_t::register_format) - .def_readwrite("wide_register_format", &config_t::wide_register_format) - .def_readwrite("csv_register_format", &config_t::csv_register_format) - .def_readwrite("plot_amount_format", &config_t::plot_amount_format) - .def_readwrite("plot_total_format", &config_t::plot_total_format) - .def_readwrite("print_format", &config_t::print_format) - .def_readwrite("write_hdr_format", &config_t::write_hdr_format) - .def_readwrite("write_xact_format", &config_t::write_xact_format) - .def_readwrite("equity_format", &config_t::equity_format) - .def_readwrite("prices_format", &config_t::prices_format) - .def_readwrite("pricesdb_format", &config_t::pricesdb_format) - .def_readwrite("date_format", &config_t::date_format) - .def_readwrite("sort_string", &config_t::sort_string) - .def_readwrite("amount_expr", &config_t::amount_expr) - .def_readwrite("total_expr", &config_t::total_expr) - .def_readwrite("total_expr_template", &config_t::total_expr_template) - .def_readwrite("forecast_limit", &config_t::forecast_limit) - .def_readwrite("reconcile_balance", &config_t::reconcile_balance) - .def_readwrite("reconcile_date", &config_t::reconcile_date) - .def_readwrite("budget_flags", &config_t::budget_flags) - .def_readwrite("pricing_leeway", &config_t::pricing_leeway) - .def_readwrite("show_collapsed", &config_t::show_collapsed) - .def_readwrite("show_subtotal", &config_t::show_subtotal) - .def_readwrite("show_totals", &config_t::show_totals) - .def_readwrite("show_related", &config_t::show_related) - .def_readwrite("show_all_related", &config_t::show_all_related) - .def_readwrite("show_inverted", &config_t::show_inverted) - .def_readwrite("show_empty", &config_t::show_empty) - .def_readwrite("head_entries", &config_t::head_entries) - .def_readwrite("tail_entries", &config_t::tail_entries) - .def_readwrite("pager", &config_t::pager) - .def_readwrite("days_of_the_week", &config_t::days_of_the_week) - .def_readwrite("by_payee", &config_t::by_payee) - .def_readwrite("comm_as_payee", &config_t::comm_as_payee) - .def_readwrite("show_revalued", &config_t::show_revalued) - .def_readwrite("show_revalued_only", &config_t::show_revalued_only) - .def_readwrite("download_quotes", &config_t::download_quotes) - .def_readwrite("use_cache", &config_t::use_cache) - .def_readwrite("cache_dirty", &config_t::cache_dirty) - - .def("process_options", py_process_options) - ; - - scope().attr("config") = ptr(config); - - def("option_help", py_option_help); - def("add_config_option_handlers", py_add_config_option_handlers); -} - -#endif // USE_BOOST_PYTHON diff --git a/configure.in b/configure.in index 0059e0ea..49b3e773 100644 --- a/configure.in +++ b/configure.in @@ -187,46 +187,6 @@ else AM_CONDITIONAL(HAVE_LIBOFX, false) fi -# check for Python -AC_ARG_ENABLE(python, - [ --enable-python Turn on Python support], - [case "${enableval}" in - yes) python=true ;; - no) python=false ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-python) ;; - esac],[python=false]) -AM_CONDITIONAL(USE_PYTHON, test x$python = xtrue) - -if [test x$python = xtrue ]; then - AM_PATH_PYTHON(2.2,, :) - if [test "$PYTHON" != :]; then - AC_CACHE_CHECK( - [if boost_python is available], - [boost_python_cpplib_avail], - [boost_python_save_libs=$LIBS - LIBS="-lboost_python -lpython$PYTHON_VERSION $LIBS" - AC_LANG_PUSH(C++) - AC_TRY_LINK( - [#include <boost/python.hpp> - using namespace boost::python; - class foo {}; - BOOST_PYTHON_MODULE(samp) { - class_< foo > ("foo") ; - }], - [return 0], - [boost_python_cpplib_avail=true], - [boost_python_cpplib_avail=false]) - AC_LANG_POP - LIBS=$boost_python_save_libs]) - AM_CONDITIONAL(HAVE_BOOST_PYTHON, - test x$boost_python_cpplib_avail = xtrue) - else - AM_CONDITIONAL(HAVE_BOOST_PYTHON, false) - fi -else - AM_CONDITIONAL(HAVE_BOOST_PYTHON, false) -fi - # Check for options AC_ARG_ENABLE(debug, [ --enable-debug Turn on debugging], diff --git a/datetime.cc b/datetime.cc index 07d19624..e26ddf98 100644 --- a/datetime.cc +++ b/datetime.cc @@ -373,82 +373,3 @@ bool quick_parse_date(const char * date_str, std::time_t * result) } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -unsigned int interval_len(interval_t& interval) -{ - int periods = 1; - std::time_t when = interval.first(); - while (interval.end && when < interval.end) { - when = interval.increment(when); - if (when < interval.end) - periods++; - } - return periods; -} - -std::time_t interval_getitem(interval_t& interval, int i) -{ - static std::time_t last_index = 0; - static std::time_t last_moment = 0; - - if (i == 0) { - last_index = 0; - last_moment = interval.first(); - } - else { - last_moment = interval.increment(last_moment); - if (interval.end && last_moment >= interval.end) { - PyErr_SetString(PyExc_IndexError, "Index out of range"); - throw_error_already_set(); - } - } - return last_moment; -} - -std::time_t py_parse_date(const char * date_str) -{ - std::time_t temp; - if (parse_date(date_str, &temp)) - return temp; - return 0; -} - -std::time_t py_parse_date_yr(const char * date_str, const int year) -{ - std::time_t temp; - if (parse_date(date_str, &temp, year)) - return temp; - return 0; -} - -void export_datetime() -{ - class_< interval_t > - ("Interval", init<optional<int, int, int, std::time_t, std::time_t> >()) - .def(init<std::string>()) - .def(! self) - - .def_readwrite("years", &interval_t::years) - .def_readwrite("months", &interval_t::months) - .def_readwrite("seconds", &interval_t::seconds) - .def_readwrite("begin", &interval_t::begin) - .def_readwrite("end", &interval_t::end) - - .def("__len__", interval_len) - .def("__getitem__", interval_getitem) - - .def("increment", &interval_t::increment) - ; - - def("parse_date", py_parse_date); - def("parse_date", py_parse_date_yr); -} - -#endif // USE_BOOST_PYTHON @@ -132,30 +132,3 @@ entry_t * derive_new_entry(journal_t& journal, } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> -#include <boost/python/detail/api_placeholder.hpp> - -using namespace boost::python; -using namespace ledger; - -entry_t * py_derive_new_entry(journal_t& journal, list args) -{ - strings_list strs; - - int l = len(args); - for (int i = 0; i < l; i++) - strs.push_back(extract<std::string>(args[i])); - - return derive_new_entry(journal, strs.begin(), strs.end()); -} - -void export_derive() -{ - def("derive_new_entry", py_derive_new_entry, - return_value_policy<manage_new_object>()); -} - -#endif // USE_BOOST_PYTHON @@ -77,26 +77,3 @@ void format_emacs_transactions::operator()(transaction_t& xact) } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -void export_emacs() -{ - typedef - pystream_handler_wrap<format_emacs_transactions, transaction_t> - format_emacs_transactions_wrap; - - class_< format_emacs_transactions_wrap, bases<item_handler<transaction_t> > > - ("FormatEmacsTransactions", - init<PyObject *>()[with_custodian_and_ward<1, 2>()]) - .def("flush", &format_emacs_transactions_wrap::flush) - .def("__call__", &format_emacs_transactions_wrap::operator()) - ; -} - -#endif // USE_BOOST_PYTHON @@ -1,9 +1,6 @@ #include "format.h" #include "error.h" #include "util.h" -#ifdef USE_BOOST_PYTHON -#include "py_eval.h" -#endif #include <cstdlib> #include <ctime> @@ -175,18 +172,6 @@ element_t * format_t::parse_elements(const std::string& fmt) break; } - case '@': { - const char * s = ++p; - while (*p && *p != '(') - p++; - if (*p && *++p != ')') - throw format_error("Missing ')'"); - - current->type = element_t::INTERP_FUNC; - current->chars = std::string(s, (p - s) - 1); - break; - } - case '[': { ++p; const char * b = p; @@ -585,20 +570,6 @@ void format_t::format(std::ostream& out_str, const details_t& details) const } break; - case element_t::INTERP_FUNC: -#ifdef USE_BOOST_PYTHON - try { - object func = python_eval(elem->chars); - out << call<std::string>(func.ptr(), details); - } - catch(const boost::python::error_already_set&) { - PyErr_Print(); - throw format_error(std::string("While calling Python function '") + - elem->chars + "'"); - } -#endif - break; - default: assert(0); break; @@ -842,91 +813,3 @@ void format_equity::operator()(account_t& account) } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -std::string py_format_1(format_t& format, const details_t& item) -{ - std::ostringstream out; - format.format(out, item); - return out.str(); -} - -template <typename T> -std::string py_format(format_t& format, const T& item) -{ - std::ostringstream out; - format.format(out, details_t(item)); - return out.str(); -} - -void export_format() -{ - typedef - pystream_handler_wrap<format_transactions, transaction_t, std::string> - format_transactions_wrap; - - class_< format_transactions_wrap, bases<item_handler<transaction_t> > > - ("FormatTransactions", - init<PyObject *, std::string>()[with_custodian_and_ward<1, 2>()]) - .def("flush", &format_transactions_wrap::flush) - .def("__call__", &format_transactions_wrap::operator()) - ; - - typedef - pystream_handler_wrap<format_entries, transaction_t, std::string> - format_entries_wrap; - - class_< format_entries_wrap, bases<item_handler<transaction_t> > > - ("FormatEntries", - init<PyObject *, std::string>()[with_custodian_and_ward<1, 2>()]) - .def("flush", &format_entries_wrap::flush) - .def("__call__", &format_entries_wrap::operator()) - ; - - typedef - pystream_handler_wrap<format_account, account_t, std::string, std::string> - format_account_wrap; - - class_< format_account_wrap, bases<item_handler<transaction_t> > > - ("FormatAccount", - init<PyObject *, std::string, std::string>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &format_account_wrap::flush) - .def("__call__", &format_account_wrap::operator()) - ; - - typedef - pystream_handler_wrap<format_equity, account_t, std::string, std::string> - format_equity_wrap; - - class_< format_equity_wrap, bases<item_handler<transaction_t> > > - ("FormatEquity", - init<PyObject *, std::string, std::string>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &format_equity_wrap::flush) - .def("__call__", &format_equity_wrap::operator()) - ; - - class_< format_t > ("Format") - .def(init<std::string>()) - .def("reset", &format_t::reset) - .def("format", py_format_1) - .def("format", py_format<account_t>) - .def("format", py_format<entry_t>) - .def("format", py_format<transaction_t>) - ; - - def("truncated", truncated); -#if 0 - def("partial_account_name", partial_account_name); -#endif - def("display_account", display_account); -} - -#endif // USE_BOOST_PYTHON @@ -38,8 +38,7 @@ struct element_t NOTE, OPT_NOTE, SPACER, - DEPTH_SPACER, - INTERP_FUNC + DEPTH_SPACER }; bool align_left; @@ -189,40 +188,4 @@ class format_equity : public item_handler<account_t> } // namespace ledger -#ifdef USE_BOOST_PYTHON - -#include "pyfstream.h" - -template <typename T, typename U, typename V = int, typename W = int> -struct pystream_handler_wrap : public ledger::item_handler<U> -{ - PyFileObject * file; - pyofstream * output; - - T handler; - - pystream_handler_wrap(PyObject * file_) - : file((PyFileObject *)file_), output(new pyofstream(file)), - handler(*output) {} - pystream_handler_wrap(PyObject * file_, const V& arg) - : file((PyFileObject *)file_), output(new pyofstream(file)), - handler(*output, arg) {} - pystream_handler_wrap(PyObject * file_, const V& arg1, const W& arg2) - : file((PyFileObject *)file_), output(new pyofstream(file)), - handler(*output, arg1, arg2) {} - - virtual ~pystream_handler_wrap() { - delete output; - } - - virtual void flush() { - handler.flush(); - } - virtual void operator()(U& item) { - handler.operator()(item); - } -}; - -#endif // USE_BOOST_PYTHON - -#endif // _REPORT_H +#endif // _FORMAT_H @@ -415,22 +415,3 @@ unsigned int gnucash_parser_t::parse(std::istream& in, } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(gnucash_parse_overloads, - gnucash_parser_t::parse, 2, 4) - -void export_gnucash() { - class_< gnucash_parser_t, bases<parser_t> > ("GnucashParser") - .def("test", &gnucash_parser_t::test) - .def("parse", &gnucash_parser_t::parse, gnucash_parse_overloads()) - ; -} - -#endif // USE_BOOST_PYTHON @@ -3,9 +3,6 @@ #include "valexpr.h" #include "mask.h" #include "error.h" -#ifdef USE_BOOST_PYTHON -#include "py_eval.h" -#endif #include "acconf.h" #include <fstream> @@ -290,14 +287,6 @@ void auto_entry_t::extend_entry(entry_base_t& entry) if (fullname == "$account") account = (*i)->account; -#ifdef USE_BOOST_PYTHON - else if (fullname[0] == '@') { - value_expr_t * expr = parse_value_expr(fullname); - if (expr->kind == value_expr_t::F_INTERP_FUNC) - python_call(expr->constant_s, expr->right, details_t(**i), - *(*t)->account); - } -#endif transaction_t * xact = new transaction_t(account, amt, (*t)->flags | TRANSACTION_AUTO); @@ -525,358 +514,3 @@ bool journal_t::valid() const } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> -#include <boost/python/exception_translator.hpp> - -using namespace boost::python; -using namespace ledger; - -entry_t& transaction_entry(const transaction_t& xact) -{ - return *xact.entry; -} - -unsigned int transactions_len(entry_base_t& entry) -{ - return entry.transactions.size(); -} - -transaction_t& transactions_getitem(entry_base_t& entry, int i) -{ - static int last_index = 0; - static entry_base_t * last_entry = NULL; - static transactions_list::iterator elem; - - std::size_t len = entry.transactions.size(); - - if (abs(i) >= len) { - PyErr_SetString(PyExc_IndexError, "Index out of range"); - throw_error_already_set(); - } - - if (&entry == last_entry && i == last_index + 1) { - last_index = i; - return **++elem; - } - - int x = i < 0 ? len + i : i; - elem = entry.transactions.begin(); - while (--x >= 0) - elem++; - - last_entry = &entry; - last_index = i; - - return **elem; -} - -unsigned int entries_len(journal_t& journal) -{ - return journal.entries.size(); -} - -entry_t& entries_getitem(journal_t& journal, int i) -{ - static int last_index = 0; - static journal_t * last_journal = NULL; - static entries_list::iterator elem; - - std::size_t len = journal.entries.size(); - - if (abs(i) >= len) { - PyErr_SetString(PyExc_IndexError, "Index out of range"); - throw_error_already_set(); - } - - if (&journal == last_journal && i == last_index + 1) { - last_index = i; - return **++elem; - } - - int x = i < 0 ? len + i : i; - elem = journal.entries.begin(); - while (--x >= 0) - elem++; - - last_journal = &journal; - last_index = i; - - return **elem; -} - -unsigned int accounts_len(account_t& account) -{ - return account.accounts.size(); -} - -account_t& accounts_getitem(account_t& account, int i) -{ - static int last_index = 0; - static account_t * last_account = NULL; - static accounts_map::iterator elem; - - std::size_t len = account.accounts.size(); - - if (abs(i) >= len) { - PyErr_SetString(PyExc_IndexError, "Index out of range"); - throw_error_already_set(); - } - - if (&account == last_account && i == last_index + 1) { - last_index = i; - return *(*++elem).second; - } - - int x = i < 0 ? len + i : i; - elem = account.accounts.begin(); - while (--x >= 0) - elem++; - - last_account = &account; - last_index = i; - - return *(*elem).second; -} - -PyObject * py_account_get_data(account_t& account) -{ - return (PyObject *) account.data; -} - -void py_account_set_data(account_t& account, PyObject * obj) -{ - account.data = obj; -} - -account_t * py_find_account_1(journal_t& journal, const std::string& name) -{ - return journal.find_account(name); -} - -account_t * py_find_account_2(journal_t& journal, const std::string& name, - const bool auto_create) -{ - return journal.find_account(name, auto_create); -} - -bool py_add_entry(journal_t& journal, entry_t * entry) { - return journal.add_entry(new entry_t(*entry)); -} - -void py_add_transaction(entry_base_t& entry, transaction_t * xact) { - return entry.add_transaction(new transaction_t(*xact)); -} - -struct entry_base_wrap : public entry_base_t -{ - PyObject * self; - entry_base_wrap(PyObject * self_) : self(self_) {} - - virtual bool valid() const { - return call_method<bool>(self, "valid"); - } -}; - -struct py_entry_finalizer_t : public entry_finalizer_t { - object pyobj; - py_entry_finalizer_t() {} - py_entry_finalizer_t(object obj) : pyobj(obj) {} - py_entry_finalizer_t(const py_entry_finalizer_t& other) - : pyobj(other.pyobj) {} - virtual bool operator()(entry_t& entry) { - return call<bool>(pyobj.ptr(), entry); - } -}; - -std::list<py_entry_finalizer_t> py_finalizers; - -void py_add_entry_finalizer(journal_t& journal, object x) -{ - py_finalizers.push_back(py_entry_finalizer_t(x)); - journal.add_entry_finalizer(&py_finalizers.back()); -} - -void py_remove_entry_finalizer(journal_t& journal, object x) -{ - for (std::list<py_entry_finalizer_t>::iterator i = py_finalizers.begin(); - i != py_finalizers.end(); - i++) - if ((*i).pyobj == x) { - journal.remove_entry_finalizer(&(*i)); - py_finalizers.erase(i); - return; - } -} - -void py_run_entry_finalizers(journal_t& journal, entry_t& entry) -{ - run_hooks(journal.entry_finalize_hooks, entry); -} - -#define EXC_TRANSLATOR(type) \ - void exc_translate_ ## type(const type& err) { \ - PyErr_SetString(PyExc_RuntimeError, err.what()); \ - } - -EXC_TRANSLATOR(error) -EXC_TRANSLATOR(interval_expr_error) -EXC_TRANSLATOR(format_error) -EXC_TRANSLATOR(parse_error) - -void export_journal() -{ - scope().attr("TRANSACTION_NORMAL") = TRANSACTION_NORMAL; - scope().attr("TRANSACTION_VIRTUAL") = TRANSACTION_VIRTUAL; - scope().attr("TRANSACTION_BALANCE") = TRANSACTION_BALANCE; - scope().attr("TRANSACTION_AUTO") = TRANSACTION_AUTO; - scope().attr("TRANSACTION_BULK_ALLOC") = TRANSACTION_BULK_ALLOC; - - class_< transaction_t > ("Transaction") - .def(init<account_t *, amount_t, optional<unsigned int, std::string> >()) - - .def(self == self) - .def(self != self) - - .add_property("entry", - make_getter(&transaction_t::entry, - return_value_policy<reference_existing_object>())) - .add_property("account", - make_getter(&transaction_t::account, - return_value_policy<reference_existing_object>())) - .def_readwrite("amount", &transaction_t::amount) - .add_property("cost", - make_getter(&transaction_t::cost, - return_internal_reference<1>())) - .def_readwrite("state", &transaction_t::state) - .def_readwrite("flags", &transaction_t::flags) - .def_readwrite("note", &transaction_t::note) -#if 0 - .def_readwrite("data", &transaction_t::data) -#endif - - .def("valid", &transaction_t::valid) - ; - - enum_< transaction_t::state_t > ("State") - .value("UNCLEARED", transaction_t::UNCLEARED) - .value("CLEARED", transaction_t::CLEARED) - .value("PENDING", transaction_t::PENDING) - ; - - class_< account_t > - ("Account", - init<optional<account_t *, std::string, std::string> >() - [with_custodian_and_ward<1, 2>()]) - .def(self == self) - .def(self != self) - - .def_readonly("journal", &account_t::journal) - .add_property("parent", - make_getter(&account_t::parent, - return_internal_reference<1>())) - .def_readwrite("name", &account_t::name) - .def_readwrite("note", &account_t::note) - .def_readonly("depth", &account_t::depth) - .add_property("data", py_account_get_data, py_account_set_data) - .def_readonly("ident", &account_t::ident) - - .def(self_ns::str(self)) - - .def("fullname", &account_t::fullname) - .def("add_account", &account_t::add_account) - .def("remove_account", &account_t::remove_account) - .def("find_account", &account_t::find_account, - return_value_policy<reference_existing_object>()) - - .def("valid", &account_t::valid) - ; - - class_< journal_t > ("Journal") - .def(self == self) - .def(self != self) - - .add_property("master", - make_getter(&journal_t::master, - return_internal_reference<1>())) - .add_property("basket", - make_getter(&journal_t::basket, - return_internal_reference<1>())) - .def_readwrite("price_db", &journal_t::price_db) - .def_readonly("sources", &journal_t::sources) - - .def("__len__", entries_len) - .def("__getitem__", entries_getitem, return_internal_reference<1>()) - .def("add_account", &journal_t::add_account) - .def("remove_account", &journal_t::remove_account) - .def("find_account", py_find_account_1, return_internal_reference<1>()) - .def("find_account", py_find_account_2, return_internal_reference<1>()) - .def("find_account_re", &journal_t::find_account_re, - return_internal_reference<1>()) - - .def("add_entry", py_add_entry) - .def("remove_entry", &journal_t::remove_entry) - .def("add_entry_finalizer", py_add_entry_finalizer) - .def("remove_entry_finalizer", py_remove_entry_finalizer) - .def("run_entry_finalizers", py_run_entry_finalizers) - - .def("valid", &journal_t::valid) - ; - - class_< entry_base_t, entry_base_wrap, boost::noncopyable > ("EntryBase") - .def("__len__", transactions_len) - .def("__getitem__", transactions_getitem, - return_internal_reference<1>()) - - .def_readonly("journal", &entry_base_t::journal) - .def_readonly("src_idx", &entry_base_t::src_idx) - .def_readonly("beg_pos", &entry_base_t::beg_pos) - .def_readonly("beg_line", &entry_base_t::beg_line) - .def_readonly("end_pos", &entry_base_t::end_pos) - .def_readonly("end_line", &entry_base_t::end_line) - - .def("add_transaction", py_add_transaction) - .def("remove_transaction", &entry_base_t::remove_transaction) - - .def(self == self) - .def(self != self) - - .def("valid", &entry_base_t::valid) - ; - - scope in_entry = class_< entry_t, bases<entry_base_t> > ("Entry") - .def_readwrite("date", &entry_t::date) - .def_readwrite("code", &entry_t::code) - .def_readwrite("payee", &entry_t::payee) - - .def("valid", &entry_t::valid) - ; - - class_< auto_entry_t, bases<entry_base_t> > ("AutoEntry") - .add_property("predicate", - make_getter(&auto_entry_t::predicate, - return_internal_reference<1>())) - .def_readonly("predicate_string", &auto_entry_t::predicate_string) - - .def("valid", &auto_entry_t::valid) - ; - - class_< period_entry_t, bases<entry_base_t> > ("PeriodEntry") - .def_readonly("period", &period_entry_t::period) - .def_readonly("period_string", &period_entry_t::period_string) - - .def("valid", &period_entry_t::valid) - ; - -#define EXC_TRANSLATE(type) \ - register_exception_translator<type>(&exc_translate_ ## type); - - EXC_TRANSLATE(error); - EXC_TRANSLATE(interval_expr_error); - EXC_TRANSLATE(format_error); - EXC_TRANSLATE(parse_error); -} - -#endif // USE_BOOST_PYTHON diff --git a/ledger.texi b/ledger.texi index b8da037a..f271f5a1 100644 --- a/ledger.texi +++ b/ledger.texi @@ -64,7 +64,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * Running Ledger:: * Keeping a ledger:: * Using XML:: -* Extending with Python:: @end menu @node Introduction, Running Ledger, Top, Top @@ -2260,14 +2259,6 @@ precedence order of operators. @item [DATE] Useful specifying a date in plain terms. For example, you could say @samp{[2004/06/01]}. - -@item @@STR(ARGS,...) -If Python support is compiled in, this calls the Python function -@code{STR}. It is always be passed at least one argument, of type -@var{ledger.Details}, representing the known account, entry, and -transaction details at the time the value expression is computed. -Other value expression arguments may also be passed by the user, all -of type @var{Value}. @end table @node Period expressions, File format, Value expressions, Running Ledger @@ -2431,13 +2422,6 @@ transactions that follow, until @samp{!end} is seen. @item !end Ends an account block. - -@item !python -If Python support is available, all of the lines following -@samp{!python} will be passed to the Python interpretor. Any -functions defined will be available to later Python blocks, and can be -called from a value expression. The Python code block must be ended -with @samp{!end}. @end table @item ; @@ -3699,8 +3683,8 @@ description is a ledger account name, these in/out pairs may be viewed as virtual transactions, adding time commodities (hours) to that account. -For example, the command-line version of the timeclock tool (which is -written in Python) could be used to begin a timelog file like: +For example, the command-line version of the timeclock tool could be +used to begin a timelog file like: @example export TIMELOG=$HOME/.timelog @@ -3778,7 +3762,7 @@ accounting ledger, with the attached prefix @samp{Billable}: Receivable:ClientOne @end smallexample -@node Using XML, Extending with Python, Keeping a ledger, Top +@node Using XML, , Keeping a ledger, Top @chapter Using XML By default, Ledger uses a human-readable data format, and displays its @@ -3930,29 +3914,4 @@ output such data if the @command{xml} command is used, and can read the same data as long as the @file{expat} library was available when Ledger was built. -@node Extending with Python, , Using XML, Top -@chapter Extending with Python - -Ledger fully supports Python as an extension language. It may be used -in a few different forms, which fall into three basic categories: - -@enumerate -@item -Defining Python functions to use in value expressions -@item -Using the ledger library as a Python module -@item -Setting up custom initialization using Python -@end enumerate - -Note that this feature, while functional, is still under development. -It will not be documented until it has been fully proven, probably in -the next version of ledger. For now, if you wish to make this of this -functionality and are willing to debug problems that come up, pass the -option @samp{--enable-python} to configure, and contact the author via -email. - -One example of using Python to create a more complex report is in the -script file @file{scripts/trend}. - @bye @@ -18,9 +18,6 @@ #endif #include "ledger.h" -#ifdef USE_BOOST_PYTHON -#include "py_eval.h" -#endif #include "timing.h" using namespace ledger; @@ -232,33 +229,6 @@ int parse_and_report(int argc, char * argv[], char * envp[]) else format = &config.print_format; -#ifdef USE_BOOST_PYTHON - - // If Python support is compiled, we can easily report minimum and - // maximum values for each commodity. There is a line in config.cc - // which configures the prices report to call these two functions, - // if Python is available. - - if (command == "P") - python_eval("\ -min_val = 0\n\ -def vmin(d, val):\n\ - global min_val\n\ - if not min_val or val < min_val:\n\ - min_val = val\n\ - return val\n\ - return min_val\n\ -\n\ -max_val = 0\n\ -def vmax(d, val):\n\ - global max_val\n\ - if not max_val or val > max_val:\n\ - max_val = val\n\ - return val\n\ - return max_val\n", PY_EVAL_MULTI); - -#endif // USE_BOOST_PYTHON - TIMER_STOP(process); // Walk the entries based on the report type and the options diff --git a/main.py b/main.py deleted file mode 100644 index 57ba84c5..00000000 --- a/main.py +++ /dev/null @@ -1,373 +0,0 @@ -#!/usr/bin/env python - -# Ledger, the command-line accounting tool -# -# Copyright (c) 2003-2004, New Artisans LLC. All rights reserved. -# -# This program is made available under the terms of the BSD Public -# License. See the LICENSE file included with the distribution for -# details and disclaimer. -# -# This script provides a Python front-end to the ledger library, and -# replicates the functionality of the C++ front-end, main.cc. It is -# provided as an example, and as a starting point for creating custom -# front-ends based on the Ledger module. See the documentation for an -# API reference, and how to use this module. - -import os -import sys -import string -import time - -true, false = 1, 0 - -from ledger import * - -# Create the main journal object, into which all entries will be -# recorded. Once done, the 'journal' may be iterated to yield those -# entries, in the same order as which they appeared in the journal -# file. - -journal = Journal () - -# This call registers all of the default command-line options that -# Ledger supports into the option handling mechanism. Skip this call -# if you wish to do all of your own processing -- in which case simply -# modify the 'config' object however you like. - -add_config_option_handlers () - -averages = {} -compute_monthly_avg = false - -def get_index (xact): - return time.strftime ("%Y/%m", time.localtime (xact.entry.date)) - -class ComputeMonthlyAvg (TransactionHandler): - def __call__ (self, xact): - global averages - index = get_index (xact) - if not averages.has_key(index): - averages[index] = [Value (), 0] - add_transaction_to (xact, averages[index][0]) - averages[index][1] += 1 - TransactionHandler.__call__ (self, xact) - -def monthly_avg (details): - index = get_index (xact) - return averages[index][0] / averages[index][1] - -def show_monthly_averages (arg): - global compute_monthly_avg - compute_monthly_avg = true - config.report_period = "monthly"; - config.total_expr = "@monthly_avg()" - -add_option_handler ("monthly-avg", "", show_monthly_averages) - -# Process the command-line arguments, test whether caching should be -# enabled, and then process any option settings from the execution -# environment. Some historical environment variable names are also -# supported. - -args = process_arguments (sys.argv[1:]) -config.use_cache = not config.data_file -process_environment (os.environ, "LEDGER_") - -if os.environ.has_key ("LEDGER"): - process_option ("file", os.getenv ("LEDGER")) -if os.environ.has_key ("PRICE_HIST"): - process_option ("price-db", os.getenv ("PRICE_HIST")) -if os.environ.has_key ("PRICE_EXP"): - process_option ("price-exp", os.getenv ("PRICE_EXP")) - -# If no argument remain, then no command word was given. Report the -# default help text and exit. - -if len (args) == 0: - option_help () - sys.exit (0) - -# The command word is in the first argument. Canonicalize it to a -# unique, simple form that the remaining code can use to find out -# which command was specified. - -command = args.pop (0); - -if command == "balance" or command == "bal" or command == "b": - command = "b" -elif command == "register" or command == "reg" or command == "r": - command = "r" -elif command == "print" or command == "p": - command = "p" -elif command == "output": - command = "w" -elif command == "emacs": - command = "x" -elif command == "xml": - command = "X" -elif command == "entry": - command = "e" -elif command == "equity": - command = "E" -elif command == "prices": - command = "P" -elif command == "pricesdb": - command = "D"; -else: - print "Unrecognized command:", command - sys.exit (1) - -# Create all the parser objects to be used. They are all registered, -# so that Ledger will try each one in turn whenever it is presented -# with a data file. They are attempted in reverse order to their -# registry. Note that Gnucash parsing is only available if the Ledger -# module was built with such support (which requires the expat C -# library). - -bin_parser = BinaryParser () -gnucash_parser = None -xml_parser = None -try: xml_parser = GnucashParser () -except: pass -try: gnucash_parser = GnucashParser () -except: pass -try: ofx_parser = OfxParser () -except: pass -qif_parser = QifParser () -text_parser = TextualParser () - -register_parser (bin_parser) -if xml_parser: - register_parser (xml_parser) -if gnucash_parser: - register_parser (gnucash_parser) -if ofx_parser: - register_parser (ofx_parser) -register_parser (qif_parser) -register_parser (text_parser) - -# Parse all entries from the user specified locations (found in -# 'config') into the journal object we created. The two parsers given -# as explicit arguments indicate: the parser to be used for standard -# input, and the parser to be used for cache files. - -parse_ledger_data (journal, bin_parser) - -# Now that everything has been correctly parsed (parse_ledger_data -# would have thrown an exception if not), we can take time to further -# process the configuration options. This changes the configuration a -# bit based on previous option settings, the command word, and the -# remaining arguments. - -config.process_options (command, args); - -# If the command is "e", use the method journal.derive_entry to create -# a brand new entry based on the arguments given. - -new_entry = None -if command == "e": - new_entry = derive_new_entry (journal, args) - if new_entry is None: - sys.exit (1) - -# Determine the format string to used, based on the command. - -if config.format_string: - format = config.format_string -elif command == "b": - format = config.balance_format -elif command == "r": - format = config.register_format -elif command == "E": - format = config.equity_format -elif command == "P": - min_val = 0 - def vmin(d, val): - global min_val - if not min_val or val < min_val: - min_val = val - return val - return min_val - - max_val = 0 - def vmax(d, val): - global max_val - if not max_val or val > max_val: - max_val = val - return val - return max_val - - format = config.prices_format -elif command == "D": - format = config.pricesdb_format -elif command == "w": - format = config.write_xact_format -else: - format = config.print_format - -# Configure the output file - -if config.output_file: - out = open (config.output_file, "w") -else: - out = sys.stdout - -# Set the final transaction handler: for balances and equity reports, -# it will simply add the value of the transaction to the account's -# xdata, which is used a bit later to report those totals. For all -# other reports, the transaction data is sent to the configured output -# location (default is sys.stdout). - -if command == "b" or command == "E": - handler = SetAccountValue () -elif command == "p" or command == "e": - handler = FormatEntries (out, format) -elif command == "x": - handler = FormatEmacsTransactions (out) -elif command == "X": - handler = FormatXmlEntries (out, config.show_totals) -else: - handler = FormatTransactions (out, format) - -if command == "w": - write_textual_journal(journal, args, handler, out); -else: - # Chain transaction filters on top of the base handler. Most of these - # filters customize the output for reporting. None of this is done - # for balance or equity reports, which don't need it. - - if not (command == "b" or command == "E"): - if config.head_entries or config.tail_entries: - handler = TruncateEntries (handler, config.head_entries, - config.tail_entries) - - if config.display_predicate: - handler = FilterTransactions (handler, config.display_predicate) - - handler = CalcTransactions (handler) - - if config.reconcile_balance: - reconcilable = False - if config.reconcile_balance == "<all>": - reconcilable = True - else: - target_balance = Value (config.reconcile_balance) - - cutoff = time.time () - if config.reconcile_date: - cutoff = parse_date (config.reconcile_date) - - handler = ReconcileTransactions (handler, target_balance, - cutoff, reconcilable) - - if config.sort_string: - handler = SortTransactions (handler, config.sort_string) - - if config.show_revalued: - handler = ChangedValueTransactions (handler, - config.show_revalued_only) - - if config.show_collapsed: - handler = CollapseTransactions (handler); - - if config.show_subtotal and not (command == "b" or command == "E"): - handler = SubtotalTransactions (handler) - - if config.days_of_the_week: - handler = DowTransactions (handler) - elif config.by_payee: - handler = ByPayeeTransactions (handler) - - if config.report_period: - handler = IntervalTransactions (handler, config.report_period, - config.report_period_sort) - handler = SortTransactions (handler, "d") - - if compute_monthly_avg: - handler = ComputeMonthlyAvg (handler) - - # The next set of transaction filters are used by all reports. - - if config.show_inverted: - handler = InvertTransactions (handler) - - if config.show_related: - handler = RelatedTransactions (handler, config.show_all_related) - - if config.predicate: - handler = FilterTransactions (handler, config.predicate) - - if config.budget_flags: - handler = BudgetTransactions (handler, config.budget_flags) - handler.add_period_entries (journal) - elif config.forecast_limit: - handler = ForecastTransactions (handler, config.forecast_limit) - handler.add_period_entries (journal) - - if config.comm_as_payee: - handler = SetCommAsPayee (handler) - - # Walk the journal's entries, and pass each entry's transaction to the - # handler chain established above. And although a journal's entries - # can be walked using Python, it is significantly faster to do this - # simple walk in C++, using `walk_entries'. - # - # if command == "e": - # for xact in new_entry: - # handler (xact) - # else: - # for entry in journal: - # for xact in entry: - # handler (xact) - - if command == "e": - walk_transactions (new_entry, handler) - elif command == "P" or command == "D": - walk_commodities (handler) - else: - walk_entries (journal, handler) - - # Flush the handlers, causing them to output whatever data is still - # pending. - - if command != "P" and command != "D": - handler.flush () - -# For the balance and equity reports, the account totals now need to -# be displayed. This is different from outputting transactions, in -# that we are now outputting account totals to display a summary of -# the transactions that were just walked. - -if command == "b": - acct_formatter = FormatAccount (out, format, config.display_predicate) - sum_accounts (journal.master) - walk_accounts (journal.master, acct_formatter, config.sort_string) - acct_formatter.final (journal.master) - acct_formatter.flush () - - if account_has_xdata (journal.master): - xdata = account_xdata (journal.master) - if not config.show_collapsed and xdata.total: - out.write("--------------------\n") - xdata.value = xdata.total - # jww (2005-02-15): yet to convert - #acct_formatter.format.format (out, details_t (journal.master)) - -elif command == "E": - acct_formatter = FormatEquity (out, format, config.display_predicate) - sum_accounts (journal.master) - walk_accounts (journal.master, acct_formatter, config.sort_string) - acct_formatter.flush () - -# If it were important to clean things up, we would have to clear out -# the accumulated xdata at this point: - -#clear_all_xdata () - -# If the cache is being used, and is dirty, update it now. - -if config.use_cache and config.cache_dirty and config.cache_file: - write_binary_journal (config.cache_file, journal); - -# We're done! @@ -220,22 +220,3 @@ unsigned int ofx_parser_t::parse(std::istream& in, } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(ofx_parse_overloads, - ofx_parser_t::parse, 2, 4) - -void export_ofx() { - class_< ofx_parser_t, bases<parser_t> > ("OfxParser") - .def("test", &ofx_parser_t::test) - .def("parse", &ofx_parser_t::parse, ofx_parse_overloads()) - ; -} - -#endif // USE_BOOST_PYTHON @@ -168,94 +168,3 @@ void process_environment(std::list<option_t>& options, process_option(options, buf, q + 1); } } - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> -#include <boost/python/detail/api_placeholder.hpp> -#include <vector> - -using namespace boost::python; - -struct func_option_wrapper : public option_handler -{ - object self; - func_option_wrapper(object _self) : self(_self) {} - - virtual void operator()(const char * arg) { - call<void>(self.ptr(), arg); - } -}; - -namespace { - std::list<func_option_wrapper> wrappers; - std::list<option_t> options; -} - -void py_add_option_handler(const std::string& long_opt, - const std::string& short_opt, object func) -{ - wrappers.push_back(func_option_wrapper(func)); - add_option_handler(options, long_opt, short_opt, wrappers.back()); -} - -void add_other_option_handlers(const std::list<option_t>& other) -{ - options.insert(options.begin(), other.begin(), other.end()); -} - -bool py_process_option(const std::string& opt, const char * arg) -{ - return process_option(options, opt, arg); -} - -list py_process_arguments(list args, bool anywhere = false) -{ - std::vector<char *> strs; - - int l = len(args); - for (int i = 0; i < l; i++) - strs.push_back(extract<char *>(args[i])); - - std::list<std::string> newargs; - process_arguments(options, strs.size(), &strs.front(), anywhere, newargs); - - list py_newargs; - for (std::list<std::string>::iterator i = newargs.begin(); - i != newargs.end(); - i++) - py_newargs.append(*i); - return py_newargs; -} - -BOOST_PYTHON_FUNCTION_OVERLOADS(py_proc_args_overloads, - py_process_arguments, 1, 2) - -void py_process_environment(object env, const std::string& tag) -{ - std::vector<char *> strs; - std::vector<std::string> storage; - - list items = call_method<list>(env.ptr(), "items"); - int l = len(items); - for (int i = 0; i < l; i++) { - tuple pair = extract<tuple>(items[i]); - std::string s = extract<std::string>(pair[0]); - s += "="; - s += extract<std::string>(pair[1]); - storage.push_back(s); - strs.push_back(const_cast<char *>(storage.back().c_str())); - } - - process_environment(options, &strs.front(), tag); -} - -void export_option() -{ - def("add_option_handler", py_add_option_handler); - def("process_option", py_process_option); - def("process_arguments", py_process_arguments, py_proc_args_overloads()); - def("process_environment", py_process_environment); -} - -#endif // USE_BOOST_PYTHON @@ -191,51 +191,3 @@ unsigned int parse_ledger_data(journal_t * journal, config_t& config) } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> -#include <Python.h> - -using namespace boost::python; -using namespace ledger; - -struct parser_wrap : public parser_t -{ - PyObject * self; - parser_wrap(PyObject * self_) : self(self_) {} - - virtual bool test(std::istream& in) const { - return call_method<bool>(self, "test", in); - } - - virtual unsigned int parse(std::istream& in, - journal_t * journal, - account_t * master = NULL, - const std::string * original_file = NULL) { - return call_method<unsigned int>(self, "__call__", in, journal, master, - original_file); - } -}; - -BOOST_PYTHON_FUNCTION_OVERLOADS(parse_journal_overloads, parse_journal, 2, 4) -BOOST_PYTHON_FUNCTION_OVERLOADS(parse_journal_file_overloads, - parse_journal_file, 2, 4) - -BOOST_PYTHON_FUNCTION_OVERLOADS(parse_ledger_data_overloads, - parse_ledger_data, 1, 2) - -void export_parser() { - class_< parser_t, parser_wrap, boost::noncopyable > ("Parser") - ; - - def("register_parser", register_parser); - def("unregister_parser", unregister_parser); - def("parse_journal", parse_journal, parse_journal_overloads()); - def("parse_journal_file", parse_journal_file, parse_journal_file_overloads()); -#if 0 - def("parse_ledger_data", parse_ledger_data, parse_ledger_data_overloads()); -#endif -} - -#endif // USE_BOOST_PYTHON diff --git a/py_eval.cc b/py_eval.cc deleted file mode 100644 index 3baa3d30..00000000 --- a/py_eval.cc +++ /dev/null @@ -1,163 +0,0 @@ -#include "py_eval.h" -#include "journal.h" -#include "error.h" -#include "acconf.h" - -#include <sstream> -#include <map> - -namespace { - bool python_initialized = false; - bool module_initialized = false; -} - -void export_amount(); -void export_balance(); -void export_value(); -void export_journal(); -void export_parser(); -void export_textual(); -void export_binary(); -void export_qif(); -#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE) -void export_xml(); -void export_gnucash(); -#endif -#ifdef HAVE_LIBOFX -void export_ofx(); -#endif -void export_option(); -void export_config(); -void export_walk(); -void export_format(); -void export_valexpr(); -void export_datetime(); -void export_derive(); -void export_reconcile(); -void export_emacs(); - -void initialize_ledger_for_python() -{ - export_amount(); - export_balance(); - export_value(); - export_journal(); - export_parser(); - export_textual(); - export_binary(); - export_qif(); -#if defined(HAVE_EXPAT) || defined(HAVE_XMLPARSE) - export_xml(); - export_gnucash(); -#endif -#ifdef HAVE_LIBOFX - export_ofx(); -#endif - export_option(); - export_config(); - export_walk(); - export_format(); - export_valexpr(); - export_datetime(); - export_derive(); - export_reconcile(); - export_emacs(); - - module_initialized = true; -} - -namespace ledger { - -static struct python_main_t -{ - handle<> mmodule; - dict nspace; - python_main_t() - : mmodule(borrowed(PyImport_AddModule("__main__"))), - nspace(handle<>(borrowed(PyModule_GetDict(mmodule.get())))) {} -} - * python_main = NULL; - -struct python_run -{ - object result; - python_run(const std::string& str, int input_mode) - : result(handle<>(borrowed(PyRun_String(str.c_str(), input_mode, - python_main->nspace.ptr(), - python_main->nspace.ptr())))) {} - operator object() { - return result; - } -}; - -static struct cleanup_python { - ~cleanup_python() { - if (python_main) { - delete python_main; - python_main = NULL; - } - if (python_initialized) - Py_Finalize(); - } -} _cleanup; - -void init_python() -{ - if (! module_initialized) { - Py_Initialize(); - python_initialized = true; - detail::init_module("ledger", &initialize_ledger_for_python); - } - python_main = new python_main_t; -} - -object python_eval(std::istream& in, py_eval_mode_t mode) -{ - if (! python_initialized) - init_python(); - - bool first = true; - std::string buffer; - buffer.reserve(4096); - - while (! in.eof()) { - char buf[256]; - in.getline(buf, 255); - if (buf[0] == '!') - break; - if (first) - first = false; - else - buffer += "\n"; - buffer += buf; - } - - try { - int input_mode; - switch (mode) { - case PY_EVAL_EXPR: input_mode = Py_eval_input; break; - case PY_EVAL_STMT: input_mode = Py_single_input; break; - case PY_EVAL_MULTI: input_mode = Py_file_input; break; - } - assert(Py_IsInitialized()); - return python_run(buffer, input_mode); - } - catch(const boost::python::error_already_set&) { - PyErr_Print(); - throw error("Evaluating Python code"); - } -} - -object python_eval(const std::string& str, py_eval_mode_t mode) -{ - std::istringstream stream(str); - return python_eval(stream, mode); -} - -object python_eval(const char * c_str, py_eval_mode_t mode) -{ - std::string str(c_str); - return python_eval(str, mode); -} - -} // namespace ledger diff --git a/py_eval.h b/py_eval.h deleted file mode 100644 index 8327f9a4..00000000 --- a/py_eval.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _PYTHON_H -#define _PYTHON_H - -#include "valexpr.h" - -#include <string> -#include <iostream> - -#include <boost/python.hpp> - -using namespace boost::python; - -namespace ledger { - -enum py_eval_mode_t { - PY_EVAL_EXPR, - PY_EVAL_STMT, - PY_EVAL_MULTI -}; - -object python_eval(std::istream& in, py_eval_mode_t mode = PY_EVAL_EXPR); -object python_eval(const std::string& str, py_eval_mode_t mode = PY_EVAL_EXPR); -object python_eval(const char * c_str, py_eval_mode_t mode = PY_EVAL_EXPR); - -template <typename T> -bool python_call(const std::string& func_name, value_expr_t * arg_expr, - const details_t& details, T& result) -{ - try { - object func = python_eval(func_name); - if (arg_expr) { - if (arg_expr->right) { - list args; - args.append(details); - for (value_expr_t * arg = arg_expr; arg; arg = arg->right) { - assert(arg->kind == value_expr_t::O_ARG); - value_t value; - arg->left->compute(value, details); - args.append(value); - } - - if (PyObject * val = PyObject_CallObject(func.ptr(), - tuple(args).ptr())) { - result = extract<T>(val)(); - Py_DECREF(val); - } - else if (PyObject * err = PyErr_Occurred()) { - PyErr_Print(); - throw value_expr_error(std::string("While calling Python function '") + - func_name + "'"); - } - else { - return false; - } - } else { - assert(arg_expr->kind == value_expr_t::O_ARG); - value_t value; - arg_expr->left->compute(value, details); - result = call<T>(func.ptr(), details, value); - } - } else { - result = call<T>(func.ptr(), details); - } - return true; - } - catch(const boost::python::error_already_set&) { - PyErr_Print(); - throw value_expr_error(std::string("While calling Python function '") + - func_name + "'"); - } - } - -} // namespace ledger - -#endif // _PYTHON_H diff --git a/pyfstream.h b/pyfstream.h deleted file mode 100644 index c41940f5..00000000 --- a/pyfstream.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef _PYFSTREAM_H -#define _PYFSTREAM_H - -#include <istream> -#include <ostream> -#include <streambuf> -#include <cstdio> -#include <cstring> - -#include "Python.h" - -// pyofstream -// - a stream that writes on a Python file object - -class pyoutbuf : public std::streambuf { - protected: - PyFileObject * fo; // Python file object - public: - // constructor - pyoutbuf (PyFileObject * _fo) : fo(_fo) {} - - protected: - // write one character - virtual int_type overflow (int_type c) { - if (c != EOF) { - char z[2]; - z[0] = c; - z[1] = '\0'; - if (PyFile_WriteString(z, (PyObject *)fo) < 0) { - return EOF; - } - } - return c; - } - - // write multiple characters - virtual std::streamsize xsputn (const char* s, std::streamsize num) { - char * buf = new char[num + 1]; - std::strncpy(buf, s, num); - buf[num] = '\0'; - if (PyFile_WriteString(buf, (PyObject *)fo) < 0) - num = 0; - delete[] buf; - return num; - } -}; - -class pyofstream : public std::ostream { - protected: - pyoutbuf buf; - public: - pyofstream (PyFileObject * fo) : std::ostream(0), buf(fo) { - rdbuf(&buf); - } -}; - -// pyifstream -// - a stream that reads on a file descriptor - -class pyinbuf : public std::streambuf { - protected: - PyFileObject * fo; // Python file object - protected: - /* data buffer: - * - at most, pbSize characters in putback area plus - * - at most, bufSize characters in ordinary read buffer - */ - static const int pbSize = 4; // size of putback area - static const int bufSize = 1024; // size of the data buffer - char buffer[bufSize + pbSize]; // data buffer - - public: - /* constructor - * - initialize file descriptor - * - initialize empty data buffer - * - no putback area - * => force underflow() - */ - pyinbuf (PyFileObject * _fo) : fo(_fo) { - setg (buffer+pbSize, // beginning of putback area - buffer+pbSize, // read position - buffer+pbSize); // end position - } - - protected: - // insert new characters into the buffer - virtual int_type underflow () { -#ifndef _MSC_VER - using std::memmove; -#endif - - // is read position before end of buffer? - if (gptr() < egptr()) { - return traits_type::to_int_type(*gptr()); - } - - /* process size of putback area - * - use number of characters read - * - but at most size of putback area - */ - int numPutback; - numPutback = gptr() - eback(); - if (numPutback > pbSize) { - numPutback = pbSize; - } - - /* copy up to pbSize characters previously read into - * the putback area - */ - memmove (buffer+(pbSize-numPutback), gptr()-numPutback, - numPutback); - - // read at most bufSize new characters - int num; - PyObject *line = PyFile_GetLine((PyObject *)fo, bufSize); - if (! line || ! PyString_Check(line)) { - // ERROR or EOF - return EOF; - } - - num = PyString_Size(line); - if (num == 0) - return EOF; - - memmove (buffer+pbSize, PyString_AsString(line), num); - - // reset buffer pointers - setg (buffer+(pbSize-numPutback), // beginning of putback area - buffer+pbSize, // read position - buffer+pbSize+num); // end of buffer - - // return next character - return traits_type::to_int_type(*gptr()); - } -}; - -class pyifstream : public std::istream { - protected: - pyinbuf buf; - public: - pyifstream (PyFileObject * fo) : std::istream(0), buf(fo) { - rdbuf(&buf); - } -}; - -#endif // _PYFSTREAM_H diff --git a/pyledger.cc b/pyledger.cc deleted file mode 100644 index dc65a4a3..00000000 --- a/pyledger.cc +++ /dev/null @@ -1,9 +0,0 @@ -#include <boost/python.hpp> - -using namespace boost::python; - -void initialize_ledger_for_python(); - -BOOST_PYTHON_MODULE(ledger) { - initialize_ledger_for_python(); -} diff --git a/pyledger.h b/pyledger.h deleted file mode 100644 index 9d8cafdf..00000000 --- a/pyledger.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _PYLEDGER_H -#define _PYLEDGER_H - -////////////////////////////////////////////////////////////////////// -// -// Ledger Accounting Tool (with Python support via Boost.Python) -// -// A command-line tool for general double-entry accounting. -// -// Copyright (c) 2003,2004 John Wiegley <johnw@newartisans.com> -// - -#include <ledger.h> -#include <py_eval.h> - -#endif // _PYLEDGER_H @@ -246,22 +246,3 @@ unsigned int qif_parser_t::parse(std::istream& in, } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(qif_parse_overloads, - qif_parser_t::parse, 2, 4) - -void export_qif() { - class_< qif_parser_t, bases<parser_t> > ("QifParser") - .def("test", &qif_parser_t::test) - .def("parse", &qif_parser_t::parse, qif_parse_overloads()) - ; -} - -#endif // USE_BOOST_PYTHON diff --git a/reconcile.cc b/reconcile.cc index b28718ee..ec893c0b 100644 --- a/reconcile.cc +++ b/reconcile.cc @@ -86,23 +86,3 @@ void reconcile_transactions::flush() } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -void export_reconcile() -{ - class_< reconcile_transactions, bases<item_handler<transaction_t> > > - ("ReconcileTransactions", - init<item_handler<transaction_t> *, const value_t&, time_t>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &reconcile_transactions::flush) - .def("__call__", &reconcile_transactions::operator()) - ; -} - -#endif // USE_BOOST_PYTHON diff --git a/setup.py b/setup.py deleted file mode 100755 index 79ed0d5f..00000000 --- a/setup.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python - -from distutils.core import setup, Extension - -import os - -libs = ["ledger", "boost_python", "gmp", "pcre"] - -if os.environ.has_key ("HAVE_EXPAT") and\ - os.environ["HAVE_EXPAT"] == "true": - libs.extend (["expat"]) - -if os.environ.has_key ("HAVE_XMLPARSE") and\ - os.environ["HAVE_XMLPARSE"] == "true": - libs.extend (["xmlparse", "xmltok"]) - -if os.environ.has_key ("HAVE_LIBOFX") and\ - os.environ["HAVE_LIBOFX"] == "true": - libs.extend (["ofx"]) - -setup(name = "Ledger", - version = "2.5", - description = "Ledger Accounting Tool", - author = "John Wiegley", - author_email = "johnw@newartisans.com", - url = "http://www.newartisans.com/ledger.html", - ext_modules = [ - Extension("ledger", ["pyledger.cc"], - define_macros = [('PYTHON_MODULE', 1)], - libraries = libs)]) @@ -12,9 +12,6 @@ #include "timing.h" #include "util.h" #include "acconf.h" -#ifdef USE_BOOST_PYTHON -#include "py_eval.h" -#endif #include <fstream> #include <sstream> @@ -733,11 +730,6 @@ unsigned int textual_parser_t::parse(std::istream& in, else if (word == "end") { account_stack.pop_front(); } -#ifdef USE_BOOST_PYTHON - else if (word == "python") { - python_eval(in, PY_EVAL_MULTI); - } -#endif else if (word == "alias") { char * b = skip_ws(p); if (char * e = std::strchr(b, '=')) { @@ -904,22 +896,3 @@ void write_textual_journal(journal_t& journal, std::string path, } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(textual_parse_overloads, - textual_parser_t::parse, 2, 4) - -void export_textual() { - class_< textual_parser_t, bases<parser_t> > ("TextualParser") - .def("test", &textual_parser_t::test) - .def("parse", &textual_parser_t::parse, textual_parse_overloads()) - ; -} - -#endif // USE_BOOST_PYTHON diff --git a/timeclock b/timeclock deleted file mode 100755 index 496c3471..00000000 --- a/timeclock +++ /dev/null @@ -1,461 +0,0 @@ -#!/usr/bin/env python - -# timeclock, a time-keeping program based on the Ledger library -# -# Copyright (c) 2003-2004, New Artisans LLC. All rights reserved. -# -# This program is made available under the terms of the BSD Public -# License. See the LICENSE file included with the distribution for -# details and disclaimer. -# -# This program implements a simple timeclock, using the identical -# format as my timeclock.el module for Emacs (which is part of the -# Emacs 21 distribution). This allows you to use either this script -# or that module for creating time events. -# -# Usage is very simple: Set the environment variable TIMELOG to the -# path to your timelog file (if this variable is unset, any events -# created will simply be printed to stdout). Once this variable is -# set: -# -# timeclock in "project" what aspect of the project will I do today -# timeclock out what did I accomplish -# -# The description text is optional, but the project is required when -# clocking in. This project should be a account name, which means it -# can use ":" to separate the project from the task, for example: -# -# timeclock in Client:Meetings at the code review meeting -# -# To generate a balance report of time spent, use "timeclock" with no -# arguments, or "timeclock balance". The options available are the -# same as those used for ledger. - -import os -import sys -import string -import time - -true, false = 1, 0 - -from ledger import * - -home = os.getenv ("HOME") -config.init_file = home + "/.timeclockrc"; -config.cache_file = home + "/.timeclock-cache"; - -# Define some functions for reporting time quantities - -workday = 8 * 60 * 60 # length of a nominal workday - -def secstr (secs): - return "%d:%02d" % (abs (secs) / 60 / 60, (abs (secs) / 60) % 60) - -def daystr (amt): - dy = int (amt) / int (workday) - amt = amt - (dy * workday) - if dy >= 5: - wk = dy / 5 - dy = dy % 5 - if dy: amt = "%sw %sd %s" % (wk, dy, secstr (amt)) - else: amt = "%sw %s" % (wk, secstr (amt)) - else: - if dy: amt = "%sd %s" % (dy, secstr (amt)) - else: amt = secstr (amt) - return amt - -def adaystr (details): - result = "" - for amt in account_xdata(details.account).total: - if amt.commodity ().symbol == "s": - result = daystr (float (amt)) - break - return result - -config.amount_expr = "{1.00h}*(a/{3600.00h})" -config.total_expr = "{1.00h}*(O/{3600.00h})" -config.balance_format = "%20@adaystr() %8T %2_%-a\n"; - -# Help text specific to timeclock - -def show_version (arg): - print """Timeclock, a command-line timekeeping tool - -Copyright (c) 2003-2004, New Artisans LLC. All rights reserved. - -This program is made available under the terms of the BSD Public -License. See the LICENSE file included with the distribution for -details and disclaimer.""" - sys.exit (0) - -def option_help (arg): - print """usage: timeclock [options] COMMAND [ACCT REGEX]... - -Basic options: - -h, --help display this help text - -v, --version show version information - -i, --init FILE initialize ledger by loading FILE (def: ~/.ledgerrc) - --cache FILE use FILE as a binary cache when --file is not used - -f, --file FILE read ledger data from FILE - -o, --output FILE write output to FILE - -Report filtering: - -b, --begin DATE set report begin date - -e, --end DATE set report end date - -c, --current show only current and past entries (not future) - -C, --cleared consider only cleared transactions - -U, --uncleared consider only uncleared transactions - -R, --real consider only real (non-virtual) transactions - -Z, --actual consider only actual (non-automated) transactions - -r, --related calculate report using related transactions - -Output customization: - -F, --format STR use STR as the format; for each report type, use: - --balance-format --register-format - --plot-amount-format --plot-total-format - -y, --date-format STR use STR as the date format (def: %Y/%m/%d) - --wide for the default register report, use 132 columns - -E, --empty balance: show accounts with zero balance - -n, --collapse register: collapse entries with multiple transactions - -s, --subtotal balance: show sub-accounts; register: show subtotals - -S, --sort EXPR sort report according to the value expression EXPR - -p, --period STR report using the given period - --period-sort EXPR sort each report period's entries by EXPR - --dow show a days-of-the-week report - -W, --weekly show weekly sub-totals - -M, --monthly show monthly sub-totals - -Y, --yearly show yearly sub-totals - -l, --limit EXPR calculate only transactions matching EXPR - -d, --display EXPR display only transactions matching EXPR - -t, --amount EXPR use EXPR to calculate the displayed amount - -T, --total EXPR use EXPR to calculate the displayed total - -j, --amount-data print only raw amount data (useful for scripting) - -J, --total-data print only raw total data - -Commodity reporting: - -A, --average report average transaction amount - -D, --deviation report deviation from the average - -Commands: - balance [REGEXP]... show balance totals for matching accounts - register [REGEXP]... show register of matching events""" - sys.exit (0) - -# This call registers all of the default command-line options that -# Ledger supports into the option handling mechanism. Skip this call -# if you wish to do all of your own processing -- in which case simply -# modify the 'config' object however you like. - -add_config_option_handlers () - -add_option_handler ("help", "h", option_help) -add_option_handler ("version", "v", show_version) - -# Process the command-line arguments, test whether caching should be -# enabled, and then process any option settings from the execution -# environment. Some historical environment variable names are also -# supported. - -args = process_arguments (sys.argv[1:]) -config.use_cache = not config.data_file -process_environment (os.environ, "TIMECLOCK_") - -if os.environ.has_key ("TIMELOG"): - process_option ("file", os.getenv ("TIMELOG")) - -# The command word is in the first argument. Canonicalize it to a -# unique, simple form that the remaining code can use to find out -# which command was specified. - -if len (args) == 0: - args = ["balance"] - -command = args.pop (0); - -if command == "balance" or command == "bal" or command == "b": - command = "b" -elif command == "register" or command == "reg" or command == "r": - command = "r" -elif command == "entry": - command = "e" -elif command == "in" or command == "out": - if config.data_file: - log = open (config.data_file, "a") - else: - log = sys.stdout - - if command == "in": - if len (args) == 0: - print "A project name is required when clocking in." - sys.exit (1) - log.write ("i %s %s" % (time.strftime ("%Y/%m/%d %H:%M:%S"), - args.pop (0))) - if len (args) > 0: - log.write (" %s\n" % string.join (args, " ")) - else: - log.write ("o %s" % time.strftime ("%Y/%m/%d %H:%M:%S")) - if len (args) > 0: - log.write (" %s" % string.join (args, " ")) - - log.write ("\n") - log.close () - sys.exit (0) -else: - print "Unrecognized command:", command - sys.exit (1) - -# Create the main journal object, into which all entries will be -# recorded. Once done, the 'journal' may be iterated to yield those -# entries, in the same order as which they appeared in the journal -# file. - -journal = Journal () - -# This parser is intended only for timelog files. - -class Event: - def __init__(self, kind, when, desc): - self.kind = kind - self.when = when - self.desc = desc - -class Interval: - def __init__(self, begin, end): - self.begin = begin - self.end = end - - def length(self): - "Return the length of the interval in seconds." - return self.end.when - self.begin.when - -def parse_timelog(path, journal): - import re - if not os.path.exists (path): - print "Cannot read timelog file '%s'" % path - sys.exit (1) - file = open(path) - history = [] - begin = None - linenum = 0 - for line in file: - linenum += 1 - match = re.match("([iIoO])\s+([0-9/]+\s+[0-9:]+)\s*(.+)", line) - if match: - (kind, when, desc) = match.groups() - when = time.strptime(when, "%Y/%m/%d %H:%M:%S") - when = time.mktime(when) - event = Event(kind, when, desc) - if kind == "i" or kind == "I": - begin = event - else: - if begin.desc: - match = re.match ("(.+?) (.+)", begin.desc) - if match: - acct = match.group (1) - desc = match.group (2) - else: - acct = begin.desc - desc = "" - else: - acct = "Misc" - desc = event.desc - - l = Interval(begin, event).length () - e = Entry () - e.date = int (begin.when) - e.payee = desc - - x = Transaction (journal.find_account (acct), - Amount ("%ss" % l), TRANSACTION_VIRTUAL) - e.add_transaction (x) - - if not journal.add_entry (e): - print "%s, %d: Failed to entry" % (path, linenum) - sys.exit (1) - -parse_timelog (config.data_file, journal) - -# Now that everything has been correctly parsed (parse_ledger_data -# would have thrown an exception if not), we can take time to further -# process the configuration options. This changes the configuration a -# bit based on previous option settings, the command word, and the -# remaining arguments. - -if command == "b" and \ - config.amount_expr == "{1.00h}*(a/{3600.00h})": - config.amount_expr = "a" - -config.process_options (command, args); - -# Determine the format string to used, based on the command. - -if config.format_string: - format = config.format_string -elif command == "b": - format = config.balance_format -elif command == "r": - format = config.register_format -else: - format = config.print_format - -# The following two classes are responsible for outputing transactions -# and accounts to the user. There are corresponding C++ versions to -# these, but they rely on I/O streams, which Boost.Python does not -# provide a conversion layer for. - -class FormatTransactions (TransactionHandler): - last_entry = None - output = None - - def __init__ (self, fmt): - try: - i = string.index (fmt, '%/') - self.formatter = Format (fmt[: i]) - self.nformatter = Format (fmt[i + 2 :]) - except ValueError: - self.formatter = Format (fmt) - self.nformatter = None - - self.last_entry = None - - if config.output_file: - self.output = open (config.output_file, "w") - else: - self.output = sys.stdout - - TransactionHandler.__init__ (self) - - def __del__ (self): - if config.output_file: - self.output.close () - - def flush (self): - self.output.flush () - - def __call__ (self, xact): - if not transaction_has_xdata (xact) or \ - not transaction_xdata (xact).dflags & TRANSACTION_DISPLAYED: - if self.nformatter is not None and \ - self.last_entry is not None and \ - xact.entry == self.last_entry: - self.output.write (self.nformatter.format (xact)) - else: - self.output.write (self.formatter.format (xact)) - self.last_entry = xact.entry - transaction_xdata (xact).dflags |= TRANSACTION_DISPLAYED - -class FormatAccounts (AccountHandler): - output = None - - def __init__ (self, fmt, pred): - self.formatter = Format (fmt) - self.predicate = AccountPredicate (pred) - - if config.output_file: - self.output = open (config.output_file, "w") - else: - self.output = sys.stdout - - AccountHandler.__init__ (self) - - def __del__ (self): - if config.output_file: - self.output.close () - - def final (self, account): - if account_has_xdata (account): - xdata = account_xdata (account) - if xdata.dflags & ACCOUNT_TO_DISPLAY: - print "-------------------- ---------" - xdata.value = xdata.total - self.output.write (self.formatter.format (account)) - - def flush (self): - self.output.flush () - - def __call__ (self, account): - if display_account (account, self.predicate): - if not account.parent: - account_xdata (account).dflags |= ACCOUNT_TO_DISPLAY - else: - self.output.write (self.formatter.format (account)) - account_xdata (account).dflags |= ACCOUNT_DISPLAYED - -# Set the final transaction handler: for balances and equity reports, -# it will simply add the value of the transaction to the account's -# xdata, which is used a bit later to report those totals. For all -# other reports, the transaction data is sent to the configured output -# location (default is sys.stdout). - -if command == "b": - handler = SetAccountValue () -else: - handler = FormatTransactions (format) - -# Chain transaction filters on top of the base handler. Most of these -# filters customize the output for reporting. None of this is done -# for balance or equity reports, which don't need it. - -if command != "b": - if config.display_predicate: - handler = FilterTransactions (handler, config.display_predicate) - - handler = CalcTransactions (handler) - - if config.sort_string: - handler = SortTransactions (handler, config.sort_string) - - if config.show_revalued: - handler = ChangedValueTransactions (handler, config.show_revalued_only) - - if config.show_collapsed: - handler = CollapseTransactions (handler); - -if config.show_subtotal and not (command == "b" or command == "E"): - handler = SubtotalTransactions (handler) - -if config.days_of_the_week: - handler = DowTransactions (handler) -elif config.by_payee: - handler = ByPayeeTransactions (handler) - -if config.report_period: - handler = IntervalTransactions (handler, config.report_period, - config.report_period_sort) - handler = SortTransactions (handler, "d") - -# The next two transaction filters are used by all reports. - -if config.show_inverted: - handler = InvertTransactions (handler) - -if config.show_related: - handler = RelatedTransactions (handler, config.show_all_related) - -if config.predicate: - handler = FilterTransactions (handler, config.predicate) - -if config.comm_as_payee: - handler = SetCommAsPayee (handler) - -# Walk the journal's entries, and pass each entry's transaction to the -# handler chain established above. - -walk_entries (journal, handler) - -# Flush the handlers, causing them to output whatever data is still -# pending. - -handler.flush () - -# For the balance and equity reports, the account totals now need to -# be displayed. This is different from outputting transactions, in -# that we are now outputting account totals to display a summary of -# the transactions that were just walked. - -if command == "b": - acct_formatter = FormatAccounts (format, config.display_predicate) - sum_accounts (journal.master) - walk_accounts (journal.master, acct_formatter, config.sort_string) - acct_formatter.final (journal.master) - acct_formatter.flush () diff --git a/timeclock.el b/timeclock.el index 709ea25f..03159e94 100644 --- a/timeclock.el +++ b/timeclock.el @@ -284,10 +284,10 @@ display (non-nil means on)." (> (prefix-numeric-value arg) 0) (not timeclock-modeline-display)))) (if on-p - (progn - (or (memq 'timeclock-mode-string global-mode-string) - (setq global-mode-string - (append global-mode-string '(timeclock-mode-string)))) + (progn + (or (memq 'timeclock-mode-string global-mode-string) + (setq global-mode-string + (append global-mode-string '(timeclock-mode-string)))) (unless (memq 'timeclock-update-modeline timeclock-event-hook) (add-hook 'timeclock-event-hook 'timeclock-update-modeline)) (when timeclock-update-timer @@ -296,13 +296,13 @@ display (non-nil means on)." (if (boundp 'display-time-hook) (remove-hook 'display-time-hook 'timeclock-update-modeline)) (if timeclock-use-display-time - (progn - ;; Update immediately so there is a visible change - ;; on calling this function. - (if display-time-mode (timeclock-update-modeline) - (message "Activate `display-time-mode' to see \ + (progn + ;; Update immediately so there is a visible change + ;; on calling this function. + (if display-time-mode (timeclock-update-modeline) + (message "Activate `display-time-mode' to see \ timeclock information")) - (add-hook 'display-time-hook 'timeclock-update-modeline)) + (add-hook 'display-time-hook 'timeclock-update-modeline)) (setq timeclock-update-timer (run-at-time nil 60 'timeclock-update-modeline)))) (setq global-mode-string @@ -358,9 +358,9 @@ discover the name of the project." (timeclock-reread-log)) ;; Either no log file, or day has rolled over. (unless (and timeclock-last-event - (equal (timeclock-time-to-date - (cadr timeclock-last-event)) - (timeclock-time-to-date (current-time)))) + (equal (timeclock-time-to-date + (cadr timeclock-last-event)) + (timeclock-time-to-date (current-time)))) (let ((workday (or (and (numberp arg) arg) (and arg 0) (and timeclock-get-workday-function @@ -412,8 +412,8 @@ If TODAY-ONLY is non-nil, the value returned will be relative only to the time worked today, and not to past time." (let ((discrep (timeclock-find-discrep))) (if discrep - (- (if today-only (cadr discrep) - (car discrep))) + (- (if today-only (cadr discrep) + (car discrep))) 0.0))) ;;;###autoload @@ -424,8 +424,8 @@ If TODAY-ONLY is non-nil, the display will be relative only to time worked today, ignoring the time worked on previous days." (interactive "P") (let ((remainder (timeclock-workday-remaining)) ; today-only? - (last-in (equal (car timeclock-last-event) "i")) - status) + (last-in (equal (car timeclock-last-event) "i")) + status) (setq status (format "Currently %s since %s (%s), %s %s, leave at %s" (if last-in "IN" "OUT") @@ -619,7 +619,7 @@ The value of `timeclock-relative' affects the display as described in that variable's documentation." (interactive) (let ((remainder (timeclock-workday-remaining (not timeclock-relative))) - (last-in (equal (car timeclock-last-event) "i"))) + (last-in (equal (car timeclock-last-event) "i"))) (when (and (< remainder 0) (not (and timeclock-day-over (equal timeclock-day-over @@ -629,12 +629,12 @@ that variable's documentation." (timeclock-time-to-date (current-time))) (run-hooks 'timeclock-day-over-hook)) (setq timeclock-mode-string - (propertize - (format " %c%s%c " - (if last-in ?< ?[) - (timeclock-seconds-to-string remainder nil t) + (propertize + (format " %c%s%c " + (if last-in ?< ?[) + (timeclock-seconds-to-string remainder nil t) (if last-in ?> ?])) - 'help-echo "timeclock: time remaining")))) + 'help-echo "timeclock: time remaining")))) (put 'timeclock-mode-string 'risky-local-variable t) @@ -4,9 +4,6 @@ #include "datetime.h" #include "debug.h" #include "util.h" -#ifdef USE_BOOST_PYTHON -#include "py_eval.h" -#endif namespace ledger { @@ -325,16 +322,6 @@ void value_expr_t::compute(value_t& result, const details_t& details) const break; } - case F_INTERP_FUNC: { -#ifdef USE_BOOST_PYTHON - if (! python_call(constant_s, right, details, result)) - result = 0L; -#else - result = 0L; -#endif - break; - } - case O_NOT: left->compute(result, details); result.negate(); @@ -594,34 +581,6 @@ value_expr_t * parse_value_term(std::istream& in) break; } - case '@': { - READ_INTO(in, buf, 255, c, c != '('); - if (c != '(') - unexpected(c, '('); - - node.reset(new value_expr_t(value_expr_t::F_INTERP_FUNC)); - node->constant_s = buf; - - in.get(c); - if (peek_next_nonws(in) == ')') { - in.get(c); - } else { - node->right = new value_expr_t(value_expr_t::O_ARG); - value_expr_t * cur = node->right; - cur->left = parse_value_expr(in, true); - in.get(c); - while (! in.eof() && c == ',') { - cur->right = new value_expr_t(value_expr_t::O_ARG); - cur = cur->right; - cur->left = parse_value_expr(in, true); - in.get(c); - } - if (c != ')') - unexpected(c, ')'); - } - break; - } - case '(': node.reset(parse_value_expr(in, true)); in.get(c); @@ -935,12 +894,6 @@ void dump_value_expr(std::ostream& out, const value_expr_t * node) out << ')'; break; - case value_expr_t::F_INTERP_FUNC: - out << "F_INTERP[" << node->constant_s << "]("; - dump_value_expr(out, node->right); - out << ')'; - break; - case value_expr_t::O_NOT: out << '!'; dump_value_expr(out, node->left); @@ -1022,95 +975,6 @@ void dump_value_expr(std::ostream& out, const value_expr_t * node) } // namespace ledger -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -value_t py_compute_1(value_expr_t& value_expr, const details_t& item) -{ - value_t result; - value_expr.compute(result, item); - return result; -} - -template <typename T> -value_t py_compute(value_expr_t& value_expr, const T& item) -{ - value_t result; - value_expr.compute(result, details_t(item)); - return result; -} - -value_expr_t * py_parse_value_expr_1(const std::string& str) -{ - return parse_value_expr(str); -} - -value_expr_t * py_parse_value_expr_2(const std::string& str, const bool partial) -{ - return parse_value_expr(str, partial); -} - -#define EXC_TRANSLATOR(type) \ - void exc_translate_ ## type(const type& err) { \ - PyErr_SetString(PyExc_RuntimeError, err.what()); \ - } - -EXC_TRANSLATOR(value_expr_error) -EXC_TRANSLATOR(compute_error) -EXC_TRANSLATOR(mask_error) - -void export_valexpr() -{ - class_< details_t > ("Details", init<const entry_t&>()) - .def(init<const transaction_t&>()) - .def(init<const account_t&>()) - .add_property("entry", - make_getter(&details_t::entry, - return_value_policy<reference_existing_object>())) - .add_property("xact", - make_getter(&details_t::xact, - return_value_policy<reference_existing_object>())) - .add_property("account", - make_getter(&details_t::account, - return_value_policy<reference_existing_object>())) - ; - - class_< value_expr_t > ("ValueExpr", init<value_expr_t::kind_t>()) - .def("compute", py_compute_1) - .def("compute", py_compute<account_t>) - .def("compute", py_compute<entry_t>) - .def("compute", py_compute<transaction_t>) - ; - - def("parse_value_expr", py_parse_value_expr_1, - return_value_policy<manage_new_object>()); - def("parse_value_expr", py_parse_value_expr_2, - return_value_policy<manage_new_object>()); - - class_< item_predicate<transaction_t> > - ("TransactionPredicate", init<std::string>()) - .def("__call__", &item_predicate<transaction_t>::operator()) - ; - - class_< item_predicate<account_t> > - ("AccountPredicate", init<std::string>()) - .def("__call__", &item_predicate<account_t>::operator()) - ; - -#define EXC_TRANSLATE(type) \ - register_exception_translator<type>(&exc_translate_ ## type); - - EXC_TRANSLATE(value_expr_error); - EXC_TRANSLATE(compute_error); - EXC_TRANSLATE(mask_error); -} - -#endif // USE_BOOST_PYTHON - #ifdef TEST int main(int argc, char *argv[]) @@ -73,7 +73,6 @@ struct value_expr_t F_ACCOUNT_MASK, F_SHORT_ACCOUNT_MASK, F_COMMODITY_MASK, - F_INTERP_FUNC, // Binary operators O_ADD, @@ -790,273 +790,3 @@ value_t& value_t::add(const amount_t& amount, const amount_t * cost) } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -long balance_len(balance_t& bal); -amount_t balance_getitem(balance_t& bal, int i); -long balance_pair_len(balance_pair_t& bal_pair); -amount_t balance_pair_getitem(balance_pair_t& bal_pair, int i); - -long value_len(value_t& value) -{ - switch (value.type) { - case value_t::BOOLEAN: - case value_t::INTEGER: - case value_t::AMOUNT: - return 1; - - case value_t::BALANCE: - return balance_len(*((balance_t *) value.data)); - - case value_t::BALANCE_PAIR: - return balance_pair_len(*((balance_pair_t *) value.data)); - - default: - assert(0); - break; - } - assert(0); - return 0; -} - -amount_t value_getitem(value_t& value, int i) -{ - std::size_t len = value_len(value); - - if (abs(i) >= len) { - PyErr_SetString(PyExc_IndexError, "Index out of range"); - throw_error_already_set(); - } - - switch (value.type) { - case value_t::BOOLEAN: - case value_t::INTEGER: - return long(value); - - case value_t::AMOUNT: - return *((amount_t *) value.data); - - case value_t::BALANCE: - return balance_getitem(*((balance_t *) value.data), i); - - case value_t::BALANCE_PAIR: - return balance_pair_getitem(*((balance_pair_t *) value.data), i); - - default: - assert(0); - break; - } - assert(0); - return 0L; -} - -double py_to_float(value_t& value) -{ - return double(value); -} - -void export_value() -{ - scope in_value = class_< value_t > ("Value") - .def(init<value_t>()) - .def(init<balance_pair_t>()) - .def(init<balance_t>()) - .def(init<amount_t>()) - .def(init<std::string>()) - .def(init<double>()) - .def(init<long>()) - - .def(self + self) - .def(self + other<balance_pair_t>()) - .def(self + other<balance_t>()) - .def(self + other<amount_t>()) - .def(self + long()) - .def(self + double()) - - .def(other<balance_pair_t>() + self) - .def(other<balance_t>() + self) - .def(other<amount_t>() + self) - .def(long() + self) - .def(double() + self) - - .def(self - self) - .def(self - other<balance_pair_t>()) - .def(self - other<balance_t>()) - .def(self - other<amount_t>()) - .def(self - long()) - .def(self - double()) - - .def(other<balance_pair_t>() - self) - .def(other<balance_t>() - self) - .def(other<amount_t>() - self) - .def(long() - self) - .def(double() - self) - - .def(self * self) - .def(self * other<balance_pair_t>()) - .def(self * other<balance_t>()) - .def(self * other<amount_t>()) - .def(self * long()) - .def(self * double()) - - .def(other<balance_pair_t>() * self) - .def(other<balance_t>() * self) - .def(other<amount_t>() * self) - .def(long() * self) - .def(double() * self) - - .def(self / self) - .def(self / other<balance_pair_t>()) - .def(self / other<balance_t>()) - .def(self / other<amount_t>()) - .def(self / long()) - .def(self / double()) - - .def(other<balance_pair_t>() / self) - .def(other<balance_t>() / self) - .def(other<amount_t>() / self) - .def(long() / self) - .def(double() / self) - - .def(- self) - - .def(self += self) - .def(self += other<balance_pair_t>()) - .def(self += other<balance_t>()) - .def(self += other<amount_t>()) - .def(self += long()) - .def(self += double()) - - .def(self -= self) - .def(self -= other<balance_pair_t>()) - .def(self -= other<balance_t>()) - .def(self -= other<amount_t>()) - .def(self -= long()) - .def(self -= double()) - - .def(self *= self) - .def(self *= other<balance_pair_t>()) - .def(self *= other<balance_t>()) - .def(self *= other<amount_t>()) - .def(self *= long()) - .def(self *= double()) - - .def(self /= self) - .def(self /= other<balance_pair_t>()) - .def(self /= other<balance_t>()) - .def(self /= other<amount_t>()) - .def(self /= long()) - .def(self /= double()) - - .def(self < self) - .def(self < other<balance_pair_t>()) - .def(self < other<balance_t>()) - .def(self < other<amount_t>()) - .def(self < long()) - .def(self < double()) - - .def(other<balance_pair_t>() < self) - .def(other<balance_t>() < self) - .def(other<amount_t>() < self) - .def(long() < self) - .def(double() < self) - - .def(self <= self) - .def(self <= other<balance_pair_t>()) - .def(self <= other<balance_t>()) - .def(self <= other<amount_t>()) - .def(self <= long()) - .def(self <= double()) - - .def(other<balance_pair_t>() <= self) - .def(other<balance_t>() <= self) - .def(other<amount_t>() <= self) - .def(long() <= self) - .def(double() <= self) - - .def(self > self) - .def(self > other<balance_pair_t>()) - .def(self > other<balance_t>()) - .def(self > other<amount_t>()) - .def(self > long()) - .def(self > double()) - - .def(other<balance_pair_t>() > self) - .def(other<balance_t>() > self) - .def(other<amount_t>() > self) - .def(long() > self) - .def(double() > self) - - .def(self >= self) - .def(self >= other<balance_pair_t>()) - .def(self >= other<balance_t>()) - .def(self >= other<amount_t>()) - .def(self >= long()) - .def(self >= double()) - - .def(other<balance_pair_t>() >= self) - .def(other<balance_t>() >= self) - .def(other<amount_t>() >= self) - .def(long() >= self) - .def(double() >= self) - - .def(self == self) - .def(self == other<balance_pair_t>()) - .def(self == other<balance_t>()) - .def(self == other<amount_t>()) - .def(self == long()) - .def(self == double()) - - .def(other<balance_pair_t>() == self) - .def(other<balance_t>() == self) - .def(other<amount_t>() == self) - .def(long() == self) - .def(double() == self) - - .def(self != self) - .def(self != other<balance_pair_t>()) - .def(self != other<balance_t>()) - .def(self != other<amount_t>()) - .def(self != long()) - .def(self != double()) - - .def(other<balance_pair_t>() != self) - .def(other<balance_t>() != self) - .def(other<amount_t>() != self) - .def(long() != self) - .def(double() != self) - - .def(! self) - - .def(self_ns::int_(self)) - .def(self_ns::float_(self)) - .def(self_ns::str(self)) - .def(abs(self)) - - .def_readonly("type", &value_t::type) - - .def("__len__", value_len) - .def("__getitem__", value_getitem) - - .def("cast", &value_t::cast) - .def("negate", &value_t::negate) - .def("cost", &value_t::cost) - .def("add", &value_t::add, return_internal_reference<1>()) - ; - - enum_< value_t::type_t > ("ValueType") - .value("BOOLEAN", value_t::BOOLEAN) - .value("INTEGER", value_t::INTEGER) - .value("AMOUNT", value_t::AMOUNT) - .value("BALANCE", value_t::BALANCE) - .value("BALANCE_PAIR", value_t::BALANCE_PAIR) - ; -} - -#endif // USE_BOOST_PYTHON @@ -843,308 +843,3 @@ void walk_commodities(commodities_map& commodities, } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -template <typename T> -struct item_handler_wrap : public item_handler<T> -{ - PyObject * self; - - item_handler_wrap(PyObject * self_) : self(self_) {} - item_handler_wrap(PyObject * self_, const item_handler<T>& _handler) - : item_handler<T>(const_cast<item_handler<T> *>(&_handler)), - self(self_) {} - item_handler_wrap(PyObject * self_, item_handler<T> * _handler) - : item_handler<T>(_handler), self(self_) {} - - virtual void flush() { - call_method<void>(self, "flush"); - } - void default_flush() { - item_handler<T>::flush(); - } - - virtual void operator()(T& item) { - call_method<void>(self, "__call__", ptr(&item)); - } - void default_call(T& item) { - item_handler<T>::operator()(item); - } -}; - -void (subtotal_transactions::*subtotal_transactions_flush)() = - &subtotal_transactions::flush; - -void py_walk_entries(journal_t& journal, - item_handler<transaction_t>& handler) { - walk_entries(journal.entries, handler); -} - -void py_walk_transactions(entry_t& entry, - item_handler<transaction_t>& handler) { - walk_transactions(entry.transactions, handler); -} - -void py_walk_accounts_1(account_t& account, - item_handler<account_t>& handler) { - walk_accounts(account, handler); -} - -void py_walk_accounts_2(account_t& account, - item_handler<account_t>& handler, - const value_expr_t * sort_order) { - walk_accounts(account, handler, sort_order); -} - -void py_walk_accounts_3(account_t& account, - item_handler<account_t>& handler, - const std::string& sort_string) { - walk_accounts(account, handler, sort_string); -} - -void py_walk_commodities(item_handler<transaction_t>& handler) { - walk_commodities(commodity_t::commodities, handler); -} - -void py_add_period_entries(generate_transactions& handler, - journal_t * journal) { - handler.add_period_entries(journal->period_entries); -} - -void export_walk() -{ - typedef item_handler<transaction_t> xact_handler_t; - - scope().attr("TRANSACTION_RECEIVED") = TRANSACTION_RECEIVED; - scope().attr("TRANSACTION_HANDLED") = TRANSACTION_HANDLED; - scope().attr("TRANSACTION_TO_DISPLAY") = TRANSACTION_TO_DISPLAY; - scope().attr("TRANSACTION_DISPLAYED") = TRANSACTION_DISPLAYED; - scope().attr("TRANSACTION_NO_TOTAL") = TRANSACTION_NO_TOTAL; - scope().attr("TRANSACTION_SORT_CALC") = TRANSACTION_SORT_CALC; - scope().attr("TRANSACTION_COMPOSITE") = TRANSACTION_COMPOSITE; - scope().attr("TRANSACTION_MATCHES") = TRANSACTION_MATCHES; - - class_< transaction_xdata_t > ("TransactionXData") - .def_readwrite("total", &transaction_xdata_t::total) - .def_readwrite("sort_value", &transaction_xdata_t::sort_value) - .def_readwrite("composite_amount", &transaction_xdata_t::composite_amount) - .def_readwrite("index", &transaction_xdata_t::index) - .def_readwrite("dflags", &transaction_xdata_t::dflags) - ; - - def("transaction_has_xdata", transaction_has_xdata); - def("transaction_xdata", transaction_xdata, return_internal_reference<1>()); - def("add_transaction_to", add_transaction_to); - - class_< xact_handler_t, item_handler_wrap<transaction_t> > - ("TransactionHandler") - .def(init<xact_handler_t *>()[with_custodian_and_ward<1, 2>()]) - - .def("flush", &xact_handler_t::flush, - &item_handler_wrap<transaction_t>::default_flush) - .def("__call__", &xact_handler_t::operator(), - &item_handler_wrap<transaction_t>::default_call) - ; - - class_< ignore_transactions, bases<xact_handler_t> > - ("IgnoreTransactions") - .def("flush", &xact_handler_t::flush) - .def("__call__", &ignore_transactions::operator()); - ; - - class_< clear_transaction_xdata, bases<xact_handler_t> > - ("ClearTransactionXData") - .def("flush", &xact_handler_t::flush) - .def("__call__", &clear_transaction_xdata::operator()); - ; - - class_< truncate_entries, bases<xact_handler_t> > - ("TruncateEntries", init<xact_handler_t *, int, int>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &truncate_entries::flush) - .def("__call__", &truncate_entries::operator()); - ; - - class_< set_account_value, bases<xact_handler_t> > ("SetAccountValue") - .def(init<xact_handler_t *>()[with_custodian_and_ward<1, 2>()]) - .def("flush", &xact_handler_t::flush) - .def("__call__", &set_account_value::operator()); - ; - - class_< sort_transactions, bases<xact_handler_t> > - ("SortTransactions", init<xact_handler_t *, const value_expr_t *>() - [with_custodian_and_ward<1, 2>()]) - .def(init<xact_handler_t *, const std::string&>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &sort_transactions::flush) - .def("__call__", &sort_transactions::operator()); - ; - - class_< filter_transactions, bases<xact_handler_t> > - ("FilterTransactions", init<xact_handler_t *, std::string>() - [with_custodian_and_ward<1, 2>()]) - .def(init<xact_handler_t *, const std::string&>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &xact_handler_t::flush) - .def("__call__", &filter_transactions::operator()); - ; - - class_< calc_transactions, bases<xact_handler_t> > - ("CalcTransactions", init<xact_handler_t *>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &xact_handler_t::flush) - .def("__call__", &calc_transactions::operator()); - ; - - class_< invert_transactions, bases<xact_handler_t> > - ("InvertTransactions", init<xact_handler_t *>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &xact_handler_t::flush) - .def("__call__", &invert_transactions::operator()); - ; - - class_< collapse_transactions, bases<xact_handler_t> > - ("CollapseTransactions", init<xact_handler_t *>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &collapse_transactions::flush) - .def("__call__", &collapse_transactions::operator()); - ; - - class_< related_transactions, bases<xact_handler_t> > - ("RelatedTransactions", init<xact_handler_t *, optional<bool> >() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &xact_handler_t::flush) - .def("__call__", &related_transactions::operator()); - ; - - class_< changed_value_transactions, bases<xact_handler_t> > - ("ChangeValueTransactions", init<xact_handler_t *, bool>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &changed_value_transactions::flush) - .def("__call__", &changed_value_transactions::operator()); - ; - - class_< subtotal_transactions, bases<xact_handler_t> > - ("SubtotalTransactions", init<xact_handler_t *>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", subtotal_transactions_flush) - .def("__call__", &subtotal_transactions::operator()); - ; - - class_< interval_transactions, bases<xact_handler_t> > - ("IntervalTransactions", - init<xact_handler_t *, interval_t, optional<value_expr_t *> >() - [with_custodian_and_ward<1, 2>()]) - .def(init<xact_handler_t *, const std::string&, - optional<const std::string&> >() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &xact_handler_t::flush) - .def("__call__", &interval_transactions::operator()); - ; - - class_< by_payee_transactions, bases<xact_handler_t> > - ("ByPayeeTransactions", init<xact_handler_t *>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &by_payee_transactions::flush) - .def("__call__", &by_payee_transactions::operator()); - ; - - class_< set_comm_as_payee, bases<xact_handler_t> > - ("SetCommAsPayee", init<xact_handler_t *>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &xact_handler_t::flush) - .def("__call__", &xact_handler_t::operator()); - ; - - class_< dow_transactions, bases<xact_handler_t> > - ("DowTransactions", init<xact_handler_t *>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &dow_transactions::flush) - .def("__call__", &dow_transactions::operator()); - ; - - scope().attr("BUDGET_BUDGETED") = BUDGET_BUDGETED; - scope().attr("BUDGET_UNBUDGETED") = BUDGET_UNBUDGETED; - - class_< generate_transactions, bases<xact_handler_t> > - ("GenerateTransactions", init<xact_handler_t *>() - [with_custodian_and_ward<1, 2>()]) - .def("add_transaction", &generate_transactions::add_transaction) - .def("add_period_entries", py_add_period_entries) - .def("flush", &xact_handler_t::flush) - .def("__call__", &xact_handler_t::operator()); - ; - - class_< budget_transactions, bases<generate_transactions> > - ("BudgetTransactions", - init<xact_handler_t *, unsigned long>() - [with_custodian_and_ward<1, 2>()]) - .def("add_transaction", &generate_transactions::add_transaction) - .def("add_period_entries", py_add_period_entries) - .def("flush", &budget_transactions::flush) - .def("__call__", &xact_handler_t::operator()); - ; - - class_< forecast_transactions, bases<generate_transactions> > - ("ForecastTransactions", - init<xact_handler_t *, std::string>() - [with_custodian_and_ward<1, 2>()]) - .def("add_transaction", &forecast_transactions::add_transaction) - .def("add_period_entries", py_add_period_entries) - .def("flush", &forecast_transactions::flush) - .def("__call__", &xact_handler_t::operator()); - ; - - def("walk_entries", py_walk_entries); - def("walk_transactions", py_walk_transactions); - - typedef item_handler<account_t> account_handler_t; - - scope().attr("ACCOUNT_TO_DISPLAY") = ACCOUNT_TO_DISPLAY; - scope().attr("ACCOUNT_DISPLAYED") = ACCOUNT_DISPLAYED; - scope().attr("ACCOUNT_SORT_CALC") = ACCOUNT_SORT_CALC; - - class_< account_xdata_t > ("AccountXData") - .def_readwrite("value", &account_xdata_t::value) - .def_readwrite("total", &account_xdata_t::total) - .def_readwrite("sort_value", &account_xdata_t::sort_value) - .def_readwrite("count", &account_xdata_t::count) - .def_readwrite("total_count", &account_xdata_t::total_count) - .def_readwrite("virtuals", &account_xdata_t::virtuals) - .def_readwrite("dflags", &account_xdata_t::dflags) - ; - - def("account_has_xdata", account_has_xdata); - def("account_xdata", account_xdata, return_internal_reference<1>()); - - class_< account_handler_t, item_handler_wrap<account_t> > - ("AccountHandler") - .def(init<account_handler_t *>()[with_custodian_and_ward<1, 2>()]) - - .def("flush", &account_handler_t::flush, - &item_handler_wrap<account_t>::default_flush) - .def("__call__", &account_handler_t::operator(), - &item_handler_wrap<account_t>::default_call) - ; - - class_< clear_account_xdata, bases<account_handler_t> > - ("ClearAccountXData") - .def("flush", &account_handler_t::flush) - .def("__call__", &clear_account_xdata::operator()); - ; - - def("sum_accounts", sum_accounts); - def("walk_accounts", py_walk_accounts_1); - def("walk_accounts", py_walk_accounts_2); - def("walk_accounts", py_walk_accounts_3); - - def("walk_commodities", py_walk_commodities); -} - -#endif // USE_BOOST_PYTHON @@ -442,33 +442,3 @@ void format_xml_entries::format_last_entry() } } // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(xml_parse_overloads, - xml_parser_t::parse, 2, 4) - -void export_xml() { - class_< xml_parser_t, bases<parser_t> > ("XmlParser") - .def("test", &xml_parser_t::test) - .def("parse", &xml_parser_t::parse, xml_parse_overloads()) - ; - - typedef - pystream_handler_wrap<format_xml_entries, transaction_t, bool> - format_xml_entries_wrap; - - class_< format_xml_entries_wrap, bases<item_handler<transaction_t> > > - ("FormatXmlEntries", - init<PyObject *, bool>()[with_custodian_and_ward<1, 2>()]) - .def("flush", &format_xml_entries_wrap::flush) - .def("__call__", &format_xml_entries_wrap::operator()) - ; -} - -#endif // USE_BOOST_PYTHON |