Example #1
0
 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
Example #2
0
 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'])))
Example #3
0
 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'])))
Example #4
0
 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'])))
Example #5
0
    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')
Example #6
0
    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')
Example #7
0
 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))
Example #8
0
 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))
Example #9
0
 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'])))
Example #10
0
    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)
Example #11
0
 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'])))
Example #12
0
 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)))
Example #13
0
 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)))
Example #14
0
 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))
Example #15
0
 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))
Example #16
0
 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)))
Example #17
0
 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'])))
Example #18
0
    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)
Example #19
0
    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'])
Example #20
0
    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']))