summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexis Hildebrandt <afh@surryhill.net>2014-02-15 17:01:33 +0100
committerAlexis Hildebrandt <afh@surryhill.net>2014-02-19 06:52:43 +0100
commit3d9faef448fcbf85bf565ffa9a5830a9fb67fcdd (patch)
treeb02666e15d611feb857b46bd62d30e45447afc56
parent90988feebcd2f37c2715627d53b9c4a12dea51a5 (diff)
downloadfork-ledger-3d9faef448fcbf85bf565ffa9a5830a9fb67fcdd.tar.gz
fork-ledger-3d9faef448fcbf85bf565ffa9a5830a9fb67fcdd.tar.bz2
fork-ledger-3d9faef448fcbf85bf565ffa9a5830a9fb67fcdd.zip
DocTests: Allow inline input to be used with different example commands
-rw-r--r--doc/ledger3.texi89
-rwxr-xr-xtest/DocTests.py73
2 files changed, 116 insertions, 46 deletions
diff --git a/doc/ledger3.texi b/doc/ledger3.texi
index ac5939aa..54441188 100644
--- a/doc/ledger3.texi
+++ b/doc/ledger3.texi
@@ -56,7 +56,8 @@
@c the documentation itself, in that case the journal example data
@c needs to be specially marked as well using @smallexample @c input:UUID,
@c again with the UUID being the UUID of the corresponding ledger example
-@c command, e.g.:
+@c command. If multiple inputs with the same UUID are found they will be
+@c concatenated together and given as one set of data to the example command.
@c
@c @smallexample @c input:35CB2A3
@c 2014/02/09 The Italian Place
@@ -72,7 +73,19 @@
@c Assets:Cash
@c Expenses:Food:Dining
@c @end smallexample
-@c
+@c
+@c To use different example commands with the same input from the documentation
+@c add with_input:UUID to the example command, where UUID is the UUID of the input,
+@c e.g.:
+@c
+@c @smallexample @c command:94FD2B6,with_input:35CB2A3
+@c $ ledger -f inline.dat bal expenses
+@c @end smallexample
+@c
+@c @smallexample @c output:94FD2B6
+@c $ 36.84 Expenses:Food:Dining
+@c @end smallexample
+@c
@c Additionally DocTests.py will pass --init-file /dev/null to ledger to
@c ignore any default arguments to ledger the user running the tests
@c has configured.
@@ -306,7 +319,7 @@ And just for the sake of example---as a starting point for those who
want to dive in head-first---here are the journal transactions from
above, formatted as the Ledger program wishes to see them:
-@smallexample
+@smallexample @c input:48DDF26
2004/09/29 Pacific Bell
Expenses:Pacific Bell $23.00
Assets:Checking
@@ -315,12 +328,37 @@ above, formatted as the Ledger program wishes to see them:
The account balances and registers in this file, if saved as
@file{ledger.dat}, could be reported using:
-@smallexample
+@smallexample @c command:48DDF26
$ ledger -f ledger.dat balance
+@end smallexample
+
+@smallexample @c output:48DDF26
+ $-23.00 Assets:Checking
+ $23.00 Expenses:Pacific Bell
+--------------------
+ 0
+@end smallexample
+
+Or
+
+@smallexample @c command:8C7295F,with_input:48DDF26
$ ledger -f ledger.dat register checking
+@end smallexample
+
+@smallexample @c output:8C7295F
+04-Sep-29 Pacific Bell Assets:Checking $-23.00 $-23.00
+@end smallexample
+
+And even:
+
+@smallexample @c command:BB32EF2,with_input:48DDF26
$ ledger -f ledger.dat register Bell
@end smallexample
+@smallexample @c output:BB32EF2
+04-Sep-29 Pacific Bell Expenses:Pacific Bell $23.00 $23.00
+@end smallexample
+
An important difference between Ledger and other finance packages is
that Ledger will never alter your input file. You can create and edit
that file in any way you prefer, but Ledger is only for analyzing the
@@ -548,7 +586,7 @@ If you would like to find transaction to only a certain payee use
$ ledger -f drewr3.dat register payee "Organic"
@end smallexample
-@smallexample @c output:C10BC57E
+@smallexample @c output:C6BC57E
10-Dec-20 Organic Co-op Expense:Food:Groceries $ 37.50 $ 37.50
Expense:Food:Groceries $ 37.50 $ 75.00
Expense:Food:Groceries $ 37.50 $ 112.50
@@ -748,10 +786,17 @@ flow. A positive cash flow means you are spending more than you make,
since income is always a negative figure. To see your current cash
flow, use this command:
-@smallexample
+@smallexample @c command:DB128F3,with_input:6B43DD4
$ ledger balance ^income ^expenses
@end smallexample
+@smallexample @c output:DB128F3
+ $25.00 Expenses:Dining
+ $-500.00 Income:Salary
+--------------------
+ $-475.00
+@end smallexample
+
Another common question to ask of your expenses is: How much do I
spend each month on X? Ledger provides a simple way of displaying
monthly totals for any account. Here is an example that summarizes
@@ -1827,7 +1872,7 @@ function on a transaction-wide or per-posting basis.
Lastly, you can specify the valuation function/value for any specific
amount using the @samp{(( ))} commodity annotation.
-@smallexample
+@smallexample @c input:814A366
2012-03-02 KFC
Expenses:Food2 $1 ((2 EUR))
Assets:Cash2
@@ -1863,20 +1908,24 @@ amount using the @samp{(( ))} commodity annotation.
Assets:Cash9
@end smallexample
-@smallexample
-ledger reg -V food
+@smallexample @c command:814A366
+$ ledger reg -V food
+@end smallexample
+
+@smallexample @c output:814A366
12-Mar-02 KFC Expenses:Food2 2 EUR 2 EUR
-12-Mar-03 KFC <Adjustment> -1 EUR 1 EUR
- Expenses:Food3 3 EUR 4 EUR
-12-Mar-04 KFC <Adjustment> -2 EUR 2 EUR
- Expenses:Food4 4 EUR 6 EUR
-12-Mar-05 KFC <Adjustment> -3 EUR 3 EUR
- Expenses:Food5 5 EUR 8 EUR
-12-Mar-06 KFC <Adjustment> -4 EUR 4 EUR
- Expenses:Food6 6 EUR 10 EUR
-12-Mar-07 KFC Expenses:Food7 7 EUR 17 EUR
-12-Mar-08 XACT Expenses:Food8 8 EUR 25 EUR
-12-Mar-09 POST (Expenses:Food9) 9 EUR 34 EUR
+12-Mar-03 KFC Expenses:Food3 3 EUR 5 EUR
+12-Mar-04 KFC Expenses:Food4 4 EUR 9 EUR
+12-Mar-05 KFC Expenses:Food5 $1 $1
+ 9 EUR
+12-Mar-06 KFC Expenses:Food6 $1 $2
+ 9 EUR
+12-Mar-07 KFC Expenses:Food7 1 CAD $2
+ 1 CAD
+ 9 EUR
+12-Mar-08 XACT Expenses:Food8 $1 $3
+ 1 CAD
+ 9 EUR
@end smallexample
@node Keeping it Consistent, Journal Format, Currency and Commodities, Keeping a Journal
diff --git a/test/DocTests.py b/test/DocTests.py
index 60d8c637..cc540aa9 100755
--- a/test/DocTests.py
+++ b/test/DocTests.py
@@ -22,6 +22,7 @@ class DocTests:
self.testin_token = 'command'
self.testout_token = 'output'
self.testdat_token = 'input'
+ self.testwithdat_token = 'with_input'
def read_example(self):
endexample = re.compile(r'^@end\s+smallexample\s*$')
@@ -37,7 +38,7 @@ class DocTests:
return hashlib.sha1(example.rstrip()).hexdigest()[0:7].upper()
def find_examples(self):
- startexample = re.compile(r'^@smallexample\s+@c\s+(%s|%s|%s)(?::([\dA-Fa-f]+))?'
+ startexample = re.compile(r'^@smallexample\s+@c\s+(%s|%s|%s)(?::([\dA-Fa-f]+))?(?:,(.*))?'
% (self.testin_token, self.testout_token, self.testdat_token))
while True:
line = self.file.readline()
@@ -50,6 +51,13 @@ class DocTests:
test_begin_line = self.current_line
test_kind = startmatch.group(1)
test_id = startmatch.group(2)
+ test_options = dict()
+ for pair in re.split(r',\s*', str(startmatch.group(3))):
+ kv = re.split(r':\s*', pair, 2)
+ try:
+ test_options[kv[0]] = kv[1]
+ except IndexError:
+ pass
example = self.read_example()
test_end_pos = self.file.tell()
test_end_line = self.current_line
@@ -78,17 +86,42 @@ class DocTests:
'epos': test_end_pos,
'blin': test_begin_line,
'elin': test_end_line,
+ 'opts': test_options,
test_kind: example,
}
+ def parse_command(self, test_id, example):
+ try:
+ command = example[self.testin_token][self.testin_token]
+ except KeyError:
+ return None
+
+ command = command.rstrip().split()
+ if command[0] == '$': command.remove('$')
+ index = command.index('ledger')
+ command[index] = self.ledger
+ command.insert(index+1, '--init-file')
+ command.insert(index+2, '/dev/null')
+ try:
+ findex = command.index('-f')
+ except ValueError:
+ try:
+ findex = command.index('--file')
+ except ValueError:
+ findex = index+1
+ command.insert(findex, '--file')
+ command.insert(findex+1, test_id + '.dat')
+ return (command, findex+1)
+
def test_examples(self):
failed = set()
for test_id in self.examples:
example = self.examples[test_id]
try:
- command = example[self.testin_token][self.testin_token]
- except KeyError:
- command = None
+ (command, findex) = self.parse_command(test_id, example)
+ except TypeError:
+ failed.add(test_id)
+ continue
try:
output = example[self.testout_token][self.testout_token]
@@ -98,44 +131,32 @@ class DocTests:
try:
input = example[self.testdat_token][self.testdat_token]
except KeyError:
- input = None
+ try:
+ with_input = example[self.testin_token]['opts'][self.testwithdat_token]
+ input = self.examples[with_input][self.testdat_token][self.testdat_token]
+ except KeyError:
+ input = None
if command and output:
- command = command.rstrip().split()
- if command[0] == '$': command.remove('$')
- index = command.index('ledger')
- command[index] = self.ledger
- command.insert(index+1, '--init-file')
- command.insert(index+2, '/dev/null')
- try:
- findex = command.index('-f')
- except ValueError:
- try:
- findex = command.index('--file')
- except ValueError:
- findex = index+1
- command.insert(findex, '--file')
- command.insert(findex+1, test_id + '.dat')
-
+ test_file_created = False
if findex:
scriptpath = os.path.dirname(os.path.realpath(__file__))
test_input_dir = scriptpath + '/../test/input/'
- test_file = command[findex+1]
- test_file_created = False
+ test_file = command[findex]
if not os.path.exists(test_file):
if input:
test_file_created = True
with open(test_file, 'w') as f:
f.write(input)
elif os.path.exists(test_input_dir + test_file):
- command[findex+1] = test_input_dir + test_file
+ command[findex] = test_input_dir + test_file
try:
verify = subprocess.check_output(command)
except:
verify = str()
- if test_file_created:
- os.remove(test_file)
valid = (output == verify)
+ if valid and test_file_created:
+ os.remove(test_file)
if self.verbose > 0:
print test_id, ':', 'Passed' if valid else 'FAILED'
else: