def get_matching_entries(entries, options_map, query): query_text = 'SELECT * ' + query parser = query_parser.Parser() parsed_query = parser.parse(query_text) c_from = None if parsed_query.from_clause: c_from = query_compile.compile_from(parsed_query.from_clause, query_env.FilterEntriesEnvironment()) c_where = None if parsed_query.where_clause: c_where = query_compile.compile_expression(parsed_query.where_clause, query_env.FilterPostingsEnvironment()) # Figure out if we need to compute balance. balance = None if c_where and query_execute.uses_balance_column(c_where): balance = inventory.Inventory() context = query_execute.RowContext() context.balance = balance # Initialize some global properties for use by some of the accessors. context.options_map = options_map context.account_types = options.get_account_types(options_map) context.open_close_map = getters.get_account_open_close(entries) #context.commodity_map = getters.get_commodity_map(entries) context.price_map = prices.build_price_map(entries) if c_from is not None: filtered_entries = query_execute.filter_entries(c_from, entries, options_map) else: filtered_entries = entries return filtered_entries
def transform_balances(balances): """Translate a Balances entry into an uncompiled Select statement. Args: balances: An instance of a Balance object. Returns: An instance of an uncompiled Select object. """ ## FIXME: Change the aggregation rules to allow GROUP-BY not to include the ## non-aggregate ORDER-BY columns, so we could just GROUP-BY accounts here ## instead of having to include the sort-key. I think it should be fine if ## the first or last sort-order value gets used, because it would simplify ## the input statement. cooked_select = query_parser.Parser().parse(""" SELECT account, SUM({}(position)) GROUP BY account, ACCOUNT_SORTKEY(account) ORDER BY ACCOUNT_SORTKEY(account) """.format(balances.summary_func or "")) return query_parser.Select(cooked_select.targets, balances.from_clause, balances.where_clause, cooked_select.group_by, cooked_select.order_by, None, None, None, None)
def transform_journal(journal): """Translate a Journal entry into an uncompiled Select statement. Args: journal: An instance of a Journal object. Returns: An instance of an uncompiled Select object. """ cooked_select = query_parser.Parser().parse(""" SELECT date, flag, MAXWIDTH(payee, 48), MAXWIDTH(narration, 80), account, {summary_func}(position), {summary_func}(balance) {where} """.format(where=('WHERE account ~ "{}"'.format(journal.account) if journal.account else ''), summary_func=journal.summary_func or '')) return query_parser.Select(cooked_select.targets, journal.from_clause, cooked_select.where_clause, None, None, None, None, None, None)
def __init__(self, is_interactive, loadfun, outfile): super().__init__(is_interactive, query_parser.Parser(), outfile) self.loadfun = loadfun self.entries = None self.errors = None self.options_map = None self.env_targets = query_env.TargetsEnvironment() self.env_entries = query_env.FilterEntriesEnvironment() self.env_postings = query_env.FilterPostingsEnvironment()
def __init__(self, is_interactive, loadfun, outfile, default_format='text', do_numberify=False): super().__init__(is_interactive, query_parser.Parser(), outfile, default_format, do_numberify) self.loadfun = loadfun self.entries = None self.errors = None self.options_map = None self.env_targets = query_env.TargetsEnvironment() self.env_entries = query_env.FilterEntriesEnvironment() self.env_postings = query_env.FilterPostingsEnvironment()
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
"""A token having a certain type and value. The lexer attribute only exists since PLY writes to it in case of a parser error. """ __slots__ = ['type', 'value', 'lexer'] def __init__(self, type_, value): self.type = type_ self.value = value def __repr__(self): return 'Token({}, {})'.format(self.type, self.value) QUERY_PARSER = query_parser.Parser() ENV_ENTRIES = query_env.FilterEntriesEnvironment() class FilterSyntaxLexer(object): """Lexer for Fava's filter syntax.""" # pylint: disable=missing-docstring,invalid-name,no-self-use tokens = ( 'ANY', 'KEY', 'LINK', 'STRING', 'TAG', )
def setUp(self): super().setUp() self.parser = query_parser.Parser()
def setUp(self): self.parser = qp.Parser()
def __init__(self): super().__init__() self.parser = query_parser.Parser() self.env_entries = query_env.FilterEntriesEnvironment() self.c_from = None