Merge branch 'next'

This commit is contained in:
John Wiegley 2009-11-03 12:09:23 -05:00
commit 94b2518c41
18 changed files with 1152 additions and 518 deletions

View file

@ -770,7 +770,7 @@ commodity_t& amount_t::commodity() const
bool amount_t::has_commodity() const
{
return commodity_ && commodity_ != commodity_->parent().null_commodity;
return commodity_ && commodity_ != commodity_->pool().null_commodity;
}
void amount_t::annotate(const annotation_t& details)
@ -795,7 +795,7 @@ void amount_t::annotate(const annotation_t& details)
<< *this << std::endl << details);
if (commodity_t * ann_comm =
this_base->parent().find_or_create(*this_base, details))
this_base->pool().find_or_create(*this_base, details))
set_commodity(*ann_comm);
#ifdef ASSERTS_ON
else

View file

@ -185,12 +185,12 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep)
(keep_date && details.date) ||
(keep_tag && details.tag))
{
new_comm = parent().find_or_create
new_comm = pool().find_or_create
(referent(), annotation_t(keep_price ? details.price : none,
keep_date ? details.date : none,
keep_tag ? details.tag : none));
} else {
new_comm = parent().find_or_create(base_symbol());
new_comm = pool().find_or_create(base_symbol());
}
assert(new_comm);
@ -199,7 +199,7 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep)
void annotated_commodity_t::write_annotations(std::ostream& out) const
{
details.print(out, parent().keep_base);
details.print(out, pool().keep_base);
}
} // namespace ledger

View file

@ -375,7 +375,7 @@ commodity_t::check_for_updated_price(const optional<price_point_t>& point,
const optional<datetime_t>& moment,
const optional<commodity_t&>& in_terms_of)
{
if (parent().get_quotes && ! has_flags(COMMODITY_NOMARKET)) {
if (pool().get_quotes && ! has_flags(COMMODITY_NOMARKET)) {
bool exceeds_leeway = true;
if (point) {
@ -389,8 +389,8 @@ commodity_t::check_for_updated_price(const optional<price_point_t>& point,
DEBUG("commodity.download", "slip.now = " << seconds_diff);
}
DEBUG("commodity.download", "leeway = " << parent().quote_leeway);
if (seconds_diff < parent().quote_leeway)
DEBUG("commodity.download", "leeway = " << pool().quote_leeway);
if (seconds_diff < pool().quote_leeway)
exceeds_leeway = false;
}
@ -398,7 +398,7 @@ commodity_t::check_for_updated_price(const optional<price_point_t>& point,
DEBUG("commodity.download",
"attempting to download a more current quote...");
if (optional<price_point_t> quote =
parent().get_commodity_quote(*this, in_terms_of)) {
pool().get_commodity_quote(*this, in_terms_of)) {
if (! in_terms_of ||
(quote->price.has_commodity() &&
quote->price.commodity() == *in_terms_of))
@ -411,7 +411,7 @@ commodity_t::check_for_updated_price(const optional<price_point_t>& point,
commodity_t::operator bool() const
{
return this != parent().null_commodity;
return this != pool().null_commodity;
}
bool commodity_t::symbol_needs_quotes(const string& symbol)
@ -568,7 +568,7 @@ void commodity_t::parse_symbol(char *& p, string& symbol)
bool commodity_t::valid() const
{
if (symbol().empty() && this != parent().null_commodity) {
if (symbol().empty() && this != pool().null_commodity) {
DEBUG("ledger.validate",
"commodity_t: symbol().empty() && this != null_commodity");
return false;

View file

@ -222,8 +222,6 @@ protected:
#endif // HAVE_BOOST_SERIALIZATION
};
static bool symbol_needs_quotes(const string& symbol);
shared_ptr<base_t> base;
commodity_pool_t * parent_;
@ -247,28 +245,31 @@ public:
operator bool() const;
bool is_annotated() const {
return annotated;
}
virtual bool operator==(const commodity_t& comm) const {
if (comm.annotated)
return comm == *this;
return base.get() == comm.base.get();
}
static bool symbol_needs_quotes(const string& symbol);
virtual commodity_t& referent() {
return *this;
}
virtual const commodity_t& referent() const {
return *this;
}
bool is_annotated() const {
return annotated;
}
virtual commodity_t& strip_annotations(const keep_details_t&) {
return *this;
}
virtual void write_annotations(std::ostream&) const {}
commodity_pool_t& parent() const {
commodity_pool_t& pool() const {
return *parent_;
}
@ -329,7 +330,6 @@ public:
optional<history_t&> history(const optional<commodity_t&>& commodity);
public:
// These methods provide a transparent pass-through to the underlying
// base->varied_history object.

View file

@ -118,7 +118,7 @@ string commodity_pool_t::make_qualified_name(const commodity_t& comm,
std::ostringstream name;
comm.print(name);
details.print(name, comm.parent().keep_base);
details.print(name, comm.pool().keep_base);
DEBUG("amounts.commodities", "make_qualified_name for "
<< *comm.qualified_symbol << std::endl << details);

222
src/py_account.cc Normal file
View file

@ -0,0 +1,222 @@
/*
* 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"
#include "account.h"
#include "post.h"
namespace ledger {
using namespace boost::python;
namespace {
long accounts_len(account_t& account)
{
return account.accounts.size();
}
account_t& accounts_getitem(account_t& account, long i)
{
static long last_index = 0;
static account_t * last_account = NULL;
static accounts_map::iterator elem;
long len = account.accounts.size();
if (labs(i) >= len) {
PyErr_SetString(PyExc_IndexError, _("Index out of range"));
throw_error_already_set();
}
if (&account == last_account && i == last_index + 1) {
last_index = i;
return *(*++elem).second;
}
long x = i < 0 ? len + i : i;
elem = account.accounts.begin();
while (--x >= 0)
elem++;
last_account = &account;
last_index = i;
return *(*elem).second;
}
account_t * py_find_account_1(journal_t& journal, const string& name)
{
return journal.find_account(name);
}
account_t * py_find_account_2(journal_t& journal, const string& name,
const bool auto_create)
{
return journal.find_account(name, auto_create);
}
account_t::xdata_t& py_xdata(account_t& account) {
return account.xdata();
}
} // unnamed namespace
void export_account()
{
scope().attr("ACCOUNT_EXT_SORT_CALC") = ACCOUNT_EXT_SORT_CALC;
scope().attr("ACCOUNT_EXT_HAS_NON_VIRTUALS") = ACCOUNT_EXT_HAS_NON_VIRTUALS;
scope().attr("ACCOUNT_EXT_HAS_UNB_VIRTUALS") = ACCOUNT_EXT_HAS_UNB_VIRTUALS;
scope().attr("ACCOUNT_EXT_AUTO_VIRTUALIZE") = ACCOUNT_EXT_AUTO_VIRTUALIZE;
scope().attr("ACCOUNT_EXT_VISITED") = ACCOUNT_EXT_VISITED;
scope().attr("ACCOUNT_EXT_MATCHING") = ACCOUNT_EXT_MATCHING;
scope().attr("ACCOUNT_EXT_TO_DISPLAY") = ACCOUNT_EXT_TO_DISPLAY;
scope().attr("ACCOUNT_EXT_DISPLAYED") = ACCOUNT_EXT_DISPLAYED;
class_< account_t::xdata_t::details_t > ("AccountXDataDetails")
.def_readonly("total", &account_t::xdata_t::details_t::total)
.def_readonly("calculated", &account_t::xdata_t::details_t::calculated)
.def_readonly("gathered", &account_t::xdata_t::details_t::gathered)
.def_readonly("posts_count", &account_t::xdata_t::details_t::posts_count)
.def_readonly("posts_virtuals_count",
&account_t::xdata_t::details_t::posts_virtuals_count)
.def_readonly("posts_cleared_count",
&account_t::xdata_t::details_t::posts_cleared_count)
.def_readonly("posts_last_7_count",
&account_t::xdata_t::details_t::posts_last_7_count)
.def_readonly("posts_last_30_count",
&account_t::xdata_t::details_t::posts_last_30_count)
.def_readonly("posts_this_month_count",
&account_t::xdata_t::details_t::posts_this_month_count)
.def_readonly("earliest_post",
&account_t::xdata_t::details_t::earliest_post)
.def_readonly("earliest_cleared_post",
&account_t::xdata_t::details_t::earliest_cleared_post)
.def_readonly("latest_post",
&account_t::xdata_t::details_t::latest_post)
.def_readonly("latest_cleared_post",
&account_t::xdata_t::details_t::latest_cleared_post)
.def_readonly("filenames", &account_t::xdata_t::details_t::filenames)
.def_readonly("accounts_referenced",
&account_t::xdata_t::details_t::accounts_referenced)
.def_readonly("payees_referenced",
&account_t::xdata_t::details_t::payees_referenced)
.def(self += self)
.def("update", &account_t::xdata_t::details_t::update)
;
class_< account_t::xdata_t > ("AccountXData")
#if 1
.def("flags", &supports_flags<uint_least16_t>::flags)
.def("has_flags", &supports_flags<uint_least16_t>::has_flags)
.def("set_flags", &supports_flags<uint_least16_t>::set_flags)
.def("clear_flags", &supports_flags<uint_least16_t>::clear_flags)
.def("add_flags", &supports_flags<uint_least16_t>::add_flags)
.def("drop_flags", &supports_flags<uint_least16_t>::drop_flags)
#endif
.def_readonly("self_details", &account_t::xdata_t::self_details)
.def_readonly("family_details", &account_t::xdata_t::family_details)
.def_readonly("reported_posts", &account_t::xdata_t::reported_posts)
.def_readonly("sort_values", &account_t::xdata_t::sort_values)
;
scope().attr("ACCOUNT_NORMAL") = ACCOUNT_NORMAL;
scope().attr("ACCOUNT_KNOWN") = ACCOUNT_KNOWN;
scope().attr("ACCOUNT_TEMP") = ACCOUNT_TEMP;
class_< account_t > ("Account")
#if 1
.def("flags", &supports_flags<>::flags)
.def("has_flags", &supports_flags<>::has_flags)
.def("set_flags", &supports_flags<>::set_flags)
.def("clear_flags", &supports_flags<>::clear_flags)
.def("add_flags", &supports_flags<>::add_flags)
.def("drop_flags", &supports_flags<>::drop_flags)
#endif
.add_property("parent",
make_getter(&account_t::parent,
return_value_policy<reference_existing_object>()))
.def_readwrite("name", &account_t::name)
.def_readwrite("note", &account_t::note)
.def_readonly("depth", &account_t::depth)
.def_readonly("accounts", &account_t::accounts)
.def_readonly("posts", &account_t::posts)
.def(self_ns::str(self))
.def("fullname", &account_t::fullname)
.def("partial_name", &account_t::partial_name)
.def("add_account", &account_t::add_account)
.def("remove_account", &account_t::remove_account)
.def("find_account", &account_t::find_account,
return_value_policy<reference_existing_object>())
.def("find_account_re", &account_t::find_account,
return_value_policy<reference_existing_object>())
.def("add_post", &account_t::add_post)
.def("remove_post", &account_t::remove_post)
.def("valid", &account_t::valid)
.def("__len__", accounts_len)
.def("__getitem__", accounts_getitem, return_internal_reference<1>())
.def("has_xdata", &account_t::has_xdata)
.def("clear_xdata", &account_t::clear_xdata)
.def("xdata", py_xdata,
return_value_policy<reference_existing_object>())
.def("amount", &account_t::amount)
.def("total", &account_t::total)
.def("self_details", &account_t::self_details,
return_value_policy<reference_existing_object>())
.def("family_details", &account_t::family_details,
return_value_policy<reference_existing_object>())
.def("has_xflags", &account_t::has_xflags)
.def("children_with_flags", &account_t::children_with_flags)
;
}
} // namespace ledger

View file

@ -282,9 +282,6 @@ internal precision."))
.def("parse_conversion", &amount_t::parse_conversion)
.staticmethod("parse_conversion")
.def("print_", py_print)
.def("dump", &amount_t::dump)
.def("valid", &amount_t::valid)
;

View file

@ -211,9 +211,6 @@ void export_balance()
.def("strip_annotations", &balance_t::strip_annotations)
.def("print_", py_print)
.def("dump", &balance_t::dump)
.def("valid", &balance_t::valid)
;

View file

@ -33,20 +33,149 @@
#include "pyinterp.h"
#include "commodity.h"
#include "annotate.h"
#include "pool.h"
namespace ledger {
using namespace boost::python;
void py_add_price(commodity_t& commodity,
const datetime_t& date,
const amount_t& price)
{
commodity.add_price(date, price);
}
namespace {
commodity_t * py_create_1(commodity_pool_t& pool,
const string& symbol)
{
return pool.create(symbol);
}
commodity_t * py_create_2(commodity_pool_t& pool,
const string& symbol,
const annotation_t& details)
{
return pool.create(symbol, details);
}
commodity_t * py_find_or_create_1(commodity_pool_t& pool,
const string& symbol)
{
return pool.find_or_create(symbol);
}
commodity_t * py_find_or_create_2(commodity_pool_t& pool,
const string& symbol,
const annotation_t& details)
{
return pool.find_or_create(symbol, details);
}
commodity_t * py_find_1(commodity_pool_t& pool,
const string& name)
{
return pool.find(name);
}
commodity_t * py_find_2(commodity_pool_t& pool,
const string& symbol,
const annotation_t& details)
{
return pool.find(symbol, details);
}
// Exchange one commodity for another, while recording the factored price.
void py_exchange_3(commodity_pool_t& pool,
commodity_t& commodity,
const amount_t& per_unit_cost,
const datetime_t& moment)
{
pool.exchange(commodity, per_unit_cost, moment);
}
cost_breakdown_t py_exchange_5(commodity_pool_t& pool,
const amount_t& amount,
const amount_t& cost,
const bool is_per_unit,
const boost::optional<datetime_t>& moment,
const boost::optional<string>& tag)
{
return pool.exchange(amount, cost, is_per_unit, moment, tag);
}
void py_add_price_2(commodity_t& commodity,
const datetime_t& date, const amount_t& price) {
commodity.add_price(date, price);
}
void py_add_price_3(commodity_t& commodity, const datetime_t& date,
const amount_t& price, const bool reflexive) {
commodity.add_price(date, price, reflexive);
}
bool py_keep_all_0(keep_details_t& details) {
return details.keep_all();
}
bool py_keep_all_1(keep_details_t& details, const commodity_t& comm) {
return details.keep_all(comm);
}
bool py_keep_any_0(keep_details_t& details) {
return details.keep_any();
}
bool py_keep_any_1(keep_details_t& details, const commodity_t& comm) {
return details.keep_any(comm);
}
} // unnamed namespace
void export_commodity()
{
class_< commodity_pool_t, boost::noncopyable > ("CommodityPool", no_init)
.add_property("null_commodity",
make_getter(&commodity_pool_t::null_commodity,
return_value_policy<reference_existing_object>()),
make_setter(&commodity_pool_t::null_commodity,
with_custodian_and_ward<1, 2>()))
.add_property("default_commodity",
make_getter(&commodity_pool_t::default_commodity,
return_value_policy<reference_existing_object>()),
make_setter(&commodity_pool_t::default_commodity,
with_custodian_and_ward<1, 2>()))
.add_property("keep_base",
make_getter(&commodity_pool_t::keep_base),
make_setter(&commodity_pool_t::keep_base))
.add_property("price_db",
make_getter(&commodity_pool_t::price_db),
make_setter(&commodity_pool_t::price_db))
.add_property("quote_leeway",
make_getter(&commodity_pool_t::quote_leeway),
make_setter(&commodity_pool_t::quote_leeway))
.add_property("get_quotes",
make_getter(&commodity_pool_t::get_quotes),
make_setter(&commodity_pool_t::get_quotes))
.add_property("get_commodity_quote",
make_getter(&commodity_pool_t::get_commodity_quote),
make_setter(&commodity_pool_t::get_commodity_quote))
.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("find_or_create", py_find_or_create_1,
return_value_policy<reference_existing_object>())
.def("find_or_create", py_find_or_create_2,
return_value_policy<reference_existing_object>())
.def("find", py_find_1, return_value_policy<reference_existing_object>())
.def("find", py_find_2, return_value_policy<reference_existing_object>())
.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>())
;
scope().attr("COMMODITY_STYLE_DEFAULTS") = COMMODITY_STYLE_DEFAULTS;
scope().attr("COMMODITY_STYLE_SUFFIXED") = COMMODITY_STYLE_SUFFIXED;
scope().attr("COMMODITY_STYLE_SEPARATED") = COMMODITY_STYLE_SEPARATED;
@ -55,29 +184,136 @@ void export_commodity()
scope().attr("COMMODITY_NOMARKET") = COMMODITY_NOMARKET;
scope().attr("COMMODITY_BUILTIN") = COMMODITY_BUILTIN;
scope().attr("COMMODITY_WALKED") = COMMODITY_WALKED;
scope().attr("COMMODITY_KNOWN") = COMMODITY_KNOWN;
scope().attr("COMMODITY_PRIMARY") = COMMODITY_PRIMARY;
class_< commodity_t, boost::noncopyable > ("Commodity", no_init)
#if 1
.def("flags", &delegates_flags<uint_least16_t>::flags)
.def("has_flags", &delegates_flags<uint_least16_t>::has_flags)
.def("set_flags", &delegates_flags<uint_least16_t>::set_flags)
.def("clear_flags", &delegates_flags<uint_least16_t>::clear_flags)
.def("add_flags", &delegates_flags<uint_least16_t>::add_flags)
.def("drop_flags", &delegates_flags<uint_least16_t>::drop_flags)
#endif
.add_static_property("european_by_default",
make_getter(&commodity_t::european_by_default),
make_setter(&commodity_t::european_by_default))
.def("__nonzero__", &commodity_t::operator bool)
class_< commodity_t, bases<>,
commodity_t, boost::noncopyable > ("Commodity", no_init)
.def(self == self)
.def("drop_flags", &commodity_t::drop_flags)
.def("add_price", py_add_price)
.def("precision", &commodity_t::precision)
;
.def("symbol_needs_quotes", &commodity_t::symbol_needs_quotes)
.staticmethod("symbol_needs_quotes")
#if 0
class_< annotation_t, bases<>,
commodity_t, boost::noncopyable > ("Annotation", no_init)
;
class_< keep_details_t, bases<>,
commodity_t, boost::noncopyable > ("KeepDetails", no_init)
;
class_< annotated_commodity_t, bases<>,
commodity_t, boost::noncopyable > ("AnnotatedCommodity", no_init)
;
.def("referent", &commodity_t::referent,
return_value_policy<reference_existing_object>())
#endif
.def("is_annotated", &commodity_t::is_annotated)
.def("strip_annotations", &commodity_t::strip_annotations,
return_value_policy<reference_existing_object>())
.def("write_annotations", &commodity_t::write_annotations)
.def("pool", &commodity_t::pool,
return_value_policy<reference_existing_object>())
.def("base_symbol", &commodity_t::base_symbol)
.def("symbol", &commodity_t::symbol)
.def("mapping_key", &commodity_t::mapping_key)
.def("name", &commodity_t::name)
.def("set_name", &commodity_t::set_name)
.def("note", &commodity_t::note)
.def("set_note", &commodity_t::set_note)
.def("precision", &commodity_t::precision)
.def("set_precision", &commodity_t::set_precision)
.def("smaller", &commodity_t::smaller)
.def("set_smaller", &commodity_t::set_smaller)
.def("larger", &commodity_t::larger)
.def("set_larger", &commodity_t::set_larger)
.def("add_price", py_add_price_2)
.def("add_price", py_add_price_3)
.def("remove_price", &commodity_t::remove_price,
with_custodian_and_ward<1, 3>())
.def("find_price", &commodity_t::find_price)
.def("check_for_updated_price", &commodity_t::check_for_updated_price)
.def("valid", &commodity_t::valid)
;
class_< annotation_t > ("Annotation", no_init)
#if 1
.def("flags", &supports_flags<>::flags)
.def("has_flags", &supports_flags<>::has_flags)
.def("set_flags", &supports_flags<>::set_flags)
.def("clear_flags", &supports_flags<>::clear_flags)
.def("add_flags", &supports_flags<>::add_flags)
.def("drop_flags", &supports_flags<>::drop_flags)
#endif
.add_property("price",
make_getter(&annotation_t::price),
make_setter(&annotation_t::price))
.add_property("date",
make_getter(&annotation_t::date),
make_setter(&annotation_t::date))
.add_property("tag",
make_getter(&annotation_t::tag),
make_setter(&annotation_t::tag))
.def("__nonzero__", &annotation_t::operator bool)
.def(self == self)
.def("valid", &annotation_t::valid)
;
class_< keep_details_t > ("KeepDetails")
.def(init<bool, bool, bool, bool>())
.add_property("keep_price",
make_getter(&keep_details_t::keep_price),
make_setter(&keep_details_t::keep_price))
.add_property("keep_date",
make_getter(&keep_details_t::keep_date),
make_setter(&keep_details_t::keep_date))
.add_property("keep_tag",
make_getter(&keep_details_t::keep_tag),
make_setter(&keep_details_t::keep_tag))
.add_property("only_actuals",
make_getter(&keep_details_t::only_actuals),
make_setter(&keep_details_t::only_actuals))
.def("keep_all", py_keep_all_0)
.def("keep_all", py_keep_all_1)
.def("keep_any", py_keep_any_0)
.def("keep_any", py_keep_any_1)
;
class_< annotated_commodity_t, bases<commodity_t>,
annotated_commodity_t, boost::noncopyable >
("AnnotatedCommodity", no_init)
.add_property("details",
make_getter(&annotated_commodity_t::details),
make_setter(&annotated_commodity_t::details))
.def(self == self)
.def(self == other<commodity_t>())
#if 0
.def("referent", &annotated_commodity_t::referent,
return_value_policy<reference_existing_object>())
#endif
.def("strip_annotations", &annotated_commodity_t::strip_annotations,
return_value_policy<reference_existing_object>())
.def("write_annotations", &annotated_commodity_t::write_annotations)
;
}
} // namespace ledger

View file

@ -32,11 +32,40 @@
#include <system.hh>
#include "pyinterp.h"
#include "scope.h"
#include "mask.h"
#include "item.h"
namespace ledger {
using namespace boost::python;
namespace {
bool py_has_tag_1s(item_t& item, const string& tag) {
return item.has_tag(tag);
}
bool py_has_tag_1m(item_t& item, const mask_t& tag_mask) {
return item.has_tag(tag_mask);
}
bool py_has_tag_2m(item_t& item, const mask_t& tag_mask,
const boost::optional<mask_t>& value_mask) {
return item.has_tag(tag_mask, value_mask);
}
boost::optional<string> py_get_tag_1s(item_t& item, const string& tag) {
return item.get_tag(tag);
}
boost::optional<string> py_get_tag_1m(item_t& item, const mask_t& tag_mask) {
return item.get_tag(tag_mask);
}
boost::optional<string> py_get_tag_2m(item_t& item, const mask_t& tag_mask,
const boost::optional<mask_t>& value_mask) {
return item.get_tag(tag_mask, value_mask);
}
} // unnamed namespace
#define EXC_TRANSLATOR(type) \
void exc_translate_ ## type(const type& err) { \
PyErr_SetString(PyExc_ArithmeticError, err.what()); \
@ -46,19 +75,89 @@ using namespace boost::python;
void export_item()
{
#if 0
class_< item_t > ("Item")
class_< position_t > ("Position")
.add_property("pathname",
make_getter(&position_t::pathname),
make_setter(&position_t::pathname))
.add_property("beg_pos",
make_getter(&position_t::beg_pos),
make_setter(&position_t::beg_pos))
.add_property("beg_line",
make_getter(&position_t::beg_line),
make_setter(&position_t::beg_line))
.add_property("end_pos",
make_getter(&position_t::end_pos),
make_setter(&position_t::end_pos))
.add_property("end_line",
make_getter(&position_t::end_line),
make_setter(&position_t::end_line))
;
scope().attr("ITEM_NORMAL") = ITEM_NORMAL;
scope().attr("ITEM_GENERATED") = ITEM_GENERATED;
scope().attr("ITEM_TEMP") = ITEM_TEMP;
enum_< item_t::state_t > ("State")
.value("Uncleared", item_t::UNCLEARED)
.value("Cleared", item_t::CLEARED)
.value("Pending", item_t::PENDING)
;
#if 0
class_< item_t, bases<scope_t> > ("JournalItem", init<uint_least8_t>())
#else
class_< item_t > ("JournalItem", init<uint_least8_t>())
#endif
#if 1
.def("flags", &supports_flags<>::flags)
.def("has_flags", &supports_flags<>::has_flags)
.def("set_flags", &supports_flags<>::set_flags)
.def("clear_flags", &supports_flags<>::clear_flags)
.def("add_flags", &supports_flags<>::add_flags)
.def("drop_flags", &supports_flags<>::drop_flags)
#endif
//register_optional_to_python<amount_t>();
.add_property("note",
make_getter(&item_t::note),
make_setter(&item_t::note))
.add_property("pos",
make_getter(&item_t::pos),
make_setter(&item_t::pos))
.add_property("metadata",
make_getter(&item_t::metadata),
make_setter(&item_t::metadata))
//implicitly_convertible<string, amount_t>();
.def("copy_details", &item_t::copy_details)
#define EXC_TRANSLATE(type) \
register_exception_translator<type>(&exc_translate_ ## type);
.def(self == self)
.def(self != self)
//EXC_TRANSLATE(item_error);
.def("has_tag", py_has_tag_1s)
.def("has_tag", py_has_tag_1m)
.def("has_tag", py_has_tag_2m)
.def("get_tag", py_get_tag_1s)
.def("get_tag", py_get_tag_1m)
.def("get_tag", py_get_tag_2m)
.def("set_tag", &item_t::set_tag)
.def("parse_tags", &item_t::parse_tags)
.def("append_note", &item_t::append_note)
.add_static_property("use_effective_date",
make_getter(&item_t::use_effective_date),
make_setter(&item_t::use_effective_date))
.def("date", &item_t::date)
.def("effective_date", &item_t::effective_date)
.def("set_state", &item_t::set_state)
.def("state", &item_t::state)
.def("lookup", &item_t::lookup)
.def("valid", &item_t::valid)
;
}
} // namespace ledger

View file

@ -32,334 +32,176 @@
#include <system.hh>
#include "pyinterp.h"
#include "pyutils.h"
#include "hooks.h"
#include "journal.h"
#include "xact.h"
namespace ledger {
using namespace boost::python;
#define EXC_TRANSLATOR(type) \
void exc_translate_ ## type(const type& err) { \
PyErr_SetString(PyExc_ArithmeticError, err.what()); \
namespace {
account_t& py_account_master(journal_t& journal) {
return *journal.master;
}
//EXC_TRANSLATOR(journal_error)
void export_journal()
{
#if 0
class_< journal_t > ("Journal")
;
#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(journal_error);
}
} // namespace ledger
#if 0
xact_t& post_xact(const post_t& post)
{
return *post.xact;
}
unsigned int posts_len(xact_base_t& xact)
{
return xact.posts.size();
}
post_t& posts_getitem(xact_base_t& xact, int i)
{
static int last_index = 0;
static xact_base_t * last_xact = NULL;
static posts_list::iterator elem;
std::size_t len = xact.posts.size();
if (abs(i) >= len) {
PyErr_SetString(PyExc_IndexError, _("Index out of range"));
throw_error_already_set();
commodity_pool_t& py_commodity_pool(journal_t& journal) {
return *journal.commodity_pool;
}
if (&xact == last_xact && i == last_index + 1) {
last_index = i;
return **++elem;
long xacts_len(journal_t& journal)
{
return journal.xacts.size();
}
int x = i < 0 ? len + i : i;
elem = xact.posts.begin();
while (--x >= 0)
elem++;
xact_t& xacts_getitem(journal_t& journal, long i)
{
static long last_index = 0;
static journal_t * last_journal = NULL;
static xacts_list::iterator elem;
last_xact = &xact;
last_index = i;
long len = journal.xacts.size();
return **elem;
}
unsigned int xacts_len(journal_t& journal)
{
return journal.xacts.size();
}
xact_t& xacts_getitem(journal_t& journal, int i)
{
static int last_index = 0;
static journal_t * last_journal = NULL;
static xacts_list::iterator elem;
std::size_t len = journal.xacts.size();
if (abs(i) >= len) {
PyErr_SetString(PyExc_IndexError, _("Index out of range"));
throw_error_already_set();
}
if (&journal == last_journal && i == last_index + 1) {
last_index = i;
return **++elem;
}
int x = i < 0 ? len + i : i;
elem = journal.xacts.begin();
while (--x >= 0)
elem++;
last_journal = &journal;
last_index = i;
return **elem;
}
unsigned int accounts_len(account_t& account)
{
return account.accounts.size();
}
account_t& accounts_getitem(account_t& account, int i)
{
static int last_index = 0;
static account_t * last_account = NULL;
static accounts_map::iterator elem;
std::size_t len = account.accounts.size();
if (abs(i) >= len) {
PyErr_SetString(PyExc_IndexError, _("Index out of range"));
throw_error_already_set();
}
if (&account == last_account && i == last_index + 1) {
last_index = i;
return *(*++elem).second;
}
int x = i < 0 ? len + i : i;
elem = account.accounts.begin();
while (--x >= 0)
elem++;
last_account = &account;
last_index = i;
return *(*elem).second;
}
account_t * py_find_account_1(journal_t& journal, const string& name)
{
return journal.find_account(name);
}
account_t * py_find_account_2(journal_t& journal, const string& name,
const bool auto_create)
{
return journal.find_account(name, auto_create);
}
bool py_add_xact(journal_t& journal, xact_t * xact) {
return journal.add_xact(new xact_t(*xact));
}
void py_add_post(xact_base_t& xact, post_t * post) {
return xact.add_post(new post_t(*post));
}
struct xact_base_wrap : public xact_base_t
{
PyObject * self;
xact_base_wrap(PyObject * self_) : self(self_) {}
virtual bool valid() const {
return call_method<bool>(self, "valid");
}
};
struct py_xact_finalizer_t : public xact_finalizer_t {
object pyobj;
py_xact_finalizer_t() {}
py_xact_finalizer_t(object obj) : pyobj(obj) {}
py_xact_finalizer_t(const py_xact_finalizer_t& other)
: pyobj(other.pyobj) {}
virtual bool operator()(xact_t& xact, bool post) {
return call<bool>(pyobj.ptr(), xact, post);
}
};
std::list<py_xact_finalizer_t> py_finalizers;
void py_add_xact_finalizer(journal_t& journal, object x)
{
py_finalizers.push_back(py_xact_finalizer_t(x));
journal.add_xact_finalizer(&py_finalizers.back());
}
void py_remove_xact_finalizer(journal_t& journal, object x)
{
for (std::list<py_xact_finalizer_t>::iterator i = py_finalizers.begin();
i != py_finalizers.end();
i++)
if ((*i).pyobj == x) {
journal.remove_xact_finalizer(&(*i));
py_finalizers.erase(i);
return;
if (labs(i) >= len) {
PyErr_SetString(PyExc_IndexError, _("Index out of range"));
throw_error_already_set();
}
}
void py_run_xact_finalizers(journal_t& journal, xact_t& xact, bool post)
{
run_hooks(journal.xact_finalize_hooks, xact, post);
}
if (&journal == last_journal && i == last_index + 1) {
last_index = i;
return **++elem;
}
#define EXC_TRANSLATOR(type) \
void exc_translate_ ## type(const type& err) { \
PyErr_SetString(PyExc_RuntimeError, err.what()); \
long x = i < 0 ? len + i : i;
elem = journal.xacts.begin();
while (--x >= 0)
elem++;
last_journal = &journal;
last_index = i;
return **elem;
}
EXC_TRANSLATOR(balance_error)
EXC_TRANSLATOR(interval_expr_error)
EXC_TRANSLATOR(format_error)
EXC_TRANSLATOR(parse_error)
long accounts_len(account_t& account)
{
return account.accounts.size();
}
value_t py_post_amount(post_t * post) {
return value_t(post->amount);
}
account_t& accounts_getitem(account_t& account, long i)
{
static long last_index = 0;
static account_t * last_account = NULL;
static accounts_map::iterator elem;
post_t::state_t py_xact_state(xact_t * xact) {
post_t::state_t state;
if (xact->get_state(&state))
return state;
else
return post_t::UNCLEARED;
}
long len = account.accounts.size();
if (labs(i) >= len) {
PyErr_SetString(PyExc_IndexError, _("Index out of range"));
throw_error_already_set();
}
if (&account == last_account && i == last_index + 1) {
last_index = i;
return *(*++elem).second;
}
long x = i < 0 ? len + i : i;
elem = account.accounts.begin();
while (--x >= 0)
elem++;
last_account = &account;
last_index = i;
return *(*elem).second;
}
account_t * py_find_account_1(journal_t& journal, const string& name)
{
return journal.find_account(name);
}
account_t * py_find_account_2(journal_t& journal, const string& name,
const bool auto_create)
{
return journal.find_account(name, auto_create);
}
struct py_xact_finalizer_t : public xact_finalizer_t {
object pyobj;
py_xact_finalizer_t() {}
py_xact_finalizer_t(object obj) : pyobj(obj) {}
py_xact_finalizer_t(const py_xact_finalizer_t& other)
: pyobj(other.pyobj) {}
virtual bool operator()(xact_t& xact, bool post) {
return call<bool>(pyobj.ptr(), xact, post);
}
};
std::list<py_xact_finalizer_t> py_finalizers;
void py_add_xact_finalizer(journal_t& journal, object x)
{
py_finalizers.push_back(py_xact_finalizer_t(x));
journal.add_xact_finalizer(&py_finalizers.back());
}
void py_remove_xact_finalizer(journal_t& journal, object x)
{
for (std::list<py_xact_finalizer_t>::iterator i = py_finalizers.begin();
i != py_finalizers.end();
i++)
if ((*i).pyobj == x) {
journal.remove_xact_finalizer(&(*i));
py_finalizers.erase(i);
return;
}
}
void py_run_xact_finalizers(journal_t& journal, xact_t& xact, bool post)
{
journal.xact_finalize_hooks.run_hooks(xact, post);
}
} // unnamed namespace
void export_journal()
{
scope().attr("POST_NORMAL") = POST_NORMAL;
scope().attr("POST_VIRTUAL") = POST_VIRTUAL;
scope().attr("POST_BALANCE") = POST_BALANCE;
scope().attr("POST_AUTO") = POST_AUTO;
scope().attr("POST_BULK_ALLOC") = POST_BULK_ALLOC;
scope().attr("POST_CALCULATED") = POST_CALCULATED;
enum_< post_t::state_t > ("State")
.value("Uncleared", post_t::UNCLEARED)
.value("Cleared", post_t::CLEARED)
.value("Pending", post_t::PENDING)
class_< journal_t::fileinfo_t > ("FileInfo")
.add_property("filename",
make_getter(&journal_t::fileinfo_t::filename),
make_setter(&journal_t::fileinfo_t::filename))
.add_property("size",
make_getter(&journal_t::fileinfo_t::size),
make_setter(&journal_t::fileinfo_t::size))
.add_property("modtime",
make_getter(&journal_t::fileinfo_t::modtime),
make_setter(&journal_t::fileinfo_t::modtime))
.add_property("from_stream",
make_getter(&journal_t::fileinfo_t::from_stream),
make_setter(&journal_t::fileinfo_t::from_stream))
;
class_< post_t > ("Post")
.def(init<optional<account_t *> >())
.def(init<account_t *, amount_t, optional<unsigned int, const string&> >())
.def(self == self)
.def(self != self)
.add_property("xact",
make_getter(&post_t::xact,
return_value_policy<reference_existing_object>()))
.add_property("account",
make_getter(&post_t::account,
return_value_policy<reference_existing_object>()))
.add_property("amount", &py_post_amount)
.def_readonly("amount_expr", &post_t::amount_expr)
.add_property("cost",
make_getter(&post_t::cost,
return_internal_reference<1>()))
.def_readonly("cost_expr", &post_t::cost_expr)
.def_readwrite("state", &post_t::state)
.def_readwrite("flags", &post_t::flags)
.def_readwrite("note", &post_t::note)
.def_readonly("beg_pos", &post_t::beg_pos)
.def_readonly("beg_line", &post_t::beg_line)
.def_readonly("end_pos", &post_t::end_pos)
.def_readonly("end_line", &post_t::end_line)
.def("actual_date", &post_t::actual_date)
.def("effective_date", &post_t::effective_date)
.def("date", &post_t::date)
.def("use_effective_date", &post_t::use_effective_date)
.def("valid", &post_t::valid)
;
class_< account_t >
("Account", init<optional<account_t *, string, string> >()
[with_custodian_and_ward<1, 2>()])
.def(self == self)
.def(self != self)
.def(self_ns::str(self))
.def("__len__", accounts_len)
.def("__getitem__", accounts_getitem, return_internal_reference<1>())
.add_property("journal",
make_getter(&account_t::journal,
return_value_policy<reference_existing_object>()))
.add_property("parent",
make_getter(&account_t::parent,
return_value_policy<reference_existing_object>()))
.def_readwrite("name", &account_t::name)
.def_readwrite("note", &account_t::note)
.def_readonly("depth", &account_t::depth)
.def_readonly("ident", &account_t::ident)
.def("fullname", &account_t::fullname)
.def("add_account", &account_t::add_account)
.def("remove_account", &account_t::remove_account)
.def("find_account", &account_t::find_account,
return_value_policy<reference_existing_object>())
.def("valid", &account_t::valid)
;
class_< journal_t > ("Journal")
.def(self == self)
.def(self != self)
.def("__len__", xacts_len)
.def("__getitem__", xacts_getitem, return_internal_reference<1>())
class_< journal_t, boost::noncopyable > ("Journal")
.add_property("master", make_getter(&journal_t::master,
return_internal_reference<1>()))
.add_property("basket", make_getter(&journal_t::basket,
return_internal_reference<1>()))
.def_readonly("sources", &journal_t::sources)
.def_readwrite("price_db", &journal_t::price_db)
.add_property("basket",
make_getter(&journal_t::basket,
return_internal_reference<1>()),
make_setter(&journal_t::basket))
.add_property("sources", make_getter(&journal_t::sources))
.add_property("was_loaded", make_getter(&journal_t::was_loaded))
.add_property("commodity_pool",
make_getter(&journal_t::commodity_pool,
return_internal_reference<1>()))
#if 0
.add_property("xact_finalize_hooks",
make_getter(&journal_t::xact_finalize_hooks),
make_setter(&journal_t::xact_finalize_hooks))
#endif
.def("add_account", &journal_t::add_account)
.def("remove_account", &journal_t::remove_account)
@ -369,58 +211,18 @@ void export_journal()
.def("find_account_re", &journal_t::find_account_re,
return_internal_reference<1>())
.def("add_xact", py_add_xact)
.def("add_xact", &journal_t::add_xact)
.def("remove_xact", &journal_t::remove_xact)
.def("add_xact_finalizer", py_add_xact_finalizer)
.def("remove_xact_finalizer", py_remove_xact_finalizer)
.def("run_xact_finalizers", py_run_xact_finalizers)
.def("__len__", xacts_len)
.def("__getitem__", xacts_getitem, return_internal_reference<1>())
.def("valid", &journal_t::valid)
;
class_< xact_base_t, xact_base_wrap, boost::noncopyable > ("XactBase")
.def("__len__", posts_len)
.def("__getitem__", posts_getitem,
return_internal_reference<1>())
.def_readonly("journal", &xact_base_t::journal)
.def_readonly("src_idx", &xact_base_t::src_idx)
.def_readonly("beg_pos", &xact_base_t::beg_pos)
.def_readonly("beg_line", &xact_base_t::beg_line)
.def_readonly("end_pos", &xact_base_t::end_pos)
.def_readonly("end_line", &xact_base_t::end_line)
.def("add_post", py_add_post)
.def("remove_post", &xact_base_t::remove_post)
.def(self == self)
.def(self != self)
.def("finalize", &xact_base_t::finalize)
.def("valid", &xact_base_t::valid)
;
class_< xact_t, bases<xact_base_t> > ("Xact")
.add_property("date", &xact_t::date)
.add_property("effective_date", &xact_t::effective_date)
.add_property("actual_date", &xact_t::actual_date)
.def_readwrite("code", &xact_t::code)
.def_readwrite("payee", &xact_t::payee)
.add_property("state", &py_xact_state)
.def("valid", &xact_t::valid)
;
#define EXC_TRANSLATE(type) \
register_error_translator<type>(&exc_translate_ ## type);
EXC_TRANSLATE(balance_error);
EXC_TRANSLATE(interval_expr_error);
EXC_TRANSLATE(format_error);
EXC_TRANSLATE(parse_error);
}
#endif
} // namespace ledger

View file

@ -32,33 +32,150 @@
#include <system.hh>
#include "pyinterp.h"
#include "post.h"
#include "xact.h"
namespace ledger {
using namespace boost::python;
#define EXC_TRANSLATOR(type) \
void exc_translate_ ## type(const type& err) { \
PyErr_SetString(PyExc_ArithmeticError, err.what()); \
namespace {
bool py_has_tag_1s(post_t& post, const string& tag) {
return post.has_tag(tag);
}
bool py_has_tag_1m(post_t& post, const mask_t& tag_mask) {
return post.has_tag(tag_mask);
}
bool py_has_tag_2m(post_t& post, const mask_t& tag_mask,
const boost::optional<mask_t>& value_mask) {
return post.has_tag(tag_mask, value_mask);
}
//EXC_TRANSLATOR(post_error)
boost::optional<string> py_get_tag_1s(post_t& post, const string& tag) {
return post.get_tag(tag);
}
boost::optional<string> py_get_tag_1m(post_t& post, const mask_t& tag_mask) {
return post.get_tag(tag_mask);
}
boost::optional<string> py_get_tag_2m(post_t& post, const mask_t& tag_mask,
const boost::optional<mask_t>& value_mask) {
return post.get_tag(tag_mask, value_mask);
}
post_t::xdata_t& py_xdata(post_t& post) {
return post.xdata();
}
account_t * py_reported_account(post_t& post) {
return post.reported_account();
}
} // unnamed namespace
void export_post()
{
#if 0
class_< post_t > ("Post")
;
scope().attr("POST_EXT_RECEIVED") = POST_EXT_RECEIVED;
scope().attr("POST_EXT_HANDLED") = POST_EXT_HANDLED;
scope().attr("POST_EXT_DISPLAYED") = POST_EXT_DISPLAYED;
scope().attr("POST_EXT_DIRECT_AMT") = POST_EXT_DIRECT_AMT;
scope().attr("POST_EXT_SORT_CALC") = POST_EXT_SORT_CALC;
scope().attr("POST_EXT_COMPOUND") = POST_EXT_COMPOUND;
scope().attr("POST_EXT_VISITED") = POST_EXT_VISITED;
scope().attr("POST_EXT_MATCHES") = POST_EXT_MATCHES;
scope().attr("POST_EXT_CONSIDERED") = POST_EXT_CONSIDERED;
class_< post_t::xdata_t > ("PostingXData")
#if 1
.def("flags", &supports_flags<uint_least16_t>::flags)
.def("has_flags", &supports_flags<uint_least16_t>::has_flags)
.def("set_flags", &supports_flags<uint_least16_t>::set_flags)
.def("clear_flags", &supports_flags<uint_least16_t>::clear_flags)
.def("add_flags", &supports_flags<uint_least16_t>::add_flags)
.def("drop_flags", &supports_flags<uint_least16_t>::drop_flags)
#endif
//register_optional_to_python<amount_t>();
.add_property("visited_value",
make_getter(&post_t::xdata_t::visited_value),
make_setter(&post_t::xdata_t::visited_value))
.add_property("compound_value",
make_getter(&post_t::xdata_t::compound_value),
make_setter(&post_t::xdata_t::compound_value))
.add_property("total",
make_getter(&post_t::xdata_t::total),
make_setter(&post_t::xdata_t::total))
.add_property("count",
make_getter(&post_t::xdata_t::count),
make_setter(&post_t::xdata_t::count))
.add_property("date",
make_getter(&post_t::xdata_t::date),
make_setter(&post_t::xdata_t::date))
.add_property("datetime",
make_getter(&post_t::xdata_t::datetime),
make_setter(&post_t::xdata_t::datetime))
.add_property("account",
make_getter(&post_t::xdata_t::account),
make_setter(&post_t::xdata_t::account))
.add_property("sort_values",
make_getter(&post_t::xdata_t::sort_values),
make_setter(&post_t::xdata_t::sort_values))
;
//implicitly_convertible<string, amount_t>();
scope().attr("POST_VIRTUAL") = POST_VIRTUAL;
scope().attr("POST_MUST_BALANCE") = POST_MUST_BALANCE;
scope().attr("POST_CALCULATED") = POST_CALCULATED;
scope().attr("POST_COST_CALCULATED") = POST_COST_CALCULATED;
#define EXC_TRANSLATE(type) \
register_exception_translator<type>(&exc_translate_ ## type);
class_< post_t, bases<item_t> > ("Posting")
//.def(init<account_t *>())
//EXC_TRANSLATE(post_error);
.add_property("xact",
make_getter(&post_t::xact,
return_value_policy<reference_existing_object>()),
make_setter(&post_t::xact,
with_custodian_and_ward<1, 2>()))
.add_property("account",
make_getter(&post_t::account,
return_value_policy<reference_existing_object>()),
make_setter(&post_t::account,
with_custodian_and_ward<1, 2>()))
.add_property("amount",
make_getter(&post_t::amount),
make_setter(&post_t::amount))
.add_property("cost",
make_getter(&post_t::cost),
make_setter(&post_t::cost))
.add_property("assigned_amount",
make_getter(&post_t::assigned_amount),
make_setter(&post_t::assigned_amount))
.def("has_tag", py_has_tag_1s)
.def("has_tag", py_has_tag_1m)
.def("has_tag", py_has_tag_2m)
.def("get_tag", py_get_tag_1s)
.def("get_tag", py_get_tag_1m)
.def("get_tag", py_get_tag_2m)
.def("date", &post_t::date)
.def("effective_date", &post_t::effective_date)
.def("must_balance", &post_t::must_balance)
.def("lookup", &post_t::lookup)
.def("valid", &post_t::valid)
.def("has_xdata", &post_t::has_xdata)
.def("clear_xdata", &post_t::clear_xdata)
.def("xdata", py_xdata,
return_value_policy<reference_existing_object>())
.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>())
;
}
} // namespace ledger

View file

@ -164,6 +164,50 @@ typedef register_python_conversion<std::ostream, ostream_to_python, ostream_from
void export_utils()
{
class_< supports_flags<uint_least8_t> > ("SupportFlags8")
.def(init<supports_flags<uint_least8_t> >())
.def(init<uint_least8_t>())
.def("flags", &supports_flags<uint_least8_t>::flags)
.def("has_flags", &supports_flags<uint_least8_t>::has_flags)
.def("set_flags", &supports_flags<uint_least8_t>::set_flags)
.def("clear_flags", &supports_flags<uint_least8_t>::clear_flags)
.def("add_flags", &supports_flags<uint_least8_t>::add_flags)
.def("drop_flags", &supports_flags<uint_least8_t>::drop_flags)
;
class_< supports_flags<uint_least16_t> > ("SupportFlags16")
.def(init<supports_flags<uint_least16_t> >())
.def(init<uint_least16_t>())
.def("flags", &supports_flags<uint_least16_t>::flags)
.def("has_flags", &supports_flags<uint_least16_t>::has_flags)
.def("set_flags", &supports_flags<uint_least16_t>::set_flags)
.def("clear_flags", &supports_flags<uint_least16_t>::clear_flags)
.def("add_flags", &supports_flags<uint_least16_t>::add_flags)
.def("drop_flags", &supports_flags<uint_least16_t>::drop_flags)
;
#if 0
class_< basic_flags_t<uint_least8_t>,
bases<supports_flags<uint_least8_t> > > ("BasicFlags8")
.def(init<uint_least8_t>())
.def("plus_flags", &basic_flags_t<uint_least8_t>::plus_flags)
.def("minus_flags", &basic_flags_t<uint_least8_t>::minus_flags)
;
#endif
class_< delegates_flags<uint_least16_t>,
boost::noncopyable > ("DelegatesFlags16", no_init)
.def("flags", &delegates_flags<uint_least16_t>::flags)
.def("has_flags", &delegates_flags<uint_least16_t>::has_flags)
.def("set_flags", &delegates_flags<uint_least16_t>::set_flags)
.def("clear_flags", &delegates_flags<uint_least16_t>::clear_flags)
.def("add_flags", &delegates_flags<uint_least16_t>::add_flags)
.def("drop_flags", &delegates_flags<uint_least16_t>::drop_flags)
;
bool_python_conversion();
string_python_conversion();
istream_python_conversion();

View file

@ -41,8 +41,12 @@ namespace ledger {
using namespace boost::python;
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(value_overloads, value, 0, 2)
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(exchange_commodities_overloads,
exchange_commodities, 1, 2)
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(set_string_overloads, set_string, 0, 2)
namespace {
expr_t py_value_getattr(const value_t& value, const string& name)
{
if (value.is_scope()) {
@ -69,28 +73,47 @@ namespace {
return amount.set_string(str);
}
} // unnamed namespace
#define EXC_TRANSLATOR(type) \
void exc_translate_ ## type(const type& err) { \
PyErr_SetString(PyExc_ArithmeticError, err.what()); \
}
EXC_TRANSLATOR(value_error)
}
EXC_TRANSLATOR(value_error)
void export_value()
{
enum_< value_t::type_t >("ValueType")
.value("VOID", value_t::VOID)
.value("BOOLEAN", value_t::BOOLEAN)
.value("DATETIME", value_t::DATETIME)
.value("DATE", value_t::DATE)
.value("INTEGER", value_t::INTEGER)
.value("AMOUNT", value_t::AMOUNT)
.value("BALANCE", value_t::BALANCE)
.value("STRING", value_t::STRING)
.value("SEQUENCE", value_t::SEQUENCE)
.value("SCOPE", value_t::SCOPE)
;
class_< value_t > ("Value")
.def("initialize", &value_t::initialize)
.staticmethod("initialize")
.def("shutdown", &value_t::shutdown)
.staticmethod("shutdown")
.def(init<double>())
.def(init<long>())
.def(init<std::string>())
.def(init<date_t>())
.def(init<bool>())
.def(init<datetime_t>())
.def(init<date_t>())
.def(init<long>())
.def(init<double>())
.def(init<amount_t>())
.def(init<balance_t>())
.def(init<mask_t>())
.def(init<std::string>())
// jww (2009-11-02): Need to support conversion of sequences
//.def(init<value_t::sequence_t>())
.def(init<value_t>())
.def("is_equal_to", &value_t::is_equal_to)
@ -100,80 +123,88 @@ void export_value()
.def(self == self)
.def(self == long())
.def(long() == self)
.def(self == double())
.def(double() == self)
.def(self == other<amount_t>())
.def(other<amount_t>() == self)
.def(self == other<balance_t>())
.def(other<balance_t>() == self)
.def(self != self)
.def(self != long())
.def(long() != self)
.def(self != double())
.def(double() != self)
.def(self != other<amount_t>())
.def(other<amount_t>() != self)
.def(self != other<balance_t>())
.def(other<balance_t>() != self)
.def(! self)
.def(self < self)
.def(self < long())
.def(long() < self)
.def(self < double())
.def(double() < self)
.def(self < other<amount_t>())
.def(other<amount_t>() < self)
.def(self <= self)
.def(self <= long())
.def(long() <= self)
.def(self <= double())
.def(double() <= self)
.def(self <= other<amount_t>())
.def(other<amount_t>() <= self)
.def(self > self)
.def(self > long())
.def(long() > self)
.def(self > double())
.def(double() > self)
.def(self > other<amount_t>())
.def(other<amount_t>() > self)
.def(self >= self)
.def(self >= long())
.def(long() >= self)
.def(self >= double())
.def(double() >= self)
.def(self >= other<amount_t>())
.def(other<amount_t>() >= self)
.def(self += self)
.def(self += long())
.def(self += double())
.def(self += other<amount_t>())
.def(self += other<balance_t>())
.def(self + self)
.def(self + long())
.def(long() + self)
.def(self + double())
.def(double() + self)
.def(self + self)
.def(self + long())
.def(long() + self)
.def(self + other<amount_t>())
.def(other<amount_t>() + self)
.def(self + other<balance_t>())
.def(self -= self)
.def(self -= long())
.def(self -= double())
.def(self -= other<amount_t>())
.def(self -= other<balance_t>())
.def(self - self)
.def(self - long())
.def(long() - self)
.def(self - double())
.def(double() - self)
.def(self - self)
.def(self - long())
.def(long() - self)
.def(self - other<amount_t>())
.def(other<amount_t>() - self)
.def(self - other<balance_t>())
.def(self *= self)
.def(self *= long())
.def(self *= double())
.def(self *= other<amount_t>())
.def(self * self)
.def(self * long())
.def(long() * self)
.def(self * double())
.def(double() * self)
.def(self * self)
.def(self * long())
.def(long() * self)
.def(self * other<amount_t>())
.def(other<amount_t>() * self)
.def(self /= self)
.def(self /= long())
.def(self /= double())
.def(self /= other<amount_t>())
.def(self / self)
.def(self / long())
.def(long() / self)
.def(self / double())
.def(double() / self)
.def(self / self)
.def(self / long())
.def(long() / self)
.def(self / other<amount_t>())
.def(other<amount_t>() / self)
.def("negated", &value_t::negated)
.def("in_place_negate", &value_t::in_place_negate)
@ -184,15 +215,20 @@ void export_value()
.def("__abs__", &value_t::abs)
.def("rounded", &value_t::rounded)
.def("in_place_round", &value_t::in_place_round)
.def("truncated", &value_t::truncated)
.def("in_place_truncate", &value_t::in_place_truncate)
.def("unrounded", &value_t::unrounded)
.def("in_place_unround", &value_t::in_place_unround)
.def("reduced", &value_t::reduced)
.def("in_place_reduce", &value_t::in_place_reduce)
.def("unreduced", &value_t::unreduced)
.def("in_place_unreduce", &value_t::in_place_unreduce)
.def("value", &value_t::value, value_overloads())
.def("price", &value_t::price)
.def("exchange_commodities", &value_t::exchange_commodities,
exchange_commodities_overloads())
.def("__nonzero__", &value_t::is_nonzero)
.def("is_nonzero", &value_t::is_nonzero)
@ -206,9 +242,6 @@ void export_value()
.def("is_boolean", &value_t::is_boolean)
.def("set_boolean", &value_t::set_boolean)
.def("is_boolean", &value_t::is_boolean)
.def("set_boolean", &value_t::set_boolean)
.def("is_datetime", &value_t::is_datetime)
.def("set_datetime", &value_t::set_datetime)
@ -219,11 +252,17 @@ void export_value()
.def("set_long", &value_t::set_long)
.def("is_amount", &value_t::is_amount)
.def("is_amount", &value_t::is_amount)
.def("is_balance", &value_t::is_balance)
.def("is_balance", &value_t::is_balance)
.def("is_string", &value_t::is_string)
.def("set_string", py_set_string)
.def("is_mask", &value_t::is_mask)
.def("is_mask", &value_t::is_mask)
.def("is_sequence", &value_t::is_sequence)
.def("set_sequence", &value_t::set_sequence)
@ -232,7 +271,10 @@ void export_value()
.def("__int__", &value_t::to_long)
.def("to_datetime", &value_t::to_datetime)
.def("to_date", &value_t::to_date)
.def("to_amount", &value_t::to_amount)
.def("to_balance", &value_t::to_balance)
.def("to_string", &value_t::to_string)
.def("to_mask", &value_t::to_mask)
.def("to_sequence", &value_t::to_sequence)
.def("__str__", py_dump_relaxed)
@ -240,59 +282,39 @@ void export_value()
.def("casted", &value_t::casted)
.def("in_place_cast", &value_t::in_place_cast)
.def("simplified", &value_t::simplified)
.def("in_place_simplify", &value_t::in_place_simplify)
// jww (2009-02-07): Allow annotating, and retrieving annotations
.def("annotate", &value_t::annotate)
.def("is_annotated", &value_t::is_annotated)
#if 0
.def("annotation", &value_t::annotation)
#endif
.def("strip_annotations", &value_t::strip_annotations)
// jww (2009-01-28): Allow for transparent exchanging with sequence
// protocol objects in Python too; and conversion to a list.
#if 0
// jww (2009-02-07): Methods to implement:
// Allow accepting and returning tuples as sequences
// count_commodities
// has_commodity(COMM)
// decompose
.def("__getitem__", &value_t::operator[])
#endif
.def("__getattr__", py_value_getattr)
.def("push_back", &value_t::push_back)
.def("pop_back", &value_t::pop_back)
.def("size", &value_t::size)
.def("label", &value_t::label)
.def("dump", &value_t::dump)
.def("print", &value_t::print)
.def("valid", &value_t::valid)
.def("__getattr__", py_value_getattr)
;
enum_< value_t::type_t >("ValueType")
.value("VOID", value_t::VOID)
.value("BOOLEAN", value_t::BOOLEAN)
.value("DATETIME", value_t::DATETIME)
.value("DATE", value_t::DATE)
.value("INTEGER", value_t::INTEGER)
.value("AMOUNT", value_t::AMOUNT)
.value("BALANCE", value_t::BALANCE)
.value("STRING", value_t::STRING)
.value("SEQUENCE", value_t::SEQUENCE)
.value("SCOPE", value_t::SCOPE)
;
scope().attr("NULL_VALUE") = NULL_VALUE;
scope().attr("string_value") = &string_value;
scope().attr("mask_value") = &mask_value;
scope().attr("value_context") = &value_context;
register_optional_to_python<value_t>();
implicitly_convertible<double, value_t>();
implicitly_convertible<long, value_t>();
implicitly_convertible<string, value_t>();
// jww (2009-11-02): ask mask objects here
implicitly_convertible<date_t, value_t>();
implicitly_convertible<datetime_t, value_t>();

View file

@ -32,45 +32,141 @@
#include <system.hh>
#include "pyinterp.h"
#include "pyutils.h"
#include "xact.h"
#include "post.h"
namespace ledger {
using namespace boost::python;
#define EXC_TRANSLATOR(type) \
void exc_translate_ ## type(const type& err) { \
PyErr_SetString(PyExc_ArithmeticError, err.what()); \
namespace {
long posts_len(xact_base_t& xact)
{
return xact.posts.size();
}
//EXC_TRANSLATOR(xact_error)
post_t& posts_getitem(xact_base_t& xact, long i)
{
static long last_index = 0;
static xact_base_t * last_xact = NULL;
static posts_list::iterator elem;
long len = xact.posts.size();
if (labs(i) >= len) {
PyErr_SetString(PyExc_IndexError, _("Index out of range"));
throw_error_already_set();
}
if (&xact == last_xact && i == last_index + 1) {
last_index = i;
return **++elem;
}
long x = i < 0 ? len + i : i;
elem = xact.posts.begin();
while (--x >= 0)
elem++;
last_xact = &xact;
last_index = i;
return **elem;
}
} // unnamed namespace
using namespace boost::python;
void export_xact()
{
#if 0
class_< xact_base_t > ("XactBase")
;
class_< xact_t > ("Xact")
;
struct_< xact_finalizer_t > ("XactFinalizer")
;
class_< auto_xact_t > ("AutoXact")
;
struct_< auto_xact_finalizer_t > ("AutoXactFinalizer")
;
class_< period_xact_t > ("PeriodXact")
;
class_< func_finalizer_t > ("FuncFinalizer")
;
#endif
class_< xact_base_t, bases<item_t> > ("TransactionBase")
.add_property("journal",
make_getter(&xact_base_t::journal,
return_value_policy<reference_existing_object>()),
make_setter(&xact_base_t::journal,
with_custodian_and_ward<1, 2>()))
.add_property("posts",
make_getter(&xact_base_t::posts),
make_setter(&xact_base_t::posts))
//register_optional_to_python<amount_t>();
.def("__len__", posts_len)
.def("__getitem__", posts_getitem,
return_value_policy<reference_existing_object>())
//implicitly_convertible<string, amount_t>();
.def("add_post", &xact_base_t::add_post, with_custodian_and_ward<1, 2>())
.def("remove_post", &xact_base_t::add_post)
#define EXC_TRANSLATE(type) \
register_exception_translator<type>(&exc_translate_ ## type);
.def("finalize", &xact_base_t::finalize)
.def("valid", &xact_base_t::valid)
;
//EXC_TRANSLATE(xact_error);
class_< xact_t, bases<xact_base_t> > ("Transaction")
.add_property("code",
make_getter(&xact_t::code),
make_setter(&xact_t::code))
.add_property("payee",
make_getter(&xact_t::payee),
make_setter(&xact_t::payee))
.def("add_post", &xact_t::add_post, with_custodian_and_ward<1, 2>())
.def("magnitude", &xact_t::magnitude)
.def("idstring", &xact_t::idstring)
.def("id", &xact_t::id)
.def("lookup", &xact_t::lookup)
.def("valid", &xact_t::valid)
;
class_< xact_finalizer_t, boost::noncopyable >
("TransactionFinalizer", no_init)
.def("__call__", &xact_finalizer_t::operator())
;
class_< auto_xact_t, bases<xact_base_t> > ("AutomatedTransaction")
.def(init<item_predicate>())
.add_property("predicate",
make_getter(&auto_xact_t::predicate),
make_setter(&auto_xact_t::predicate))
.def("extend_xact", &auto_xact_t::extend_xact)
;
class_< auto_xact_finalizer_t, bases<xact_finalizer_t> >
("AutomatedTransactionFinalizer")
.add_property("journal",
make_getter(&auto_xact_finalizer_t::journal,
return_value_policy<reference_existing_object>()),
make_setter(&auto_xact_finalizer_t::journal,
with_custodian_and_ward<1, 2>()))
.def("__call__", &auto_xact_finalizer_t::operator())
;
class_< period_xact_t, bases<xact_base_t> > ("PeriodicTransaction")
.def(init<string>())
.add_property("period",
make_getter(&period_xact_t::period),
make_setter(&period_xact_t::period))
.add_property("period_string",
make_getter(&period_xact_t::period_string),
make_setter(&period_xact_t::period_string))
;
class_< func_finalizer_t, bases<xact_finalizer_t> >
("FunctionalFinalizer", init<func_finalizer_t::func_t>())
.add_property("func",
make_getter(&func_finalizer_t::func),
make_setter(&func_finalizer_t::func))
.def("__call__", &func_finalizer_t::operator())
;
scope().attr("extend_xact_base") = &extend_xact_base;
}
} // namespace ledger

View file

@ -41,6 +41,7 @@ shared_ptr<python_interpreter_t> python_session;
char * argv0;
void export_account();
void export_amount();
void export_balance();
void export_chain();
@ -63,6 +64,7 @@ void export_xact();
void initialize_for_python()
{
export_account();
export_amount();
export_balance();
export_chain();

View file

@ -87,8 +87,7 @@ public:
* The sequence_t member type abstracts the type used to represent a
* resizable "array" of value_t objects.
*/
typedef std::vector<value_t> sequence_t;
typedef std::vector<value_t> sequence_t;
typedef sequence_t::iterator iterator;
typedef sequence_t::const_iterator const_iterator;
typedef sequence_t::difference_type difference_type;

View file

@ -205,6 +205,7 @@ lib_LTLIBRARIES += libledger_python.la
libledger_python_la_SOURCES = \
src/pyutils.h \
src/pyfstream.h \
src/py_account.cc \
src/py_amount.cc \
src/py_balance.cc \
src/py_chain.cc \