Changeset - ca12496880d6
[Not reviewed]
0 10 0
Brett Smith - 3 years ago 2021-02-26 21:13:02
brettcsmith@brettcsmith.org
typing: Updates to pass type checking under mypy>=0.800.

Most of these account for the fact that mypy now reports that Hashable is
not an allowed return type for sort key functions.

That, plus the new ignore for the regression in config.py.
10 files changed with 22 insertions and 18 deletions:
0 comments (0 inline, 0 general)
conservancy_beancount/beancount_types.py
Show inline comments
...
 
@@ -25,12 +25,15 @@ from typing import (
 
    Type,
 
    Union,
 
)
 

	
 
if TYPE_CHECKING:
 
    from . import errors as errormod
 
    from _typeshed import SupportsLessThan as Sortable
 
else:
 
    from typing import Hashable as Sortable
 

	
 
Account = bc_data.Account
 
Currency = bc_data.Currency
 
Meta = bc_data.Meta
 
MetaKey = str
 
MetaValue = Any
conservancy_beancount/cliutil.py
Show inline comments
...
 
@@ -39,13 +39,12 @@ from typing import (
 
    cast,
 
    Any,
 
    BinaryIO,
 
    Callable,
 
    Container,
 
    Generic,
 
    Hashable,
 
    IO,
 
    Iterable,
 
    Iterator,
 
    List,
 
    NamedTuple,
 
    NoReturn,
...
 
@@ -55,12 +54,13 @@ from typing import (
 
    Type,
 
    TypeVar,
 
    Union,
 
)
 
from .beancount_types import (
 
    MetaKey,
 
    Sortable,
 
)
 

	
 
ET = TypeVar('ET', bound=enum.Enum)
 
OutputFile = Union[int, IO]
 

	
 
CPU_COUNT = len(os.sched_getaffinity(0))
...
 
@@ -111,21 +111,21 @@ class EnumArgument(Generic[ET]):
 

	
 
    def value_type(self, arg: str) -> Any:
 
        return self.enum_type(arg).value
 

	
 
    def choices_str(self, sep: str=', ', fmt: str='{!r}') -> str:
 
        """Return a user-formatted string of enum names"""
 
        sortkey: Callable[[ET], Hashable] = getattr(
 
        sortkey: Callable[[ET], Sortable] = getattr(
 
            self.base, '_choices_sortkey', self._choices_sortkey,
 
        )
 
        return sep.join(
 
            fmt.format(choice.name.lower())
 
            for choice in sorted(self.base, key=sortkey)
 
        )
 

	
 
    def _choices_sortkey(self, choice: ET) -> Hashable:
 
    def _choices_sortkey(self, choice: ET) -> Sortable:
 
        return choice.name
 

	
 

	
 
class ExceptHook:
 
    def __init__(self, logger: Optional[logging.Logger]=None) -> None:
 
        if logger is None:
...
 
@@ -204,13 +204,13 @@ class ExtendAction(argparse.Action):
 
    pattern you provide. Typical usage looks like::
 

	
 
        parser = argparse.ArgumentParser()
 
        parser.add_argument(
 
          '--option', ...,
 
          action=ExtendAction,
 
          const=regexp_pattern,  # default is r'\s*,\s*'
 
          const=regexp_pattern,  # default is '\\s*,\\s*'
 
          ...,
 
        )
 
    """
 
    DEFAULT_PATTERN = r'\s*,\s*'
 

	
 
    def __call__(self,
...
 
@@ -255,13 +255,13 @@ class LogLevel(enum.IntEnum):
 
    ERROR = logging.ERROR
 
    CRITICAL = logging.CRITICAL
 
    WARN = WARNING
 
    ERR = ERROR
 
    CRIT = CRITICAL
 

	
 
    def _choices_sortkey(self) -> Hashable:
 
    def _choices_sortkey(self) -> Sortable:
 
        return self.value
 

	
 

	
 
class SearchTerm(NamedTuple):
 
    """NamedTuple representing a user's metadata filter
 

	
conservancy_beancount/config.py
Show inline comments
...
 
@@ -225,7 +225,8 @@ class Config:
 
    def rt_wrapper(self,
 
                  credentials: RTCredentials=None,
 
                  client: Type[rt.Rt]=rt.Rt,
 
    ) -> Optional[rtutil.RT]:
 
        if credentials is None:
 
            credentials = self.rt_credentials()
 
        return self._rt_wrapper(credentials, client)
 
        # type ignore for <https://github.com/python/typeshed/issues/4638>
 
        return self._rt_wrapper(credentials, client)  # type:ignore[arg-type]
conservancy_beancount/reconcile/paypal.py
Show inline comments
...
 
@@ -31,24 +31,26 @@ from .. import config as configmod
 
from .. import data
 
from ..ranges import DateRange
 
from ..reports import core
 

	
 
from typing import (
 
    Any,
 
    Hashable,
 
    Iterable,
 
    Iterator,
 
    List,
 
    Mapping,
 
    NamedTuple,
 
    Optional,
 
    Sequence,
 
    TextIO,
 
    Tuple,
 
    Union,
 
)
 
from ..beancount_types import (
 
    Sortable,
 
)
 

	
 
PROGNAME = 'reconcile-paypal'
 
logger = logging.getLogger('conservancy_beancount.reconcile.paypal')
 

	
 
class ReconcileProblems(enum.IntFlag):
 
    NOT_IN_STATEMENT = enum.auto()
...
 
@@ -161,13 +163,13 @@ class PayPalReconciler:
 
                if problems & ~ReconcileProblems.DATE_DIFF:
 
                    return problems
 
                else:
 
                    worst_problem = worst_problem or problems
 
            return worst_problem
 

	
 
    def sort_key(self) -> Hashable:
 
    def sort_key(self) -> Sortable:
 
        try:
 
            post = self.statement_posts[0]
 
        except IndexError:
 
            post = self.books_posts[0]
 
        return post.date
 

	
conservancy_beancount/reports/balance_sheet.py
Show inline comments
...
 
@@ -18,13 +18,12 @@ from pathlib import Path
 

	
 
from typing import (
 
    Any,
 
    Callable,
 
    Collection,
 
    Dict,
 
    Hashable,
 
    Iterable,
 
    Iterator,
 
    List,
 
    Mapping,
 
    NamedTuple,
 
    Optional,
conservancy_beancount/reports/budget.py
Show inline comments
...
 
@@ -24,13 +24,12 @@ from pathlib import Path
 

	
 
from typing import (
 
    Any,
 
    Callable,
 
    Collection,
 
    Dict,
 
    Hashable,
 
    Iterable,
 
    Iterator,
 
    List,
 
    Mapping,
 
    NamedTuple,
 
    Optional,
conservancy_beancount/reports/core.py
Show inline comments
...
 
@@ -49,13 +49,12 @@ from typing import (
 
    Any,
 
    BinaryIO,
 
    Callable,
 
    Collection,
 
    Dict,
 
    Generic,
 
    Hashable,
 
    Iterable,
 
    Iterator,
 
    List,
 
    Mapping,
 
    MutableMapping,
 
    NamedTuple,
...
 
@@ -67,12 +66,13 @@ from typing import (
 
    TypeVar,
 
    Union,
 
)
 
from ..beancount_types import (
 
    MetaKey,
 
    MetaValue,
 
    Sortable,
 
)
 

	
 
OPENING_BALANCE_NAME = "OPENING BALANCE"
 
ENDING_BALANCE_NAME = "ENDING BALANCE"
 

	
 
DecimalCompat = data.DecimalCompat
...
 
@@ -436,13 +436,13 @@ class Balances:
 
            elif key.period & sort_period:
 
                class_bals[key.classification] += balance
 
            else:
 
                # Ensure the balance exists in the mapping
 
                class_bals[key.classification]
 
        norm_func = normalize_amount_func(f'{account}:RootsOK')
 
        def sortkey(acct: data.Account) -> Hashable:
 
        def sortkey(acct: data.Account) -> Sortable:
 
            prefix, _, _ = acct.rpartition(':')
 
            balance = norm_func(class_bals[acct])
 
            try:
 
                max_bal = max(amount.number for amount in balance.values())
 
            except ValueError:
 
                max_bal = Decimal(0)
conservancy_beancount/reports/ledger.py
Show inline comments
...
 
@@ -43,13 +43,12 @@ import logging
 
import sys
 

	
 
from typing import (
 
    Any,
 
    Callable,
 
    Dict,
 
    Hashable,
 
    Iterable,
 
    Iterator,
 
    List,
 
    Mapping,
 
    Optional,
 
    Sequence,
...
 
@@ -58,12 +57,13 @@ from typing import (
 
    Tuple,
 
    Type,
 
    Union,
 
    cast,
 
)
 
from ..beancount_types import (
 
    Sortable,
 
    Transaction,
 
)
 

	
 
from pathlib import Path
 

	
 
import odf.table  # type:ignore[import]
...
 
@@ -527,13 +527,13 @@ class ReportType(enum.IntFlag):
 
            return cls.ZERO_TRANSACTIONS
 
        elif number > 0:
 
            return cls.CREDIT_TRANSACTIONS
 
        else:
 
            return cls.DEBIT_TRANSACTIONS
 

	
 
    def _choices_sortkey(self) -> Hashable:
 
    def _choices_sortkey(self) -> Sortable:
 
        subtype, _, maintype = self.name.partition('_')
 
        return (maintype, subtype)
 

	
 

	
 
class TransactionODS(LedgerODS):
 
    CORE_COLUMNS: Sequence[str] = [
conservancy_beancount/tools/opening_balances.py
Show inline comments
...
 
@@ -24,13 +24,12 @@ import enum
 
import locale
 
import logging
 
import sys
 

	
 
from typing import (
 
    Dict,
 
    Hashable,
 
    Iterable,
 
    Iterator,
 
    Mapping,
 
    NamedTuple,
 
    Optional,
 
    Sequence,
...
 
@@ -38,12 +37,13 @@ from typing import (
 
    Tuple,
 
)
 
from ..beancount_types import (
 
    Error,
 
    MetaKey,
 
    MetaValue,
 
    Sortable,
 
    Transaction,
 
)
 

	
 
from decimal import Decimal, ROUND_HALF_EVEN, ROUND_HALF_UP
 

	
 
from .. import books
...
 
@@ -73,13 +73,13 @@ def quantize_amount(
 
    return amount._replace(number=amount.number.quantize(exp, rounding=rounding))
 

	
 
class AccountWithFund(NamedTuple):
 
    account: data.Account
 
    fund: Optional[MetaValue]
 

	
 
    def sortkey(self) -> Hashable:
 
    def sortkey(self) -> Sortable:
 
        account, fund = self
 
        return (
 
            0 if fund is None else 1,
 
            locale.strxfrm(account),
 
            locale.strxfrm(str(fund).casefold()),
 
        )
conservancy_beancount/tools/sort_entries.py
Show inline comments
...
 
@@ -19,21 +19,21 @@ from pathlib import Path
 

	
 
from beancount.core import display_context as bc_dcontext
 
from beancount import loader as bc_loader
 
from beancount.parser import printer as bc_printer
 

	
 
from typing import (
 
    Hashable,
 
    Optional,
 
    Sequence,
 
    TextIO,
 
)
 
from ..beancount_types import (
 
    Directive,
 
    Entries,
 
    Errors,
 
    Sortable,
 
)
 

	
 
from .. import cliutil
 

	
 
PROGNAME = 'bean-sort'
 
logger = logging.getLogger('conservancy_beancount.tools.sort_entries')
...
 
@@ -53,13 +53,13 @@ def parse_arguments(arglist: Optional[Sequence[str]]=None) -> argparse.Namespace
 
        type=Path,
 
        nargs=argparse.ONE_OR_MORE,
 
        help="""Beancount path(s) to read entries from
 
""")
 
    return parser.parse_args(arglist)
 

	
 
def entry_sorter(entry: Directive) -> Hashable:
 
def entry_sorter(entry: Directive) -> Sortable:
 
    type_name = type(entry).__name__
 
    if type_name == 'Transaction':
 
        return (entry.date, type_name, entry.narration, entry.payee or '')  # type:ignore[attr-defined]
 
    else:
 
        return (entry.date, type_name)
 

	
0 comments (0 inline, 0 general)