class Filters: """The possible entry filters.""" __slots__ = ("account", "filter", "time") def __init__(self, options: BeancountOptions, fava_options: FavaOptions) -> None: self.account = AccountFilter(options, fava_options) self.filter = AdvancedFilter(options, fava_options) self.time = TimeFilter(options, fava_options) def set( self, account: str | None = None, filter: str | None = None, # pylint: disable=redefined-builtin time: str | None = None, ) -> bool: """Set the filters and check if one of them changed.""" return any([ self.account.set(account), self.filter.set(filter), self.time.set(time), ]) def apply(self, entries: Entries) -> Entries: """Apply the filters to the entries.""" entries = self.account.apply(entries) entries = self.filter.apply(entries) entries = self.time.apply(entries) return entries
def __init__(self, path): #: The path to the main Beancount file. self.beancount_file_path = path self._is_encrypted = is_encrypted_file(path) self._filters = { 'account': AccountFilter(), 'filter': AdvancedFilter(), 'time': TimeFilter(), } #: An :class:`AttributesModule` instance. self.attributes = AttributesModule(self) #: A :class:`.BudgetModule` instance. self.budgets = BudgetModule(self) #: A :class:`.ChartModule` instance. self.charts = ChartModule(self) #: A :class:`.ExtensionModule` instance. self.extensions = ExtensionModule(self) #: A :class:`.FileModule` instance. self.file = FileModule(self) #: A :class:`.IngestModule` instance. self.ingest = IngestModule(self) #: A :class:`.FavaMisc` instance. self.misc = FavaMisc(self) #: A :class:`.QueryShell` instance. self.query_shell = QueryShell(self) self._watcher = Watcher() #: List of all (unfiltered) entries. self.all_entries = None #: Dict of list of all (unfiltered) entries by type. self.all_entries_by_type = None #: A list of all errors reported by Beancount. self.errors = None #: A Beancount options map. self.options = None #: A Namedtuple containing the names of the five base accounts. self.account_types = None #: A dict containing information about the accounts. self.accounts = _AccountDict() #: A dict with all of Fava's option values. self.fava_options = None self.load_file()
def load_file(self): """Load the main file and all included files and set attributes.""" # use the internal function to disable cache if not self._is_encrypted: # pylint: disable=protected-access self.all_entries, self.errors, self.options = loader._load( [(self.beancount_file_path, True)], None, None, None ) else: self.all_entries, self.errors, self.options = loader.load_file( self.beancount_file_path ) self.account_types = get_account_types(self.options) self.price_map = prices.build_price_map(self.all_entries) self.all_root_account = realization.realize( self.all_entries, self.account_types ) entries_by_type = collections.defaultdict(list) for entry in self.all_entries: entries_by_type[type(entry)].append(entry) self.all_entries_by_type = entries_by_type self.accounts = _AccountDict() for entry in entries_by_type[Open]: self.accounts.setdefault(entry.account).meta = entry.meta for entry in entries_by_type[Close]: self.accounts.setdefault(entry.account).close_date = entry.date self.fava_options, errors = parse_options(entries_by_type[Custom]) self.errors.extend(errors) if not self._is_encrypted: self._watcher.update(*self.paths_to_watch()) for mod in MODULES: getattr(self, mod).load_file() self._filters = { "account": AccountFilter(self.options, self.fava_options), "filter": AdvancedFilter(self.options, self.fava_options), "time": TimeFilter(self.options, self.fava_options), } self.filter(True)
def __init__(self, options: BeancountOptions, fava_options: FavaOptions) -> None: self.account = AccountFilter(options, fava_options) self.filter = AdvancedFilter(options, fava_options) self.time = TimeFilter(options, fava_options)
def test_lexer_parentheses(): data = "(payee:asdfasdf ^some_link) (somekey:'testtest')" assert [(tok.type, tok.value) for tok in LEX(data)] == [ ("(", "("), ("KEY", "payee"), ("STRING", "asdfasdf"), ("LINK", "some_link"), (")", ")"), ("(", "("), ("KEY", "somekey"), ("STRING", "testtest"), (")", ")"), ] FILTER = AdvancedFilter({}, {}) def test_filterexception(): with pytest.raises(FilterException) as exception: raise FilterException("type", "error") exception = exception.value assert str(exception) == "error" assert str(exception) == exception.message with pytest.raises(FilterException): FILTER.set('who:"fff') assert str(exception) == 'Illegal character """ in filter: who:"fff' with pytest.raises(FilterException): FILTER.set('any(who:"Martin"')
def test_lexer_parentheses(): data = "(payee:asdfasdf ^some_link) (somekey:'testtest')" assert [(tok.type, tok.value) for tok in LEX(data)] == [ ('(', '('), ('KEY', 'payee'), ('STRING', 'asdfasdf'), ('LINK', 'some_link'), (')', ')'), ('(', '('), ('KEY', 'somekey'), ('STRING', 'testtest'), (')', ')'), ] FILTER = AdvancedFilter() def test_filterexception(): with pytest.raises(FilterException) as exception: raise FilterException('type', 'error') exception = exception.value assert str(exception) == 'error' assert str(exception) == exception.message with pytest.raises(FilterException): FILTER.set('from:invalid') @pytest.mark.parametrize('string,number', [ ('from:\'has_account("Assets:US:ETrade")\'', 53),
def test_lexer_parentheses() -> None: data = "(payee:asdfasdf ^some_link) (somekey:'testtest')" assert [(tok.type, tok.value) for tok in LEX(data)] == [ ("(", "("), ("KEY", "payee"), ("STRING", "asdfasdf"), ("LINK", "some_link"), (")", ")"), ("(", "("), ("KEY", "somekey"), ("STRING", "testtest"), (")", ")"), ] FILTER = AdvancedFilter(OPTIONS_DEFAULTS, FavaOptions()) def test_filterexception() -> None: with pytest.raises(FilterException) as exception: FILTER.set('who:"fff') assert str(exception) == 'Illegal character """ in filter: who:"fff' with pytest.raises(FilterException) as exception: FILTER.set('any(who:"Martin"') assert str(exception) == 'Failed to parse filter: any(who:"Martin"' @pytest.mark.parametrize( "string,number", [