diff --git a/conservancy_beancount/errors.py b/conservancy_beancount/errors.py
index 3d9bdd2..486676a 100644
--- a/conservancy_beancount/errors.py
+++ b/conservancy_beancount/errors.py
@@ -14,24 +14,53 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
+import beancount.core.data as bc_data
+
from typing import (
+ Any,
Iterable,
+ Optional,
)
+from .beancount_types import (
+ Directive,
+ MetaKey,
+ MetaValue,
+ Posting,
+ Transaction,
+ Type,
+)
+
+Meta = Optional[bc_data.Meta]
+
class Error(Exception):
- def __init__(self, message, entry, source=None):
+ def __init__(self,
+ message: str,
+ entry: Optional[Directive],
+ source: Meta=None,
+ ) -> None:
self.message = message
self.entry = entry
- self.source = entry.meta if source is None else source
+ if source:
+ self.source = source
+ elif entry is not None:
+ self.source = entry.meta
+ else:
+ self.source = {}
+ self._fill_source(self.source, '')
- def __repr__(self):
+ def __repr__(self) -> str:
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):
+ def _fill_source(self,
+ source: bc_data.Meta,
+ filename: str='conservancy_beancount',
+ lineno: int=0,
+ ) -> None:
source.setdefault('filename', filename)
source.setdefault('lineno', lineno)
@@ -39,15 +68,27 @@ class Error(Exception):
Iter = Iterable[Error]
class BrokenLinkError(Error):
- def __init__(self, txn, key, link, source=None):
+ def __init__(self,
+ txn: Transaction,
+ key: MetaKey,
+ link: str,
+ source: Meta=None,
+ ) -> 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):
+ def __init__(self,
+ txn: Transaction,
+ key: MetaKey,
+ link: str,
+ parsed: Any=True,
+ source: Meta=None,
+ ) -> None:
if parsed:
msg_fmt = "{} not found in RT: {}"
else:
@@ -58,8 +99,13 @@ class BrokenRTLinkError(Error):
source,
)
+
class ConfigurationError(Error):
- def __init__(self, message, entry=None, source=None):
+ def __init__(self,
+ message: str,
+ entry: Optional[Directive]=None,
+ source: Meta=None,
+ ) -> None:
if source is None:
source = {}
self._fill_source(source)
@@ -67,7 +113,14 @@ class ConfigurationError(Error):
class InvalidMetadataError(Error):
- def __init__(self, txn, key, value=None, post=None, need_type=str, source=None):
+ def __init__(self,
+ txn: Transaction,
+ key: MetaKey,
+ value: Optional[MetaValue]=None,
+ post: Optional[bc_data.Posting]=None,
+ need_type: Type=str,
+ source: Meta=None,
+ ) -> None:
if post is None:
srcname = 'transaction'
else:
diff --git a/conservancy_beancount/plugin/core.py b/conservancy_beancount/plugin/core.py
index 241d7f9..2107045 100644
--- a/conservancy_beancount/plugin/core.py
+++ b/conservancy_beancount/plugin/core.py
@@ -69,8 +69,9 @@ class Hook(Generic[Entry], metaclass=abc.ABCMeta):
@abc.abstractmethod
def run(self, entry: Entry) -> errormod.Iter: ...
- def __init_subclass__(cls):
- cls.DIRECTIVE = cls.__orig_bases__[0].__args__[0]
+ def __init_subclass__(cls) -> None:
+ # cls.__orig_bases__ comes from the ABCMeta metaclass
+ cls.DIRECTIVE = cls.__orig_bases__[0].__args__[0] # type:ignore[attr-defined]
TransactionHook = Hook[Transaction]
diff --git a/conservancy_beancount/plugin/meta_project.py b/conservancy_beancount/plugin/meta_project.py
index 343a100..ec221cb 100644
--- a/conservancy_beancount/plugin/meta_project.py
+++ b/conservancy_beancount/plugin/meta_project.py
@@ -31,6 +31,7 @@ from ..beancount_types import (
from typing import (
Any,
Dict,
+ NoReturn,
Optional,
Set,
)
@@ -43,7 +44,7 @@ class MetaProject(core._NormalizePostingMetadataHook):
def __init__(self, config: configmod.Config, source_path: Path=PROJECT_DATA_PATH) -> None:
repo_path = config.repository_path()
if repo_path is None:
- raise self._config_error("no repository configured")
+ self._config_error("no repository configured")
project_data_path = repo_path / source_path
source = {'filename': str(project_data_path)}
try:
@@ -68,7 +69,7 @@ class MetaProject(core._NormalizePostingMetadataHook):
else:
self.VALUES_ENUM = core.MetadataEnum(self.METADATA_KEY, names, aliases)
- def _config_error(self, msg: str, filename: Optional[Path]=None):
+ def _config_error(self, msg: str, filename: Optional[Path]=None) -> NoReturn:
source = {}
if filename is not None:
source['filename'] = str(filename)
diff --git a/conservancy_beancount/rtutil.py b/conservancy_beancount/rtutil.py
index cb2dd37..2fa8c5f 100644
--- a/conservancy_beancount/rtutil.py
+++ b/conservancy_beancount/rtutil.py
@@ -196,11 +196,12 @@ class RT:
# to be a method, it's just an internal decrator.
def _cache_method(func: _URLLookup) -> _URLLookup: # type:ignore[misc]
@functools.wraps(func)
- def caching_wrapper(self,
+ def caching_wrapper(self: 'RT',
ticket_id: RTId,
attachment_id: Optional[RTId]=None,
) -> Optional[str]:
- cache_key = (str(ticket_id), attachment_id and str(attachment_id))
+ cache_key = (str(ticket_id),
+ None if attachment_id is None else str(attachment_id))
url: Optional[str]
try:
url = self._cache[cache_key]
diff --git a/setup.cfg b/setup.cfg
index c7858f3..7ea8404 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -4,6 +4,7 @@ typecheck=pytest --addopts="--mypy conservancy_beancount"
[mypy]
disallow_any_unimported = True
+disallow_untyped_defs = True
show_error_codes = True
strict_equality = True
warn_redundant_casts = True