Exemplo n.º 1
0
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
Exemplo n.º 2
0
    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()
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
 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)
Exemplo n.º 5
0
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"')
Exemplo n.º 6
0
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),
Exemplo n.º 7
0
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",
    [