Use "from __future__ import annotations" to be less verbose

This commit is contained in:
Alessio Bogon 2022-02-24 15:32:20 +01:00
parent 4fd1ab950c
commit 021aa3a2e3
18 changed files with 97 additions and 77 deletions

View File

@ -22,4 +22,4 @@ repos:
rev: v2.31.0 rev: v2.31.0
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: [--py37-plus] args: ["--py37-plus", "--keep-runtime-typing"]

View File

@ -1,4 +1,5 @@
"""pytest-bdd public API.""" """pytest-bdd public API."""
from __future__ import annotations
from pytest_bdd.scenario import scenario, scenarios from pytest_bdd.scenario import scenario, scenarios
from pytest_bdd.steps import given, then, when from pytest_bdd.steps import given, then, when

View File

@ -1,4 +1,5 @@
"""Cucumber json output formatter.""" """Cucumber json output formatter."""
from __future__ import annotations
import json import json
import math import math
@ -13,7 +14,7 @@ if TYPE_CHECKING:
from _pytest.terminal import TerminalReporter from _pytest.terminal import TerminalReporter
def add_options(parser: "Parser") -> None: def add_options(parser: Parser) -> None:
"""Add pytest-bdd options.""" """Add pytest-bdd options."""
group = parser.getgroup("bdd", "Cucumber JSON") group = parser.getgroup("bdd", "Cucumber JSON")
group.addoption( group.addoption(
@ -27,7 +28,7 @@ def add_options(parser: "Parser") -> None:
) )
def configure(config: "Config") -> None: def configure(config: Config) -> None:
cucumber_json_path = config.option.cucumber_json_path cucumber_json_path = config.option.cucumber_json_path
# prevent opening json log on worker nodes (xdist) # prevent opening json log on worker nodes (xdist)
if cucumber_json_path and not hasattr(config, "workerinput"): if cucumber_json_path and not hasattr(config, "workerinput"):
@ -35,7 +36,7 @@ def configure(config: "Config") -> None:
config.pluginmanager.register(config._bddcucumberjson) config.pluginmanager.register(config._bddcucumberjson)
def unconfigure(config: "Config") -> None: def unconfigure(config: Config) -> None:
xml = getattr(config, "_bddcucumberjson", None) xml = getattr(config, "_bddcucumberjson", None)
if xml is not None: if xml is not None:
del config._bddcucumberjson del config._bddcucumberjson
@ -55,7 +56,7 @@ class LogBDDCucumberJSON:
def append(self, obj): def append(self, obj):
self.features[-1].append(obj) self.features[-1].append(obj)
def _get_result(self, step: Dict[str, Any], report: "TestReport", error_message: bool = False) -> Dict[str, Any]: def _get_result(self, step: Dict[str, Any], report: TestReport, error_message: bool = False) -> Dict[str, Any]:
"""Get scenario test run result. """Get scenario test run result.
:param step: `Step` step we get result for :param step: `Step` step we get result for
@ -86,7 +87,7 @@ class LogBDDCucumberJSON:
""" """
return [{"name": tag, "line": item["line_number"] - 1} for tag in item["tags"]] return [{"name": tag, "line": item["line_number"] - 1} for tag in item["tags"]]
def pytest_runtest_logreport(self, report: "TestReport") -> None: def pytest_runtest_logreport(self, report: TestReport) -> None:
try: try:
scenario = report.scenario scenario = report.scenario
except AttributeError: except AttributeError:
@ -145,5 +146,5 @@ class LogBDDCucumberJSON:
with open(self.logfile, "w", encoding="utf-8") as logfile: with open(self.logfile, "w", encoding="utf-8") as logfile:
logfile.write(json.dumps(list(self.features.values()))) logfile.write(json.dumps(list(self.features.values())))
def pytest_terminal_summary(self, terminalreporter: "TerminalReporter") -> None: def pytest_terminal_summary(self, terminalreporter: TerminalReporter) -> None:
terminalreporter.write_sep("-", f"generated json file: {self.logfile}") terminalreporter.write_sep("-", f"generated json file: {self.logfile}")

View File

@ -1,4 +1,5 @@
"""pytest-bdd Exceptions.""" """pytest-bdd Exceptions."""
from __future__ import annotations
class ScenarioIsDecoratorOnly(Exception): class ScenarioIsDecoratorOnly(Exception):

View File

@ -23,6 +23,8 @@ Syntax example:
:note: There are no multiline steps, the description of the step must fit in :note: There are no multiline steps, the description of the step must fit in
one line. one line.
""" """
from __future__ import annotations
import os.path import os.path
import typing import typing

View File

@ -1,4 +1,5 @@
"""pytest-bdd missing test code generation.""" """pytest-bdd missing test code generation."""
from __future__ import annotations
import itertools import itertools
import os.path import os.path
@ -50,7 +51,7 @@ def cmdline_main(config: Config) -> Optional[int]:
return show_missing_code(config) return show_missing_code(config)
def generate_code(features: "List[Feature]", scenarios: "List[ScenarioTemplate]", steps: "List[Step]") -> str: def generate_code(features: List[Feature], scenarios: List[ScenarioTemplate], steps: List[Step]) -> str:
"""Generate test code for the given filenames.""" """Generate test code for the given filenames."""
grouped_steps = group_steps(steps) grouped_steps = group_steps(steps)
template = template_lookup.get_template("test.py.mak") template = template_lookup.get_template("test.py.mak")
@ -71,7 +72,7 @@ def show_missing_code(config: Config) -> int:
return wrap_session(config, _show_missing_code_main) return wrap_session(config, _show_missing_code_main)
def print_missing_code(scenarios: "List[ScenarioTemplate]", steps: "List[Step]") -> None: def print_missing_code(scenarios: List[ScenarioTemplate], steps: List[Step]) -> None:
"""Print missing code with TerminalWriter.""" """Print missing code with TerminalWriter."""
tw = py.io.TerminalWriter() tw = py.io.TerminalWriter()
scenario = step = None scenario = step = None
@ -138,7 +139,7 @@ def _find_step_fixturedef(
return None return None
def parse_feature_files(paths: List[str], **kwargs: Any) -> "Tuple[List[Feature], List[ScenarioTemplate], List[Step]]": def parse_feature_files(paths: List[str], **kwargs: Any) -> Tuple[List[Feature], List[ScenarioTemplate], List[Step]]:
"""Parse feature files of given paths. """Parse feature files of given paths.
:param paths: `list` of paths (file or dirs) :param paths: `list` of paths (file or dirs)
@ -157,7 +158,7 @@ def parse_feature_files(paths: List[str], **kwargs: Any) -> "Tuple[List[Feature]
return features, scenarios, steps return features, scenarios, steps
def group_steps(steps: "List[Step]") -> "List[Step]": def group_steps(steps: List[Step]) -> List[Step]:
"""Group steps by type.""" """Group steps by type."""
steps = sorted(steps, key=lambda step: step.type) steps = sorted(steps, key=lambda step: step.type)
seen_steps = set() seen_steps = set()

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from typing import Any, Optional from typing import Any, Optional
from _pytest.config import Config from _pytest.config import Config

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest import pytest
"""Pytest-bdd pytest hooks.""" """Pytest-bdd pytest hooks."""

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import os.path import os.path
import re import re
import textwrap import textwrap
@ -75,7 +77,7 @@ def get_step_type(line: str) -> Optional[str]:
return None return None
def parse_feature(basedir: str, filename: str, encoding: str = "utf-8") -> "Feature": def parse_feature(basedir: str, filename: str, encoding: str = "utf-8") -> Feature:
"""Parse the feature file. """Parse the feature file.
:param str basedir: Feature files base directory. :param str basedir: Feature files base directory.
@ -186,7 +188,7 @@ class Feature:
rel_filename: str, rel_filename: str,
name: Optional[str], name: Optional[str],
tags: Set, tags: Set,
background: "Optional[Background]", background: Optional[Background],
line_number: int, line_number: int,
description: str, description: str,
) -> None: ) -> None:
@ -197,7 +199,7 @@ class Feature:
self.name: Optional[str] = name self.name: Optional[str] = name
self.line_number: int = line_number self.line_number: int = line_number
self.description: str = description self.description: str = description
self.background: "Optional[Background]" = background self.background: Optional[Background] = background
class ScenarioTemplate: class ScenarioTemplate:
@ -205,7 +207,7 @@ class ScenarioTemplate:
Created when parsing the feature file, it will then be combined with the examples to create a Scenario.""" Created when parsing the feature file, it will then be combined with the examples to create a Scenario."""
def __init__(self, feature: "Feature", name: str, line_number: int, tags=None): def __init__(self, feature: Feature, name: str, line_number: int, tags=None):
""" """
:param str name: Scenario name. :param str name: Scenario name.
@ -214,12 +216,12 @@ class ScenarioTemplate:
""" """
self.feature = feature self.feature = feature
self.name = name self.name = name
self._steps: "typing.List[Step]" = [] self._steps: typing.List[Step] = []
self.examples = Examples() self.examples = Examples()
self.line_number = line_number self.line_number = line_number
self.tags = tags or set() self.tags = tags or set()
def add_step(self, step: "Step") -> None: def add_step(self, step: Step) -> None:
"""Add step to the scenario. """Add step to the scenario.
:param pytest_bdd.parser.Step step: Step. :param pytest_bdd.parser.Step step: Step.
@ -228,11 +230,11 @@ class ScenarioTemplate:
self._steps.append(step) self._steps.append(step)
@property @property
def steps(self) -> "List[Step]": def steps(self) -> List[Step]:
background = self.feature.background background = self.feature.background
return (background.steps if background else []) + self._steps return (background.steps if background else []) + self._steps
def render(self, context: typing.Mapping[str, typing.Any]) -> "Scenario": def render(self, context: typing.Mapping[str, typing.Any]) -> Scenario:
steps = [ steps = [
Step( Step(
name=templated_step.render(context), name=templated_step.render(context),
@ -250,7 +252,7 @@ class Scenario:
"""Scenario.""" """Scenario."""
def __init__(self, feature: "Feature", name: str, line_number: int, steps: "typing.List[Step]", tags=None): def __init__(self, feature: Feature, name: str, line_number: int, steps: typing.List[Step], tags=None):
"""Scenario constructor. """Scenario constructor.
:param pytest_bdd.parser.Feature feature: Feature. :param pytest_bdd.parser.Feature feature: Feature.
@ -288,8 +290,8 @@ class Step:
self.failed: bool = False self.failed: bool = False
self.start: int = 0 # TODO: Unused self.start: int = 0 # TODO: Unused
self.stop: int = 0 # TODO: Unused self.stop: int = 0 # TODO: Unused
self.scenario: "Optional[ScenarioTemplate]" = None self.scenario: Optional[ScenarioTemplate] = None
self.background: "Optional[Background]" = None self.background: Optional[Background] = None
def add_line(self, line: str) -> None: def add_line(self, line: str) -> None:
"""Add line to the multiple step. """Add line to the multiple step.
@ -340,17 +342,17 @@ class Background:
"""Background.""" """Background."""
def __init__(self, feature: "Feature", line_number: int) -> None: def __init__(self, feature: Feature, line_number: int) -> None:
"""Background constructor. """Background constructor.
:param pytest_bdd.parser.Feature feature: Feature. :param pytest_bdd.parser.Feature feature: Feature.
:param int line_number: Line number. :param int line_number: Line number.
""" """
self.feature: "Feature" = feature self.feature: Feature = feature
self.line_number: int = line_number self.line_number: int = line_number
self.steps: "typing.List[Step]" = [] self.steps: typing.List[Step] = []
def add_step(self, step: "Step") -> None: def add_step(self, step: Step) -> None:
"""Add step to the background.""" """Add step to the background."""
step.background = self step.background = self
self.steps.append(step) self.steps.append(step)

View File

@ -1,8 +1,7 @@
"""Step parsers.""" """Step parsers."""
from __future__ import annotations
import re as base_re import re as base_re
from functools import partial
from typing import Any, Dict, cast from typing import Any, Dict, cast
import parse as base_parse import parse as base_parse

View File

@ -1,4 +1,5 @@
"""Pytest plugin entry point. Used for any fixtures needed.""" """Pytest plugin entry point. Used for any fixtures needed."""
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, Optional from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, Optional
@ -17,7 +18,7 @@ if TYPE_CHECKING:
from .parser import Feature, Scenario, Step from .parser import Feature, Scenario, Step
def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None: def pytest_addhooks(pluginmanager: PytestPluginManager) -> None:
"""Register plugin hooks.""" """Register plugin hooks."""
from pytest_bdd import hooks from pytest_bdd import hooks
@ -46,7 +47,7 @@ def _pytest_bdd_example() -> Dict:
return {} return {}
def pytest_addoption(parser: "Parser") -> None: def pytest_addoption(parser: Parser) -> None:
"""Add pytest-bdd options.""" """Add pytest-bdd options."""
add_bdd_ini(parser) add_bdd_ini(parser)
cucumber_json.add_options(parser) cucumber_json.add_options(parser)
@ -54,42 +55,42 @@ def pytest_addoption(parser: "Parser") -> None:
gherkin_terminal_reporter.add_options(parser) gherkin_terminal_reporter.add_options(parser)
def add_bdd_ini(parser: "Parser") -> None: def add_bdd_ini(parser: Parser) -> None:
parser.addini("bdd_features_base_dir", "Base features directory.") parser.addini("bdd_features_base_dir", "Base features directory.")
@pytest.mark.trylast @pytest.mark.trylast
def pytest_configure(config: "Config") -> None: def pytest_configure(config: Config) -> None:
"""Configure all subplugins.""" """Configure all subplugins."""
CONFIG_STACK.append(config) CONFIG_STACK.append(config)
cucumber_json.configure(config) cucumber_json.configure(config)
gherkin_terminal_reporter.configure(config) gherkin_terminal_reporter.configure(config)
def pytest_unconfigure(config: "Config") -> None: def pytest_unconfigure(config: Config) -> None:
"""Unconfigure all subplugins.""" """Unconfigure all subplugins."""
CONFIG_STACK.pop() CONFIG_STACK.pop()
cucumber_json.unconfigure(config) cucumber_json.unconfigure(config)
@pytest.mark.hookwrapper @pytest.mark.hookwrapper
def pytest_runtest_makereport(item: "Item", call: "CallInfo") -> Iterator: def pytest_runtest_makereport(item: Item, call: CallInfo) -> Iterator:
outcome = yield outcome = yield
reporting.runtest_makereport(item, call, outcome.get_result()) reporting.runtest_makereport(item, call, outcome.get_result())
@pytest.mark.tryfirst @pytest.mark.tryfirst
def pytest_bdd_before_scenario(request: "FixtureRequest", feature: "Feature", scenario: "Scenario") -> None: def pytest_bdd_before_scenario(request: FixtureRequest, feature: Feature, scenario: Scenario) -> None:
reporting.before_scenario(request, feature, scenario) reporting.before_scenario(request, feature, scenario)
@pytest.mark.tryfirst @pytest.mark.tryfirst
def pytest_bdd_step_error( def pytest_bdd_step_error(
request: "FixtureRequest", request: FixtureRequest,
feature: "Feature", feature: Feature,
scenario: "Scenario", scenario: Scenario,
step: "Step", step: Step,
step_func: "Callable", step_func: Callable,
step_func_args: Dict, step_func_args: Dict,
exception: Exception, exception: Exception,
) -> None: ) -> None:
@ -98,27 +99,27 @@ def pytest_bdd_step_error(
@pytest.mark.tryfirst @pytest.mark.tryfirst
def pytest_bdd_before_step( def pytest_bdd_before_step(
request: "FixtureRequest", feature: "Feature", scenario: "Scenario", step: "Step", step_func: "Callable" request: FixtureRequest, feature: Feature, scenario: Scenario, step: Step, step_func: Callable
) -> None: ) -> None:
reporting.before_step(request, feature, scenario, step, step_func) reporting.before_step(request, feature, scenario, step, step_func)
@pytest.mark.tryfirst @pytest.mark.tryfirst
def pytest_bdd_after_step( def pytest_bdd_after_step(
request: "FixtureRequest", request: FixtureRequest,
feature: "Feature", feature: Feature,
scenario: "Scenario", scenario: Scenario,
step: "Step", step: Step,
step_func: "Callable", step_func: Callable,
step_func_args: Dict[str, Any], step_func_args: Dict[str, Any],
) -> None: ) -> None:
reporting.after_step(request, feature, scenario, step, step_func, step_func_args) reporting.after_step(request, feature, scenario, step, step_func, step_func_args)
def pytest_cmdline_main(config: "Config") -> Optional[int]: def pytest_cmdline_main(config: Config) -> Optional[int]:
return generation.cmdline_main(config) return generation.cmdline_main(config)
def pytest_bdd_apply_tag(tag: str, function: "Callable") -> "Callable": def pytest_bdd_apply_tag(tag: str, function: Callable) -> Callable:
mark = getattr(pytest.mark, tag) mark = getattr(pytest.mark, tag)
return mark(function) return mark(function)

View File

@ -3,6 +3,7 @@
Collection of the scenario execution statuses, timing and other information Collection of the scenario execution statuses, timing and other information
that enriches the pytest test reporting. that enriches the pytest test reporting.
""" """
from __future__ import annotations
import time import time
from typing import TYPE_CHECKING, Any, Callable, Dict from typing import TYPE_CHECKING, Any, Callable, Dict
@ -22,7 +23,7 @@ class StepReport:
failed = False failed = False
stopped = None stopped = None
def __init__(self, step: "Step") -> None: def __init__(self, step: Step) -> None:
"""Step report constructor. """Step report constructor.
:param pytest_bdd.parser.Step step: Step. :param pytest_bdd.parser.Step step: Step.
@ -70,7 +71,7 @@ class ScenarioReport:
"""Scenario execution report.""" """Scenario execution report."""
# TODO: Remove unused argument "node" # TODO: Remove unused argument "node"
def __init__(self, scenario: "Scenario", node: Any) -> None: def __init__(self, scenario: Scenario, node: Any) -> None:
"""Scenario report constructor. """Scenario report constructor.
:param pytest_bdd.parser.Scenario scenario: Scenario. :param pytest_bdd.parser.Scenario scenario: Scenario.
@ -80,7 +81,7 @@ class ScenarioReport:
self.step_reports = [] self.step_reports = []
@property @property
def current_step_report(self) -> "StepReport": def current_step_report(self) -> StepReport:
"""Get current step report. """Get current step report.
:return: Last or current step report. :return: Last or current step report.
@ -88,7 +89,7 @@ class ScenarioReport:
""" """
return self.step_reports[-1] return self.step_reports[-1]
def add_step_report(self, step_report: "StepReport") -> None: def add_step_report(self, step_report: StepReport) -> None:
"""Add new step report. """Add new step report.
:param step_report: New current step report. :param step_report: New current step report.
@ -132,7 +133,7 @@ class ScenarioReport:
self.add_step_report(report) self.add_step_report(report)
def runtest_makereport(item: "Item", call: "CallInfo", rep: "TestReport") -> None: def runtest_makereport(item: Item, call: CallInfo, rep: TestReport) -> None:
"""Store item in the report object.""" """Store item in the report object."""
try: try:
scenario_report = item.__scenario_report__ scenario_report = item.__scenario_report__
@ -143,17 +144,17 @@ def runtest_makereport(item: "Item", call: "CallInfo", rep: "TestReport") -> Non
rep.item = {"name": item.name} rep.item = {"name": item.name}
def before_scenario(request: "FixtureRequest", feature: "Feature", scenario: "Scenario") -> None: def before_scenario(request: FixtureRequest, feature: Feature, scenario: Scenario) -> None:
"""Create scenario report for the item.""" """Create scenario report for the item."""
request.node.__scenario_report__ = ScenarioReport(scenario=scenario, node=request.node) request.node.__scenario_report__ = ScenarioReport(scenario=scenario, node=request.node)
def step_error( def step_error(
request: "FixtureRequest", request: FixtureRequest,
feature: "Feature", feature: Feature,
scenario: "Scenario", scenario: Scenario,
step: "Step", step: Step,
step_func: "Callable", step_func: Callable,
step_func_args: Dict, step_func_args: Dict,
exception: Exception, exception: Exception,
) -> None: ) -> None:
@ -161,19 +162,17 @@ def step_error(
request.node.__scenario_report__.fail() request.node.__scenario_report__.fail()
def before_step( def before_step(request: FixtureRequest, feature: Feature, scenario: Scenario, step: Step, step_func: Callable) -> None:
request: "FixtureRequest", feature: "Feature", scenario: "Scenario", step: "Step", step_func: "Callable"
) -> None:
"""Store step start time.""" """Store step start time."""
request.node.__scenario_report__.add_step_report(StepReport(step=step)) request.node.__scenario_report__.add_step_report(StepReport(step=step))
def after_step( def after_step(
request: "FixtureRequest", request: FixtureRequest,
feature: "Feature", feature: Feature,
scenario: "Scenario", scenario: Scenario,
step: "Step", step: Step,
step_func: "Callable", step_func: Callable,
step_func_args: Dict, step_func_args: Dict,
) -> None: ) -> None:
"""Finalize the step report as successful.""" """Finalize the step report as successful."""

View File

@ -10,6 +10,8 @@ test_publish_article = scenario(
scenario_name="Publishing the article", scenario_name="Publishing the article",
) )
""" """
from __future__ import annotations
import collections import collections
import os import os
import re import re
@ -57,7 +59,7 @@ def find_argumented_step_fixture_name(
return None return None
def _find_step_function(request: FixtureRequest, step: "Step", scenario: "Scenario") -> Any: def _find_step_function(request: FixtureRequest, step: Step, scenario: Scenario) -> Any:
"""Match the step defined by the regular expression pattern. """Match the step defined by the regular expression pattern.
:param request: PyTest request object. :param request: PyTest request object.
@ -85,7 +87,7 @@ def _find_step_function(request: FixtureRequest, step: "Step", scenario: "Scenar
) )
def _execute_step_function(request: FixtureRequest, scenario: "Scenario", step: "Step", step_func: Callable) -> None: def _execute_step_function(request: FixtureRequest, scenario: Scenario, step: Step, step_func: Callable) -> None:
"""Execute step function. """Execute step function.
:param request: PyTest request. :param request: PyTest request.
@ -128,7 +130,7 @@ def _execute_step_function(request: FixtureRequest, scenario: "Scenario", step:
raise raise
def _execute_scenario(feature: "Feature", scenario: "Scenario", request): def _execute_scenario(feature: Feature, scenario: Scenario, request):
"""Execute the scenario. """Execute the scenario.
:param feature: Feature. :param feature: Feature.
@ -157,7 +159,7 @@ FakeRequest = collections.namedtuple("FakeRequest", ["module"])
def _get_scenario_decorator( def _get_scenario_decorator(
feature: "Feature", feature_name: str, templated_scenario: "ScenarioTemplate", scenario_name: str feature: Feature, feature_name: str, templated_scenario: ScenarioTemplate, scenario_name: str
): ):
# HACK: Ideally we would use `def decorator(fn)`, but we want to return a custom exception # HACK: Ideally we would use `def decorator(fn)`, but we want to return a custom exception
# when the decorator is misused. # when the decorator is misused.
@ -202,8 +204,8 @@ def _get_scenario_decorator(
def collect_example_parametrizations( def collect_example_parametrizations(
templated_scenario: "ScenarioTemplate", templated_scenario: ScenarioTemplate,
) -> "typing.Optional[typing.List[ParameterSet]]": ) -> typing.Optional[typing.List[ParameterSet]]:
# We need to evaluate these iterators and store them as lists, otherwise # We need to evaluate these iterators and store them as lists, otherwise
# we won't be able to do the cartesian product later (the second iterator will be consumed) # we won't be able to do the cartesian product later (the second iterator will be consumed)
contexts = list(templated_scenario.examples.as_contexts()) contexts = list(templated_scenario.examples.as_contexts())

View File

@ -1,4 +1,5 @@
"""pytest-bdd scripts.""" """pytest-bdd scripts."""
from __future__ import annotations
import argparse import argparse
import os.path import os.path

View File

@ -34,6 +34,7 @@ def given_beautiful_article(article):
pass pass
""" """
from __future__ import annotations
from typing import Any, Callable, Dict, Optional, Union from typing import Any, Callable, Dict, Optional, Union

View File

@ -1,4 +1,5 @@
"""Common type definitions.""" """Common type definitions."""
from __future__ import annotations
FEATURE = "feature" FEATURE = "feature"
SCENARIO_OUTLINE = "scenario outline" SCENARIO_OUTLINE = "scenario outline"

View File

@ -1,4 +1,6 @@
"""Various utility functions.""" """Various utility functions."""
from __future__ import annotations
import base64 import base64
import pickle import pickle
import re import re
@ -11,7 +13,7 @@ if typing.TYPE_CHECKING:
from _pytest.config import Config from _pytest.config import Config
from _pytest.pytester import RunResult from _pytest.pytester import RunResult
CONFIG_STACK: "List[Config]" = [] CONFIG_STACK: List[Config] = []
def get_args(func: Callable) -> List[str]: def get_args(func: Callable) -> List[str]:
@ -57,7 +59,7 @@ def dump_obj(*objects: Any) -> None:
print(f"{_DUMP_START}{encoded}{_DUMP_END}") print(f"{_DUMP_START}{encoded}{_DUMP_END}")
def collect_dumped_objects(result: "RunResult"): def collect_dumped_objects(result: RunResult):
"""Parse all the objects dumped with `dump_object` from the result. """Parse all the objects dumped with `dump_object` from the result.
Note: You must run the result with output to stdout enabled. Note: You must run the result with output to stdout enabled.

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Optional from typing import TYPE_CHECKING, Any, Optional
import pytest import pytest
@ -13,7 +15,7 @@ PYTEST_6 = PYTEST_VERSION >= Version("6")
if PYTEST_6: if PYTEST_6:
def assert_outcomes( def assert_outcomes(
result: "RunResult", result: RunResult,
passed: int = 0, passed: int = 0,
skipped: int = 0, skipped: int = 0,
failed: int = 0, failed: int = 0,
@ -29,7 +31,7 @@ if PYTEST_6:
else: else:
def assert_outcomes( def assert_outcomes(
result: "RunResult", result: RunResult,
passed=0, passed=0,
skipped=0, skipped=0,
failed=0, failed=0,