def test_load_cache_override_filename_pattern(self): orig_load_file = loader._load_file prev_env = os.getenv('BEANCOUNT_LOAD_CACHE_FILENAME') os.environ['BEANCOUNT_LOAD_CACHE_FILENAME'] = '__{filename}__' loader.initialize() try: with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ 2014-01-01 open Assets:Apples """ }) filename = path.join(tmp, 'apples.beancount') entries, errors, options_map = loader.load_file(filename) self.assertEqual({'__apples.beancount__', 'apples.beancount'}, set(os.listdir(tmp))) finally: # Restore pre-test values. loader._load_file = orig_load_file if prev_env is None: del os.environ['BEANCOUNT_LOAD_CACHE_FILENAME'] else: os.environ['BEANCOUNT_LOAD_CACHE_FILENAME'] = prev_env
def test_load_file_return_include_filenames(self): # Also check that they are normalized paths. with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ include "oranges.beancount" 2014-01-01 open Assets:Apples """, 'oranges.beancount': """ include "bananas.beancount" 2014-01-02 open Assets:Oranges """, 'bananas.beancount': """ 2014-01-02 open Assets:Bananas """ }) entries, errors, options_map = loader.load_file( path.join(tmp, 'apples.beancount')) self.assertFalse(errors) self.assertEqual(3, len(entries)) self.assertTrue( all(path.isabs(filename) for filename in options_map['include'])) self.assertEqual( ['apples.beancount', 'bananas.beancount', 'oranges.beancount'], list(map(path.basename, options_map['include'])))
def test_load_file_with_duplicate_includes(self): with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ include "fruits/oranges.beancount" include "{root}/legumes/tomates.beancount" 2014-01-01 open Assets:Apples """, 'fruits/oranges.beancount': """ include "../legumes/tomates.beancount" 2014-01-02 open Assets:Oranges """, 'legumes/tomates.beancount': """ 2014-01-03 open Assets:Tomates """, 'legumes/patates.beancount': """ 2014-01-04 open Assets:Patates """ }) entries, errors, options_map = loader.load_file( path.join(tmp, 'apples.beancount')) self.assertTrue(errors) self.assertEqual(3, len(entries)) self.assertEqual( ['apples.beancount', 'oranges.beancount', 'tomates.beancount'], list(map(path.basename, options_map['include'])))
def test_load_string_with_relative_include(self): with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ include "fruits/oranges.beancount" 2014-01-01 open Assets:Apples """, 'fruits/oranges.beancount': """ 2014-01-02 open Assets:Oranges """ }) try: cwd = os.getcwd() os.chdir(tmp) entries, errors, options_map = loader.load_file( path.join(tmp, 'apples.beancount')) finally: os.chdir(cwd) self.assertFalse(errors) self.assertEqual(2, len(entries)) self.assertEqual(['apples.beancount', 'oranges.beancount'], list(map(path.basename, options_map['include'])))
def test_create_temporary_files(self): with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ include "{root}/fruits/oranges.beancount" 2014-01-01 open Assets:Apples """, 'fruits/oranges.beancount': """ 2014-01-02 open Assets:Oranges """ }) # Check the total list of files. apples = path.join(tmp, 'apples.beancount') oranges = path.join(tmp, 'fruits/oranges.beancount') self.assertEqual({apples, oranges}, set( path.join(root, filename) for root, _, files in os.walk(tmp) for filename in files)) # Check the contents of apples (with replacement of root). apples_content = open(apples).read() self.assertRegex(apples_content, 'open Assets:Apples') self.assertNotRegex(apples_content, '{root}') # Check the contents of oranges. oranges_content = open(oranges).read() self.assertRegex(oranges_content, 'open Assets:Oranges')
def test_include_encrypted(self): with test_utils.tempdir() as tmpdir: test_utils.create_temporary_files( tmpdir, { 'apples.beancount': """ include "oranges.beancount.asc" 2014-01-01 open Assets:Apples """, 'oranges.beancount': """ 2014-01-02 open Assets:Oranges """ }) # Encrypt the oranges file and remove the unencrypted file. with open(path.join(tmpdir, 'oranges.beancount')) as infile: self.encrypt_as_file( infile.read(), path.join(tmpdir, 'oranges.beancount.asc')) os.remove(path.join(tmpdir, 'oranges.beancount')) # Load the top-level file which includes the encrypted file. with test_utils.environ('GNUPGHOME', self.ringdir): entries, errors, options_map = loader.load_file( path.join(tmpdir, 'apples.beancount')) self.assertFalse(errors) self.assertEqual(2, len(entries)) self.assertRegex(entries[0].meta['filename'], 'apples.beancount') self.assertRegex(entries[1].meta['filename'], 'oranges.+count.asc')
def test_load_file_with_multiple_includes(self): # Including recursive includes and mixed and absolute. with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ include "fruits/oranges.beancount" include "{root}/legumes/patates.beancount" 2014-01-01 open Assets:Apples """, 'fruits/oranges.beancount': """ include "../legumes/tomates.beancount" 2014-01-02 open Assets:Oranges """, 'legumes/tomates.beancount': """ 2014-01-03 open Assets:Tomates """, 'legumes/patates.beancount': """ 2014-01-04 open Assets:Patates """ }) entries, errors, options_map = loader.load_file( path.join(tmp, 'apples.beancount')) self.assertFalse(errors) self.assertEqual(4, len(entries))
def test_load_file_with_nonexist_include(self): with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'root.beancount': """ include "/some/file/that/does/not/exist.beancount" """ }) entries, errors, options_map = loader.load_file( path.join(tmp, 'root.beancount')) self.assertEqual(1, len(errors)) self.assertTrue(re.search('does not exist', errors[0].message))
def test_load_file_no_includes(self): with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ 2014-01-01 open Assets:Apples """ }) entries, errors, options_map = loader.load_file( path.join(tmp, 'apples.beancount')) self.assertEqual(0, len(errors)) self.assertEqual(['apples.beancount'], list(map(path.basename, options_map['include'])))
def test_load_cache(self): # Create an initial set of files and load file, thus creating a cache. with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ include "oranges.beancount" 2014-01-01 open Assets:Apples """, 'oranges.beancount': """ include "bananas.beancount" 2014-01-02 open Assets:Oranges """, 'bananas.beancount': """ 2014-01-02 open Assets:Bananas """ }) top_filename = path.join(tmp, 'apples.beancount') entries, errors, options_map = loader.load_file(top_filename) self.assertFalse(errors) self.assertEqual(3, len(entries)) self.assertEqual(1, self.num_calls) # Make sure the cache was created. self.assertTrue( path.exists(path.join(tmp, '.apples.beancount.picklecache'))) # Load the root file again, make sure the cache is being hit. entries, errors, options_map = loader.load_file(top_filename) self.assertEqual(1, self.num_calls) # Touch the top-level file and ensure it's a cache miss. with open(top_filename, 'a') as file: file.write('\n') entries, errors, options_map = loader.load_file(top_filename) self.assertEqual(2, self.num_calls) # Load the root file again, make sure the cache is being hit. entries, errors, options_map = loader.load_file(top_filename) self.assertEqual(2, self.num_calls) # Touch the top-level file and ensure it's a cache miss. with open(top_filename, 'a') as file: file.write('\n') entries, errors, options_map = loader.load_file(top_filename) self.assertEqual(3, self.num_calls)
def test_load_file_with_nonexist_include(self): with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'root.beancount': """ include "/some/file/that/does/not/exist.beancount" """ }) entries, errors, options_map = loader.load_file( path.join(tmp, 'root.beancount')) self.assertEqual(1, len(errors)) self.assertRegex(errors[0].message, 'does not exist') self.assertEqual(['root.beancount'], list(map(path.basename, options_map['include'])))
def test_load_cache_override_filename_pattern_by_argument(self): with test_utils.tempdir() as tmp: cache_filename = path.join(tmp, "__{filename}__") loader.initialize(use_cache=True, cache_filename=cache_filename) test_utils.create_temporary_files( tmp, { 'apples.beancount': """ 2014-01-01 open Assets:Apples """ }) filename = path.join(tmp, 'apples.beancount') entries, errors, options_map = loader.load_file(filename) self.assertEqual({'__apples.beancount__', 'apples.beancount'}, set(os.listdir(tmp)))
def test_load_cache_override_filename_pattern_by_env_var(self): with test_utils.environ('BEANCOUNT_LOAD_CACHE_FILENAME', '__{filename}__'): loader.initialize(use_cache=True) with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ 2014-01-01 open Assets:Apples """ }) filename = path.join(tmp, 'apples.beancount') entries, errors, options_map = loader.load_file(filename) self.assertEqual({'__apples.beancount__', 'apples.beancount'}, set(os.listdir(tmp)))
def test_load_cache_read_only_fs(self, remove_mock, warn_mock): # Create an initial set of files and load file, thus creating a cache. with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ 2014-01-01 open Assets:Apples """ }) filename = path.join(tmp, 'apples.beancount') entries, errors, options_map = loader.load_file(filename) with open(filename, 'w'): pass entries, errors, options_map = loader.load_file(filename) self.assertEqual(1, len(warn_mock.mock_calls))
def test_load_file_with_relative_include(self): with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ include "fruits/oranges.beancount" 2014-01-01 open Assets:Apples """, 'fruits/oranges.beancount': """ 2014-01-02 open Assets:Oranges """ }) entries, errors, options_map = loader.load_file( path.join(tmp, 'apples.beancount')) self.assertFalse(errors) self.assertEqual(2, len(entries))
def test_load_cache_disable(self): with test_utils.tempdir() as tmp: cache_filename = path.join(tmp, "__{filename}__") for kwargs in [ dict(use_cache=False), dict(use_cache=False, cache_filename=cache_filename) ]: loader.initialize(**kwargs) test_utils.create_temporary_files( tmp, { 'apples.beancount': """ 2014-01-01 open Assets:Apples """ }) filename = path.join(tmp, 'apples.beancount') entries, errors, options_map = loader.load_file(filename) self.assertEqual({'apples.beancount'}, set(os.listdir(tmp)))
def test_load_file_with_absolute_include(self): with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ include "{root}/fruits/oranges.beancount" 2014-01-01 open Assets:Apples """, 'fruits/oranges.beancount': """ 2014-01-02 open Assets:Oranges """ }) entries, errors, options_map = loader.load_file( path.join(tmp, 'apples.beancount')) self.assertFalse(errors) self.assertEqual(2, len(entries)) self.assertEqual(['apples.beancount', 'oranges.beancount'], list(map(path.basename, options_map['include'])))
def test_load_cache_moved_file(self): # Create an initial set of files and load file, thus creating a cache. with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ include "oranges.beancount" 2014-01-01 open Assets:Apples """, 'oranges.beancount': """ 2014-01-02 open Assets:Oranges """ }) top_filename = path.join(tmp, 'apples.beancount') entries, errors, options_map = loader.load_file(top_filename) self.assertFalse(errors) self.assertEqual(2, len(entries)) self.assertEqual(1, self.num_calls) # Make sure the cache was created. self.assertTrue( path.exists(path.join(tmp, '.apples.beancount.picklecache'))) # CHeck that it doesn't need refresh self.assertFalse(loader.needs_refresh(options_map)) # Move the input file. new_top_filename = path.join(tmp, 'bigapples.beancount') os.rename(top_filename, new_top_filename) # Check that it needs refresh. self.assertTrue(loader.needs_refresh(options_map)) # Load the root file again, make sure the cache is being hit. entries, errors, options_map = loader.load_file(top_filename) self.assertEqual(2, self.num_calls)
def test_aggregate_commodities(self): with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ include "oranges.beancount" include "bananas.beancount" option "operating_currency" "USD" """, 'oranges.beancount': """ 2015-12-12 open Assets:CA:Checking CAD """, 'bananas.beancount': """ 2015-12-13 open Assets:FR:Checking EUR """ }) top_filename = path.join(tmp, 'apples.beancount') entries, errors, options_map = loader.load_file(top_filename) self.assertEqual({'EUR', 'CAD'}, options_map['commodities'])
def test_aggregate_operating_currencies(self): with test_utils.tempdir() as tmp: test_utils.create_temporary_files( tmp, { 'apples.beancount': """ include "oranges.beancount" include "bananas.beancount" option "operating_currency" "USD" """, 'oranges.beancount': """ option "operating_currency" "CAD" """, 'bananas.beancount': """ option "operating_currency" "EUR" """ }) top_filename = path.join(tmp, 'apples.beancount') entries, errors, options_map = loader.load_file(top_filename) self.assertEqual({'USD', 'EUR', 'CAD'}, set(options_map['operating_currency']))