diff options
author | Alexis Hildebrandt <afh@surryhill.net> | 2014-02-15 17:01:33 +0100 |
---|---|---|
committer | Alexis Hildebrandt <afh@surryhill.net> | 2014-02-19 06:52:43 +0100 |
commit | 3d9faef448fcbf85bf565ffa9a5830a9fb67fcdd (patch) | |
tree | b02666e15d611feb857b46bd62d30e45447afc56 | |
parent | 90988feebcd2f37c2715627d53b9c4a12dea51a5 (diff) | |
download | fork-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.texi | 89 | ||||
-rwxr-xr-x | test/DocTests.py | 73 |
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: |