Updated developer section

This commit is contained in:
Craig Earls 2013-02-01 21:28:36 -07:00
parent 0f3fef427f
commit 37ea7f9b1f

View file

@ -77,8 +77,8 @@ twinkling in their father's CRT.
* Budgeting and Forecasting::
* Value Expressions::
* Format Strings::
* Ledger for Developers::
* Extending with Python::
* Ledger for Developers::
* Major Changes from version 2.6::
* Example Data File::
* Miscellaneous Notes::
@ -4093,7 +4093,6 @@ of the balance.
* Primary Financial Reports:: Reports in other formats:: Reports about
* Reports in other Formats::
* Reports about your Journals::
* Developer Commands::
@end menu
@node Primary Financial Reports, Reports in other Formats, Reporting Commands, Reporting Commands
@ -4774,7 +4773,7 @@ by Ledger. This is useful for generating and tidying up pricedb
database files.
@node Reports about your Journals, Developer Commands, Reports in other Formats, Reporting Commands
@node Reports about your Journals, , Reports in other Formats, Reporting Commands
@section Reports about your Journals
@menu
@ -4879,199 +4878,6 @@ macbook-2:$
@node Developer Commands, , Reports about your Journals, Reporting Commands
@section Developer Commands
@menu
* echo::
* reload::
* source::
* Debug Options::
* Pre-commands::
@end menu
@node echo, reload, Developer Commands, Developer Commands
@subsection @command{echo}
This command simply echos its argument back to the output.
@node reload, source, echo, Developer Commands
@subsection @command{reload}
Forces ledger to reload any journal files. This function exists to
support external programs controlling a running ledger process and does
nothing for a command line user.
@node source, Debug Options, reload, Developer Commands
@subsection @command{source}
The @code{source} command take a journal file as an argument and parses
it checking for errors, no other reports are generated, and no other
arguments are necessary. Ledger will return success if no errors are
found.
@node Debug Options, Pre-commands, source, Developer Commands
@subsection Debug Options
These options are primarily for Ledger developers, but may be of some
use to a user trying something new.
@table @code
@item --args-only
ignore init
files and environment variables for the ledger run.
@item --verify
enable additional assertions during run-time. This causes a significant
slowdown. When combined with @code{--debug} ledger will produce
memory trace information.
@item --debug "argument"
If Ledger has been built with debug options this will provide extra data
during the run. The following are the available arguments to debug:
@multitable @columnfractions .32 .43 .27
@item @code{account.display} @tab @code{expr.calc.when} @tab @code{org.next_amount}
@item @code{accounts.sorted} @tab @code{expr.compile} @tab @code{org.next_total}
@item @code{amount.convert} @tab @code{filters.changed_value} @tab @code{parser.error}
@item @code{amount.is_zero} @tab @code{filters.changed_value.rounding} @tab @code{pool.commodities}
@item @code{amount.parse} @tab @code{filters.collapse} @tab @code{post.assign}
@item @code{amount.price} @tab @code{filters.forecast} @tab @code{python.init}
@item @code{amount.truncate} @tab @code{filters.revalued} @tab @code{python.interp}
@item @code{amount.unround} @tab @code{format.abbrev} @tab @code{query.mask}
@item @code{amounts.commodities} @tab @code{format.expr} @tab @code{report.predicate}
@item @code{amounts.refs} @tab @code{generate.post} @tab @code{scope.symbols}
@item @code{archive.journal} @tab @code{generate.post.string} @tab @code{textual.include}
@item @code{auto.columns} @tab @code{item.meta} @tab @code{textual.parse}
@item @code{budget.generate} @tab @code{ledger.read} @tab @code{timelog}
@item @code{commodity.annotated.strip} @tab @code{ledger.validate} @tab @code{times.epoch}
@item @code{commodity.annotations} @tab @code{lookup} @tab @code{times.interval}
@item @code{commodity.compare} @tab @code{lookup.account} @tab @code{times.parse}
@item @code{commodity.download} @tab @code{mask.match} @tab @code{value.sort}
@item @code{commodity.prices.add} @tab @code{memory.counts} @tab @code{value.storage.refcount}
@item @code{commodity.prices.find} @tab @code{memory.counts.live} @tab @code{xact.extend}
@item @code{convert.csv} @tab @code{memory.debug} @tab @code{xact.extend.cleared}
@item @code{csv.mappings} @tab @code{op.cons} @tab @code{xact.extend.fail}
@item @code{csv.parse} @tab @code{op.memory} @tab @code{xact.finalize}
@item @code{draft.xact} @tab @code{option.args}
@item @code{expr.calc} @tab @code{option.names}
@end multitable
@item --trace INTEGER_TRACE_LEVEL
Enable tracing. The integer specifies the level of trace desired:
@multitable @columnfractions .3 .7
@item @code{LOG_OFF} @tab 0
@item @code{LOG_CRIT} @tab 1
@item @code{LOG_FATAL} @tab 2
@item @code{LOG_ASSERT} @tab 3
@item @code{LOG_ERROR} @tab 4
@item @code{LOG_VERIFY} @tab 5
@item @code{LOG_WARN} @tab 6
@item @code{LOG_INFO} @tab 7
@item @code{LOG_EXCEPT} @tab 8
@item @code{LOG_DEBUG} @tab 9
@item @code{LOG_TRACE} @tab 10
@item @code{LOG_ALL} @tab 11
@end multitable
@item --verbose
Print detailed information on the execution of Ledger.
@item --version
Print version information and exit.
@end table
@node Pre-commands, , Debug Options, Developer Commands
@subsection Pre-Commands
Pre-commands are useful when you aren't sure how a command or option
will work.
@table @code
@item args
evaluate the given arguments against the following model transaction:
@smallexample
2004/05/27 Book Store
; This note applies to all postings. :SecondTag:
Expenses:Books 20 BOOK @@ $10
; Metadata: Some Value
; Typed:: $100 + $200
; :ExampleTag:
; Here follows a note describing the posting.
Liabilities:MasterCard $-200.00
@end smallexample
@item eval
evaluate the given value expression against the model transaction
@item expr "LIMIT EXPRESSION"
Print details of how ledger parses the given limit expression and apply
it against a model transaction.
@item format "FORMATTING"
Print details of how ledger uses the given formatting description and
apply it against a model transaction.
@item generate
Randomly generates syntactically valid Ledger data from a seed. Used by the
GenerateTests harness for development testing
@item parse <VALUE EXPR>
Print details of how ledger uses the given value expression description
and apply it against a model transaction.
@item period
evaluate the given period and report how Ledger interprets it:
@smallexample
20:22:21 ~/ledger (next)> ledger period "this year"
--- Period expression tokens ---
TOK_THIS: this
TOK_YEAR: year
END_REACHED: <EOF>
--- Before stabilization ---
range: in year 2011
--- After stabilization ---
range: in year 2011
start: 11-Jan-01
finish: 12-Jan-01
--- Sample dates in range (max. 20) ---
1: 11-Jan-01
@end smallexample
@item query
evaluate the given query and report how Ledger interprets it against the
model transaction:
@smallexample
20:25:42 ~/ledger (next)> ledger query "/Book/"
--- Input arguments ---
("/Book/")
--- Context is first posting of the following transaction ---
2004/05/27 Book Store
; This note applies to all postings. :SecondTag:
Expenses:Books 20 BOOK @@ $10
; Metadata: Some Value
; Typed:: $100 + $200
; :ExampleTag:
; Here follows a note describing the posting.
Liabilities:MasterCard $-200.00
--- Input expression ---
(account =~ /Book/)
--- Text as parsed ---
(account =~ /Book/)
--- Expression tree ---
0x7fd639c0da40 O_MATCH (1)
0x7fd639c10170 IDENT: account (1)
0x7fd639c10780 VALUE: /Book/ (1)
--- Compiled tree ---
0x7fd639c10520 O_MATCH (1)
0x7fd639c0d6c0 IDENT: account (1)
0x7fd639c0d680 FUNCTION (1)
0x7fd639c10780 VALUE: /Book/ (1)
--- Calculated value ---
true
@end smallexample
@item template
Shows the insertion template that a @code{draft} or @code{xact} sub-command generates.
This is a debugging command.
@end table
@node Command-line Syntax, Budgeting and Forecasting, Reporting Commands, Top
@chapter Command-line Syntax
@ -7241,7 +7047,7 @@ Useful specifying a date in plain terms. For example, you could say
@item @code{value_date } @tab @code{} @tab
@end multitable
@node Format Strings, Ledger for Developers, Value Expressions, Top
@node Format Strings, Extending with Python, Value Expressions, Top
@chapter Format Strings
@menu
@ -7667,15 +7473,172 @@ line number in @code{filename} where posting's entry for posting ends, abbreviat
@node Extending with Python, Ledger for Developers, Format Strings, Top
@chapter Extending with Python
Python can be used to extend your Ledger
experience. But first, a word must be said about Ledger's data model, so that
other things make sense later.
@menu
* Basic data traversal::
* Raw vs. Cooked::
* Queries::
* Embedded Python::
* Amounts::
@end menu
@node Basic data traversal, Raw vs. Cooked, Extending with Python, Extending with Python
@section 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
`@code{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:
@smallexample
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)
@end smallexample
@node Raw vs. Cooked, Queries, Basic data traversal, Extending with Python
@section 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:
@smallexample
= true
(Assets:Cash) $100
2012-03-01 KFC
Expenses:Food $100
Assets:Credit
@end smallexample
In this case, the @emph{raw} regular transaction in this file is:
@smallexample
2012-03-01 KFC
Expenses:Food $100
Assets:Credit
@end smallexample
While the @emph{cooked} form is:
@smallexample
2012-03-01 KFC
Expenses:Food $100
Assets:Credit $-100
(Assets:Cash) $100
@end smallexample
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:
@smallexample
for post in ledger.read_journal("sample.dat").query("food"):
print "Transferring %s to/from %s" % (post.amount, post.account)
@end smallexample
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:
@smallexample
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
@end smallexample
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.
@node Queries, Embedded Python, Raw vs. Cooked, Extending with Python
@section 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.
@node Embedded Python, Amounts, Queries, Extending with Python
@section Embedded Python
Can you embed Python into your data files using the 'python' directive:
@smallexample
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
@end smallexample
Any Python functions you define this way become immediately available as
valexpr functions.
@node Amounts, , Embedded Python, Extending with Python
@section 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:
@smallexample
total = Balance()
for post in ledger.read_journal("sample.dat").query(""):
total += post.amount
print total
@end smallexample
@node Ledger for Developers, Extending with Python, Format Strings, Top
@node Ledger for Developers, Major Changes from version 2.6, Extending with Python, Top
@chapter Ledger for Developers
@menu
* Internal Design::
* Journal File Format::
* Developer Commands::
* Ledger Development Environment::
@end menu
@node Internal Design, Journal File Format, Ledger for Developers, Ledger for Developers
@ -7902,7 +7865,7 @@ And that's Ledger in a nutshell. All the rest are details, such as which
value expressions each journal item exposes, how many filters currently exist,
which options the report and session scopes define, etc.
@node Journal File Format, , Internal Design, Ledger for Developers
@node Journal File Format, Developer Commands, Internal Design, Ledger for Developers
@section Journal File Format for Developers
This chapter offers a complete description of the journal data format,
@ -8168,163 +8131,250 @@ considered a primary. In fact, when Ledger goes about ensures that
all transactions balance to zero, it only ever asks this of primary
commodities.
@node Extending with Python, Major Changes from version 2.6, Ledger for Developers, Top
@chapter Extending with Python
Python can be used to extend your Ledger
experience. But first, a word must be said about Ledger's data model, so that
other things make sense later.
@node Developer Commands, Ledger Development Environment, Journal File Format, Ledger for Developers
@section Developer Commands
@menu
* Basic data traversal::
* Raw vs. Cooked::
* Queries::
* Embedded Python::
* Amounts::
* echo::
* reload::
* source::
* Debug Options::
* Pre-commands::
@end menu
@node Basic data traversal, Raw vs. Cooked, Extending with Python, Extending with Python
@section Basic data traversal
@node echo, reload, Developer Commands, Developer Commands
@subsection @command{echo}
This command simply echos its argument back to the output.
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
`@code{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.
@node reload, source, echo, Developer Commands
@subsection @command{reload}
Forces ledger to reload any journal files. This function exists to
support external programs controlling a running ledger process and does
nothing for a command line user.
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.
@node source, Debug Options, reload, Developer Commands
@subsection @command{source}
The @code{source} command take a journal file as an argument and parses
it checking for errors, no other reports are generated, and no other
arguments are necessary. Ledger will return success if no errors are
found.
Here is how you would traverse all the postings in your data file:
@node Debug Options, Pre-commands, source, Developer Commands
@subsection Debug Options
These options are primarily for Ledger developers, but may be of some
use to a user trying something new.
@table @code
@item --args-only
ignore init
files and environment variables for the ledger run.
@item --verify
enable additional assertions during run-time. This causes a significant
slowdown. When combined with @code{--debug} ledger will produce
memory trace information.
@item --debug "argument"
If Ledger has been built with debug options this will provide extra data
during the run. The following are the available arguments to debug:
@multitable @columnfractions .32 .43 .27
@item @code{account.display} @tab @code{expr.calc.when} @tab @code{org.next_amount}
@item @code{accounts.sorted} @tab @code{expr.compile} @tab @code{org.next_total}
@item @code{amount.convert} @tab @code{filters.changed_value} @tab @code{parser.error}
@item @code{amount.is_zero} @tab @code{filters.changed_value.rounding} @tab @code{pool.commodities}
@item @code{amount.parse} @tab @code{filters.collapse} @tab @code{post.assign}
@item @code{amount.price} @tab @code{filters.forecast} @tab @code{python.init}
@item @code{amount.truncate} @tab @code{filters.revalued} @tab @code{python.interp}
@item @code{amount.unround} @tab @code{format.abbrev} @tab @code{query.mask}
@item @code{amounts.commodities} @tab @code{format.expr} @tab @code{report.predicate}
@item @code{amounts.refs} @tab @code{generate.post} @tab @code{scope.symbols}
@item @code{archive.journal} @tab @code{generate.post.string} @tab @code{textual.include}
@item @code{auto.columns} @tab @code{item.meta} @tab @code{textual.parse}
@item @code{budget.generate} @tab @code{ledger.read} @tab @code{timelog}
@item @code{commodity.annotated.strip} @tab @code{ledger.validate} @tab @code{times.epoch}
@item @code{commodity.annotations} @tab @code{lookup} @tab @code{times.interval}
@item @code{commodity.compare} @tab @code{lookup.account} @tab @code{times.parse}
@item @code{commodity.download} @tab @code{mask.match} @tab @code{value.sort}
@item @code{commodity.prices.add} @tab @code{memory.counts} @tab @code{value.storage.refcount}
@item @code{commodity.prices.find} @tab @code{memory.counts.live} @tab @code{xact.extend}
@item @code{convert.csv} @tab @code{memory.debug} @tab @code{xact.extend.cleared}
@item @code{csv.mappings} @tab @code{op.cons} @tab @code{xact.extend.fail}
@item @code{csv.parse} @tab @code{op.memory} @tab @code{xact.finalize}
@item @code{draft.xact} @tab @code{option.args}
@item @code{expr.calc} @tab @code{option.names}
@end multitable
@item --trace INTEGER_TRACE_LEVEL
Enable tracing. The integer specifies the level of trace desired:
@multitable @columnfractions .3 .7
@item @code{LOG_OFF} @tab 0
@item @code{LOG_CRIT} @tab 1
@item @code{LOG_FATAL} @tab 2
@item @code{LOG_ASSERT} @tab 3
@item @code{LOG_ERROR} @tab 4
@item @code{LOG_VERIFY} @tab 5
@item @code{LOG_WARN} @tab 6
@item @code{LOG_INFO} @tab 7
@item @code{LOG_EXCEPT} @tab 8
@item @code{LOG_DEBUG} @tab 9
@item @code{LOG_TRACE} @tab 10
@item @code{LOG_ALL} @tab 11
@end multitable
@item --verbose
Print detailed information on the execution of Ledger.
@item --version
Print version information and exit.
@end table
@node Pre-commands, , Debug Options, Developer Commands
@subsection Pre-Commands
Pre-commands are useful when you aren't sure how a command or option
will work.
@table @code
@item args
evaluate the given arguments against the following model transaction:
@smallexample
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)
2004/05/27 Book Store
; This note applies to all postings. :SecondTag:
Expenses:Books 20 BOOK @@ $10
; Metadata: Some Value
; Typed:: $100 + $200
; :ExampleTag:
; Here follows a note describing the posting.
Liabilities:MasterCard $-200.00
@end smallexample
@item eval
evaluate the given value expression against the model transaction
@item expr "LIMIT EXPRESSION"
Print details of how ledger parses the given limit expression and apply
it against a model transaction.
@item format "FORMATTING"
Print details of how ledger uses the given formatting description and
apply it against a model transaction.
@item generate
Randomly generates syntactically valid Ledger data from a seed. Used by the
GenerateTests harness for development testing
@item parse <VALUE EXPR>
Print details of how ledger uses the given value expression description
and apply it against a model transaction.
@item period
evaluate the given period and report how Ledger interprets it:
@smallexample
20:22:21 ~/ledger (next)> ledger period "this year"
--- Period expression tokens ---
TOK_THIS: this
TOK_YEAR: year
END_REACHED: <EOF>
@node Raw vs. Cooked, Queries, Basic data traversal, Extending with Python
@section Raw vs. Cooked
--- Before stabilization ---
range: in year 2011
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:
--- After stabilization ---
range: in year 2011
start: 11-Jan-01
finish: 12-Jan-01
--- Sample dates in range (max. 20) ---
1: 11-Jan-01
@end smallexample
@item query
evaluate the given query and report how Ledger interprets it against the
model transaction:
@smallexample
= true
(Assets:Cash) $100
20:25:42 ~/ledger (next)> ledger query "/Book/"
--- Input arguments ---
("/Book/")
2012-03-01 KFC
Expenses:Food $100
Assets:Credit
--- Context is first posting of the following transaction ---
2004/05/27 Book Store
; This note applies to all postings. :SecondTag:
Expenses:Books 20 BOOK @@ $10
; Metadata: Some Value
; Typed:: $100 + $200
; :ExampleTag:
; Here follows a note describing the posting.
Liabilities:MasterCard $-200.00
--- Input expression ---
(account =~ /Book/)
--- Text as parsed ---
(account =~ /Book/)
--- Expression tree ---
0x7fd639c0da40 O_MATCH (1)
0x7fd639c10170 IDENT: account (1)
0x7fd639c10780 VALUE: /Book/ (1)
--- Compiled tree ---
0x7fd639c10520 O_MATCH (1)
0x7fd639c0d6c0 IDENT: account (1)
0x7fd639c0d680 FUNCTION (1)
0x7fd639c10780 VALUE: /Book/ (1)
--- Calculated value ---
true
@end smallexample
@item template
Shows the insertion template that a @code{draft} or @code{xact} sub-command generates.
This is a debugging command.
@end table
@node Ledger Development Environment, , Developer Commands, Ledger for Developers
@section Ledger Development Environment
@menu
* acrep build configuration tool::
* Testing Framework::
@end menu
@node acrep build configuration tool, Testing Framework, Ledger Development Environment, Ledger Development Environment
@subsection @code{acprep} build configuration tool
@node Testing Framework, , acrep build configuration tool, Ledger Development Environment
@subsection Testing Framework
Ledger source ships with a farily complete set of tests to verify that
all is well, and no old errors have been resurfaced. Tests are run
individually with @code{ctest}. All tests can be run using @code{make
check} or @code{ninja check} depending on which build tool you prefer.
Once built, the ledger executable resides under the @file{build}
subdirectory in the source tree. Tests are built and stored in the test
subdirectory for the build. For example,
@file{~/ledger/build/ledger/opt/test}.
@menu
* Running Tests::
* Writing Tests::
@end menu
In this case, the @emph{raw} regular transaction in this file is:
@node Running Tests, Writing Tests, Testing Framework, Testing Framework
@subsubsection Running Tests
@smallexample
2012-03-01 KFC
Expenses:Food $100
Assets:Credit
@end smallexample
The complete test sweet can be run from the build directory using the
check option for the build tool you use. For example, @code{make
check}. The entire test suit tast around a minute for the optimized
built and many times longer for the debug version. While developing and
debugging, running individual tests can save a great deal of time.
While the @emph{cooked} form is:
Individual tests can be run fron the @file{test} subdirectory of the
build location. To execute a single test use @code{ctest -V -R regex},
where the regex mathes the name of the test you want to build.
@smallexample
2012-03-01 KFC
Expenses:Food $100
Assets:Credit $-100
(Assets:Cash) $100
@end smallexample
There are nearly 300 tests stored under the @file{test} sudirectoro
tmain source distribution. They are broken into two broad categories,
baseline and regression. To run the @file{5FBF2ED8} test, for example,
issue @code{ctest -V -R "5FB"}.
@node Writing Tests, , Running Tests, Testing Framework
@subsubsection Writing Tests
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:
@smallexample
for post in ledger.read_journal("sample.dat").query("food"):
print "Transferring %s to/from %s" % (post.amount, post.account)
@end smallexample
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:
@smallexample
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
@end smallexample
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.
@node Queries, Embedded Python, Raw vs. Cooked, Extending with Python
@section 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.
@node Embedded Python, Amounts, Queries, Extending with Python
@section Embedded Python
Can you embed Python into your data files using the 'python' directive:
@smallexample
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
@end smallexample
Any Python functions you define this way become immediately available as
valexpr functions.
@node Amounts, , Embedded Python, Extending with Python
@section 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:
@smallexample
total = Balance()
for post in ledger.read_journal("sample.dat").query(""):
total += post.amount
print total
@end smallexample
@node Major Changes from version 2.6, Example Data File, Extending with Python, Top
@node Major Changes from version 2.6, Example Data File, Ledger for Developers, Top
@chapter Major Changes from version 2.6
@itemize