summaryrefslogtreecommitdiff
path: root/src/pyinterp.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2009-11-05 17:16:59 -0500
committerJohn Wiegley <johnw@newartisans.com>2009-11-05 17:16:59 -0500
commit1bdb9330e56e49ecd660f3aafdc2d349a20e3044 (patch)
treef352e064a65bc7f3a87a634b1fcc689bb2441305 /src/pyinterp.cc
parent312d4c5f5339c61253e86cd9ce825370eb4be053 (diff)
downloadfork-ledger-1bdb9330e56e49ecd660f3aafdc2d349a20e3044.tar.gz
fork-ledger-1bdb9330e56e49ecd660f3aafdc2d349a20e3044.tar.bz2
fork-ledger-1bdb9330e56e49ecd660f3aafdc2d349a20e3044.zip
Simplified passing of scope objects in Python
Diffstat (limited to 'src/pyinterp.cc')
-rw-r--r--src/pyinterp.cc103
1 files changed, 63 insertions, 40 deletions
diff --git a/src/pyinterp.cc b/src/pyinterp.cc
index 8c79e9c7..3c86ed4b 100644
--- a/src/pyinterp.cc
+++ b/src/pyinterp.cc
@@ -32,6 +32,9 @@
#include <system.hh>
#include "pyinterp.h"
+#include "account.h"
+#include "xact.h"
+#include "post.h"
namespace ledger {
@@ -46,12 +49,10 @@ void export_amount();
void export_balance();
void export_commodity();
void export_expr();
-void export_flags();
void export_format();
void export_item();
void export_journal();
void export_post();
-void export_scope();
void export_times();
void export_utils();
void export_value();
@@ -64,22 +65,14 @@ void initialize_for_python()
export_balance();
export_commodity();
export_expr();
- export_flags();
export_format();
export_item();
export_journal();
export_post();
- export_scope();
export_times();
export_utils();
export_value();
export_xact();
-
-#if 0
- // jww (2009-11-04): This is not valid unless I export the session object.
- // But I think Python scripters will interace with a journal instead.
- scope().attr("current_session") = python_session;
-#endif
}
struct python_run
@@ -323,11 +316,39 @@ expr_t::ptr_op_t python_interpreter_t::lookup(const symbol_t::kind_t kind,
return NULL;
}
+
+namespace {
+ void append_value(list& lst, const value_t& value)
+ {
+ if (value.is_scope()) {
+ const scope_t * scope = value.as_scope();
+ if (const post_t * post = dynamic_cast<const post_t *>(scope))
+ lst.append(ptr(post));
+ else if (const xact_t * xact = dynamic_cast<const xact_t *>(scope))
+ lst.append(ptr(xact));
+ else if (const account_t * account =
+ dynamic_cast<const account_t *>(scope))
+ lst.append(ptr(account));
+ else if (const period_xact_t * period_xact =
+ dynamic_cast<const period_xact_t *>(scope))
+ lst.append(ptr(period_xact));
+ else if (const auto_xact_t * auto_xact =
+ dynamic_cast<const auto_xact_t *>(scope))
+ lst.append(ptr(auto_xact));
+ else
+ throw_(std::runtime_error,
+ _("Cannot downcast scoped object to specific type"));
+ } else {
+ lst.append(value);
+ }
+ }
+}
value_t python_interpreter_t::functor_t::operator()(call_scope_t& args)
{
try {
std::signal(SIGINT, SIG_DFL);
+
if (! PyCallable_Check(func.ptr())) {
extract<value_t> val(func);
std::signal(SIGINT, sigint_handler);
@@ -341,40 +362,42 @@ value_t python_interpreter_t::functor_t::operator()(call_scope_t& args)
throw_(calc_error,
_("Could not evaluate Python variable '%1'") << name);
#endif
- } else {
- if (args.size() > 0) {
- list arglist;
- if (args.value().is_sequence())
- foreach (const value_t& value, args.value().as_sequence())
- arglist.append(value);
- else
- arglist.append(args.value());
-
- if (PyObject * val =
- PyObject_CallObject(func.ptr(), python::tuple(arglist).ptr())) {
- extract<value_t> xval(val);
- value_t result;
- if (xval.check()) {
- result = xval();
- Py_DECREF(val);
- } else {
- Py_DECREF(val);
- throw_(calc_error,
- _("Could not evaluate Python variable '%1'") << name);
- }
- std::signal(SIGINT, sigint_handler);
- return result;
- }
- else if (PyErr_Occurred()) {
- PyErr_Print();
- throw_(calc_error, _("Failed call to Python function '%1'") << name);
+ }
+ else if (args.size() > 0) {
+ list arglist;
+ // jww (2009-11-05): What about a single argument which is a sequence,
+ // rather than a sequence of arguments?
+ if (args.value().is_sequence())
+ foreach (const value_t& value, args.value().as_sequence())
+ append_value(arglist, value);
+ else
+ append_value(arglist, args.value());
+
+ if (PyObject * val =
+ PyObject_CallObject(func.ptr(), python::tuple(arglist).ptr())) {
+ extract<value_t> xval(val);
+ value_t result;
+ if (xval.check()) {
+ result = xval();
+ Py_DECREF(val);
} else {
- assert(false);
+ Py_DECREF(val);
+ throw_(calc_error,
+ _("Could not evaluate Python variable '%1'") << name);
}
- } else {
std::signal(SIGINT, sigint_handler);
- return call<value_t>(func.ptr());
+ return result;
}
+ else if (PyErr_Occurred()) {
+ PyErr_Print();
+ throw_(calc_error, _("Failed call to Python function '%1'") << name);
+ } else {
+ assert(false);
+ }
+ }
+ else {
+ std::signal(SIGINT, sigint_handler);
+ return call<value_t>(func.ptr());
}
}
catch (const error_already_set&) {