Merge branch 'next'

This commit is contained in:
John Wiegley 2009-11-06 15:35:16 -05:00
commit f03d386013
41 changed files with 287 additions and 377 deletions

View file

@ -480,6 +480,13 @@ public:
optional<amount_t> optional<amount_t>
commodity_amount(const optional<const commodity_t&>& commodity = none) const; commodity_amount(const optional<const commodity_t&>& commodity = none) const;
balance_t number() const {
balance_t temp;
foreach (const amounts_map::value_type& pair, amounts)
temp += pair.second.number();
return temp;
}
/** /**
* Annotated commodity methods. The amounts contained by a balance * Annotated commodity methods. The amounts contained by a balance
* may use annotated commodities. The `strip_annotations' method * may use annotated commodities. The `strip_annotations' method

View file

@ -159,15 +159,15 @@ post_handler_ptr chain_post_handlers(report_t& report,
handler.reset(new sort_posts(handler, "date")); handler.reset(new sort_posts(handler, "date"));
} }
if (report.HANDLED(set_reported_account_)) if (report.HANDLED(account_))
handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT, handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
report.session.journal->master, report.session.journal->master,
report.HANDLER(set_reported_account_).str(), report.HANDLER(account_).str(),
report)); report));
else if (report.HANDLED(set_reported_payee_)) if (report.HANDLED(payee_))
handler.reset(new transfer_details(handler, transfer_details::SET_PAYEE, handler.reset(new transfer_details(handler, transfer_details::SET_PAYEE,
report.session.journal->master, report.session.journal->master,
report.HANDLER(set_reported_payee_).str(), report.HANDLER(payee_).str(),
report)); report));
// related_posts will pass along all posts related to the post received. If // related_posts will pass along all posts related to the post received. If
@ -236,37 +236,6 @@ post_handler_ptr chain_post_handlers(report_t& report,
report)); report));
} }
if (report.HANDLED(set_account_))
handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
report.session.journal->master,
report.HANDLER(set_account_).str(),
report));
else if (report.HANDLED(set_payee_))
handler.reset(new transfer_details(handler, transfer_details::SET_PAYEE,
report.session.journal->master,
report.HANDLER(set_payee_).str(),
report));
else if (report.HANDLED(comm_as_payee))
handler.reset(new transfer_details(handler, transfer_details::SET_PAYEE,
report.session.journal->master,
expr_t("commodity"), report));
else if (report.HANDLED(code_as_payee))
handler.reset(new transfer_details(handler, transfer_details::SET_PAYEE,
report.session.journal->master,
expr_t("code"), report));
else if (report.HANDLED(payee_as_account))
handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
report.session.journal->master,
expr_t("payee"), report));
else if (report.HANDLED(comm_as_account))
handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
report.session.journal->master,
expr_t("commodity"), report));
else if (report.HANDLED(code_as_account))
handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
report.session.journal->master,
expr_t("code"), report));
return handler; return handler;
} }

View file

@ -711,6 +711,7 @@ void transfer_details::operator()(post_t& post)
case SET_PAYEE: case SET_PAYEE:
xact.payee = expr.calc(bound_scope).to_string(); xact.payee = expr.calc(bound_scope).to_string();
break; break;
case SET_ACCOUNT: { case SET_ACCOUNT: {
std::list<string> account_names; std::list<string> account_names;
temp.account->remove_post(&temp); temp.account->remove_post(&temp);
@ -720,6 +721,7 @@ void transfer_details::operator()(post_t& post)
temp.account->add_post(&temp); temp.account->add_post(&temp);
break; break;
} }
default: default:
assert(false); assert(false);
break; break;

View file

@ -255,7 +255,7 @@ int global_scope_t::execute_command_wrapper(strings_list args, bool at_repl)
void global_scope_t::report_options(report_t& report, std::ostream& out) void global_scope_t::report_options(report_t& report, std::ostream& out)
{ {
out << "<=============================================================================>" out << "==============================================================================="
<< std::endl; << std::endl;
out << "[Global scope options]" << std::endl; out << "[Global scope options]" << std::endl;
@ -272,7 +272,7 @@ void global_scope_t::report_options(report_t& report, std::ostream& out)
out << std::endl << "[Report scope options]" << std::endl; out << std::endl << "[Report scope options]" << std::endl;
report.report_options(out); report.report_options(out);
out << "<=============================================================================>" out << "==============================================================================="
<< std::endl; << std::endl;
} }

View file

@ -201,7 +201,8 @@ std::size_t journal_t::read(const path& pathname,
ifstream stream(filename); ifstream stream(filename);
std::size_t count = read(stream, filename, master, scope); std::size_t count = read(stream, filename, master, scope);
sources.push_back(fileinfo_t(filename)); if (count > 0)
sources.push_back(fileinfo_t(filename));
return count; return count;
} }

View file

@ -147,16 +147,16 @@ query_lexer_t::token_t query_lexer_t::next_token()
return token_t(token_t::TOK_OR); return token_t(token_t::TOK_OR);
else if (ident == "not") else if (ident == "not")
return token_t(token_t::TOK_NOT); return token_t(token_t::TOK_NOT);
else if (ident == "account") else if (ident == "code")
return token_t(token_t::TOK_ACCOUNT); return token_t(token_t::TOK_CODE);
else if (ident == "desc") else if (ident == "desc")
return token_t(token_t::TOK_PAYEE); return token_t(token_t::TOK_PAYEE);
else if (ident == "payee") else if (ident == "payee")
return token_t(token_t::TOK_PAYEE); return token_t(token_t::TOK_PAYEE);
else if (ident == "code")
return token_t(token_t::TOK_CODE);
else if (ident == "note") else if (ident == "note")
return token_t(token_t::TOK_NOTE); return token_t(token_t::TOK_NOTE);
else if (ident == "account")
return token_t(token_t::TOK_ACCOUNT);
else if (ident == "tag") else if (ident == "tag")
return token_t(token_t::TOK_META); return token_t(token_t::TOK_META);
else if (ident == "meta") else if (ident == "meta")
@ -169,9 +169,16 @@ query_lexer_t::token_t query_lexer_t::next_token()
DEBUG("pred.show", "string = " << (*begin).as_string()); DEBUG("pred.show", "string = " << (*begin).as_string());
return token_t(token_t::END_REACHED); return token_t(token_t::END_REACHED);
} }
#if 0
// jww (2009-11-06): This is disabled for the time being.
else if (ident == "date") {
// The date keyword takes the whole of the next string as its argument.
consume_whitespace = true;
return token_t(token_t::TOK_DATE);
}
#endif
else if (ident == "expr") { else if (ident == "expr") {
// The expr keyword takes the whole of the next string as its // The expr keyword takes the whole of the next string as its argument.
// argument.
consume_whitespace = true; consume_whitespace = true;
return token_t(token_t::TOK_EXPR); return token_t(token_t::TOK_EXPR);
} }
@ -227,10 +234,11 @@ query_parser_t::parse_query_term(query_lexer_t::token_t::kind_t tok_context)
case query_lexer_t::token_t::END_REACHED: case query_lexer_t::token_t::END_REACHED:
break; break;
case query_lexer_t::token_t::TOK_ACCOUNT: case query_lexer_t::token_t::TOK_DATE:
case query_lexer_t::token_t::TOK_PAYEE:
case query_lexer_t::token_t::TOK_CODE: case query_lexer_t::token_t::TOK_CODE:
case query_lexer_t::token_t::TOK_PAYEE:
case query_lexer_t::token_t::TOK_NOTE: case query_lexer_t::token_t::TOK_NOTE:
case query_lexer_t::token_t::TOK_ACCOUNT:
case query_lexer_t::token_t::TOK_META: case query_lexer_t::token_t::TOK_META:
case query_lexer_t::token_t::TOK_EXPR: case query_lexer_t::token_t::TOK_EXPR:
node = parse_query_term(tok.kind); node = parse_query_term(tok.kind);
@ -241,16 +249,54 @@ query_parser_t::parse_query_term(query_lexer_t::token_t::kind_t tok_context)
case query_lexer_t::token_t::TERM: case query_lexer_t::token_t::TERM:
assert(tok.value); assert(tok.value);
if (tok_context == query_lexer_t::token_t::TOK_META) { switch (tok_context) {
case query_lexer_t::token_t::TOK_DATE: {
expr_t::ptr_op_t ident = new expr_t::op_t(expr_t::op_t::IDENT);
ident->set_ident("date");
date_interval_t interval(*tok.value);
if (interval.start) {
node = new expr_t::op_t(expr_t::op_t::O_GTE);
node->set_left(ident);
expr_t::ptr_op_t arg1 = new expr_t::op_t(expr_t::op_t::VALUE);
arg1->set_value(*interval.start);
node->set_right(arg1);
}
if (interval.end) {
expr_t::ptr_op_t lt = new expr_t::op_t(expr_t::op_t::O_LT);
lt->set_left(ident);
expr_t::ptr_op_t arg1 = new expr_t::op_t(expr_t::op_t::VALUE);
arg1->set_value(*interval.end);
lt->set_right(arg1);
if (node) {
expr_t::ptr_op_t prev(node);
node = new expr_t::op_t(expr_t::op_t::O_AND);
node->set_left(prev);
node->set_right(lt);
} else {
node = lt;
}
}
break;
}
case query_lexer_t::token_t::TOK_EXPR:
node = expr_t(*tok.value).get_op();
break;
case query_lexer_t::token_t::TOK_META: {
node = new expr_t::op_t(expr_t::op_t::O_CALL); node = new expr_t::op_t(expr_t::op_t::O_CALL);
expr_t::ptr_op_t ident; expr_t::ptr_op_t ident = new expr_t::op_t(expr_t::op_t::IDENT);
ident = new expr_t::op_t(expr_t::op_t::IDENT);
ident->set_ident("has_tag"); ident->set_ident("has_tag");
node->set_left(ident); node->set_left(ident);
expr_t::ptr_op_t arg1; expr_t::ptr_op_t arg1 = new expr_t::op_t(expr_t::op_t::VALUE);
arg1 = new expr_t::op_t(expr_t::op_t::VALUE);
arg1->set_value(mask_t(*tok.value)); arg1->set_value(mask_t(*tok.value));
tok = lexer.peek_token(); tok = lexer.peek_token();
@ -261,11 +307,9 @@ query_parser_t::parse_query_term(query_lexer_t::token_t::kind_t tok_context)
throw_(parse_error, throw_(parse_error,
_("Metadata equality operator not followed by term")); _("Metadata equality operator not followed by term"));
expr_t::ptr_op_t cons; expr_t::ptr_op_t cons = new expr_t::op_t(expr_t::op_t::O_CONS);
cons = new expr_t::op_t(expr_t::op_t::O_CONS);
expr_t::ptr_op_t arg2; expr_t::ptr_op_t arg2 = new expr_t::op_t(expr_t::op_t::VALUE);
arg2 = new expr_t::op_t(expr_t::op_t::VALUE);
assert(tok.value); assert(tok.value);
arg2->set_value(mask_t(*tok.value)); arg2->set_value(mask_t(*tok.value));
@ -275,11 +319,13 @@ query_parser_t::parse_query_term(query_lexer_t::token_t::kind_t tok_context)
} else { } else {
node->set_right(arg1); node->set_right(arg1);
} }
} else { break;
}
default: {
node = new expr_t::op_t(expr_t::op_t::O_MATCH); node = new expr_t::op_t(expr_t::op_t::O_MATCH);
expr_t::ptr_op_t ident; expr_t::ptr_op_t ident = new expr_t::op_t(expr_t::op_t::IDENT);
ident = new expr_t::op_t(expr_t::op_t::IDENT);
switch (tok_context) { switch (tok_context) {
case query_lexer_t::token_t::TOK_ACCOUNT: case query_lexer_t::token_t::TOK_ACCOUNT:
ident->set_ident("account"); break; ident->set_ident("account"); break;
@ -293,13 +339,13 @@ query_parser_t::parse_query_term(query_lexer_t::token_t::kind_t tok_context)
assert(0); break; assert(0); break;
} }
expr_t::ptr_op_t mask; expr_t::ptr_op_t mask = new expr_t::op_t(expr_t::op_t::VALUE);
mask = new expr_t::op_t(expr_t::op_t::VALUE);
mask->set_value(mask_t(*tok.value)); mask->set_value(mask_t(*tok.value));
node->set_left(ident); node->set_left(ident);
node->set_right(mask); node->set_right(mask);
} }
}
break; break;
case query_lexer_t::token_t::LPAREN: case query_lexer_t::token_t::LPAREN:

View file

@ -135,10 +135,11 @@ public:
TOK_OR, TOK_OR,
TOK_EQ, TOK_EQ,
TOK_ACCOUNT, TOK_DATE,
TOK_PAYEE,
TOK_CODE, TOK_CODE,
TOK_PAYEE,
TOK_NOTE, TOK_NOTE,
TOK_ACCOUNT,
TOK_META, TOK_META,
TOK_EXPR, TOK_EXPR,
@ -184,10 +185,11 @@ public:
case TOK_AND: return "TOK_AND"; case TOK_AND: return "TOK_AND";
case TOK_OR: return "TOK_OR"; case TOK_OR: return "TOK_OR";
case TOK_EQ: return "TOK_EQ"; case TOK_EQ: return "TOK_EQ";
case TOK_ACCOUNT: return "TOK_ACCOUNT"; case TOK_DATE: return "TOK_DATE";
case TOK_PAYEE: return "TOK_PAYEE";
case TOK_CODE: return "TOK_CODE"; case TOK_CODE: return "TOK_CODE";
case TOK_PAYEE: return "TOK_PAYEE";
case TOK_NOTE: return "TOK_NOTE"; case TOK_NOTE: return "TOK_NOTE";
case TOK_ACCOUNT: return "TOK_ACCOUNT";
case TOK_META: return "TOK_META"; case TOK_META: return "TOK_META";
case TOK_EXPR: return "TOK_EXPR"; case TOK_EXPR: return "TOK_EXPR";
case TERM: return string("TERM(") + *value + ")"; case TERM: return string("TERM(") + *value + ")";
@ -203,10 +205,11 @@ public:
case TOK_AND: return "and"; case TOK_AND: return "and";
case TOK_OR: return "or"; case TOK_OR: return "or";
case TOK_EQ: return "="; case TOK_EQ: return "=";
case TOK_ACCOUNT: return "account"; case TOK_DATE: return "date";
case TOK_PAYEE: return "payee";
case TOK_CODE: return "code"; case TOK_CODE: return "code";
case TOK_PAYEE: return "payee";
case TOK_NOTE: return "note"; case TOK_NOTE: return "note";
case TOK_ACCOUNT: return "account";
case TOK_META: return "meta"; case TOK_META: return "meta";
case TOK_EXPR: return "expr"; case TOK_EXPR: return "expr";

View file

@ -189,9 +189,9 @@ void export_account()
.def("remove_account", &account_t::remove_account) .def("remove_account", &account_t::remove_account)
.def("find_account", &account_t::find_account, .def("find_account", &account_t::find_account,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("find_account_re", &account_t::find_account, .def("find_account_re", &account_t::find_account,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("add_post", &account_t::add_post) .def("add_post", &account_t::add_post)
.def("remove_post", &account_t::remove_post) .def("remove_post", &account_t::remove_post)
@ -211,15 +211,15 @@ void export_account()
.def("has_xdata", &account_t::has_xdata) .def("has_xdata", &account_t::has_xdata)
.def("clear_xdata", &account_t::clear_xdata) .def("clear_xdata", &account_t::clear_xdata)
.def("xdata", py_xdata, .def("xdata", py_xdata,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("amount", &account_t::amount) .def("amount", &account_t::amount)
.def("total", &account_t::total) .def("total", &account_t::total)
.def("self_details", &account_t::self_details, .def("self_details", &account_t::self_details,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("family_details", &account_t::family_details, .def("family_details", &account_t::family_details,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("has_xflags", &account_t::has_xflags) .def("has_xflags", &account_t::has_xflags)
.def("children_with_flags", &account_t::children_with_flags) .def("children_with_flags", &account_t::children_with_flags)

View file

@ -115,7 +115,7 @@ void export_amount()
class_< amount_t > ("Amount") class_< amount_t > ("Amount")
.add_static_property("current_pool", .add_static_property("current_pool",
make_getter(&amount_t::current_pool, make_getter(&amount_t::current_pool,
return_value_policy<reference_existing_object>())) return_internal_reference<>()))
.def("initialize", py_amount_initialize) // only for the PyUnitTests .def("initialize", py_amount_initialize) // only for the PyUnitTests
.staticmethod("initialize") .staticmethod("initialize")
@ -204,7 +204,7 @@ internal precision."))
.def("negated", &amount_t::negated) .def("negated", &amount_t::negated)
.def("in_place_negate", &amount_t::in_place_negate, .def("in_place_negate", &amount_t::in_place_negate,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def(- self) .def(- self)
.def("abs", &amount_t::abs) .def("abs", &amount_t::abs)
@ -214,23 +214,23 @@ internal precision."))
.def("rounded", &amount_t::rounded) .def("rounded", &amount_t::rounded)
.def("in_place_round", &amount_t::in_place_round, .def("in_place_round", &amount_t::in_place_round,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("truncated", &amount_t::truncated) .def("truncated", &amount_t::truncated)
.def("in_place_truncate", &amount_t::in_place_truncate, .def("in_place_truncate", &amount_t::in_place_truncate,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("unrounded", &amount_t::unrounded) .def("unrounded", &amount_t::unrounded)
.def("in_place_unround", &amount_t::in_place_unround, .def("in_place_unround", &amount_t::in_place_unround,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("reduced", &amount_t::reduced) .def("reduced", &amount_t::reduced)
.def("in_place_reduce", &amount_t::in_place_reduce, .def("in_place_reduce", &amount_t::in_place_reduce,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("unreduced", &amount_t::unreduced) .def("unreduced", &amount_t::unreduced)
.def("in_place_unreduce", &amount_t::in_place_unreduce, .def("in_place_unreduce", &amount_t::in_place_unreduce,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("value", py_value_0) .def("value", py_value_0)
.def("value", py_value_1, args("primary_only")) .def("value", py_value_1, args("primary_only"))
@ -259,7 +259,7 @@ internal precision."))
.def("quantity_string", &amount_t::quantity_string) .def("quantity_string", &amount_t::quantity_string)
.def("commodity", &amount_t::commodity, .def("commodity", &amount_t::commodity,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("has_commodity", &amount_t::has_commodity) .def("has_commodity", &amount_t::has_commodity)
.def("set_commodity", &amount_t::set_commodity, .def("set_commodity", &amount_t::set_commodity,
with_custodian_and_ward<1, 2>()) with_custodian_and_ward<1, 2>())

View file

@ -159,7 +159,7 @@ void export_balance()
.def("negated", &balance_t::negated) .def("negated", &balance_t::negated)
.def("in_place_negate", &balance_t::in_place_negate, .def("in_place_negate", &balance_t::in_place_negate,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def(- self) .def(- self)
.def("abs", &balance_t::abs) .def("abs", &balance_t::abs)
@ -170,23 +170,23 @@ void export_balance()
.def("rounded", &balance_t::rounded) .def("rounded", &balance_t::rounded)
.def("in_place_round", &balance_t::in_place_round, .def("in_place_round", &balance_t::in_place_round,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("truncated", &balance_t::truncated) .def("truncated", &balance_t::truncated)
.def("in_place_truncate", &balance_t::in_place_truncate, .def("in_place_truncate", &balance_t::in_place_truncate,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("unrounded", &balance_t::unrounded) .def("unrounded", &balance_t::unrounded)
.def("in_place_unround", &balance_t::in_place_unround, .def("in_place_unround", &balance_t::in_place_unround,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("reduced", &balance_t::reduced) .def("reduced", &balance_t::reduced)
.def("in_place_reduce", &balance_t::in_place_reduce, .def("in_place_reduce", &balance_t::in_place_reduce,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("unreduced", &balance_t::unreduced) .def("unreduced", &balance_t::unreduced)
.def("in_place_unreduce", &balance_t::in_place_unreduce, .def("in_place_unreduce", &balance_t::in_place_unreduce,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("value", py_value_0) .def("value", py_value_0)
.def("value", py_value_1, args("primary_only")) .def("value", py_value_1, args("primary_only"))
@ -209,6 +209,8 @@ void export_balance()
.def("commodity_amount", py_commodity_amount_0) .def("commodity_amount", py_commodity_amount_0)
.def("commodity_amount", py_commodity_amount_1) .def("commodity_amount", py_commodity_amount_1)
.def("number", &balance_t::number)
.def("strip_annotations", &balance_t::strip_annotations) .def("strip_annotations", &balance_t::strip_annotations)
.def("valid", &balance_t::valid) .def("valid", &balance_t::valid)

View file

@ -157,23 +157,23 @@ void export_commodity()
.def("make_qualified_name", &commodity_pool_t::make_qualified_name) .def("make_qualified_name", &commodity_pool_t::make_qualified_name)
.def("create", py_create_1, return_value_policy<reference_existing_object>()) .def("create", py_create_1, return_internal_reference<>())
.def("create", py_create_2, return_value_policy<reference_existing_object>()) .def("create", py_create_2, return_internal_reference<>())
.def("find_or_create", py_find_or_create_1, .def("find_or_create", py_find_or_create_1,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("find_or_create", py_find_or_create_2, .def("find_or_create", py_find_or_create_2,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("find", py_find_1, return_value_policy<reference_existing_object>()) .def("find", py_find_1, return_internal_reference<>())
.def("find", py_find_2, return_value_policy<reference_existing_object>()) .def("find", py_find_2, return_internal_reference<>())
.def("exchange", py_exchange_3, with_custodian_and_ward<1, 2>()) .def("exchange", py_exchange_3, with_custodian_and_ward<1, 2>())
.def("exchange", py_exchange_5) .def("exchange", py_exchange_5)
.def("parse_price_directive", &commodity_pool_t::parse_price_directive) .def("parse_price_directive", &commodity_pool_t::parse_price_directive)
.def("parse_price_expression", &commodity_pool_t::parse_price_expression, .def("parse_price_expression", &commodity_pool_t::parse_price_expression,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
; ;
scope().attr("COMMODITY_STYLE_DEFAULTS") = COMMODITY_STYLE_DEFAULTS; scope().attr("COMMODITY_STYLE_DEFAULTS") = COMMODITY_STYLE_DEFAULTS;
@ -211,16 +211,16 @@ void export_commodity()
#if 0 #if 0
.def("referent", &commodity_t::referent, .def("referent", &commodity_t::referent,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
#endif #endif
.def("is_annotated", &commodity_t::is_annotated) .def("is_annotated", &commodity_t::is_annotated)
.def("strip_annotations", &commodity_t::strip_annotations, .def("strip_annotations", &commodity_t::strip_annotations,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("write_annotations", &commodity_t::write_annotations) .def("write_annotations", &commodity_t::write_annotations)
.def("pool", &commodity_t::pool, .def("pool", &commodity_t::pool,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("base_symbol", &commodity_t::base_symbol) .def("base_symbol", &commodity_t::base_symbol)
.def("symbol", &commodity_t::symbol) .def("symbol", &commodity_t::symbol)
@ -308,11 +308,11 @@ void export_commodity()
#if 0 #if 0
.def("referent", &annotated_commodity_t::referent, .def("referent", &annotated_commodity_t::referent,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
#endif #endif
.def("strip_annotations", &annotated_commodity_t::strip_annotations, .def("strip_annotations", &annotated_commodity_t::strip_annotations,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("write_annotations", &annotated_commodity_t::write_annotations) .def("write_annotations", &annotated_commodity_t::write_annotations)
; ;
} }

View file

@ -1,68 +0,0 @@
/*
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of New Artisans LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <system.hh>
#include "pyinterp.h"
namespace ledger {
using namespace boost::python;
#define EXC_TRANSLATOR(type) \
void exc_translate_ ## type(const type& err) { \
PyErr_SetString(PyExc_ArithmeticError, err.what()); \
}
//EXC_TRANSLATOR(flags_error)
void export_flags()
{
#if 0
class_< supports_flags > ("SupportsFlags")
;
class_< basic_flags_t > ("BasicFlags")
;
class_< delegates_flags > ("DelegatesFlags")
;
#endif
//register_optional_to_python<amount_t>();
//implicitly_convertible<string, amount_t>();
#define EXC_TRANSLATE(type) \
register_exception_translator<type>(&exc_translate_ ## type);
//EXC_TRANSLATE(flags_error);
}
} // namespace ledger

View file

@ -169,13 +169,13 @@ void export_post()
.def("has_xdata", &post_t::has_xdata) .def("has_xdata", &post_t::has_xdata)
.def("clear_xdata", &post_t::clear_xdata) .def("clear_xdata", &post_t::clear_xdata)
.def("xdata", py_xdata, .def("xdata", py_xdata,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("add_to_value", &post_t::add_to_value) .def("add_to_value", &post_t::add_to_value)
.def("set_reported_account", &post_t::set_reported_account) .def("set_reported_account", &post_t::set_reported_account)
.def("reported_account", py_reported_account, .def("reported_account", py_reported_account,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
; ;
} }

View file

@ -1,55 +0,0 @@
/*
* Copyright (c) 2003-2009, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of New Artisans LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <system.hh>
#include "pyinterp.h"
namespace ledger {
using namespace boost::python;
namespace {
}
void export_scope()
{
class_< scope_t, boost::noncopyable > ("Scope", no_init)
#if 0
.def("is_posting", )
.def("is_transaction", )
.def("is_account", )
.def("is_journal", )
#endif
;
}
} // namespace ledger

View file

@ -285,6 +285,8 @@ void export_value()
.def("simplified", &value_t::simplified) .def("simplified", &value_t::simplified)
.def("in_place_simplify", &value_t::in_place_simplify) .def("in_place_simplify", &value_t::in_place_simplify)
.def("number", &value_t::number)
.def("annotate", &value_t::annotate) .def("annotate", &value_t::annotate)
.def("is_annotated", &value_t::is_annotated) .def("is_annotated", &value_t::is_annotated)
#if 0 #if 0

View file

@ -91,7 +91,7 @@ void export_xact()
.def("__len__", posts_len) .def("__len__", posts_len)
.def("__getitem__", posts_getitem, .def("__getitem__", posts_getitem,
return_value_policy<reference_existing_object>()) return_internal_reference<>())
.def("add_post", &xact_base_t::add_post, with_custodian_and_ward<1, 2>()) .def("add_post", &xact_base_t::add_post, with_custodian_and_ward<1, 2>())
.def("remove_post", &xact_base_t::add_post) .def("remove_post", &xact_base_t::add_post)

View file

@ -32,6 +32,9 @@
#include <system.hh> #include <system.hh>
#include "pyinterp.h" #include "pyinterp.h"
#include "account.h"
#include "xact.h"
#include "post.h"
namespace ledger { namespace ledger {
@ -46,12 +49,10 @@ void export_amount();
void export_balance(); void export_balance();
void export_commodity(); void export_commodity();
void export_expr(); void export_expr();
void export_flags();
void export_format(); void export_format();
void export_item(); void export_item();
void export_journal(); void export_journal();
void export_post(); void export_post();
void export_scope();
void export_times(); void export_times();
void export_utils(); void export_utils();
void export_value(); void export_value();
@ -64,22 +65,14 @@ void initialize_for_python()
export_balance(); export_balance();
export_commodity(); export_commodity();
export_expr(); export_expr();
export_flags();
export_format(); export_format();
export_item(); export_item();
export_journal(); export_journal();
export_post(); export_post();
export_scope();
export_times(); export_times();
export_utils(); export_utils();
export_value(); export_value();
export_xact(); 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 struct python_run
@ -323,11 +316,39 @@ expr_t::ptr_op_t python_interpreter_t::lookup(const symbol_t::kind_t kind,
return NULL; 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) value_t python_interpreter_t::functor_t::operator()(call_scope_t& args)
{ {
try { try {
std::signal(SIGINT, SIG_DFL); std::signal(SIGINT, SIG_DFL);
if (! PyCallable_Check(func.ptr())) { if (! PyCallable_Check(func.ptr())) {
extract<value_t> val(func); extract<value_t> val(func);
std::signal(SIGINT, sigint_handler); std::signal(SIGINT, sigint_handler);
@ -341,40 +362,42 @@ value_t python_interpreter_t::functor_t::operator()(call_scope_t& args)
throw_(calc_error, throw_(calc_error,
_("Could not evaluate Python variable '%1'") << name); _("Could not evaluate Python variable '%1'") << name);
#endif #endif
} else { }
if (args.size() > 0) { else if (args.size() > 0) {
list arglist; list arglist;
if (args.value().is_sequence()) // jww (2009-11-05): What about a single argument which is a sequence,
foreach (const value_t& value, args.value().as_sequence()) // rather than a sequence of arguments?
arglist.append(value); if (args.value().is_sequence())
else foreach (const value_t& value, args.value().as_sequence())
arglist.append(args.value()); append_value(arglist, value);
else
append_value(arglist, args.value());
if (PyObject * val = if (PyObject * val =
PyObject_CallObject(func.ptr(), python::tuple(arglist).ptr())) { PyObject_CallObject(func.ptr(), python::tuple(arglist).ptr())) {
extract<value_t> xval(val); extract<value_t> xval(val);
value_t result; value_t result;
if (xval.check()) { if (xval.check()) {
result = xval(); result = xval();
Py_DECREF(val); 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 { } else {
assert(false); Py_DECREF(val);
throw_(calc_error,
_("Could not evaluate Python variable '%1'") << name);
} }
} else {
std::signal(SIGINT, sigint_handler); 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&) { catch (const error_already_set&) {

View file

@ -566,7 +566,7 @@ option_t<report_t> * report_t::lookup_option(const char * p)
break; break;
case 'a': case 'a':
OPT(abbrev_len_); OPT(abbrev_len_);
else OPT(account_); else OPT_(account_);
else OPT(actual); else OPT(actual);
else OPT(actual_dates); else OPT(actual_dates);
else OPT(add_budget); else OPT(add_budget);
@ -589,10 +589,6 @@ option_t<report_t> * report_t::lookup_option(const char * p)
case 'c': case 'c':
OPT(csv_format_); OPT(csv_format_);
else OPT(cleared); else OPT(cleared);
else OPT(code_as_payee);
else OPT_ALT(comm_as_payee, commodity_as_payee);
else OPT(code_as_account);
else OPT_ALT(comm_as_account, commodity_as_account);
else OPT(collapse); else OPT(collapse);
else OPT(collapse_if_zero); else OPT(collapse_if_zero);
else OPT(color); else OPT(color);
@ -666,7 +662,7 @@ option_t<report_t> * report_t::lookup_option(const char * p)
break; break;
case 'p': case 'p':
OPT(pager_); OPT(pager_);
else OPT(payee_as_account); else OPT(payee_);
else OPT(pending); else OPT(pending);
else OPT(percent); else OPT(percent);
else OPT_(period_); else OPT_(period_);
@ -694,11 +690,7 @@ option_t<report_t> * report_t::lookup_option(const char * p)
else OPT(revalued_total_); else OPT(revalued_total_);
break; break;
case 's': case 's':
OPT(set_account_); OPT(sort_);
else OPT(set_payee_);
else OPT(set_reported_account_);
else OPT(set_reported_payee_);
else OPT(sort_);
else OPT(sort_all_); else OPT(sort_all_);
else OPT(sort_xacts_); else OPT(sort_xacts_);
else OPT_(subtotal); else OPT_(subtotal);

View file

@ -215,10 +215,6 @@ public:
HANDLER(by_payee).report(out); HANDLER(by_payee).report(out);
HANDLER(cleared).report(out); HANDLER(cleared).report(out);
HANDLER(cleared_format_).report(out); HANDLER(cleared_format_).report(out);
HANDLER(code_as_payee).report(out);
HANDLER(comm_as_payee).report(out);
HANDLER(code_as_account).report(out);
HANDLER(comm_as_account).report(out);
HANDLER(color).report(out); HANDLER(color).report(out);
HANDLER(collapse).report(out); HANDLER(collapse).report(out);
HANDLER(collapse_if_zero).report(out); HANDLER(collapse_if_zero).report(out);
@ -262,7 +258,7 @@ public:
HANDLER(only_).report(out); HANDLER(only_).report(out);
HANDLER(output_).report(out); HANDLER(output_).report(out);
HANDLER(pager_).report(out); HANDLER(pager_).report(out);
HANDLER(payee_as_account).report(out); HANDLER(payee_).report(out);
HANDLER(pending).report(out); HANDLER(pending).report(out);
HANDLER(percent).report(out); HANDLER(percent).report(out);
HANDLER(period_).report(out); HANDLER(period_).report(out);
@ -283,10 +279,6 @@ public:
HANDLER(revalued_only).report(out); HANDLER(revalued_only).report(out);
HANDLER(revalued_total_).report(out); HANDLER(revalued_total_).report(out);
HANDLER(seed_).report(out); HANDLER(seed_).report(out);
HANDLER(set_account_).report(out);
HANDLER(set_payee_).report(out);
HANDLER(set_reported_account_).report(out);
HANDLER(set_reported_payee_).report(out);
HANDLER(sort_).report(out); HANDLER(sort_).report(out);
HANDLER(sort_all_).report(out); HANDLER(sort_all_).report(out);
HANDLER(sort_xacts_).report(out); HANDLER(sort_xacts_).report(out);
@ -429,10 +421,6 @@ public:
"---------------- ---------------- ---------\n"); "---------------- ---------------- ---------\n");
}); });
OPTION(report_t, code_as_payee);
OPTION(report_t, comm_as_payee);
OPTION(report_t, code_as_account);
OPTION(report_t, comm_as_account);
OPTION(report_t, color); OPTION(report_t, color);
OPTION_(report_t, collapse, DO() { // -n OPTION_(report_t, collapse, DO() { // -n
@ -684,7 +672,7 @@ public:
}); });
#endif // HAVE_ISATTY #endif // HAVE_ISATTY
OPTION(report_t, payee_as_account); OPTION(report_t, payee_);
OPTION_(report_t, pending, DO() { // -C OPTION_(report_t, pending, DO() { // -C
parent->HANDLER(limit_).on(string("--pending"), "pending"); parent->HANDLER(limit_).on(string("--pending"), "pending");
@ -808,10 +796,6 @@ public:
}); });
OPTION(report_t, seed_); OPTION(report_t, seed_);
OPTION(report_t, set_account_);
OPTION(report_t, set_payee_);
OPTION(report_t, set_reported_account_);
OPTION(report_t, set_reported_payee_);
OPTION_(report_t, sort_, DO_(args) { // -S OPTION_(report_t, sort_, DO_(args) { // -S
on_with(args[0].as_string(), args[1]); on_with(args[0].as_string(), args[1]);

View file

@ -75,7 +75,6 @@ session_t::session_t()
std::size_t session_t::read_data(const string& master_account) std::size_t session_t::read_data(const string& master_account)
{ {
bool populated_data_files = false; bool populated_data_files = false;
bool populated_price_db = false;
if (HANDLER(file_).data_files.empty()) { if (HANDLER(file_).data_files.empty()) {
path file; path file;
@ -101,15 +100,9 @@ std::size_t session_t::read_data(const string& master_account)
price_db_path = resolve_path(HANDLER(price_db_).str()); price_db_path = resolve_path(HANDLER(price_db_).str());
optional<archive_t> cache; optional<archive_t> cache;
if (HANDLED(cache_) && master_account.empty()) { if (HANDLED(cache_) && master_account.empty())
cache = archive_t(HANDLED(cache_).str()); cache = archive_t(HANDLED(cache_).str());
if (price_db_path) {
HANDLER(file_).data_files.push_back(*price_db_path);
populated_price_db = true;
}
}
if (! (cache && if (! (cache &&
cache->should_load(HANDLER(file_).data_files) && cache->should_load(HANDLER(file_).data_files) &&
cache->load(journal))) { cache->load(journal))) {
@ -118,7 +111,6 @@ std::size_t session_t::read_data(const string& master_account)
if (journal->read(*price_db_path) > 0) if (journal->read(*price_db_path) > 0)
throw_(parse_error, _("Transactions not allowed in price history file")); throw_(parse_error, _("Transactions not allowed in price history file"));
} }
HANDLER(file_).data_files.remove(*price_db_path);
} }
foreach (const path& pathname, HANDLER(file_).data_files) { foreach (const path& pathname, HANDLER(file_).data_files) {
@ -153,8 +145,6 @@ std::size_t session_t::read_data(const string& master_account)
if (populated_data_files) if (populated_data_files)
HANDLER(file_).data_files.clear(); HANDLER(file_).data_files.clear();
else if (populated_price_db)
HANDLER(file_).data_files.remove(*price_db_path);
VERIFY(journal->valid()); VERIFY(journal->valid());
@ -166,8 +156,8 @@ void session_t::read_journal_files()
INFO_START(journal, "Read journal file"); INFO_START(journal, "Read journal file");
string master_account; string master_account;
if (HANDLED(account_)) if (HANDLED(master_account_))
master_account = HANDLER(account_).str(); master_account = HANDLER(master_account_).str();
std::size_t count = read_data(master_account); std::size_t count = read_data(master_account);
if (count == 0) if (count == 0)
@ -197,9 +187,6 @@ option_t<session_t> * session_t::lookup_option(const char * p)
case 'Z': case 'Z':
OPT_CH(price_exp_); OPT_CH(price_exp_);
break; break;
case 'a':
OPT_(account_); // -a
break;
case 'c': case 'c':
OPT(cache_); OPT(cache_);
break; break;
@ -218,6 +205,9 @@ option_t<session_t> * session_t::lookup_option(const char * p)
case 'l': case 'l':
OPT_ALT(price_exp_, leeway_); OPT_ALT(price_exp_, leeway_);
break; break;
case 'm':
OPT(master_account_);
break;
case 'p': case 'p':
OPT(price_db_); OPT(price_db_);
else OPT(price_exp_); else OPT(price_exp_);

View file

@ -87,12 +87,12 @@ public:
void report_options(std::ostream& out) void report_options(std::ostream& out)
{ {
HANDLER(account_).report(out);
HANDLER(cache_).report(out); HANDLER(cache_).report(out);
HANDLER(download).report(out); HANDLER(download).report(out);
HANDLER(european).report(out); HANDLER(european).report(out);
HANDLER(file_).report(out); HANDLER(file_).report(out);
HANDLER(input_date_format_).report(out); HANDLER(input_date_format_).report(out);
HANDLER(master_account_).report(out);
HANDLER(price_db_).report(out); HANDLER(price_db_).report(out);
HANDLER(price_exp_).report(out); HANDLER(price_exp_).report(out);
HANDLER(strict).report(out); HANDLER(strict).report(out);
@ -107,7 +107,6 @@ public:
* Option handlers * Option handlers
*/ */
OPTION(session_t, account_); // -a
OPTION(session_t, cache_); OPTION(session_t, cache_);
OPTION(session_t, download); // -Q OPTION(session_t, download); // -Q
@ -141,6 +140,7 @@ public:
set_input_date_format(args[1].as_string().c_str()); set_input_date_format(args[1].as_string().c_str());
}); });
OPTION(session_t, master_account_);
OPTION(session_t, price_db_); OPTION(session_t, price_db_);
OPTION(session_t, strict); OPTION(session_t, strict);
}; };

View file

@ -45,7 +45,7 @@ temporaries_t::~temporaries_t()
if (! post.xact->has_flags(ITEM_TEMP)) if (! post.xact->has_flags(ITEM_TEMP))
post.xact->remove_post(&post); post.xact->remove_post(&post);
if (! post.account->has_flags(ACCOUNT_TEMP)) if (post.account && ! post.account->has_flags(ACCOUNT_TEMP))
post.account->remove_post(&post); post.account->remove_post(&post);
} }
} }

View file

@ -279,6 +279,35 @@ void value_t::in_place_simplify()
#endif #endif
} }
value_t value_t::number() const
{
switch (type()) {
case VOID:
return 0L;
case BOOLEAN:
return as_boolean() ? 1L : 0L;
case INTEGER:
return as_long();
case AMOUNT:
return as_amount().number();
case BALANCE:
return as_balance().number();
case SEQUENCE:
if (! as_sequence().empty()) {
value_t temp;
foreach (const value_t& value, as_sequence())
temp += value.number();
return temp;
}
break;
default:
break;
}
throw_(value_error, _("Cannot determine numeric value of %1") << label());
return false;
}
value_t& value_t::operator+=(const value_t& val) value_t& value_t::operator+=(const value_t& val)
{ {
if (is_string()) { if (is_string()) {

View file

@ -761,6 +761,8 @@ public:
} }
void in_place_simplify(); void in_place_simplify();
value_t number() const;
/** /**
* Annotated commodity methods. * Annotated commodity methods.
*/ */

View file

@ -83,6 +83,20 @@ void xact_base_t::clear_xdata()
post->clear_xdata(); post->clear_xdata();
} }
value_t xact_base_t::magnitude() const
{
value_t halfbal = 0L;
foreach (const post_t * post, posts) {
if (post->amount.sign() > 0) {
if (post->cost)
halfbal += *post->cost;
else
halfbal += post->amount;
}
}
return halfbal;
}
bool xact_base_t::finalize() bool xact_base_t::finalize()
{ {
// Scan through and compute the total balance for the xact. This is used // Scan through and compute the total balance for the xact. This is used
@ -321,6 +335,8 @@ bool xact_base_t::finalize()
add_error_context(item_context(*this, _("While balancing transaction"))); add_error_context(item_context(*this, _("While balancing transaction")));
add_error_context(_("Unbalanced remainder is:")); add_error_context(_("Unbalanced remainder is:"));
add_error_context(value_context(balance)); add_error_context(value_context(balance));
add_error_context(_("Amount to balance against:"));
add_error_context(value_context(magnitude()));
throw_(balance_error, _("Transaction does not balance")); throw_(balance_error, _("Transaction does not balance"));
} }
@ -368,26 +384,12 @@ void xact_t::add_post(post_t * post)
xact_base_t::add_post(post); xact_base_t::add_post(post);
} }
value_t xact_t::magnitude() const
{
value_t halfbal = 0L;
foreach (const post_t * post, posts) {
if (post->amount.sign() > 0) {
if (post->cost)
halfbal += post->cost->number();
else
halfbal += post->amount.number();
}
}
return halfbal;
}
string xact_t::idstring() const string xact_t::idstring() const
{ {
std::ostringstream buf; std::ostringstream buf;
buf << format_date(*_date, FMT_WRITTEN); buf << format_date(*_date, FMT_WRITTEN);
buf << payee; buf << payee;
magnitude().print(buf); magnitude().number().print(buf);
return buf.str(); return buf.str();
} }

View file

@ -84,6 +84,8 @@ public:
return posts.end(); return posts.end();
} }
value_t magnitude() const;
virtual bool finalize(); virtual bool finalize();
void clear_xdata(); void clear_xdata();
@ -129,7 +131,6 @@ public:
virtual void add_post(post_t * post); virtual void add_post(post_t * post);
value_t magnitude() const;
string idstring() const; string idstring() const;
string id() const; string id() const;

View file

@ -1,15 +1,11 @@
bal --account=Master reg --account='payee + ":" + commodity'
<<< <<<
2007/02/02 RD VMMXX 2007/02/02 RD VMMXX
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00 Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
Income:Dividends:Vanguard:VMMXX $-0.35 Income:Dividends:Vanguard:VMMXX $-0.35
>>>1 >>>1
$-0.35 07-Feb-02 RD VMMXX RD VMMXX:VMMXX 0.350 VMMXX 0.350 VMMXX
0.350 VMMXX Master 07-Feb-02 RD VMMXX RD VMMXX:$ $-0.35 $-0.35
0.350 VMMXX Assets:Investments:Vanguard:VMMXX 0.350 VMMXX
$-0.35 Income:Dividends:Vanguard:VMMXX
--------------------
$-0.35
0.350 VMMXX
>>>2 >>>2
=== 0 === 0

View file

@ -1,4 +1,4 @@
reg --code-as-account reg --account=code
<<< <<<
2008/01/01 * (100) January 2008/01/01 * (100) January
Expenses:Books $10.00 Expenses:Books $10.00

View file

@ -1,4 +1,4 @@
reg --code-as-payee reg --payee=code
<<< <<<
2008/01/01 * (100) January 2008/01/01 * (100) January
Expenses:Books $10.00 Expenses:Books $10.00

View file

@ -1,11 +0,0 @@
reg --comm-as-account
<<<
2007/02/02 RD VMMXX
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
Income:Dividends:Vanguard:VMMXX $-0.35
>>>1
07-Feb-02 RD VMMXX VMMXX 0.350 VMMXX 0.350 VMMXX
07-Feb-02 RD VMMXX $ $-0.35 $-0.35
0.350 VMMXX
>>>2
=== 0

View file

@ -1,11 +0,0 @@
reg --comm-as-payee
<<<
2007/02/02 RD VMMXX
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
Income:Dividends:Vanguard:VMMXX $-0.35
>>>1
07-Feb-02 VMMXX As:In:Vanguard:VMMXX 0.350 VMMXX 0.350 VMMXX
07-Feb-02 $ In:Di:Vanguard:VMMXX $-0.35 $-0.35
0.350 VMMXX
>>>2
=== 0

View file

@ -1,4 +1,4 @@
reg --commodity-as-account reg --account=commodity
<<< <<<
2007/02/02 RD VMMXX 2007/02/02 RD VMMXX
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00 Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00

View file

@ -1,4 +1,4 @@
reg --commodity-as-payee reg --payee=commodity
<<< <<<
2007/02/02 RD VMMXX 2007/02/02 RD VMMXX
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00 Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00

View file

@ -0,0 +1,15 @@
bal --master-account=Master
<<<
2007/02/02 RD VMMXX
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
Income:Dividends:Vanguard:VMMXX $-0.35
>>>1
$-0.35
0.350 VMMXX Master
0.350 VMMXX Assets:Investments:Vanguard:VMMXX
$-0.35 Income:Dividends:Vanguard:VMMXX
--------------------
$-0.35
0.350 VMMXX
>>>2
=== 0

View file

@ -1,4 +1,4 @@
reg --payee-as-account reg --account=payee
<<< <<<
2008/01/01 * (100) January 2008/01/01 * (100) January
Expenses:Books $10.00 Expenses:Books $10.00

View file

@ -1,4 +1,4 @@
reg --set-payee='account_base + ":" + commodity' reg --payee='account_base + ":" + commodity'
<<< <<<
2007/02/02 RD VMMXX 2007/02/02 RD VMMXX
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00 Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00

View file

@ -1,11 +0,0 @@
reg --set-account='payee + ":" + commodity'
<<<
2007/02/02 RD VMMXX
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
Income:Dividends:Vanguard:VMMXX $-0.35
>>>1
07-Feb-02 RD VMMXX RD VMMXX:VMMXX 0.350 VMMXX 0.350 VMMXX
07-Feb-02 RD VMMXX RD VMMXX:$ $-0.35 $-0.35
0.350 VMMXX
>>>2
=== 0

View file

@ -1,4 +1,4 @@
bal checking --set-reported-account=code bal checking --account=code
<<< <<<
2009/10/29 (XFER) Panera Bread 2009/10/29 (XFER) Panera Bread
Expenses:Food $4.50 Expenses:Food $4.50

View file

@ -1,4 +1,4 @@
bal food and tag type --set-reported-account='"Tags:" + tag("Type")' bal food and tag type --account='"Tags:" + tag("Type")'
<<< <<<
2009/11/01 Panera Bread ; Got something to eat 2009/11/01 Panera Bread ; Got something to eat
Expenses:Food $4.50 Expenses:Food $4.50

View file

@ -14,5 +14,7 @@ While balancing transaction from "$FILE", lines 3-5:
> Account2 -1000 EUR @ 1.5 USD > Account2 -1000 EUR @ 1.5 USD
Unbalanced remainder is: Unbalanced remainder is:
100.00 USD 100.00 USD
Amount to balance against:
1,600.0 USD
Error: Transaction does not balance Error: Transaction does not balance
=== 1 === 1

View file

@ -210,12 +210,10 @@ libledger_python_la_SOURCES = \
src/py_balance.cc \ src/py_balance.cc \
src/py_commodity.cc \ src/py_commodity.cc \
src/py_expr.cc \ src/py_expr.cc \
src/py_flags.cc \
src/py_format.cc \ src/py_format.cc \
src/py_item.cc \ src/py_item.cc \
src/py_journal.cc \ src/py_journal.cc \
src/py_post.cc \ src/py_post.cc \
src/py_scope.cc \
src/py_times.cc \ src/py_times.cc \
src/py_utils.cc \ src/py_utils.cc \
src/py_value.cc \ src/py_value.cc \