Hello to everyone!
This is my first post here. I have to confess that I was very impressed by
the features of ledger.
As an avid GNUCash user I was a little disappointed with the absence of
GNUCash reading capabilities.
I managed to write a perl script to parse and output a ledger-formatted
file and than I started looking for ways to present my data.
Long story short, I haven't found a way to access this Python interface, my
intent is to produce a series of scripts to output HMTL5 files with my
reports on a regular basis (probably a cron-job). How can I do this? Is
there any way to communicate with Ledger without having to put it in REPL
mode and creating the interface myself?
Thanks!
On Friday, March 2, 2012 12:06:48 AM UTC-3, John Wiegley wrote:
>
> Hello all,
>
> I think it's time for a primer on using Python to extend your Ledger
> experience. But first, a word must be said about Ledger's data model, so
> that
> other things make sense later.
>
>
> ------------------------------------------------------------------------------
> # Basic data traversal
>
> Every interaction with Ledger happens in the context of a Session. Even if
> you don't create a session manually, one is created for you by the
> top-level
> interface functions. The Session is where objects live like the
> Commodity's
> that Amount's refer to.
>
> The make a Session useful, you must read a Journal into it, using the
> function
> `read_journal`. This reads Ledger data from the given file, populates a
> Journal object within the current Session, and returns a reference to that
> Journal object.
>
> Within the Journal live all the Transaction's, Posting's, and other objects
> related to your data. There are also AutomatedTransaction's and
> PeriodicTransaction's, etc.
>
> Here is how you would traverse all the postings in your data file:
>
> import ledger
>
> for xact in ledger.read_journal("sample.dat").xacts:
> for post in xact.posts:
> print "Transferring %s to/from %s" % (post.amount,
> post.account)
>
>
> ------------------------------------------------------------------------------
> # Raw vs. Cooked
>
> Ledger data exists in one of two forms: raw and cooked. Raw objects are
> what
> you get from a traversal like the above, and represent exactly what was
> seen
> in the data file. Consider this journal:
>
> = true
> (Assets:Cash) $100
>
> 2012-03-01 KFC
> Expenses:Food $100
> Assets:Credit
>
> In this case, the *raw* regular transaction in this file is:
>
> 2012-03-01 KFC
> Expenses:Food $100
> Assets:Credit
>
> While the cooked form is:
>
> 2012-03-01 KFC
> Expenses:Food $100
> Assets:Credit $-100
> (Assets:Cash) $100
>
> So the easy way to think about raw vs. cooked is that raw is the
> unprocessed
> data, and cooked has had all considerations applied.
>
> When you traverse a Journal by iterating its transactions, you are
> generally
> looking at raw data. In order to look at cooked data, you must generate a
> report of some kind by querying the journal:
>
> for post in ledger.read_journal("sample.dat").query("food"):
> print "Transferring %s to/from %s" % (post.amount, post.account)
>
> The reason why queries iterate over postings instead of transactions is
> that
> queries often return only a "slice" of the transactions they apply to. You
> can always get at a matching posting's transaction by looking at its "xact"
> member:
>
> last_xact = None
> for post in ledger.read_journal("sample.dat").query(""):
> if post.xact != last_xact:
> for post in post.xact.posts:
> print "Transferring %s to/from %s" % (post.amount,
> post.account)
> last_xact = post.xact
>
> This query ends up reporting every cooked posting in the Journal, but does
> it
> transaction-wise. It relies on the fact that an unsorted report returns
> postings in the exact order they were parsed from the journal file.
>
>
> ------------------------------------------------------------------------------
> # Queries
>
> The Journal.query() method accepts every argument you can specify on the
> command-line, including --options.
>
> Since a query "cooks" the journal it applies to, only one query may be
> active
> for that journal at a given time. Once the query object is gone (after the
> for loop), then the data reverts back to its raw state.
>
>
> ------------------------------------------------------------------------------
> # Embedded Python
>
> Can you embed Python into your data files using the 'python' directive:
>
> python
> import so
> def check_path(path_value):
> print "%s => %s" % (str(path_value),
> os.path.isfile(str(path_value)))
> return os.path.isfile(str(path_value))
>
> tag PATH
> assert check_path(value)
>
> 2012-02-29 KFC
> ; PATH: somebogusfile.dat
> Expenses:Food $20
> Assets:Cash
>
> Any Python functions you define this way become immediately available as
> valexpr functions.
>
>
> ------------------------------------------------------------------------------
> # Amounts
>
> When numbers come from Ledger, like post.amount, the type of the value is
> Amount. It can be used just like an ordinary number, except that addition
> and subtraction are restricted to amounts with the same commodity. If you
> need to create sums of multiple commodities, use a Balance. For example:
>
> total = Balance()
> for post in ledger.read_journal("sample.dat").query(""):
> total += post.amount
> print total
>
> John
>
>