Пример #1
0
 def test_inventory(self):
     itypes = [('pos', inventory.Inventory)]
     irows = [(inventory.from_string(string), )
              for string in self.input_amounts]
     atypes, arows = numberify.numberify_results(itypes, irows)
     self.assertEqual(self.expected_types, atypes)
     self.assertEqual(self.expected_rows, arows)
Пример #2
0
 def test_position(self):
     itypes = [('pos', position.Position)]
     irows = [(position.from_string(string), )
              for string in self.input_amounts]
     atypes, arows = numberify.numberify_results(itypes, irows)
     self.assertEqual(self.expected_types, atypes)
     self.assertEqual(self.expected_rows, arows)
Пример #3
0
    def test_inventory(self):
        itypes = [('balance', inventory.Inventory)]
        irows = [[inventory.from_string('10 HOOL {23.00 USD}')],
                 [inventory.from_string('2.11 USD, 3.44 CAD')],
                 [inventory.from_string('-2 HOOL {24.00 USD}, 5.66 CAD')]]
        atypes, arows = numberify.numberify_results(itypes, irows)

        self.assertEqual([('balance (HOOL)', Decimal),
                          ('balance (CAD)', Decimal),
                          ('balance (USD)', Decimal)], atypes)

        self.assertEqual(
            [[D('10'), None, None],
             [None, D('3.44'), D('2.11')], [D('-2'), D('5.66'), None]], arows)
Пример #4
0
def run_query(entries, options_map, query, *format_args, numberify=False):
    """Compile and execute a query, return the result types and rows.

    Args:
      entries: A list of entries, as produced by the loader.
      options_map: A dict of options, as produced by the loader.
      query: A string, a single BQL query, optionally containing some new-style
        (e.g., {}) formatting specifications.
      format_args: A tuple of arguments to be formatted in the query. This is
        just provided as a convenience.
      numberify: If true, numberify the results before returning them.
    Returns:
      A pair of result types and result rows.
    Raises:
      ParseError: If the statement cannot be parsed.
      CompilationError: If the statement cannot be compiled.
    """
    env_targets = query_env.TargetsEnvironment()
    env_entries = query_env.FilterEntriesEnvironment()
    env_postings = query_env.FilterPostingsEnvironment()

    # Apply formatting to the query.
    formatted_query = query.format(*format_args)

    # Parse the statement.
    parser = query_parser.Parser()
    statement = parser.parse(formatted_query)

    # Compile the SELECT statement.
    c_query = query_compile.compile(statement, env_targets, env_postings,
                                    env_entries)

    # Execute it to obtain the result rows.
    rtypes, rrows = query_execute.execute_query(c_query, entries, options_map)

    # Numberify the results, if requested.
    if numberify:
        dformat = options_map['dcontext'].build()
        rtypes, rrows = numberify_lib.numberify_results(rtypes, rrows, dformat)

    return rtypes, rrows
Пример #5
0
    def test_precision(self):
        # Some display context.
        dcontext = display_context.DisplayContext()
        dcontext.update(D('111'), 'JPY')
        dcontext.update(D('1.111'), 'RGAGX')
        dcontext.update(D('1.11'), 'USD')
        dformat = dcontext.build()

        # Input data.
        itypes = [('number', Decimal), ('amount', amount.Amount),
                  ('position', position.Position),
                  ('inventory', inventory.Inventory)]
        irows = [[
            D(amt.split()[0]),
            A(amt),
            position.from_string(amt),
            inventory.from_string(amt)
        ] for amt in [
            '123.45678909876 JPY', '1.67321232123 RGAGX', '5.67345434543 USD'
        ]]

        # First check with no explicit quantization.
        atypes, arows = numberify.numberify_results(itypes, irows)
        erows = [[
            D('123.45678909876'), None, None,
            D('123.45678909876'), None, None,
            D('123.45678909876'), None, None,
            D('123.45678909876')
        ],
                 [
                     D('1.67321232123'), None,
                     D('1.67321232123'), None, None,
                     D('1.67321232123'), None, None,
                     D('1.67321232123'), None
                 ],
                 [
                     D('5.67345434543'),
                     D('5.67345434543'), None, None,
                     D('5.67345434543'), None, None,
                     D('5.67345434543'), None, None
                 ]]
        self.assertEqual(erows, arows)

        # Then compare with quantization.
        atypes, arows = numberify.numberify_results(itypes, irows, dformat)

        erows = [[
            D('123.45678909876'), None, None,
            D('123'), None, None,
            D('123'), None, None,
            D('123')
        ],
                 [
                     D('1.67321232123'), None,
                     D('1.673'), None, None,
                     D('1.673'), None, None,
                     D('1.673'), None
                 ],
                 [
                     D('5.67345434543'),
                     D('5.67'), None, None,
                     D('5.67'), None, None,
                     D('5.67'), None, None
                 ]]
        self.assertEqual(erows, arows)
Пример #6
0
 def test_identity(self):
     itypes = [('date', datetime.date), ('name', str), ('count', int)]
     irows = [[datetime.date(2015, 9, 8), 'Testing', 3]]
     atypes, arows = numberify.numberify_results(itypes, irows)
     self.assertEqual(itypes, atypes)
     self.assertEqual(irows, arows)
Пример #7
0
 def test_amount(self):
     itypes = [('pos', amount.Amount)]
     irows = [(A(string), ) for string in self.input_amounts]
     atypes, arows = numberify.numberify_results(itypes, irows)
     self.assertEqual(self.expected_types, atypes)
     self.assertEqual(self.expected_rows, arows)
Пример #8
0
    def on_Select(self, statement):
        """
        Extract data from a query on the postings.

        The general form of a SELECT statement loosely follows SQL syntax, with
        some mild and idiomatic extensions:

           SELECT [DISTINCT] [<targets>|*]
           [FROM <from_expr> [OPEN ON <date>] [CLOSE [ON <date>]] [CLEAR]]
           [WHERE <where_expr>]
           [GROUP BY <groups>]
           [ORDER BY <groups> [ASC|DESC]]
           [LIMIT num]

        Where:

          targets: A list of desired output attributes from the postings, and
            expressions on them. Some of the attributes of the parent transaction
            directive are made available in this context as well. Simple functions
            (that return a single value per row) and aggregation functions (that
            return a single value per group) are available. For the complete
            list of supported columns and functions, see help on "targets".
            You can also provide a wildcard here, which will select a reasonable
            default set of columns for rendering a journal.

          from_expr: A logical expression that matches on the attributes of
            the directives (not postings). This allows you to select a subset of
            transactions, so the accounting equation is respected for balance
            reports. For the complete list of supported columns and functions,
            see help on "from".

          where_expr: A logical expression that matches on the attributes of
            postings. The available columns are similar to those in the targets
            clause, without the aggregation functions.

          OPEN clause: replace all the transactions before the given date by
            summarizing entries and transfer Income and Expenses balances to
            Equity.

          CLOSE clause: Remove all the transactions after the given date and

          CLEAR: Transfer final Income and Expenses balances to Equity.

        """
        # Compile the SELECT statement.
        try:
            c_query = query_compile.compile(statement, self.env_targets,
                                            self.env_postings,
                                            self.env_entries)
        except query_compile.CompilationError as exc:
            print('ERROR: {}.'.format(str(exc).rstrip('.')), file=self.outfile)
            return

        # Execute it to obtain the result rows.
        rtypes, rrows = query_execute.execute_query(c_query, self.entries,
                                                    self.options_map)

        # Output the resulting rows.
        if not rrows:
            print("(empty)", file=self.outfile)
        else:
            output_format = self.vars['format']
            if output_format == 'text':
                kwds = dict(boxed=self.vars['boxed'],
                            spaced=self.vars['spaced'],
                            expand=self.vars['expand'])
                if self.outfile is sys.stdout:
                    with self.get_pager() as file:
                        query_render.render_text(rtypes, rrows,
                                                 self.options_map['dcontext'],
                                                 file, **kwds)
                else:
                    query_render.render_text(rtypes, rrows,
                                             self.options_map['dcontext'],
                                             self.outfile, **kwds)

            elif output_format == 'csv':
                # Numberify CSV output if requested.
                if self.vars['numberify']:
                    dformat = self.options_map['dcontext'].build()
                    rtypes, rrows = numberify.numberify_results(
                        rtypes, rrows, dformat)

                query_render.render_csv(rtypes,
                                        rrows,
                                        self.options_map['dcontext'],
                                        self.outfile,
                                        expand=self.vars['expand'])

            else:
                assert output_format not in _SUPPORTED_FORMATS
                print("Unsupported output format: '{}'.".format(output_format),
                      file=self.outfile)