From e3a71ea6c68ee4c2564a97da8a4fec7e0b55c172 Mon Sep 17 00:00:00 2001 From: Dima Gerasimov Date: Sun, 24 May 2020 23:42:57 +0100 Subject: [PATCH] my.core: more work on typing @warn_if_empty, extra test --- my/core/common.py | 25 +++++++++++-------------- tests/misc.py | 26 ++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/my/core/common.py b/my/core/common.py index 16a730b..30c2cf0 100644 --- a/my/core/common.py +++ b/my/core/common.py @@ -273,6 +273,7 @@ def get_valid_filename(s: str) -> str: from typing import Generic, Sized, Callable +# X = TypeVar('X') def _warn_iterator(it): emitted = False for i in it: @@ -281,27 +282,23 @@ def _warn_iterator(it): if not emitted: warnings.warn(f"Function hasn't emitted any data, make sure your config paths are correct") - -def _warn_iterable(it): +# todo need to popretly restrict to a container... ugh +C = TypeVar('C') +def _warn_iterable(it: C) -> C: if isinstance(it, Sized): sz = len(it) if sz == 0: warnings.warn(f"Function is returning empty container, make sure your config paths are correct") - return it + return it # type: ignore[return-value] else: return _warn_iterator(it) -from functools import wraps -X = TypeVar('X') - -class G(Generic[X], Iterable[X]): - pass - -CC = Callable[[], G] +CC = TypeVar('CC') def warn_if_empty(f: CC) -> CC: - @wraps(f) - def wrapped(*args, **kwargs) -> G[X]: - res = f(*args, **kwargs) + from functools import wraps + @wraps(f) # type: ignore[arg-type] + def wrapped(*args, **kwargs): + res = f(*args, **kwargs) # type: ignore[call-arg, operator] return _warn_iterable(res) - return wrapped + return wrapped # type: ignore[return-value] diff --git a/tests/misc.py b/tests/misc.py index a20399e..d425196 100644 --- a/tests/misc.py +++ b/tests/misc.py @@ -53,20 +53,38 @@ from my.core.error import test_sort_res_by from typing import Iterable, List import warnings from my.core import warn_if_empty -def test_warn_if_empty(): - +def test_warn_if_empty() -> None: @warn_if_empty def nonempty() -> Iterable[str]: yield 'a' yield 'aba' @warn_if_empty - def empty(arg: str) -> List[str]: + def empty() -> List[str]: return [] with warnings.catch_warnings(record=True) as w: assert list(nonempty()) == ['a', 'aba'] assert len(w) == 0 - assert empty('whatever') == [] + eee = empty() + assert eee == [] assert len(w) == 1 + + +def test_warn_iterable() -> None: + from my.core.common import _warn_iterable + i1: List[str] = ['a', 'b'] + i2: Iterable[int] = iter([1, 2, 3]) + # reveal_type(i1) + # reveal_type(i2) + x1 = _warn_iterable(i1) + x2 = _warn_iterable(i2) + # reveal_type(x1) + # reveal_type(x2) + with warnings.catch_warnings(record=True) as w: + assert x1 is i1 # should be unchanged! + assert len(w) == 0 + + assert list(x2) == [1, 2, 3] + assert len(w) == 0