Skip to content

Commit b39aeb2

Browse files
authored
Merge pull request #30 from last-partizan/22-stubtest
feat: Use stubtest to verify stub correctness
2 parents ffa1e51 + af1e28c commit b39aeb2

File tree

4 files changed

+47
-16
lines changed

4 files changed

+47
-16
lines changed

.github/workflows/base.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,27 @@ jobs:
7777
name: reports_dir
7878
path: ./docs/reports
7979

80+
run_stubtest:
81+
runs-on: ubuntu-latest
82+
defaults:
83+
run:
84+
shell: bash -l {0} # so that conda works
85+
steps:
86+
- uses: actions/checkout@v2
87+
88+
- name: Install conda v3.7
89+
uses: conda-incubator/setup-miniconda@v2
90+
with:
91+
python-version: '3.10'
92+
activate-environment: noxenv
93+
94+
- name: Install noxfile requirements
95+
run: pip install -r noxfile-requirements.txt
96+
97+
- run: nox -s stubtest
98+
8099
publish_release:
81-
needs: run_all_tests
100+
needs: [run_stubtest, run_all_tests]
82101
runs-on: ubuntu-latest
83102
if: github.event_name == 'push'
84103
steps:

noxfile.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,16 @@ def tests(session: PowerSession, coverage, pkg_specs):
144144
session.run2("genbadge coverage -i %s -o %s" % (Folders.coverage_xml, Folders.coverage_badge))
145145

146146

147+
@power_session(python=PY310, logsdir=Folders.runlogs)
148+
def stubtest(session: PowerSession):
149+
"""Verify type stubs correctness."""
150+
151+
session.install_reqs(setup=True, install=True, tests=True)
152+
session.run2("pip install -e . --no-deps")
153+
154+
session.run2("stubtest decopatch.main")
155+
156+
147157
@power_session(python=PY38, logsdir=Folders.runlogs)
148158
def flake8(session: PowerSession):
149159
"""Launch flake8 qualimetry."""

setup.cfg

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ install_requires =
4242
tests_require =
4343
pytest
4444
pytest_cases
45-
# syrupy and pyright is used for testing type correctness.
45+
# syrupy, pyright and mypy is used for testing type correctness.
4646
syrupy>2;python_version>'3.6'
4747
pyright;python_version>'3.6'
48+
mypy;python_version>'3.6'
4849
# for some reason these pytest dependencies were not declared in old versions of pytest
4950
six;python_version<'3.6'
5051
attr;python_version<'3.6'

src/decopatch/main.pyi

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,56 +10,57 @@ except ImportError:
1010
from decopatch.utils_disambiguation import FirstArgDisambiguation
1111
from decopatch.utils_modes import SignatureInfo
1212

13-
P = ParamSpec("P")
14-
F = TypeVar("F", bound=Callable[..., Any])
13+
_P = ParamSpec("_P")
14+
_F = TypeVar("_F", bound=Callable[..., Any])
15+
_CustomDisambugatorT = Optional[Callable[[Any], FirstArgDisambiguation]]
1516

16-
class _Decorator(Protocol[P]):
17+
class _Decorator(Protocol[_P]):
1718
"""
1819
This is callable Protocol, to distinguish between cases where
1920
created decorator is called as `@decorator` or `@decorator()`
2021
"""
2122

2223
# decorator is called without parenthesis: @decorator
2324
@overload
24-
def __call__(self, func: F) -> F: ...
25+
def __call__(self, func: _F) -> _F: ...
2526
# decorator is called with options or parenthesis: @decorator(some_option=...)
2627
@overload
27-
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> Callable[[F], F]: ...
28+
def __call__(self, *args: _P.args, **kwargs: _P.kwargs) -> Callable[[_F], _F]: ...
2829

2930
# @function_decorator is called without options or parenthesis
3031
@overload
3132
def function_decorator(
32-
enable_stack_introspection: Callable[P, Any],
33-
custom_disambiguator: Callable[[Any], FirstArgDisambiguation] = ...,
33+
enable_stack_introspection: Callable[_P, Any],
34+
custom_disambiguator: _CustomDisambugatorT = ...,
3435
flat_mode_decorated_name: Optional[str] = ...,
35-
) -> _Decorator[P]: ...
36+
) -> _Decorator[_P]: ...
3637

3738
# @function_decorator() is called with options or parenthesis.
3839
@overload
3940
def function_decorator(
4041
enable_stack_introspection: bool = ...,
41-
custom_disambiguator: Callable[[Any], FirstArgDisambiguation] = ...,
42+
custom_disambiguator: _CustomDisambugatorT = ...,
4243
flat_mode_decorated_name: Optional[str] = ...,
43-
) -> Callable[[Callable[P, Any]], _Decorator[P]]: ...
44+
) -> Callable[[Callable[_P, Any]], _Decorator[_P]]: ...
4445
def class_decorator(
4546
enable_stack_introspection: bool = ...,
46-
custom_disambiguator: Callable[[Any], FirstArgDisambiguation] = ...,
47+
custom_disambiguator: _CustomDisambugatorT = ...,
4748
flat_mode_decorated_name: Optional[str] = ...,
4849
): ...
4950
def decorator(
5051
is_function_decorator: bool = ...,
5152
is_class_decorator: bool = ...,
5253
enable_stack_introspection: bool = ...,
53-
custom_disambiguator: Callable[[Any], FirstArgDisambiguation] = ...,
54+
custom_disambiguator: _CustomDisambugatorT = ...,
5455
use_signature_trick: bool = ...,
55-
flat_mode_decorated_name: str = ...,
56+
flat_mode_decorated_name: Optional[str] = ...,
5657
): ...
5758
def create_decorator(
5859
impl_function,
5960
is_function_decorator: bool = ...,
6061
is_class_decorator: bool = ...,
6162
enable_stack_introspection: bool = ...,
62-
custom_disambiguator: Callable[[Any], FirstArgDisambiguation] = ...,
63+
custom_disambiguator: _CustomDisambugatorT = ...,
6364
use_signature_trick: bool = ...,
6465
flat_mode_decorated_name: Optional[str] = ...,
6566
): ...

0 commit comments

Comments
 (0)