Skip to content

Commit

Permalink
Merge pull request #110 from life4/lazy-annotations
Browse files Browse the repository at this point in the history
Lazy annotations
  • Loading branch information
orsinium committed Apr 12, 2022
2 parents 19a2083 + 04a48e7 commit 32309fa
Show file tree
Hide file tree
Showing 50 changed files with 365 additions and 287 deletions.
8 changes: 5 additions & 3 deletions deal/_cached_property.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from typing import Any, Callable, Generic, Optional, TypeVar, overload
from __future__ import annotations

from typing import Any, Callable, Generic, TypeVar, overload


T = TypeVar('T')
Expand All @@ -9,11 +11,11 @@ def __init__(self, func: Callable[[Any], T]) -> None:
self.func = func

@overload
def __get__(self, instance: None, owner: Optional[type] = ...) -> 'cached_property[T]':
def __get__(self, instance: None, owner: type | None = ...) -> cached_property[T]:
pass

@overload
def __get__(self, instance, owner: Optional[type] = ...) -> T:
def __get__(self, instance, owner: type | None = ...) -> T:
pass

def __get__(self, obj, cls):
Expand Down
2 changes: 2 additions & 0 deletions deal/_cli/_base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from argparse import ArgumentParser, Namespace
from pathlib import Path
from typing import TextIO
Expand Down
2 changes: 2 additions & 0 deletions deal/_cli/_common.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from pathlib import Path
from typing import Iterator

Expand Down
2 changes: 2 additions & 0 deletions deal/_cli/_decorate.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from argparse import ArgumentParser
from pathlib import Path

Expand Down
2 changes: 2 additions & 0 deletions deal/_cli/_lint.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import ast
import json
from argparse import ArgumentParser
Expand Down
8 changes: 5 additions & 3 deletions deal/_cli/_main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import annotations

import sys
from argparse import ArgumentParser
from pathlib import Path
from typing import Mapping, Optional, Sequence, TextIO, Type
from typing import Mapping, Sequence, TextIO, Type

from ._base import Command

Expand Down Expand Up @@ -29,8 +31,8 @@ def get_commands() -> CommandsType:

def main(
argv: Sequence[str], *,
commands: Optional[CommandsType] = None,
root: Optional[Path] = None,
commands: CommandsType | None = None,
root: Path | None = None,
stream: TextIO = sys.stdout,
) -> int:
if commands is None:
Expand Down
6 changes: 4 additions & 2 deletions deal/_cli/_memtest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from __future__ import annotations

from argparse import ArgumentParser
from contextlib import suppress
from importlib import import_module
from pathlib import Path
from typing import Dict, Iterable, TextIO
from typing import Iterable, TextIO

from .._colors import COLORS
from .._mem_test import MemoryTracker
Expand All @@ -18,7 +20,7 @@ def run_cases(
cases: Iterable[TestCase],
func_name: str,
stream: TextIO,
colors: Dict[str, str],
colors: dict[str, str],
) -> bool:
print(' {blue}running {name}{end}'.format(name=func_name, **colors), file=stream)
for case in cases:
Expand Down
8 changes: 5 additions & 3 deletions deal/_cli/_prove.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import annotations

import sys
from argparse import ArgumentParser
from pathlib import Path
from typing import TYPE_CHECKING, Dict, Iterator, TextIO
from typing import TYPE_CHECKING, Iterator, TextIO

from .._colors import get_colors
from ..linter._extractors import get_contracts
Expand Down Expand Up @@ -29,7 +31,7 @@

class DealTheorem(Theorem):
@staticmethod
def get_contracts(func: 'astroid.FunctionDef') -> Iterator['deal_solver.Contract']:
def get_contracts(func: astroid.FunctionDef) -> Iterator[deal_solver.Contract]:
for contract in get_contracts(func):
yield deal_solver.Contract(
name=contract.name,
Expand All @@ -41,7 +43,7 @@ def run_solver(
path: Path,
stream: TextIO,
show_skipped: bool,
colors: Dict[str, str],
colors: dict[str, str],
) -> int:
file_name_shown = False
text = path.read_text()
Expand Down
5 changes: 3 additions & 2 deletions deal/_cli/_stub.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

from argparse import ArgumentParser
from pathlib import Path
from typing import List

from ..linter import StubsManager, generate_stub
from ._base import Command
Expand Down Expand Up @@ -31,7 +32,7 @@ def init_parser(parser: ArgumentParser) -> None:
parser.add_argument('paths', nargs='+')

def __call__(self, args) -> int:
paths: List[Path] = []
paths: list[Path] = []
for arg in args.paths:
for path in get_paths(Path(arg)):
paths.append(path)
Expand Down
8 changes: 5 additions & 3 deletions deal/_cli/_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import re
import sys
import traceback
Expand All @@ -7,7 +9,7 @@
from importlib import import_module
from pathlib import Path
from textwrap import indent
from typing import Dict, Iterable, Iterator, TextIO, TypeVar
from typing import Iterable, Iterator, TextIO, TypeVar

from .._colors import COLORS
from .._testing import TestCase, cases
Expand Down Expand Up @@ -100,7 +102,7 @@ def run_cases(
cases: Iterator[TestCase],
func_name: str,
stream: TextIO,
colors: Dict[str, str],
colors: dict[str, str],
) -> bool:
print(' {blue}running {name}{end}'.format(name=func_name, **colors), file=stream)
for case in cases:
Expand All @@ -118,7 +120,7 @@ def run_cases(
return True


def format_coverage(tresult: TraceResult, colors: Dict[str, str]) -> str:
def format_coverage(tresult: TraceResult, colors: dict[str, str]) -> str:
cov = tresult.coverage
if cov >= 85:
color = colors['green']
Expand Down
5 changes: 2 additions & 3 deletions deal/_colors.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

from typing import Dict
from __future__ import annotations

from ._state import state

Expand Down Expand Up @@ -42,7 +41,7 @@ def highlight(source: str) -> str:
return source.rstrip()


def get_colors(args) -> Dict[str, str]:
def get_colors(args) -> dict[str, str]:
if not state.color:
return NOCOLORS
if args.nocolor:
Expand Down
18 changes: 10 additions & 8 deletions deal/_exceptions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import annotations

import sys
from contextlib import suppress
from pathlib import Path
from typing import Any, Dict, Optional, Tuple, Type
from typing import Any

from ._cached_property import cached_property
from ._colors import COLORS, NOCOLORS, highlight
Expand All @@ -12,7 +14,7 @@
root = str(Path(__file__).parent)


def exception_hook(etype: Type[BaseException], value: BaseException, tb):
def exception_hook(etype: type[BaseException], value: BaseException, tb):
"""Exception hook to remove deal from the traceback for ContractError.
"""
if not issubclass(etype, ContractError):
Expand Down Expand Up @@ -43,18 +45,18 @@ class ContractError(AssertionError):
"""The base class for all errors raised by deal contracts.
"""
message: str
errors: Optional[Any]
errors: Any | None
validator: Any
params: Dict[str, Any]
origin: Optional[object]
params: dict[str, Any]
origin: object | None

def __init__(
self,
message: str = '',
errors=None,
validator=None,
params: Optional[Dict[str, Any]] = None,
origin: Optional[object] = None,
params: dict[str, Any] | None = None,
origin: object | None = None,
) -> None:
self.message = message
self.errors = errors
Expand Down Expand Up @@ -180,7 +182,7 @@ class NoMatchError(Exception):
"""
__module__ = 'deal'

def __init__(self, exceptions: Tuple[PreContractError, ...]) -> None:
def __init__(self, exceptions: tuple[PreContractError, ...]) -> None:
self.exceptions = exceptions

def __str__(self) -> str:
Expand Down
10 changes: 6 additions & 4 deletions deal/_imports.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import annotations

import ast
import sys
from types import ModuleType
from typing import Any, Callable, List, Optional
from typing import Any, Callable

from _frozen_importlib_external import PathFinder # pyright: reportMissingImports=false

Expand All @@ -10,7 +12,7 @@
from ._state import state


def get_name(expr) -> Optional[str]:
def get_name(expr) -> str | None:
if isinstance(expr, ast.Name):
return expr.id
if isinstance(expr, ast.Attribute):
Expand Down Expand Up @@ -66,7 +68,7 @@ def exec_module(self, module: ModuleType) -> None:
wrapped(module)

@staticmethod
def _get_contracts(tree: ast.Module) -> List[ast.expr]:
def _get_contracts(tree: ast.Module) -> list[ast.expr]:
for node in tree.body: # type: Any
if type(node) is not ast.Expr:
continue
Expand All @@ -78,7 +80,7 @@ def _get_contracts(tree: ast.Module) -> List[ast.expr]:
return []

@classmethod
def _exec_contract(cls, node: ast.AST) -> Optional[Callable]:
def _exec_contract(cls, node: ast.AST) -> Callable | None:
"""Get AST node and return a contract function
"""
if isinstance(node, ast.Call) and not node.keywords:
Expand Down
2 changes: 2 additions & 0 deletions deal/_mem_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import gc
import typing
from collections import Counter
Expand Down
35 changes: 17 additions & 18 deletions deal/_runtime/_contracts.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from asyncio import iscoroutinefunction
from __future__ import annotations

from functools import update_wrapper
from inspect import isgeneratorfunction
from typing import (
TYPE_CHECKING, Callable, Dict, Generic, List, Optional, Tuple, Type, TypeVar,
)
from inspect import iscoroutinefunction, isgeneratorfunction
from typing import TYPE_CHECKING, Callable, Generic, TypeVar

from .._exceptions import ContractError
from .._state import state
Expand Down Expand Up @@ -33,13 +32,13 @@ class Contracts(Generic[F]):

func: F
wrapped: F
pres: List['Validator']
posts: List['Validator']
ensures: List['Validator']
examples: List['Validator']
raises: List['RaisesValidator']
reasons: List['ReasonValidator']
patcher: Optional['HasPatcher']
pres: list[Validator]
posts: list[Validator]
ensures: list[Validator]
examples: list[Validator]
raises: list[RaisesValidator]
reasons: list[ReasonValidator]
patcher: HasPatcher | None

def __init__(self, func: F) -> None:
self.func = func
Expand All @@ -52,7 +51,7 @@ def __init__(self, func: F) -> None:
self.patcher = None

@classmethod
def attach(cls, contract_type: str, validator: 'Validator', func: F) -> F:
def attach(cls, contract_type: str, validator: Validator, func: F) -> F:
if state.removed:
return func
contracts = cls._ensure_wrapped(func)
Expand All @@ -61,15 +60,15 @@ def attach(cls, contract_type: str, validator: 'Validator', func: F) -> F:
return contracts.wrapped

@classmethod
def attach_has(cls, patcher: 'HasPatcher', func: F) -> F:
def attach_has(cls, patcher: HasPatcher, func: F) -> F:
if state.removed:
return func
contracts = cls._ensure_wrapped(func)
contracts.patcher = patcher
return contracts.wrapped

@classmethod
def _ensure_wrapped(cls: Type['Contracts'], func: F) -> 'Contracts[F]':
def _ensure_wrapped(cls: type[Contracts], func: F) -> Contracts[F]:
contracts: Contracts
contracts = getattr(func, ATTR, None) # type: ignore[assignment]
if contracts is not None:
Expand Down Expand Up @@ -109,7 +108,7 @@ def wrap(self, func: F) -> F:
contracts.patcher = self.patcher
return contracts.wrapped

def _run_sync(self, args: Tuple[object, ...], kwargs: Dict[str, object]):
def _run_sync(self, args: tuple[object, ...], kwargs: dict[str, object]):
if not state.debug:
return self.func(*args, **kwargs)

Expand Down Expand Up @@ -152,7 +151,7 @@ def _run_sync(self, args: Tuple[object, ...], kwargs: Dict[str, object]):

return result

async def _run_async(self, args: Tuple[object, ...], kwargs: Dict[str, object]):
async def _run_async(self, args: tuple[object, ...], kwargs: dict[str, object]):
if not state.debug:
return await self.func(*args, **kwargs)

Expand Down Expand Up @@ -195,7 +194,7 @@ async def _run_async(self, args: Tuple[object, ...], kwargs: Dict[str, object]):

return result

def _run_iter(self, args: Tuple[object, ...], kwargs: Dict[str, object]):
def _run_iter(self, args: tuple[object, ...], kwargs: dict[str, object]):
if not state.debug:
yield from self.func(*args, **kwargs)
return
Expand Down
Loading

0 comments on commit 32309fa

Please sign in to comment.