Example #1
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 #2
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 #3
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 #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_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 #6
0
 def test_validate_local_links(self):
     with test_utils.tempdir() as tmpdir:
         os.mkdir(path.join(tmpdir, 'root'))
         os.mkdir(path.join(tmpdir, 'root/sub'))
         open(path.join(tmpdir, 'parent.html'), 'w')
         open(path.join(tmpdir, 'root/sibling.html'), 'w')
         open(path.join(tmpdir, 'root/sibling.png'), 'w')
         open(path.join(tmpdir, 'root/sub/child.html'), 'w')
         filename = path.join(tmpdir, 'root/start.html')
         with open(filename, 'w') as ffile:
             ffile.write(textwrap.dedent("""
               <html>
                 <body>
                   <a href="../parent.html">Parent</a>
                   <a href="../parent_not.html">Parent</a>
                   <a href="sibling.html">Sibling</a>
                   <a href="sibling_not.html">Sibling</a>
                   <img src="sibling.png">Sibling Image</a>
                   <a href="sub/child.html">Child</a>
                   <a href="sub/child_not.html">Child</a>
                 </body>
               </html>
             """))
         missing, empty = scrape.validate_local_links(filename)
         self.assertFalse(empty)
         self.assertEqual(3, len(missing))
         self.assertTrue(all(re.search('_not', filename)
                             for filename in missing))
Example #7
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 #8
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 #9
0
 def test_bake_missing_input(self):
     with test_utils.tempdir() as tmpdir:
         with self.assertRaises(SystemExit):
             output = path.join(tmpdir, 'output')
             filename = path.join(tmpdir, 'does_not_exist.beancount')
             test_utils.run_with_args(bake.main,
                                      self.get_args() + [filename, output])
Example #10
0
 def test_tempdir(self):
     with test_utils.tempdir() as tempdir:
         open(path.join(tempdir, 'file1'), 'w')
         os.mkdir(path.join(tempdir, 'directory'))
         open(path.join(tempdir, 'directory', 'file2'), 'w')
     self.assertFalse(path.exists(tempdir))
     self.assertFalse(path.exists(path.join(tempdir, 'file1')))
     self.assertFalse(path.exists(path.join(tempdir, 'directory')))
Example #11
0
 def test_validate_local_links__empty(self):
     with test_utils.tempdir() as tmpdir:
         filename = path.join(tmpdir, 'start.html')
         with open(filename, 'w'):
             pass
         missing, empty = scrape.validate_local_links(filename)
         self.assertTrue(empty)
         self.assertFalse(missing)
Example #12
0
    def test_save_scraped_document__ignore_directories(self):
        html = lxml.html.document_fromstring(self.test_html)
        with test_utils.tempdir() as tmp:
            response = mock.MagicMock()
            response.url = '/doc/to/'
            response.status = 200
            response.read.return_value = self.test_html.encode('utf8')
            response.info().get_content_type.return_value = 'text/html'

            bake.save_scraped_document(tmp, response.url, response,
                                       response.read.return_value, html, set())
            self.assertEqual([], os.listdir(tmp))
Example #13
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 #14
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 #15
0
    def test_save_scraped_document__file(self):
        html = lxml.html.document_fromstring(self.test_html)
        with test_utils.tempdir() as tmp:
            response = mock.MagicMock()
            response.url = '/path/to/file'
            response.status = 200
            response.read.return_value = self.test_html.encode('utf8')
            response.info().get_content_type.return_value = 'text/html'

            bake.save_scraped_document(tmp, response.url, response,
                                       response.read.return_value, html, set())
            filename = path.join(tmp, 'path/to/file.html')
            self.assertTrue(path.exists(filename))
            self.assertLines(open(filename).read(), self.expected_html)
Example #16
0
    def test_save_scraped_document__binary_content(self):
        html = lxml.html.document_fromstring(self.test_html)
        with test_utils.tempdir() as tmp:
            response = mock.MagicMock()
            response.url = '/resources/something.png'
            response.status = 200
            expected_contents = 'IMAGE!'.encode('utf8')
            response.read.return_value = expected_contents
            response.info().get_content_type.return_value = 'image/png'

            bake.save_scraped_document(
                tmp, response.url, response, expected_contents, html, set())
            actual_contents = open(path.join(tmp, 'resources/something.png'), 'rb').read()
            self.assertEqual(expected_contents, actual_contents)
Example #17
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 #18
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 #19
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 #20
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 #21
0
    def test_bake_archive__unknown(self, filename):
        """
        2013-01-01 open Expenses:Restaurant
        2013-01-01 open Assets:Cash

        2014-03-02 * "Some basic transaction"
          Expenses:Restaurant   50.02 USD
          Assets:Cash
        """
        with test_utils.tempdir() as tmpdir:
            for archive_name in ('archive.tar.zip', 'archive.tar.xz'):
                with self.assertRaises(SystemExit):
                    outfile = path.join(tmpdir, archive_name)
                    test_utils.run_with_args(
                        bake.main,
                        self.get_args() + [filename, outfile])
Example #22
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 #23
0
    def test_bake_directory(self, filename):
        """
        2013-01-01 open Expenses:Restaurant
        2013-01-01 open Assets:Cash

        2014-03-02 * "Some basic transaction"
          Expenses:Restaurant   50.02 USD
          Assets:Cash
        """
        with test_utils.tempdir() as tmpdir:
            outdir = path.join(tmpdir, 'output')
            with test_utils.capture('stdout', 'stderr') as (output, _):
                test_utils.run_with_args(bake.main, self.get_args() + [filename, outdir])
            self.assertTrue(output.getvalue())
            self.assertTrue(path.exists(outdir) and path.isdir(outdir))
            directories = [root for root, _, _ in os.walk(outdir)]
            self.assertGreater(len(directories), 10)
Example #24
0
    def test_bake_bad_link(self, filename):
        """
        plugin "beancount.plugins.auto_accounts"

        2014-03-02 * "Something" ^2015-06-14.something.pdf
          Expenses:Restaurant   1 USD
          Assets:Cash
        """
        with test_utils.tempdir(delete=0) as tmpdir:
            tmpdir = path.join(tmpdir, 'output')
            with test_utils.capture() as output:
                test_utils.run_with_args(bake.main, self.get_args() + [filename, tmpdir])
            self.assertTrue(output.getvalue())
            self.assertFalse(path.exists(
                path.join(tmpdir, 'link/2015-06-14.something.pdf')))
            self.assertTrue(path.exists(
                path.join(tmpdir, 'link/2015-06-14.something.pdf.html')))
Example #25
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 #26
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 #27
0
    def test_bake_archive__known(self, filename):
        """
        2013-01-01 open Expenses:Restaurant
        2013-01-01 open Assets:Cash

        2014-03-02 * "Some basic transaction"
          Expenses:Restaurant   50.02 USD
          Assets:Cash
        """
        with test_utils.tempdir() as tmpdir:
            for archive_name in ('archive.tar.gz',
                                 'archive.tgz',
                                 'archive.tar.bz2',
                                 'archive.zip'):
                outfile = path.join(tmpdir, archive_name)
                with test_utils.capture():
                    test_utils.run_with_args(bake.main,
                                             self.get_args() + [filename, outfile])
                self.assertFalse(path.exists(file_utils.path_greedy_split(outfile)[0]))
                self.assertTrue(path.exists(outfile) and path.getsize(outfile) > 0)
Example #28
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 #29
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 #30
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'])