Files @ 4874a107e834
Branch filter:

Location: NPO-Accounting/conservancy_beancount/conservancy_beancount/errors.py

Brett Smith
meta_rt_links: Start hook.
"""Error classes for plugins to report problems in the books"""
# Copyright © 2020  Brett Smith
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

from typing import (
    Iterable,
)

class Error(Exception):
    def __init__(self, message, entry, source=None):
        self.message = message
        self.entry = entry
        self.source = entry.meta if source is None else source

    def __repr__(self):
        return "{clsname}<{source[filename]}:{source[lineno]}: {message}>".format(
            clsname=type(self).__name__,
            message=self.message,
            source=self.source,
        )

    def _fill_source(self, source, filename='conservancy_beancount', lineno=0):
        source.setdefault('filename', filename)
        source.setdefault('lineno', lineno)


Iter = Iterable[Error]

class BrokenLinkError(Error):
    def __init__(self, txn, key, link, source=None):
        super().__init__(
            "{} not found in repository: {}".format(key, link),
            txn,
            source,
        )

class BrokenRTLinkError(Error):
    def __init__(self, txn, key, link, parsed=True, source=None):
        if parsed:
            msg_fmt = "{} not found in RT: {}"
        else:
            msg_fmt = "{} link is malformed: {}"
        super().__init__(
            msg_fmt.format(key, link),
            txn,
            source,
        )

class ConfigurationError(Error):
    def __init__(self, message, entry=None, source=None):
        if source is None:
            source = {}
        self._fill_source(source)
        super().__init__(message, entry, source)


class InvalidMetadataError(Error):
    def __init__(self, txn, post, key, value=None, source=None):
        if value is None:
            msg_fmt = "{post.account} missing {key}"
        else:
            msg_fmt = "{post.account} has invalid {key}: {value}"
        super().__init__(
            msg_fmt.format(post=post, key=key, value=value),
            txn,
            source,
        )


class InvalidEntityError(InvalidMetadataError):
    def __init__(self, txn, post=None, key='entity', value=None, source=None):
        if post is None:
            srcname = 'transaction'
        else:
            srcname = post.account
        if value is None:
            msg = "{} missing entity".format(srcname)
        else:
            msg = "{} entity malformed: {}".format(srcname, value)
        super(InvalidMetadataError, self).__init__(msg, txn, source)