Fix many types

This commit is contained in:
Alessio Bogon 2021-10-20 17:15:03 +02:00
parent 33729841eb
commit 78cf86af32
7 changed files with 53 additions and 48 deletions

View File

@ -18,5 +18,5 @@ warn_unused_configs = true
files = "pytest_bdd/**/*.py"
[[tool.mypy.overrides]]
module = ["parse", "parse_type"]
module = ["parse", "parse_type", "glob2"]
ignore_missing_imports = true

View File

@ -49,7 +49,7 @@ class LogBDDCucumberJSON:
def __init__(self, logfile: str) -> None:
logfile = os.path.expanduser(os.path.expandvars(logfile))
self.logfile = os.path.normpath(os.path.abspath(logfile))
self.features = {}
self.features: Dict[str, Dict] = {}
# TODO: Unused method?
def append(self, obj):
@ -62,7 +62,7 @@ class LogBDDCucumberJSON:
:param report: pytest `Report` object
:return: `dict` in form {"status": "<passed|failed|skipped>", ["error_message": "<error_message>"]}
"""
result = {}
result: Dict[str, Any] = {}
if report.passed or not step["failed"]: # ignore setup/teardown
result = {"status": "passed"}
elif report.failed and step["failed"]:

View File

@ -48,7 +48,7 @@ class GherkinTerminalReporter(TerminalReporter):
if not letter and not word:
# probably passed setup/teardown
return
return None
if isinstance(word, tuple):
word, word_markup = word
@ -93,3 +93,4 @@ class GherkinTerminalReporter(TerminalReporter):
else:
return super().pytest_runtest_logreport(rep)
self.stats.setdefault(cat, []).append(rep)
return None

View File

@ -3,7 +3,7 @@ import re
import textwrap
import typing
from collections import OrderedDict
from typing import Any, List, Optional, Set, Tuple
from typing import Any, List, Optional, Set, Tuple, cast
from . import exceptions, types
@ -73,6 +73,7 @@ def get_step_type(line: str) -> Optional[str]:
for prefix, _type in STEP_PREFIXES:
if line.startswith(prefix):
return _type
return None
def parse_feature(basedir: str, filename: str, encoding: str = "utf-8") -> "Feature":
@ -96,7 +97,7 @@ def parse_feature(basedir: str, filename: str, encoding: str = "utf-8") -> "Feat
description="",
)
scenario: typing.Optional[ScenarioTemplate] = None
mode = None
mode: Optional[str] = None
prev_mode = None
description: typing.List[str] = []
step = None
@ -188,11 +189,11 @@ def parse_feature(basedir: str, filename: str, encoding: str = "utf-8") -> "Feat
)
elif mode and mode not in (types.FEATURE, types.TAG):
step = Step(name=parsed_line, type=mode, indent=line_indent, line_number=line_number, keyword=keyword)
if feature.background and not scenario:
target = feature.background
if feature.background and scenario:
feature.background.add_step(step)
else:
target = scenario
target.add_step(step)
scenario = cast(ScenarioTemplate, scenario)
scenario.add_step(step)
prev_line = clean_line
feature.description = "\n".join(description).strip()
@ -207,22 +208,22 @@ class Feature:
scenarios: OrderedDict,
filename: str,
rel_filename: str,
name: Optional[Any],
name: Optional[str],
tags: Set,
examples: "Examples",
background: Optional[Any],
background: "Optional[Background]",
line_number: int,
description: str,
) -> None:
self.scenarios: typing.Dict[str, ScenarioTemplate] = scenarios
self.rel_filename = rel_filename
self.filename = filename
self.tags = tags
self.examples = examples
self.name = name
self.line_number = line_number
self.description = description
self.background = background
self.rel_filename: str = rel_filename
self.filename: str = filename
self.tags: Set = tags
self.examples: "Examples" = examples
self.name: Optional[str] = name
self.line_number: int = line_number
self.description: str = description
self.background: "Optional[Background]" = background
class ScenarioTemplate:
@ -319,17 +320,17 @@ class Step:
:param int line_number: line number.
:param str keyword: step keyword.
"""
self.name = name
self.keyword = keyword
self.lines = []
self.indent = indent
self.type = type
self.line_number = line_number
self.failed = False
self.start = 0
self.stop = 0
self.scenario: "Optional[Scenario]" = None
self.background = None
self.name: str = name
self.keyword: str = keyword
self.lines: List[str] = []
self.indent: int = indent
self.type: str = type
self.line_number: int = line_number
self.failed: bool = False
self.start: int = 0 # TODO: Unused
self.stop: int = 0 # TODO: Unused
self.scenario: "Optional[ScenarioTemplate]" = None
self.background: "Optional[Background]" = None
def add_line(self, line: str) -> None:
"""Add line to the multiple step.
@ -386,9 +387,9 @@ class Background:
:param pytest_bdd.parser.Feature feature: Feature.
:param int line_number: Line number.
"""
self.feature = feature
self.line_number = line_number
self.steps = []
self.feature: "Feature" = feature
self.line_number: int = line_number
self.steps: "typing.List[Step]" = []
def add_step(self, step: "Step") -> None:
"""Add step to the background."""
@ -402,10 +403,10 @@ class Examples:
def __init__(self) -> None:
"""Initialize examples instance."""
self.example_params = []
self.examples = []
self.vertical_examples = []
self.line_number = None
self.example_params: List[str] = []
self.examples: List[List[str]] = []
self.vertical_examples: List[List[str]] = []
self.line_number: Optional[int] = None
self.name = None
def set_param_names(self, keys: List[str]) -> None:

View File

@ -3,7 +3,7 @@
import re as base_re
from functools import partial
from typing import Any, Dict
from typing import Any, Dict, cast
import parse as base_parse
from parse_type import cfparse as base_cfparse
@ -40,6 +40,7 @@ class re(StepParser):
:return: `dict` of step arguments
"""
# TODO: This is a potential bug, as groupdict can return None (found with typing)
return self.regex.match(name).groupdict()
def is_matching(self, name: str) -> bool:
@ -60,7 +61,7 @@ class parse(StepParser):
:return: `dict` of step arguments
"""
return self.parser.parse(name).named
return cast(Dict[str, Any], self.parser.parse(name).named)
def is_matching(self, name: str) -> bool:
"""Match given name with the step name."""

View File

@ -62,9 +62,10 @@ def find_argumented_step_fixture_name(
except FixtureLookupError:
continue
return parser_name
return None
def _find_step_function(request: FixtureRequest, step: "Step", scenario: "Scenario") -> Callable:
def _find_step_function(request: FixtureRequest, step: "Step", scenario: "Scenario") -> Any:
"""Match the step defined by the regular expression pattern.
:param request: PyTest request object.
@ -81,9 +82,9 @@ def _find_step_function(request: FixtureRequest, step: "Step", scenario: "Scenar
except FixtureLookupError:
try:
# Could not find a fixture with the same name, let's see if there is a parser involved
name = find_argumented_step_fixture_name(name, step.type, request._fixturemanager, request)
if name:
return request.getfixturevalue(name)
argumented_name = find_argumented_step_fixture_name(name, step.type, request._fixturemanager, request)
if argumented_name:
return request.getfixturevalue(argumented_name)
raise
except FixtureLookupError:
raise exceptions.StepDefinitionNotFoundError(
@ -167,15 +168,15 @@ def _get_scenario_decorator(
"scenario function can only be used as a decorator. Refer to the documentation."
)
[fn] = args
args = get_args(fn)
func_args = get_args(fn)
# We need to tell pytest that the original function requires its fixtures,
# otherwise indirect fixtures would not work.
@pytest.mark.usefixtures(*args)
@pytest.mark.usefixtures(*func_args)
def scenario_wrapper(request: FixtureRequest, _pytest_bdd_example: Dict[str, str]) -> Optional[Any]:
scenario = templated_scenario.render(_pytest_bdd_example)
_execute_scenario(feature, scenario, request)
fixture_values = [request.getfixturevalue(arg) for arg in args]
fixture_values = [request.getfixturevalue(arg) for arg in func_args]
return fn(*fixture_values)
example_parametrizations = collect_example_parametrizations(templated_scenario)

View File

@ -8,9 +8,10 @@ from sys import _getframe
from typing import Any, Callable, Dict, List
if typing.TYPE_CHECKING:
from _pytest.config import Config
from _pytest.pytester import RunResult
CONFIG_STACK = []
CONFIG_STACK: "List[Config]" = []
def get_args(func: Callable) -> List[str]: