Merge branch 'next'
This commit is contained in:
commit
f03d386013
41 changed files with 287 additions and 377 deletions
|
|
@ -480,6 +480,13 @@ public:
|
|||
optional<amount_t>
|
||||
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
|
||||
* may use annotated commodities. The `strip_annotations' method
|
||||
|
|
|
|||
39
src/chain.cc
39
src/chain.cc
|
|
@ -159,15 +159,15 @@ post_handler_ptr chain_post_handlers(report_t& report,
|
|||
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,
|
||||
report.session.journal->master,
|
||||
report.HANDLER(set_reported_account_).str(),
|
||||
report.HANDLER(account_).str(),
|
||||
report));
|
||||
else if (report.HANDLED(set_reported_payee_))
|
||||
if (report.HANDLED(payee_))
|
||||
handler.reset(new transfer_details(handler, transfer_details::SET_PAYEE,
|
||||
report.session.journal->master,
|
||||
report.HANDLER(set_reported_payee_).str(),
|
||||
report.HANDLER(payee_).str(),
|
||||
report));
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -711,6 +711,7 @@ void transfer_details::operator()(post_t& post)
|
|||
case SET_PAYEE:
|
||||
xact.payee = expr.calc(bound_scope).to_string();
|
||||
break;
|
||||
|
||||
case SET_ACCOUNT: {
|
||||
std::list<string> account_names;
|
||||
temp.account->remove_post(&temp);
|
||||
|
|
@ -720,6 +721,7 @@ void transfer_details::operator()(post_t& post)
|
|||
temp.account->add_post(&temp);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
out << "<=============================================================================>"
|
||||
out << "==============================================================================="
|
||||
<< 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;
|
||||
report.report_options(out);
|
||||
out << "<=============================================================================>"
|
||||
out << "==============================================================================="
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -201,7 +201,8 @@ std::size_t journal_t::read(const path& pathname,
|
|||
|
||||
ifstream stream(filename);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,16 +147,16 @@ query_lexer_t::token_t query_lexer_t::next_token()
|
|||
return token_t(token_t::TOK_OR);
|
||||
else if (ident == "not")
|
||||
return token_t(token_t::TOK_NOT);
|
||||
else if (ident == "account")
|
||||
return token_t(token_t::TOK_ACCOUNT);
|
||||
else if (ident == "code")
|
||||
return token_t(token_t::TOK_CODE);
|
||||
else if (ident == "desc")
|
||||
return token_t(token_t::TOK_PAYEE);
|
||||
else if (ident == "payee")
|
||||
return token_t(token_t::TOK_PAYEE);
|
||||
else if (ident == "code")
|
||||
return token_t(token_t::TOK_CODE);
|
||||
else if (ident == "note")
|
||||
return token_t(token_t::TOK_NOTE);
|
||||
else if (ident == "account")
|
||||
return token_t(token_t::TOK_ACCOUNT);
|
||||
else if (ident == "tag")
|
||||
return token_t(token_t::TOK_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());
|
||||
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") {
|
||||
// The expr keyword takes the whole of the next string as its
|
||||
// argument.
|
||||
// The expr keyword takes the whole of the next string as its argument.
|
||||
consume_whitespace = true;
|
||||
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:
|
||||
break;
|
||||
|
||||
case query_lexer_t::token_t::TOK_ACCOUNT:
|
||||
case query_lexer_t::token_t::TOK_PAYEE:
|
||||
case query_lexer_t::token_t::TOK_DATE:
|
||||
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_ACCOUNT:
|
||||
case query_lexer_t::token_t::TOK_META:
|
||||
case query_lexer_t::token_t::TOK_EXPR:
|
||||
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:
|
||||
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);
|
||||
|
||||
expr_t::ptr_op_t ident;
|
||||
ident = new expr_t::op_t(expr_t::op_t::IDENT);
|
||||
expr_t::ptr_op_t ident = new expr_t::op_t(expr_t::op_t::IDENT);
|
||||
ident->set_ident("has_tag");
|
||||
node->set_left(ident);
|
||||
|
||||
expr_t::ptr_op_t arg1;
|
||||
arg1 = new expr_t::op_t(expr_t::op_t::VALUE);
|
||||
expr_t::ptr_op_t arg1 = new expr_t::op_t(expr_t::op_t::VALUE);
|
||||
arg1->set_value(mask_t(*tok.value));
|
||||
|
||||
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,
|
||||
_("Metadata equality operator not followed by term"));
|
||||
|
||||
expr_t::ptr_op_t cons;
|
||||
cons = new expr_t::op_t(expr_t::op_t::O_CONS);
|
||||
expr_t::ptr_op_t cons = new expr_t::op_t(expr_t::op_t::O_CONS);
|
||||
|
||||
expr_t::ptr_op_t arg2;
|
||||
arg2 = new expr_t::op_t(expr_t::op_t::VALUE);
|
||||
expr_t::ptr_op_t arg2 = new expr_t::op_t(expr_t::op_t::VALUE);
|
||||
assert(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 {
|
||||
node->set_right(arg1);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
node = new expr_t::op_t(expr_t::op_t::O_MATCH);
|
||||
|
||||
expr_t::ptr_op_t ident;
|
||||
ident = new expr_t::op_t(expr_t::op_t::IDENT);
|
||||
expr_t::ptr_op_t ident = new expr_t::op_t(expr_t::op_t::IDENT);
|
||||
switch (tok_context) {
|
||||
case query_lexer_t::token_t::TOK_ACCOUNT:
|
||||
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;
|
||||
}
|
||||
|
||||
expr_t::ptr_op_t mask;
|
||||
mask = new expr_t::op_t(expr_t::op_t::VALUE);
|
||||
expr_t::ptr_op_t mask = new expr_t::op_t(expr_t::op_t::VALUE);
|
||||
mask->set_value(mask_t(*tok.value));
|
||||
|
||||
node->set_left(ident);
|
||||
node->set_right(mask);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case query_lexer_t::token_t::LPAREN:
|
||||
|
|
|
|||
|
|
@ -135,10 +135,11 @@ public:
|
|||
TOK_OR,
|
||||
TOK_EQ,
|
||||
|
||||
TOK_ACCOUNT,
|
||||
TOK_PAYEE,
|
||||
TOK_DATE,
|
||||
TOK_CODE,
|
||||
TOK_PAYEE,
|
||||
TOK_NOTE,
|
||||
TOK_ACCOUNT,
|
||||
TOK_META,
|
||||
TOK_EXPR,
|
||||
|
||||
|
|
@ -184,10 +185,11 @@ public:
|
|||
case TOK_AND: return "TOK_AND";
|
||||
case TOK_OR: return "TOK_OR";
|
||||
case TOK_EQ: return "TOK_EQ";
|
||||
case TOK_ACCOUNT: return "TOK_ACCOUNT";
|
||||
case TOK_PAYEE: return "TOK_PAYEE";
|
||||
case TOK_DATE: return "TOK_DATE";
|
||||
case TOK_CODE: return "TOK_CODE";
|
||||
case TOK_PAYEE: return "TOK_PAYEE";
|
||||
case TOK_NOTE: return "TOK_NOTE";
|
||||
case TOK_ACCOUNT: return "TOK_ACCOUNT";
|
||||
case TOK_META: return "TOK_META";
|
||||
case TOK_EXPR: return "TOK_EXPR";
|
||||
case TERM: return string("TERM(") + *value + ")";
|
||||
|
|
@ -203,10 +205,11 @@ public:
|
|||
case TOK_AND: return "and";
|
||||
case TOK_OR: return "or";
|
||||
case TOK_EQ: return "=";
|
||||
case TOK_ACCOUNT: return "account";
|
||||
case TOK_PAYEE: return "payee";
|
||||
case TOK_DATE: return "date";
|
||||
case TOK_CODE: return "code";
|
||||
case TOK_PAYEE: return "payee";
|
||||
case TOK_NOTE: return "note";
|
||||
case TOK_ACCOUNT: return "account";
|
||||
case TOK_META: return "meta";
|
||||
case TOK_EXPR: return "expr";
|
||||
|
||||
|
|
|
|||
|
|
@ -189,9 +189,9 @@ void export_account()
|
|||
.def("remove_account", &account_t::remove_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,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("add_post", &account_t::add_post)
|
||||
.def("remove_post", &account_t::remove_post)
|
||||
|
|
@ -211,15 +211,15 @@ void export_account()
|
|||
.def("has_xdata", &account_t::has_xdata)
|
||||
.def("clear_xdata", &account_t::clear_xdata)
|
||||
.def("xdata", py_xdata,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("amount", &account_t::amount)
|
||||
.def("total", &account_t::total)
|
||||
|
||||
.def("self_details", &account_t::self_details,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
.def("family_details", &account_t::family_details,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("has_xflags", &account_t::has_xflags)
|
||||
.def("children_with_flags", &account_t::children_with_flags)
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ void export_amount()
|
|||
class_< amount_t > ("Amount")
|
||||
.add_static_property("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
|
||||
.staticmethod("initialize")
|
||||
|
|
@ -204,7 +204,7 @@ internal precision."))
|
|||
|
||||
.def("negated", &amount_t::negated)
|
||||
.def("in_place_negate", &amount_t::in_place_negate,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
.def(- self)
|
||||
|
||||
.def("abs", &amount_t::abs)
|
||||
|
|
@ -214,23 +214,23 @@ internal precision."))
|
|||
|
||||
.def("rounded", &amount_t::rounded)
|
||||
.def("in_place_round", &amount_t::in_place_round,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("truncated", &amount_t::truncated)
|
||||
.def("in_place_truncate", &amount_t::in_place_truncate,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("unrounded", &amount_t::unrounded)
|
||||
.def("in_place_unround", &amount_t::in_place_unround,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("reduced", &amount_t::reduced)
|
||||
.def("in_place_reduce", &amount_t::in_place_reduce,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("unreduced", &amount_t::unreduced)
|
||||
.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_1, args("primary_only"))
|
||||
|
|
@ -259,7 +259,7 @@ internal precision."))
|
|||
.def("quantity_string", &amount_t::quantity_string)
|
||||
|
||||
.def("commodity", &amount_t::commodity,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
.def("has_commodity", &amount_t::has_commodity)
|
||||
.def("set_commodity", &amount_t::set_commodity,
|
||||
with_custodian_and_ward<1, 2>())
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ void export_balance()
|
|||
|
||||
.def("negated", &balance_t::negated)
|
||||
.def("in_place_negate", &balance_t::in_place_negate,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
.def(- self)
|
||||
|
||||
.def("abs", &balance_t::abs)
|
||||
|
|
@ -170,23 +170,23 @@ void export_balance()
|
|||
|
||||
.def("rounded", &balance_t::rounded)
|
||||
.def("in_place_round", &balance_t::in_place_round,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("truncated", &balance_t::truncated)
|
||||
.def("in_place_truncate", &balance_t::in_place_truncate,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("unrounded", &balance_t::unrounded)
|
||||
.def("in_place_unround", &balance_t::in_place_unround,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("reduced", &balance_t::reduced)
|
||||
.def("in_place_reduce", &balance_t::in_place_reduce,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("unreduced", &balance_t::unreduced)
|
||||
.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_1, args("primary_only"))
|
||||
|
|
@ -209,6 +209,8 @@ void export_balance()
|
|||
.def("commodity_amount", py_commodity_amount_0)
|
||||
.def("commodity_amount", py_commodity_amount_1)
|
||||
|
||||
.def("number", &balance_t::number)
|
||||
|
||||
.def("strip_annotations", &balance_t::strip_annotations)
|
||||
|
||||
.def("valid", &balance_t::valid)
|
||||
|
|
|
|||
|
|
@ -157,23 +157,23 @@ void export_commodity()
|
|||
|
||||
.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_2, return_value_policy<reference_existing_object>())
|
||||
.def("create", py_create_1, return_internal_reference<>())
|
||||
.def("create", py_create_2, return_internal_reference<>())
|
||||
|
||||
.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,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("find", py_find_1, return_value_policy<reference_existing_object>())
|
||||
.def("find", py_find_2, return_value_policy<reference_existing_object>())
|
||||
.def("find", py_find_1, return_internal_reference<>())
|
||||
.def("find", py_find_2, return_internal_reference<>())
|
||||
|
||||
.def("exchange", py_exchange_3, with_custodian_and_ward<1, 2>())
|
||||
.def("exchange", py_exchange_5)
|
||||
|
||||
.def("parse_price_directive", &commodity_pool_t::parse_price_directive)
|
||||
.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;
|
||||
|
|
@ -211,16 +211,16 @@ void export_commodity()
|
|||
|
||||
#if 0
|
||||
.def("referent", &commodity_t::referent,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
#endif
|
||||
|
||||
.def("is_annotated", &commodity_t::is_annotated)
|
||||
.def("strip_annotations", &commodity_t::strip_annotations,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
.def("write_annotations", &commodity_t::write_annotations)
|
||||
|
||||
.def("pool", &commodity_t::pool,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("base_symbol", &commodity_t::base_symbol)
|
||||
.def("symbol", &commodity_t::symbol)
|
||||
|
|
@ -308,11 +308,11 @@ void export_commodity()
|
|||
|
||||
#if 0
|
||||
.def("referent", &annotated_commodity_t::referent,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
#endif
|
||||
|
||||
.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)
|
||||
;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -169,13 +169,13 @@ void export_post()
|
|||
.def("has_xdata", &post_t::has_xdata)
|
||||
.def("clear_xdata", &post_t::clear_xdata)
|
||||
.def("xdata", py_xdata,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
|
||||
.def("add_to_value", &post_t::add_to_value)
|
||||
.def("set_reported_account", &post_t::set_reported_account)
|
||||
|
||||
.def("reported_account", py_reported_account,
|
||||
return_value_policy<reference_existing_object>())
|
||||
return_internal_reference<>())
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -285,6 +285,8 @@ void export_value()
|
|||
.def("simplified", &value_t::simplified)
|
||||
.def("in_place_simplify", &value_t::in_place_simplify)
|
||||
|
||||
.def("number", &value_t::number)
|
||||
|
||||
.def("annotate", &value_t::annotate)
|
||||
.def("is_annotated", &value_t::is_annotated)
|
||||
#if 0
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ void export_xact()
|
|||
|
||||
.def("__len__", posts_len)
|
||||
.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("remove_post", &xact_base_t::add_post)
|
||||
|
|
|
|||
101
src/pyinterp.cc
101
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());
|
||||
}
|
||||
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 {
|
||||
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);
|
||||
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&) {
|
||||
|
|
|
|||
|
|
@ -566,7 +566,7 @@ option_t<report_t> * report_t::lookup_option(const char * p)
|
|||
break;
|
||||
case 'a':
|
||||
OPT(abbrev_len_);
|
||||
else OPT(account_);
|
||||
else OPT_(account_);
|
||||
else OPT(actual);
|
||||
else OPT(actual_dates);
|
||||
else OPT(add_budget);
|
||||
|
|
@ -589,10 +589,6 @@ option_t<report_t> * report_t::lookup_option(const char * p)
|
|||
case 'c':
|
||||
OPT(csv_format_);
|
||||
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_if_zero);
|
||||
else OPT(color);
|
||||
|
|
@ -666,7 +662,7 @@ option_t<report_t> * report_t::lookup_option(const char * p)
|
|||
break;
|
||||
case 'p':
|
||||
OPT(pager_);
|
||||
else OPT(payee_as_account);
|
||||
else OPT(payee_);
|
||||
else OPT(pending);
|
||||
else OPT(percent);
|
||||
else OPT_(period_);
|
||||
|
|
@ -694,11 +690,7 @@ option_t<report_t> * report_t::lookup_option(const char * p)
|
|||
else OPT(revalued_total_);
|
||||
break;
|
||||
case 's':
|
||||
OPT(set_account_);
|
||||
else OPT(set_payee_);
|
||||
else OPT(set_reported_account_);
|
||||
else OPT(set_reported_payee_);
|
||||
else OPT(sort_);
|
||||
OPT(sort_);
|
||||
else OPT(sort_all_);
|
||||
else OPT(sort_xacts_);
|
||||
else OPT_(subtotal);
|
||||
|
|
|
|||
20
src/report.h
20
src/report.h
|
|
@ -215,10 +215,6 @@ public:
|
|||
HANDLER(by_payee).report(out);
|
||||
HANDLER(cleared).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(collapse).report(out);
|
||||
HANDLER(collapse_if_zero).report(out);
|
||||
|
|
@ -262,7 +258,7 @@ public:
|
|||
HANDLER(only_).report(out);
|
||||
HANDLER(output_).report(out);
|
||||
HANDLER(pager_).report(out);
|
||||
HANDLER(payee_as_account).report(out);
|
||||
HANDLER(payee_).report(out);
|
||||
HANDLER(pending).report(out);
|
||||
HANDLER(percent).report(out);
|
||||
HANDLER(period_).report(out);
|
||||
|
|
@ -283,10 +279,6 @@ public:
|
|||
HANDLER(revalued_only).report(out);
|
||||
HANDLER(revalued_total_).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_all_).report(out);
|
||||
HANDLER(sort_xacts_).report(out);
|
||||
|
|
@ -429,10 +421,6 @@ public:
|
|||
"---------------- ---------------- ---------\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, collapse, DO() { // -n
|
||||
|
|
@ -684,7 +672,7 @@ public:
|
|||
});
|
||||
#endif // HAVE_ISATTY
|
||||
|
||||
OPTION(report_t, payee_as_account);
|
||||
OPTION(report_t, payee_);
|
||||
|
||||
OPTION_(report_t, pending, DO() { // -C
|
||||
parent->HANDLER(limit_).on(string("--pending"), "pending");
|
||||
|
|
@ -808,10 +796,6 @@ public:
|
|||
});
|
||||
|
||||
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
|
||||
on_with(args[0].as_string(), args[1]);
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@ session_t::session_t()
|
|||
std::size_t session_t::read_data(const string& master_account)
|
||||
{
|
||||
bool populated_data_files = false;
|
||||
bool populated_price_db = false;
|
||||
|
||||
if (HANDLER(file_).data_files.empty()) {
|
||||
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());
|
||||
|
||||
optional<archive_t> cache;
|
||||
if (HANDLED(cache_) && master_account.empty()) {
|
||||
if (HANDLED(cache_) && master_account.empty())
|
||||
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 &&
|
||||
cache->should_load(HANDLER(file_).data_files) &&
|
||||
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)
|
||||
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) {
|
||||
|
|
@ -153,8 +145,6 @@ std::size_t session_t::read_data(const string& master_account)
|
|||
|
||||
if (populated_data_files)
|
||||
HANDLER(file_).data_files.clear();
|
||||
else if (populated_price_db)
|
||||
HANDLER(file_).data_files.remove(*price_db_path);
|
||||
|
||||
VERIFY(journal->valid());
|
||||
|
||||
|
|
@ -166,8 +156,8 @@ void session_t::read_journal_files()
|
|||
INFO_START(journal, "Read journal file");
|
||||
|
||||
string master_account;
|
||||
if (HANDLED(account_))
|
||||
master_account = HANDLER(account_).str();
|
||||
if (HANDLED(master_account_))
|
||||
master_account = HANDLER(master_account_).str();
|
||||
|
||||
std::size_t count = read_data(master_account);
|
||||
if (count == 0)
|
||||
|
|
@ -197,9 +187,6 @@ option_t<session_t> * session_t::lookup_option(const char * p)
|
|||
case 'Z':
|
||||
OPT_CH(price_exp_);
|
||||
break;
|
||||
case 'a':
|
||||
OPT_(account_); // -a
|
||||
break;
|
||||
case 'c':
|
||||
OPT(cache_);
|
||||
break;
|
||||
|
|
@ -218,6 +205,9 @@ option_t<session_t> * session_t::lookup_option(const char * p)
|
|||
case 'l':
|
||||
OPT_ALT(price_exp_, leeway_);
|
||||
break;
|
||||
case 'm':
|
||||
OPT(master_account_);
|
||||
break;
|
||||
case 'p':
|
||||
OPT(price_db_);
|
||||
else OPT(price_exp_);
|
||||
|
|
|
|||
|
|
@ -87,12 +87,12 @@ public:
|
|||
|
||||
void report_options(std::ostream& out)
|
||||
{
|
||||
HANDLER(account_).report(out);
|
||||
HANDLER(cache_).report(out);
|
||||
HANDLER(download).report(out);
|
||||
HANDLER(european).report(out);
|
||||
HANDLER(file_).report(out);
|
||||
HANDLER(input_date_format_).report(out);
|
||||
HANDLER(master_account_).report(out);
|
||||
HANDLER(price_db_).report(out);
|
||||
HANDLER(price_exp_).report(out);
|
||||
HANDLER(strict).report(out);
|
||||
|
|
@ -107,7 +107,6 @@ public:
|
|||
* Option handlers
|
||||
*/
|
||||
|
||||
OPTION(session_t, account_); // -a
|
||||
OPTION(session_t, cache_);
|
||||
OPTION(session_t, download); // -Q
|
||||
|
||||
|
|
@ -141,6 +140,7 @@ public:
|
|||
set_input_date_format(args[1].as_string().c_str());
|
||||
});
|
||||
|
||||
OPTION(session_t, master_account_);
|
||||
OPTION(session_t, price_db_);
|
||||
OPTION(session_t, strict);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ temporaries_t::~temporaries_t()
|
|||
if (! post.xact->has_flags(ITEM_TEMP))
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
29
src/value.cc
29
src/value.cc
|
|
@ -279,6 +279,35 @@ void value_t::in_place_simplify()
|
|||
#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)
|
||||
{
|
||||
if (is_string()) {
|
||||
|
|
|
|||
|
|
@ -761,6 +761,8 @@ public:
|
|||
}
|
||||
void in_place_simplify();
|
||||
|
||||
value_t number() const;
|
||||
|
||||
/**
|
||||
* Annotated commodity methods.
|
||||
*/
|
||||
|
|
|
|||
32
src/xact.cc
32
src/xact.cc
|
|
@ -83,6 +83,20 @@ void xact_base_t::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()
|
||||
{
|
||||
// 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(_("Unbalanced remainder is:"));
|
||||
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"));
|
||||
}
|
||||
|
||||
|
|
@ -368,26 +384,12 @@ void xact_t::add_post(post_t * 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
|
||||
{
|
||||
std::ostringstream buf;
|
||||
buf << format_date(*_date, FMT_WRITTEN);
|
||||
buf << payee;
|
||||
magnitude().print(buf);
|
||||
magnitude().number().print(buf);
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,6 +84,8 @@ public:
|
|||
return posts.end();
|
||||
}
|
||||
|
||||
value_t magnitude() const;
|
||||
|
||||
virtual bool finalize();
|
||||
|
||||
void clear_xdata();
|
||||
|
|
@ -129,7 +131,6 @@ public:
|
|||
|
||||
virtual void add_post(post_t * post);
|
||||
|
||||
value_t magnitude() const;
|
||||
string idstring() const;
|
||||
string id() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,11 @@
|
|||
bal --account=Master
|
||||
reg --account='payee + ":" + commodity'
|
||||
<<<
|
||||
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
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
reg --code-as-account
|
||||
reg --account=code
|
||||
<<<
|
||||
2008/01/01 * (100) January
|
||||
Expenses:Books $10.00
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
reg --code-as-payee
|
||||
reg --payee=code
|
||||
<<<
|
||||
2008/01/01 * (100) January
|
||||
Expenses:Books $10.00
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
reg --commodity-as-account
|
||||
reg --account=commodity
|
||||
<<<
|
||||
2007/02/02 RD VMMXX
|
||||
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
reg --commodity-as-payee
|
||||
reg --payee=commodity
|
||||
<<<
|
||||
2007/02/02 RD VMMXX
|
||||
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
|
||||
|
|
|
|||
15
test/baseline/opt-master-account.test
Normal file
15
test/baseline/opt-master-account.test
Normal 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
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
reg --payee-as-account
|
||||
reg --account=payee
|
||||
<<<
|
||||
2008/01/01 * (100) January
|
||||
Expenses:Books $10.00
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
reg --set-payee='account_base + ":" + commodity'
|
||||
reg --payee='account_base + ":" + commodity'
|
||||
<<<
|
||||
2007/02/02 RD VMMXX
|
||||
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
|
||||
|
|
@ -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
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
bal checking --set-reported-account=code
|
||||
bal checking --account=code
|
||||
<<<
|
||||
2009/10/29 (XFER) Panera Bread
|
||||
Expenses:Food $4.50
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Expenses:Food $4.50
|
||||
|
|
|
|||
|
|
@ -14,5 +14,7 @@ While balancing transaction from "$FILE", lines 3-5:
|
|||
> Account2 -1000 EUR @ 1.5 USD
|
||||
Unbalanced remainder is:
|
||||
100.00 USD
|
||||
Amount to balance against:
|
||||
1,600.0 USD
|
||||
Error: Transaction does not balance
|
||||
=== 1
|
||||
|
|
|
|||
|
|
@ -210,12 +210,10 @@ libledger_python_la_SOURCES = \
|
|||
src/py_balance.cc \
|
||||
src/py_commodity.cc \
|
||||
src/py_expr.cc \
|
||||
src/py_flags.cc \
|
||||
src/py_format.cc \
|
||||
src/py_item.cc \
|
||||
src/py_journal.cc \
|
||||
src/py_post.cc \
|
||||
src/py_scope.cc \
|
||||
src/py_times.cc \
|
||||
src/py_utils.cc \
|
||||
src/py_value.cc \
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue