From 1477af8c4610efbf657cb07b2701ee1fcb6c6f62 Mon Sep 17 00:00:00 2001 From: Bryan Borg <71280324+jammer87@users.noreply.github.com> Date: Sun, 11 Jan 2026 01:33:01 -0600 Subject: [PATCH 1/4] Converted type comments to type hints --- docs/api_reference.md | 47 +++-- src/pytest_cases/case_funcs.py | 96 ++++----- src/pytest_cases/case_parametrizer_new.py | 157 +++++++-------- src/pytest_cases/common_others.py | 44 ++--- src/pytest_cases/common_pytest.py | 56 +++--- src/pytest_cases/common_pytest_lazy_values.py | 37 ++-- src/pytest_cases/common_pytest_marks.py | 38 ++-- src/pytest_cases/filters.py | 15 +- src/pytest_cases/fixture__creation.py | 24 +-- src/pytest_cases/fixture_core1_unions.py | 80 ++++---- src/pytest_cases/fixture_core2.py | 89 ++++----- src/pytest_cases/fixture_parametrize_plus.py | 186 +++++++++--------- src/pytest_cases/plugin.py | 67 +++---- 13 files changed, 416 insertions(+), 520 deletions(-) diff --git a/docs/api_reference.md b/docs/api_reference.md index a8800ddf..f2ef7e5a 100644 --- a/docs/api_reference.md +++ b/docs/api_reference.md @@ -28,9 +28,9 @@ As explained in the [documentation](index.md), case functions have no requiremen ### `@case` ```python -@case(id=None, # type: str # noqa - tags=None, # type: Union[Any, Iterable[Any]] - marks=(), # type: Union[MarkDecorator, Iterable[MarkDecorator]] +@case(id: str = None, # noqa + tags: Union[Any, Iterable[Any]] = None, + marks: Union[MarkDecorator, Iterable[MarkDecorator]] = (), ) ``` @@ -54,8 +54,7 @@ def case_hi(): ### `@with_case_tags` ```python -@with_case_tags(*tags, # type: Any - ): +@with_case_tags(*tags: Any): ``` This decorator can be applied to a class defining cases to apply multiple @@ -105,8 +104,8 @@ class CasesContainerClass: ### `copy_case_info` ```python -def copy_case_info(from_fun, # type: Callable - to_fun # type: Callable +def copy_case_info(from_fun: Callable, + to_fun: Callable ): ``` @@ -116,8 +115,8 @@ Copies all information from case function `from_fun` to `to_fun`. ### `set_case_id` ```python -def set_case_id(id, # type: str - case_func # type: Callable +def set_case_id(id: str, + case_func: Callable ): ``` @@ -127,8 +126,8 @@ Sets an explicit id on case function `case_func`. ### `get_case_id` ```python -def get_case_id(case_func, # type: Callable - prefix_for_default_ids='case_' # type: str +def get_case_id(case_func: Callable, + prefix_for_default_ids: str = 'case_' ): ``` @@ -147,9 +146,9 @@ If a custom id is not present, a case id is automatically created from the funct ### `get_case_marks` ```python -def get_case_marks(case_func, # type: Callable - concatenate_with_fun_marks=False, # type: bool - as_decorators=False # type: bool +def get_case_marks(case_func: Callable, + concatenate_with_fun_marks: bool = False, + as_decorators: bool = False ): ``` @@ -169,7 +168,7 @@ There are currently two ways to place a mark on a case function: either with `@p ### `get_case_tags` ```python -def get_case_tags(case_func # type: Callable +def get_case_tags(case_func: Callable ): ``` @@ -183,9 +182,9 @@ Return the tags on this case function or an empty tuple. ### `matches_tag_query` ```python -def matches_tag_query(case_fun, # type: Callable - has_tag=None, # type: Union[str, Iterable[str]] - filter=None, # type: Union[Callable[[Callable], bool], Iterable[Callable[[Callable], bool]]] # noqa +def matches_tag_query(case_fun: Callable, + has_tag: Union[str, Iterable[str]] = None, + filter: Union[Callable[[Callable], bool], Iterable[Callable[[Callable], bool]]] = None, # noqa ): ``` @@ -209,9 +208,9 @@ Returns True if the case function is selected by the query: ### `is_case_class` ```python -def is_case_class(cls, # type: Any - case_marker_in_name='Case', # type: str - check_name=True # type: bool +def is_case_class(cls: Any, + case_marker_in_name: str = 'Case', + check_name: bool = True ): ``` @@ -230,9 +229,9 @@ Returns True if the given object is a class and, if `check_name=True` (default), ### `is_case_function` ```python -def is_case_function(f, # type: Any - prefix='case_', # type: str - check_prefix=True # type: bool +def is_case_function(f: Any, + prefix: str = 'case_', + check_prefix: bool = True ): ``` diff --git a/src/pytest_cases/case_funcs.py b/src/pytest_cases/case_funcs.py index 54a1ae59..99b2224e 100644 --- a/src/pytest_cases/case_funcs.py +++ b/src/pytest_cases/case_funcs.py @@ -4,11 +4,7 @@ # License: 3-clause BSD, from copy import copy from decopatch import function_decorator, DECORATED - -try: # python 3.5+ - from typing import Callable, Union, Optional, Any, Tuple, Iterable, List, Set -except ImportError: - pass +from typing import Callable, Union, Optional, Any, Iterable from .common_mini_six import string_types from .common_pytest import safe_isclass @@ -44,13 +40,13 @@ class _CaseInfo(object): __slots__ = ('id', 'marks', 'tags') def __init__(self, - id=None, # type: str - marks=(), # type: Tuple[MarkDecorator, ...] - tags=() # type: Tuple[Any] + id: str = None, + marks: tuple[MarkDecorator, ...] = (), + tags: tuple[Any] = () ): - self.id = id - self.marks = marks # type: Tuple[MarkDecorator, ...] - self.tags = () + self.id: str = id + self.marks: tuple[MarkDecorator, ...] = marks + self.tags: tuple[Any] = () self.add_tags(tags) def __repr__(self): @@ -58,8 +54,8 @@ def __repr__(self): @classmethod def get_from(cls, - case_func, # type: Callable - create_if_missing=False # type: bool + case_func: Callable, + create_if_missing: bool = False ): """ Return the _CaseInfo associated with case_fun or None @@ -73,15 +69,11 @@ def get_from(cls, ci.attach_to(case_func) return ci - def attach_to(self, - case_func # type: Callable - ): + def attach_to(self, case_func: Callable): """attach this case_info to the given case function""" setattr(case_func, CASE_FIELD, self) - def add_tags(self, - tags # type: Union[Any, Union[List, Set, Tuple]] - ): + def add_tags(self, tags: Union[Any, Union[list, set, tuple]]): """add the given tag or tags""" if tags: if isinstance(tags, string_types) or not isinstance(tags, (set, list, tuple)): @@ -90,9 +82,7 @@ def add_tags(self, self.tags += tuple(tags) - def matches_tag_query(self, - has_tag=None, # type: Union[str, Iterable[str]] - ): + def matches_tag_query(self, has_tag: Union[str, Iterable[str]] = None): """ Returns True if the case function with this case_info is selected by the query @@ -103,8 +93,8 @@ def matches_tag_query(self, @classmethod def copy_info(cls, - from_case_func, - to_case_func): + from_case_func: Callable, + to_case_func: Callable): case_info = cls.get_from(from_case_func) if case_info is not None: # there is something to copy: do it @@ -112,8 +102,8 @@ def copy_info(cls, cp.attach_to(to_case_func) -def _tags_match_query(tags, # type: Iterable[str] - has_tag # type: Optional[Union[str, Iterable[str]]] +def _tags_match_query(tags: Iterable[str], + has_tag: Optional[Union[str, Iterable[str]]] ): """Internal routine to determine is all tags in `has_tag` are persent in `tags` Note that `has_tag` can be a single tag, or none @@ -127,23 +117,23 @@ def _tags_match_query(tags, # type: Iterable[str] return all(t in tags for t in has_tag) -def copy_case_info(from_fun, # type: Callable - to_fun # type: Callable +def copy_case_info(from_fun: Callable, + to_fun: Callable ): """Copy all information from case function `from_fun` to `to_fun`.""" _CaseInfo.copy_info(from_fun, to_fun) -def set_case_id(id, # type: str - case_func # type: Callable +def set_case_id(id: str, + case_func: Callable ): """Set an explicit id on case function `case_func`.""" ci = _CaseInfo.get_from(case_func, create_if_missing=True) ci.id = id -def get_case_id(case_func, # type: Callable - prefix_for_default_ids=CASE_PREFIX_FUN # type: str +def get_case_id(case_func: Callable, + prefix_for_default_ids: str = CASE_PREFIX_FUN ): """Return the case id associated with this case function. @@ -176,11 +166,10 @@ def get_case_id(case_func, # type: Callable # def add_case_marks: no need, equivalent of @case(marks) or @mark -def get_case_marks(case_func, # type: Callable - concatenate_with_fun_marks=False, # type: bool - as_decorators=False # type: bool - ): - # type: (...) -> Union[Tuple[Mark, ...], Tuple[MarkDecorator, ...]] +def get_case_marks(case_func: Callable, + concatenate_with_fun_marks: bool = False, + as_decorators: bool = False + ) -> Union[tuple[Mark, ...], tuple[MarkDecorator, ...]]: """Return the marks that are on the case function. There are currently two ways to place a mark on a case function: either with `@pytest.mark.` or in @@ -218,16 +207,15 @@ def get_case_marks(case_func, # type: Callable # ci.add_tags(tags) -def get_case_tags(case_func # type: Callable - ): +def get_case_tags(case_func: Callable): """Return the tags on this case function or an empty tuple""" ci = _CaseInfo.get_from(case_func) return ci.tags if ci is not None else () -def matches_tag_query(case_fun, # type: Callable - has_tag=None, # type: Union[str, Iterable[str]] - filter=None, # type: Union[Callable[[Callable], bool], Iterable[Callable[[Callable], bool]]] # noqa +def matches_tag_query(case_fun: Callable, + has_tag: Union[str, Iterable[str]] = None, + filter: Union[Callable[[Callable], bool], Iterable[Callable[[Callable], bool]]] = None, ): """ This function is the one used by `@parametrize_with_cases` to filter the case functions collected. It can be used @@ -275,16 +263,10 @@ def matches_tag_query(case_fun, # type: Callable return selected -try: - SeveralMarkDecorators = Union[Tuple[MarkDecorator, ...], List[MarkDecorator], Set[MarkDecorator]] -except: # noqa - pass - - @function_decorator -def case(id=None, # type: str # noqa - tags=None, # type: Union[Any, Iterable[Any]] - marks=(), # type: Union[MarkDecorator, SeveralMarkDecorators] +def case(id: str = None, + tags: Union[Any, Iterable[Any]] = None, + marks: Union[MarkDecorator, tuple[MarkDecorator, ...], list[MarkDecorator], set[MarkDecorator]] = (), case_func=DECORATED # noqa ): """ @@ -311,9 +293,9 @@ def case_hi(): return case_func -def is_case_class(cls, # type: Any - case_marker_in_name=CASE_PREFIX_CLS, # type: str - check_name=True # type: bool +def is_case_class(cls: Any, + case_marker_in_name: str = CASE_PREFIX_CLS, + check_name: bool = True ): """ This function is the one used by `@parametrize_with_cases` to collect cases within classes. It can be used manually @@ -335,9 +317,9 @@ def is_case_class(cls, # type: Any GEN_BY_US = '_pytestcases_gen' -def is_case_function(f, # type: Any - prefix=CASE_PREFIX_FUN, # type: str - check_prefix=True # type: bool +def is_case_function(f: Any, + prefix: str = CASE_PREFIX_FUN, + check_prefix: bool = True ): """ This function is the one used by `@parametrize_with_cases` to collect cases. It can be used manually for diff --git a/src/pytest_cases/case_parametrizer_new.py b/src/pytest_cases/case_parametrizer_new.py index ddd36bb8..3ab48943 100644 --- a/src/pytest_cases/case_parametrizer_new.py +++ b/src/pytest_cases/case_parametrizer_new.py @@ -7,10 +7,13 @@ from collections import namedtuple +import enum import functools from importlib import import_module from inspect import getmembers, ismodule import re +from typing import Union, Callable, Iterable, Any, Type, Literal +from types import ModuleType from warnings import warn try: # python 3.3+ @@ -18,13 +21,8 @@ except ImportError: from funcsigs import signature # noqa -try: - from typing import Union, Callable, Iterable, Any, Type, List, Tuple # noqa -except ImportError: - pass - from .common_mini_six import string_types -from .common_others import get_code_first_line, AUTO, qname, funcopy, needs_binding, get_function_host, \ +from .common_others import get_code_first_line, AUTO, Auto, qname, funcopy, needs_binding, get_function_host, \ in_same_module, get_host_module, get_class_that_defined_method from .common_pytest_marks import copy_pytest_marks, make_marked_parameter_value, remove_pytest_mark, filter_marks, \ get_param_argnames_as_list, Mark @@ -48,37 +46,33 @@ ModuleNotFoundError = ImportError -THIS_MODULE = object() -"""Singleton that can be used instead of a module name to indicate that the module is the current one""" - -try: - from typing import Literal, Optional # noqa - from types import ModuleType # noqa +class ThisModule(enum.Enum): + """Class to allow type hints for the THIS_MODULE Singleton""" + THIS_MODULE = object() - ModuleRef = Union[str, ModuleType, Literal[AUTO], Literal[THIS_MODULE]] # noqa - CaseType = Union[Callable, Type, ModuleRef] +THIS_MODULE = ThisModule.THIS_MODULE +"""Singleton that can be used instead of a module name to indicate that the module is the current one""" -except: # noqa - pass +ModuleRef = Union[str, ModuleType, Literal[Auto.AUTO], Literal[ThisModule.THIS_MODULE]] +CaseType = Union[Callable, Type, ModuleRef] _HOST_CLS_ATTR = '_pytestcases_host_cls' -def parametrize_with_cases(argnames, # type: Union[str, List[str], Tuple[str, ...]] - cases=AUTO, # type: Union[CaseType, List[CaseType]] - prefix=CASE_PREFIX_FUN, # type: str - glob=None, # type: str - has_tag=None, # type: Any - filter=None, # type: Callable[..., bool] # noqa - ids=None, # type: Union[Callable, Iterable[str]] - idstyle=None, # type: Union[str, Callable] - # idgen=_IDGEN, # type: Union[str, Callable] - debug=False, # type: bool - scope="function", # type: str - import_fixtures=False # type: bool - ): - # type: (...) -> Callable[[Callable], Callable] +def parametrize_with_cases(argnames: Union[str, list[str], tuple[str, ...]], + cases: Union[CaseType, list[CaseType]] = AUTO, + prefix: str = CASE_PREFIX_FUN, + glob: str = None, + has_tag: Any = None, + filter: Callable[..., bool] = None, + ids: Union[Callable, Iterable[str]] = None, + idstyle: Union[str, Callable] = None, + # idgen: Union[str, Callable] = _IDGEN, + debug: bool = False, + scope: str = "function", + import_fixtures: bool = False + ) -> Callable[[Callable], Callable]: """ A decorator for test functions or fixtures, to parametrize them based on test cases. It works similarly to `@pytest.mark.parametrize`: argnames represent a coma-separated string of arguments to inject in the decorated @@ -171,8 +165,7 @@ def _apply_parametrization(f, host_class_or_module): return _apply_parametrization -def _get_original_case_func(case_fun # type: Callable - ): +def _get_original_case_func(case_fun: Callable): """ :param case_fun: @@ -183,8 +176,7 @@ def _get_original_case_func(case_fun # type: Callable return true_case_func, case_in_class -def create_glob_name_filter(glob_str # type: str - ): +def create_glob_name_filter(glob_str: str): """ Creates a glob-like matcher for the name of case functions The only special character that is supported is `*` and it can not be @@ -206,14 +198,13 @@ def _glob_name_filter(case_fun): return _glob_name_filter -def get_all_cases(parametrization_target=None, # type: Callable - cases=AUTO, # type: Union[CaseType, List[CaseType]] - prefix=CASE_PREFIX_FUN, # type: str - glob=None, # type: str - has_tag=None, # type: Union[str, Iterable[str]] - filter=None # type: Callable[[Callable], bool] # noqa - ): - # type: (...) -> List[Callable] +def get_all_cases(parametrization_target: Callable = None, + cases: Union[CaseType, list[CaseType]] = AUTO, + prefix: str = CASE_PREFIX_FUN, + glob: str = None, + has_tag: Union[str, Iterable[str]] = None, + filter: Callable[[Callable], bool] = None + ) -> list[Callable]: """ Lists all desired cases for a given `parametrization_target` (a test function or a fixture). This function may be convenient for debugging purposes. See `@parametrize_with_cases` for details on the parameters. @@ -324,14 +315,13 @@ def get_all_cases(parametrization_target=None, # type: Callable if matches_tag_query(c, has_tag=has_tag, filter=filters)] -def get_parametrize_args(host_class_or_module, # type: Union[Type, ModuleType] - cases_funs, # type: List[Callable] - prefix, # type: str - scope="function", # type: str - import_fixtures=False, # type: bool - debug=False # type: bool - ): - # type: (...) -> List[CaseParamValue] +def get_parametrize_args(host_class_or_module: Union[Type, ModuleType], + cases_funs: list[Callable], + prefix: str, + scope: str = "function", + import_fixtures: bool = False, + debug: bool = False + ) -> list['CaseParamValue']: """ Transforms a list of cases (obtained from `get_all_cases`) into a list of argvalues for `@parametrize`. Each case function `case_fun` is transformed into one or several `lazy_value`(s) or a `fixture_ref`: @@ -408,14 +398,13 @@ def get_case_function(self, request): return f.__origcasefun__ -def case_to_argvalues(host_class_or_module, # type: Union[Type, ModuleType] - case_fun, # type: Callable - prefix, # type: str - scope, # type: str - import_fixtures=False, # type: bool - debug=False # type: bool - ): - # type: (...) -> Tuple[CaseParamValue, ...] +def case_to_argvalues(host_class_or_module: Union[Type, ModuleType], + case_fun: Callable, + prefix: str, + scope: str, + import_fixtures: bool = False, + debug: bool = False + ) -> tuple[CaseParamValue, ...]: """Transform a single case into one or several `lazy_value`(s) or a `fixture_ref` to be used in `@parametrize` If `case_fun` requires at least on fixture, a fixture will be created if not yet present, and a `fixture_ref` will @@ -485,15 +474,14 @@ def case_to_argvalues(host_class_or_module, # type: Union[Type, ModuleType] return (make_marked_parameter_value((argvalues,), marks=remaining_marks) if remaining_marks else argvalues,) -def get_or_create_case_fixture(case_id, # type: str - case_fun, # type: Callable - target_host, # type: Union[Type, ModuleType] - add_required_fixtures, # type: Iterable[str] - scope, # type: str - import_fixtures=False, # type: bool - debug=False # type: bool - ): - # type: (...) -> Tuple[str, Tuple[Mark]] +def get_or_create_case_fixture(case_id: str, + case_fun: Callable, + target_host: Union[Type, ModuleType], + add_required_fixtures: Iterable[str], + scope: str, + import_fixtures: bool = False, + debug: bool = False + ) -> tuple[str, tuple[Mark]]: """ When case functions require fixtures, we want to rely on pytest to inject everything. Therefore we create a "case fixture" wrapping the case function. Since a case function may not be located in the same place @@ -643,8 +631,7 @@ def name_changer(name, i): return fix_name, case_marks -def _get_fixture_cases(module_or_class # type: Union[ModuleType, Type] - ): +def _get_fixture_cases(module_or_class: Union[ModuleType, Type]): """ Returns our 'storage unit' in a module or class, used to remember the fixtures created from case functions. That way we can reuse fixtures already created for cases, in a given module/class. @@ -674,7 +661,7 @@ def _get_fixture_cases(module_or_class # type: Union[ModuleType, Type] return cache, imported_fixtures_list -def import_default_cases_module(test_module_name): +def import_default_cases_module(test_module_name: str): """ Implements the `module=AUTO` behaviour of `@parameterize_cases`. @@ -713,7 +700,7 @@ def hasinit(obj): if init: return init != object.__init__ - + def hasnew(obj): new = getattr(obj, "__new__", None) if new: @@ -728,12 +715,11 @@ class CasesCollectionWarning(UserWarning): __module__ = "pytest_cases" -def extract_cases_from_class(cls, - check_name=True, - case_fun_prefix=CASE_PREFIX_FUN, +def extract_cases_from_class(cls: type, + check_name: bool = True, + case_fun_prefix: str = CASE_PREFIX_FUN, _case_param_factory=None - ): - # type: (...) -> List[Callable] + ) -> list[Callable]: """ Collects all case functions (methods matching ``case_fun_prefix``) in class ``cls``. @@ -785,12 +771,11 @@ def extract_cases_from_class(cls, return [] -def extract_cases_from_module(module, # type: Union[str, ModuleRef] - package_name=None, # type: str - case_fun_prefix=CASE_PREFIX_FUN, # type: str +def extract_cases_from_module(module: Union[str, ModuleRef], + package_name: str = None, + case_fun_prefix: str = CASE_PREFIX_FUN, _case_param_factory=None - ): - # type: (...) -> List[Callable] + ) -> list[Callable]: """ Internal method used to create a list of case functions for all cases available from the given module. See `@cases_data` @@ -834,11 +819,11 @@ def extract_cases_from_module(module, # type: Union[st case_fun_prefix=case_fun_prefix) -def _extract_cases_from_module_or_class(module=None, # type: ModuleRef - cls=None, # type: Type - case_fun_prefix=CASE_PREFIX_FUN, # type: str +def _extract_cases_from_module_or_class(module: ModuleRef = None, + cls: type = None, + case_fun_prefix: str = CASE_PREFIX_FUN, _case_param_factory=None - ): # type: (...) -> List[Callable] + ) -> list[Callable]: """ Extracts all case functions from `module` or `cls` (only one non-None must be provided). @@ -1251,7 +1236,7 @@ def _get_place_as(f): def get_current_case_id(request_or_item, - argnames # type: Union[Iterable[str], str] + argnames: Union[Iterable[str], str] ): """ DEPRECATED - use `get_current_cases` instead A helper function to return the current case id for a given `pytest` item (available in some hooks) or `request` diff --git a/src/pytest_cases/common_others.py b/src/pytest_cases/common_others.py index 38d3e7ba..c735fcc5 100644 --- a/src/pytest_cases/common_others.py +++ b/src/pytest_cases/common_others.py @@ -2,6 +2,7 @@ # + All contributors to # # License: 3-clause BSD, +import enum import functools import inspect from keyword import iskeyword @@ -9,11 +10,8 @@ from importlib import import_module from inspect import findsource import re +from typing import Union, Callable, Optional, Type # noqa -try: - from typing import Union, Callable, Any, Optional, Tuple, Type # noqa -except ImportError: - pass from .common_mini_six import string_types, PY3, PY34 @@ -47,22 +45,17 @@ def get_code_first_line(f): # except ImportError: # from _pytest.compat import getfslineno as compat_getfslineno -try: - ExpectedError = Optional[Union[Type[Exception], str, Exception, Callable[[Exception], Optional[bool]]]] - """The expected error in case failure is expected. An exception type, instance, or a validation function""" - - ExpectedErrorType = Optional[Type[BaseException]] - ExpectedErrorPattern = Optional[re.Pattern] - ExpectedErrorInstance = Optional[BaseException] - ExpectedErrorValidator = Optional[Callable[[BaseException], Optional[bool]]] +ExpectedError = Optional[Union[Type[Exception], str, Exception, Callable[[Exception], Optional[bool]]]] +"""The expected error in case failure is expected. An exception type, instance, or a validation function""" -except: # noqa - pass +ExpectedErrorType = Optional[Type[BaseException]] +ExpectedErrorPattern = Optional[re.Pattern] +ExpectedErrorInstance = Optional[BaseException] +ExpectedErrorValidator = Optional[Callable[[BaseException], Optional[bool]]] -def unfold_expected_err(expected_e # type: ExpectedError - ): - # type: (...) -> Tuple[ExpectedErrorType, ExpectedErrorPattern, ExpectedErrorInstance, ExpectedErrorValidator] +def unfold_expected_err(expected_e: ExpectedError + ) -> tuple[ExpectedErrorType, ExpectedErrorPattern, ExpectedErrorInstance, ExpectedErrorValidator]: """ 'Unfolds' the expected error `expected_e` to return a tuple of - expected error type @@ -98,8 +91,7 @@ def unfold_expected_err(expected_e # type: ExpectedError "validation callable") -def assert_exception(expected # type: ExpectedError - ): +def assert_exception(expected: ExpectedError): """ A context manager to check that some bit of code raises an exception. Sometimes it might be more handy than `with pytest.raises():`. @@ -213,8 +205,11 @@ def __exit__(self, exc_type, exc_val, exc_tb): # See https://docs.python.org/2/reference/datamodel.html#object.__exit__ return True +class Auto(enum.Enum): + """Class to allow type hints for the AUTO Singleton""" + AUTO = object() -AUTO = object() +AUTO = Auto.AUTO """Marker for automatic defaults""" @@ -253,8 +248,7 @@ def get_function_host(func, fallback_to_module=True): return host -def needs_binding(f, return_bound=False): - # type: (...) -> Union[bool, Tuple[bool, Callable]] +def needs_binding(f, return_bound: bool = False) -> Union[bool, tuple[bool, Callable]]: """Utility to check if a function needs to be bound to be used """ # detect non-callables @@ -540,8 +534,7 @@ def robust_isinstance(o, cls): return False -def isidentifier(s # type: str - ): +def isidentifier(s: str): """python 2+3 compliant .isidentifier()""" try: return s.isidentifier() @@ -549,8 +542,7 @@ def isidentifier(s # type: str return re.match("[a-zA-Z_]\\w*\\Z", s) -def make_identifier(name # type: str - ): +def make_identifier(name: str): """Transform the given name into a valid python identifier""" if not isinstance(name, string_types): raise TypeError("name should be a string, found : %r" % name) diff --git a/src/pytest_cases/common_pytest.py b/src/pytest_cases/common_pytest.py index afad9d39..2fe6083a 100644 --- a/src/pytest_cases/common_pytest.py +++ b/src/pytest_cases/common_pytest.py @@ -7,6 +7,7 @@ import inspect import sys import os +from typing import Union, Callable, Any, Optional, Iterable, Sequence, Collection from importlib import import_module from makefun import add_signature_parameters, wraps @@ -18,13 +19,9 @@ from inspect import isgeneratorfunction, isclass -try: - from typing import Union, Callable, Any, Optional, Tuple, Type, Iterable, Sized, List # noqa -except ImportError: - pass - import pytest -from _pytest.python import Metafunc +from _pytest.python import CallSpec2, Metafunc +from _pytest.fixtures import FixtureDef from .common_mini_six import string_types from .common_others import get_function_host @@ -86,8 +83,7 @@ def remove_duplicates(lst): if PYTEST84_OR_GREATER: - def is_fixture(fixture_fun # type: Any - ): + def is_fixture(fixture_fun: Any): """ Returns True if the provided function is a fixture @@ -97,8 +93,7 @@ def is_fixture(fixture_fun # type: Any from _pytest.fixtures import FixtureFunctionDefinition return safe_isinstance(fixture_fun, FixtureFunctionDefinition) else: - def is_fixture(fixture_fun # type: Any - ): + def is_fixture(fixture_fun: Any): """ Returns True if the provided function is a fixture @@ -162,9 +157,7 @@ def list_all_fixtures_in(cls_or_module, return_names=True, recurse_to_module=Fal return res -def safe_isclass(obj # type: object - ): - # type: (...) -> bool +def safe_isclass(obj: object) -> bool: """Ignore any exception via isinstance on Python 3.""" try: return isclass(obj) @@ -172,9 +165,8 @@ def safe_isclass(obj # type: object return False -def safe_isinstance(obj, # type: object - cls): - # type: (...) -> bool +def safe_isinstance(obj: object, + cls: type) -> bool: """Ignore any exception via isinstance""" try: return isinstance(obj, cls) @@ -182,8 +174,7 @@ def safe_isinstance(obj, # type: object return False -def assert_is_fixture(fixture_fun # type: Any - ): +def assert_is_fixture(fixture_fun: Any): """ Raises a ValueError if the provided fixture function is not a fixture. @@ -196,8 +187,7 @@ def assert_is_fixture(fixture_fun # type: Any if PYTEST84_OR_GREATER: - def get_fixture_name(fixture_fun # type: Union[str, Callable] - ): + def get_fixture_name(fixture_fun: Union[str, Callable]): """ Internal utility to retrieve the fixture name corresponding to the given fixture function. Indeed there is currently no pytest API to do this. @@ -221,8 +211,7 @@ def get_fixture_name(fixture_fun # type: Union[str, Callable] return fixture_fun.name else: - def get_fixture_name(fixture_fun # type: Union[str, Callable] - ): + def get_fixture_name(fixture_fun: Union[str, Callable]): """ Internal utility to retrieve the fixture name corresponding to the given fixture function. Indeed there is currently no pytest API to do this. @@ -372,11 +361,10 @@ def make_test_ids(global_ids, id_marks, argnames=None, argvalues=None, precomput return p_ids -def resolve_ids(ids, # type: Optional[Union[Callable, Iterable[str]]] - argvalues, # type: Sized(Any) - full_resolve=False # type: bool - ): - # type: (...) -> Union[List[str], Callable] +def resolve_ids(ids: Optional[Union[Callable, Iterable[str]]], + argvalues: Collection[Any], + full_resolve: bool = False + ) -> Union[list[str], Callable]: """ Resolves the `ids` argument of a parametrized fixture. @@ -631,9 +619,9 @@ def set_callspec_arg_scope_to_function(callspec, arg_name): def in_callspec_explicit_args( - callspec, # type: CallSpec2 - name # type: str -): # type: (...) -> bool + callspec: CallSpec2, + name: str +) -> bool: """Return True if name is explicitly used in callspec args""" return (name in callspec.params) or (not PYTEST8_OR_GREATER and name in callspec.funcargs) @@ -663,9 +651,9 @@ def in_callspec_explicit_args( def mini_idval( - val, # type: object - argname, # type: str - idx, # type: int + val: object, + argname: str, + idx: int, ): """ A simplified version of idval where idfn, item and config do not need to be passed. @@ -793,7 +781,7 @@ def __init__(self, func): if PYTEST8_OR_GREATER: # dummy - self._arg2fixturedefs = dict() # type: dict[str, Sequence["FixtureDef[Any]"]] + self._arg2fixturedefs: dict[str, Sequence[FixtureDef[Any]]] = dict() # get parametrization marks self.pmarks = get_pytest_parametrize_marks(self.function) diff --git a/src/pytest_cases/common_pytest_lazy_values.py b/src/pytest_cases/common_pytest_lazy_values.py index 89303bc2..5092e236 100644 --- a/src/pytest_cases/common_pytest_lazy_values.py +++ b/src/pytest_cases/common_pytest_lazy_values.py @@ -3,6 +3,7 @@ # # License: 3-clause BSD, from functools import partial +from typing import Union, Callable, Any, Iterable # noqa import weakref try: # python 3.3+ @@ -10,11 +11,6 @@ except ImportError: from funcsigs import signature # noqa -try: - from typing import Union, Callable, List, Set, Tuple, Any, Sequence, Optional, Iterable # noqa -except ImportError: - pass - try: from _pytest.mark.structures import MarkDecorator, Mark # noqa except ImportError: @@ -142,7 +138,7 @@ class _LazyValue(Lazy): @classmethod def copy_from(cls, - obj # type: _LazyValue + obj: '_LazyValue' ): """Creates a copy of this _LazyValue""" new_obj = cls(valuegetter=obj.valuegetter, id=obj._id, marks=obj._marks) @@ -153,9 +149,9 @@ def copy_from(cls, # noinspection PyMissingConstructor def __init__(self, - valuegetter, # type: Callable[[], Any] - id=None, # type: str # noqa - marks=None, # type: Union[MarkDecorator, Iterable[MarkDecorator]] + valuegetter: Callable[[], Any], + id: str = None, # noqa + marks: Union[MarkDecorator, Iterable[MarkDecorator]] = None, ): self.valuegetter = valuegetter self._id = id @@ -168,9 +164,8 @@ def __hash__(self): return hash((self.__class__, self.valuegetter, self._id, self._marks)) def get_marks(self, - as_decorators=False # type: bool - ): - # type: (...) -> Union[Tuple[Mark, ...], Tuple[MarkDecorator, ...]] + as_decorators: bool = False + ) -> Union[tuple[Mark, ...], tuple[MarkDecorator, ...]]: """ Overrides default implementation to return the marks that are on the case function @@ -284,15 +279,15 @@ class _LazyTupleItem(Lazy): @classmethod def copy_from(cls, - obj # type: _LazyTupleItem + obj: '_LazyTupleItem' ): """Creates a copy of this _LazyTupleItem""" return cls(host=obj.host, item=obj.item) # noinspection PyMissingConstructor def __init__(self, - host, # type: LazyTuple - item # type: int + host: 'LazyTuple', + item: int ): self.host = host self.item = item @@ -347,7 +342,7 @@ class LazyTuple(Lazy): @classmethod def copy_from(cls, - obj # type: LazyTuple + obj: 'LazyTuple' ): # clone the inner lazy value value_copy = obj._lazyvalue.clone() @@ -355,8 +350,8 @@ def copy_from(cls, # noinspection PyMissingConstructor def __init__(self, - valueref, # type: _LazyValue - theoretical_size # type: int + valueref: _LazyValue, + theoretical_size: int ): self._lazyvalue = valueref self.theoretical_size = theoretical_size @@ -483,9 +478,9 @@ def clone(self, remove_int_base=False): return _LazyTupleItem.copy_from(self) -def lazy_value(valuegetter, # type: Callable[[], Any] - id=None, # type: str # noqa - marks=() # type: Union[MarkDecorator, Iterable[MarkDecorator]] +def lazy_value(valuegetter: Callable[[], Any], + id: str = None, # noqa + marks: Union[MarkDecorator, Iterable[MarkDecorator]] = () ): """ Creates a reference to a value getter, to be used in `parametrize`. diff --git a/src/pytest_cases/common_pytest_marks.py b/src/pytest_cases/common_pytest_marks.py index 74ce1b5b..721cb558 100644 --- a/src/pytest_cases/common_pytest_marks.py +++ b/src/pytest_cases/common_pytest_marks.py @@ -3,7 +3,7 @@ # # License: 3-clause BSD, import itertools - +from typing import Iterable, Optional, Union, Sequence import warnings from packaging.version import Version @@ -12,11 +12,6 @@ except ImportError: from funcsigs import signature # noqa -try: - from typing import Iterable, Optional, Tuple, List, Set, Union, Sequence # noqa -except ImportError: - pass - import pytest try: @@ -120,10 +115,9 @@ def copy_pytest_marks(from_f, to_f, override=False): to_f.pytestmark = to_marks + from_marks -def filter_marks(marks, # type: Iterable[Mark] - remove # type: str - ): - # type: (...) -> Tuple[Mark] +def filter_marks(marks: Iterable[Mark], + remove: str + ) -> tuple[Mark]: """ Returns a tuple of all marks in `marks` that do not have a 'parametrize' name. @@ -135,9 +129,8 @@ def filter_marks(marks, # type: Iterable[Mark] def get_pytest_marks_on_function(f, - as_decorators=False # type: bool - ): - # type: (...) -> Union[List[Mark], List[MarkDecorator]] + as_decorators: bool = False + ) -> Union[list[Mark], list[MarkDecorator]]: """ Utility to return a list of *ALL* pytest marks (not only parametrization) applied on a function Note that this also works on classes @@ -204,7 +197,7 @@ def remove_pytest_mark(f, mark_name): def get_pytest_parametrize_marks( f, - pop=False # type: bool + pop: bool = False ): """ Returns the @pytest.mark.parametrize marks associated with a function (and only those) @@ -283,10 +276,9 @@ def make_marked_parameter_value(argvalues_tuple, marks): return pytest.param(*argvalues_tuple, marks=marks_mod) -def markinfos_to_markdecorators(marks, # type: Iterable[Mark] - function_marks=False # type: bool - ): - # type: (...) -> List[MarkDecorator] +def markinfos_to_markdecorators(marks: Iterable[Mark], + function_marks: bool = False + ) -> list[MarkDecorator]: """ Transforms the provided marks (MarkInfo or Mark in recent pytest) obtained from marked cases, into MarkDecorator so that they can be re-applied to generated pytest parameters in the global @pytest.mark.parametrize. @@ -329,9 +321,8 @@ def markinfos_to_markdecorators(marks, # type: Iterable[Mark] return marks_mod -def markdecorators_as_tuple(marks # type: Optional[Union[MarkDecorator, Iterable[MarkDecorator]]] - ): - # type: (...) -> Tuple[MarkDecorator, ...] +def markdecorators_as_tuple(marks: Optional[Union[MarkDecorator, Iterable[MarkDecorator]]] + ) -> tuple[MarkDecorator, ...]: """ Internal routine used to normalize marks received from users in a `marks=` parameter @@ -349,9 +340,8 @@ def markdecorators_as_tuple(marks # type: Optional[Union[MarkDecorator, Iterabl return (marks,) -def markdecorators_to_markinfos(marks # type: Sequence[MarkDecorator] - ): - # type: (...) -> Tuple[Mark, ...] +def markdecorators_to_markinfos(marks: Sequence[MarkDecorator] + ) -> tuple[Mark, ...]: if PYTEST3_OR_GREATER: return tuple(m.mark for m in marks) elif len(marks) == 0: diff --git a/src/pytest_cases/filters.py b/src/pytest_cases/filters.py index 7131c9b1..a8c03443 100644 --- a/src/pytest_cases/filters.py +++ b/src/pytest_cases/filters.py @@ -44,8 +44,7 @@ def __invert__(self): ) -def has_tags(*tag_names # type: str - ): +def has_tags(*tag_names: str): """ Selects cases that have all tags in `tag_names`. See `@case(tags=...)` to add tags to a case. @@ -61,8 +60,7 @@ def _filter(case): return CaseFilter(_filter) -def has_tag(tag_name # type: str - ): +def has_tag(tag_name: str): """ Selects cases that have the tag `tag_name`. See `@case(tags=...)` to add tags to a case. @@ -76,8 +74,7 @@ def _filter(case): return CaseFilter(_filter) -def id_has_prefix(prefix # type: str - ): +def id_has_prefix(prefix: str): """ Selects cases that have a case id prefix `prefix`. @@ -91,8 +88,7 @@ def _filter(case): return CaseFilter(_filter) -def id_has_suffix(suffix # type: str - ): +def id_has_suffix(suffix: str): """ Selects cases that have a case id suffix `suffix`. @@ -106,8 +102,7 @@ def _filter(case): return CaseFilter(_filter) -def id_match_regex(regex # type: str - ): +def id_match_regex(regex: str): """ Select cases that have a case id matching `regex`. diff --git a/src/pytest_cases/fixture__creation.py b/src/pytest_cases/fixture__creation.py index 48812349..21e5a58f 100644 --- a/src/pytest_cases/fixture__creation.py +++ b/src/pytest_cases/fixture__creation.py @@ -5,15 +5,10 @@ from __future__ import division from inspect import getmodule, currentframe +from typing import Callable, Any, Iterable # noqa +from types import ModuleType # noqa from warnings import warn -try: - # type hints, python 3+ - from typing import Callable, Any, Union, Iterable # noqa - from types import ModuleType # noqa -except ImportError: - pass - from .common_others import make_identifier @@ -37,11 +32,11 @@ def __str__(self): def check_name_available(module, - name, # type: str - if_name_exists=RAISE, # type: int - name_changer=None, # type: Callable - caller=None, # type: Callable[[Any], Any] - extra_forbidden_names=() # type: Iterable[str] + name: str, + if_name_exists: int = RAISE, + name_changer: Callable = None, + caller: Callable[[Any], Any] = None, + extra_forbidden_names: Iterable[str] = () ): """ Routine to check that a name is not already in dir(module) + extra_forbidden_names. @@ -99,8 +94,7 @@ def name_changer(name, i): return name -def get_caller_module(frame_offset=1): - # type: (...) -> ModuleType +def get_caller_module(frame_offset: int = 1) -> ModuleType: """ Return the module where the last frame belongs. :param frame_offset: an alternate offset to look further up in the call stack @@ -111,7 +105,7 @@ def get_caller_module(frame_offset=1): return getmodule(frame) -def _get_callerframe(offset=0): +def _get_callerframe(offset: int = 0): """ Return a frame in the call stack :param offset: an alternate offset to look further up in the call stack diff --git a/src/pytest_cases/fixture_core1_unions.py b/src/pytest_cases/fixture_core1_unions.py index af5582bd..b7d92f67 100644 --- a/src/pytest_cases/fixture_core1_unions.py +++ b/src/pytest_cases/fixture_core1_unions.py @@ -5,6 +5,8 @@ from __future__ import division from inspect import isgeneratorfunction +from typing import Callable, Union, Optional, Iterable, Sequence # noqa +from types import ModuleType # noqa from warnings import warn from makefun import with_signature, add_signature_parameters, wraps @@ -30,12 +32,6 @@ def isasyncgenfunction(obj): return False -try: # type hints, python 3+ - from typing import Callable, Union, Optional, Any, List, Iterable, Sequence # noqa - from types import ModuleType # noqa -except ImportError: - pass - from .common_mini_six import string_types from .common_pytest import get_fixture_name, is_marked_parameter_value, get_marked_parameter_values, pytest_fixture, \ extract_parameterset_info, get_param_argnames_as_list, get_fixture_scope, resolve_ids @@ -66,29 +62,28 @@ class UnionIdMakers(object): """ @classmethod def nostyle(cls, - param # type: UnionFixtureAlternative + param: 'UnionFixtureAlternative' ): """ ids are """ return param.get_alternative_id() @classmethod def compact(cls, - param # type: UnionFixtureAlternative + param: 'UnionFixtureAlternative' ): """ ids are / """ return "/%s" % (param.get_alternative_id(),) @classmethod def explicit(cls, - param # type: UnionFixtureAlternative + param: 'UnionFixtureAlternative' ): """ ids are / """ return "%s/%s" % (param.get_union_id(), param.get_alternative_id()) @classmethod - def get(cls, style # type: Union[str, Callable] - ): - # type: (...) -> Callable[[UnionFixtureAlternative], str] + def get(cls, style: Union[str, Callable] + ) -> Callable[['UnionFixtureAlternative'], str]: """ Returns a function that one can use as the `ids` argument in parametrize, applying the given id style. See https://github.com/smarie/python-pytest-cases/issues/41 @@ -113,9 +108,9 @@ class UnionFixtureAlternative(object): __slots__ = 'union_name', 'alternative_name', 'alternative_index' def __init__(self, - union_name, # type: str - alternative_name, # type: str - alternative_index # type: int + union_name: str, + alternative_name: str, + alternative_index: int ): """ @@ -149,8 +144,7 @@ def __repr__(self): % (self.__class__.__name__, self.union_name, self.alternative_index, self.alternative_name) @staticmethod - def to_list_of_fixture_names(alternatives_lst # type: List[UnionFixtureAlternative] - ): + def to_list_of_fixture_names(alternatives_lst: list['UnionFixtureAlternative']): res = [] for f in alternatives_lst: if is_marked_parameter_value(f): @@ -271,14 +265,14 @@ def wrapped_fixture_func(*args, **kwargs): return wrapped_fixture_func -def fixture_union(name, # type: str - fixtures, # type: Iterable[Union[str, Callable]] - scope="function", # type: str - idstyle='compact', # type: Optional[Union[str, Callable]] - ids=None, # type: Union[Callable, Iterable[str]] - unpack_into=None, # type: Iterable[str] - autouse=False, # type: bool - hook=None, # type: Callable[[Callable], Callable] +def fixture_union(name: str, + fixtures: Iterable[Union[str, Callable]], + scope: str = "function", + idstyle: Optional[Union[str, Callable]] = 'compact', + ids: Union[Callable, Iterable[str]] = None, + unpack_into: Iterable[str] = None, + autouse: bool = False, + hook: Callable[[Callable], Callable] = None, **kwargs): """ Creates a fixture that will take all values of the provided fixtures in order. That fixture is automatically @@ -362,15 +356,15 @@ def fixture_union(name, # type: str def _fixture_union(fixtures_dest, - name, # type: str - fix_alternatives, # type: Sequence[UnionFixtureAlternative] - unique_fix_alt_names, # type: List[str] - scope="function", # type: str - idstyle="compact", # type: Optional[Union[str, Callable]] - ids=None, # type: Union[Callable, Iterable[str]] - autouse=False, # type: bool - hook=None, # type: Callable[[Callable], Callable] - caller=fixture_union, # type: Callable + name: str, + fix_alternatives: Sequence[UnionFixtureAlternative], + unique_fix_alt_names: list[str], + scope: str = "function", + idstyle: Optional[Union[str, Callable]] = "compact", + ids: Union[Callable, Iterable[str]] = None, + autouse: bool = False, + hook: Callable[[Callable], Callable] = None, + caller: Callable = fixture_union, **kwargs): """ Internal implementation for fixture_union. @@ -435,10 +429,10 @@ def _new_fixture(request, **all_fixtures): """A readable alias for callers not using the returned symbol""" -def unpack_fixture(argnames, # type: str - fixture, # type: Union[str, Callable] - in_cls=False, # type: bool - hook=None # type: Callable[[Callable], Callable] +def unpack_fixture(argnames: str, + fixture: Union[str, Callable], + in_cls: bool = False, + hook: Callable[[Callable], Callable] = None ): """ Creates several fixtures with names `argnames` from the source `fixture`. Created fixtures will correspond to @@ -505,11 +499,11 @@ def test_function(self, a, b): return _unpack_fixture(caller_module, argnames, fixture, hook=hook, in_cls=in_cls) -def _unpack_fixture(fixtures_dest, # type: ModuleType - argnames, # type: Union[str, Iterable[str]] - fixture, # type: Union[str, Callable] - in_cls, # type: bool - hook # type: Callable[[Callable], Callable] +def _unpack_fixture(fixtures_dest: ModuleType, + argnames: Union[str, Iterable[str]], + fixture: Union[str, Callable], + in_cls: bool, + hook: Callable[[Callable], Callable] ): """ diff --git a/src/pytest_cases/fixture_core2.py b/src/pytest_cases/fixture_core2.py index b41ba472..282be3ef 100644 --- a/src/pytest_cases/fixture_core2.py +++ b/src/pytest_cases/fixture_core2.py @@ -6,6 +6,7 @@ from inspect import isgeneratorfunction from itertools import product +from typing import Callable, Union, Any, Iterable, Sequence # noqa from warnings import warn from decopatch import function_decorator, DECORATED @@ -31,12 +32,6 @@ def iscoroutinefunction(obj): def isasyncgenfunction(obj): return False -try: # type hints, python 3+ - from typing import Callable, Union, Any, List, Iterable, Sequence # noqa - from types import ModuleType # noqa -except ImportError: - pass - from .common_pytest_lazy_values import get_lazy_args from .common_pytest import get_pytest_parametrize_marks, make_marked_parameter_value, get_param_argnames_as_list, \ combine_ids, is_marked_parameter_value, pytest_fixture, resolve_ids, extract_parameterset_info, make_test_ids @@ -45,13 +40,13 @@ def isasyncgenfunction(obj): from .fixture_core1_unions import ignore_unused, is_used_request, NOT_USED, _make_unpack_fixture -def param_fixture(argname, # type: str - argvalues, # type: Iterable[Any] - autouse=False, # type: bool - ids=None, # type: Union[Callable, Iterable[str]] - scope="function", # type: str - hook=None, # type: Callable[[Callable], Callable] - debug=False, # type: bool +def param_fixture(argname: str, + argvalues: Iterable[Any], + autouse: bool = False, + ids: Union[Callable, Iterable[str]] = None, + scope: str = "function", + hook: Callable[[Callable], Callable] = None, + debug: bool = False, **kwargs): """ Identical to `param_fixtures` but for a single parameter name, so that you can assign its output to a single @@ -99,14 +94,14 @@ def test_uses_param(my_parameter, fixture_uses_param): def _create_param_fixture(fixtures_dest, - argname, # type: str - argvalues, # type: Sequence[Any] - autouse=False, # type: bool - ids=None, # type: Union[Callable, Iterable[str]] - scope="function", # type: str - hook=None, # type: Callable[[Callable], Callable] - auto_simplify=False, - debug=False, + argname: str, + argvalues: Sequence[Any], + autouse: bool = False, + ids: Union[Callable, Iterable[str]] = None, + scope: str = "function", + hook: Callable[[Callable], Callable] = None, + auto_simplify: bool = False, + debug: bool = False, **kwargs): """ Internal method shared with param_fixture and param_fixtures """ @@ -147,13 +142,13 @@ def __param_fixture(request): return fix -def param_fixtures(argnames, # type: str - argvalues, # type: Iterable[Any] - autouse=False, # type: bool - ids=None, # type: Union[Callable, Iterable[str]] - scope="function", # type: str - hook=None, # type: Callable[[Callable], Callable] - debug=False, # type: bool +def param_fixtures(argnames: str, + argvalues: Iterable[Any], + autouse: bool = False, + ids: Union[Callable, Iterable[str]] = None, + scope: str = "function", + hook: Callable[[Callable], Callable] = None, + debug: bool = False, **kwargs): """ Creates one or several "parameters" fixtures - depending on the number or coma-separated names in `argnames`. The @@ -205,13 +200,13 @@ def test_uses_param2(arg1, arg2, fixture_uses_param2): def _create_params_fixture(fixtures_dest, - argnames_lst, # type: Sequence[str] - argvalues, # type: Sequence[Any] - autouse=False, # type: bool - ids=None, # type: Union[Callable, Iterable[str]] - scope="function", # type: str - hook=None, # type: Callable[[Callable], Callable] - debug=False, # type: bool + argnames_lst: Sequence[str], + argvalues: Sequence[Any], + autouse: bool = False, + ids: Union[Callable, Iterable[str]] = None, + scope: str = "function", + hook: Callable[[Callable], Callable] = None, + debug: bool = False, **kwargs): argnames = ','.join(argnames_lst) created_fixtures = [] @@ -292,11 +287,11 @@ def _fixture_plus(f): @function_decorator -def fixture(scope="function", # type: str - autouse=False, # type: bool - name=None, # type: str - unpack_into=None, # type: Iterable[str] - hook=None, # type: Callable[[Callable], Callable] +def fixture(scope: str = "function", + autouse: bool = False, + name: str = None, + unpack_into: Iterable[str] = None, + hook: Callable[[Callable], Callable] = None, fixture_func=DECORATED, # noqa **kwargs): """ decorator to mark a fixture factory function. @@ -353,7 +348,7 @@ class CombinedFixtureParamValue(object): __slots__ = 'param_defs', 'argvalues', def __init__(self, - param_defs, # type: Iterable[FixtureParam] + param_defs: Iterable[FixtureParam], argvalues): self.param_defs = param_defs self.argvalues = argvalues @@ -367,12 +362,12 @@ def __repr__(self): def _decorate_fixture_plus(fixture_func, - scope="function", # type: str - autouse=False, # type: bool - name=None, # type: str - unpack_into=None, # type: Iterable[str] - hook=None, # type: Callable[[Callable], Callable] - _caller_module_offset_when_unpack=3, # type: int + scope: str = "function", + autouse: bool = False, + name: str = None, + unpack_into: Iterable[str] = None, + hook: Callable[[Callable], Callable] = None, + _caller_module_offset_when_unpack: int = 3, **kwargs): """ decorator to mark a fixture factory function. diff --git a/src/pytest_cases/fixture_parametrize_plus.py b/src/pytest_cases/fixture_parametrize_plus.py index 13a73431..a1987d21 100644 --- a/src/pytest_cases/fixture_parametrize_plus.py +++ b/src/pytest_cases/fixture_parametrize_plus.py @@ -3,6 +3,8 @@ # # License: 3-clause BSD, from inspect import isgeneratorfunction +from typing import Union, Callable, Any, Sequence, Optional, Type, TypeVar +from types import ModuleType from warnings import warn @@ -28,13 +30,7 @@ def isasyncgenfunction(obj): except ImportError: # noqa from collections import Iterable -try: - from typing import Union, Callable, List, Any, Sequence, Optional, Type, Tuple, TypeVar # noqa - from types import ModuleType # noqa - - T = TypeVar('T', bound=Union[Type, Callable]) -except ImportError: - pass +T = TypeVar('T', bound=Union[Type, Callable]) import pytest import sys @@ -56,14 +52,14 @@ def isasyncgenfunction(obj): def _fixture_product(fixtures_dest, - name, # type: str + name: str, fixtures_or_values, fixture_positions, - scope="function", # type: str - unpack_into=None, # type: Iterable[str] - autouse=False, # type: bool - hook=None, # type: Callable[[Callable], Callable] - caller=None, # type: Callable + scope: str = "function", + unpack_into: Iterable[str] = None, + autouse: bool = False, + hook: Callable[[Callable], Callable] = None, + caller: Callable = None, **kwargs): """ Internal implementation for fixture products created by pytest parametrize plus. @@ -151,8 +147,8 @@ class fixture_ref(object): # noqa __slots__ = 'fixture', 'theoretical_size', '_id' def __init__(self, - fixture, # type: Union[str, Callable] - id=None, # type: str # noqa + fixture: Union[str, Callable], + id: str = None, # noqa ): """ @@ -206,8 +202,8 @@ class FixtureRefItem(object): __slots__ = 'host', 'item' def __init__(self, - host, # type: fixture_ref - item # type: int + host: fixture_ref, + item: int ): self.host = host self.item = item @@ -243,11 +239,11 @@ class ParamAlternative(UnionFixtureAlternative): __slots__ = ('argnames', 'decorated') def __init__(self, - union_name, # type: str - alternative_name, # type: str - param_index, # type: int - argnames, # type: Sequence[str] - decorated # type: Callable + union_name: str, + alternative_name: str, + param_index: int, + argnames: Sequence[str], + decorated: Callable ): """ @@ -278,13 +274,13 @@ class SingleParamAlternative(ParamAlternative): __slots__ = 'argval', 'id' def __init__(self, - union_name, # type: str - alternative_name, # type: str - param_index, # type: int - argnames, # type: Sequence[str] - argval, # type: Any - id, # type: Optional[str] - decorated # type: Callable + union_name: str, + alternative_name: str, + param_index: int, + argnames: Sequence[str], + argval: Any, + id: Optional[str], + decorated: Callable ): """ :param union_name: the name of the union fixture created by @parametrize to switch between param alternatives @@ -309,18 +305,17 @@ def get_alternative_id(self): @classmethod def create(cls, - new_fixture_host, # type: Union[Type, ModuleType] - test_func, # type: Callable - param_union_name, # type: str - argnames, # type: Sequence[str] - i, # type: int - argvalue, # type: Any - id, # type: Union[str, Callable] - scope=None, # type: str - hook=None, # type: Callable - debug=False # type: bool - ): - # type: (...) -> SingleParamAlternative + new_fixture_host: Union[Type, ModuleType], + test_func: Callable, + param_union_name: str, + argnames: Sequence[str], + i: int, + argvalue: Any, + id: Union[str, Callable], + scope: str = None, + hook: Callable = None, + debug: bool = False + ) -> 'SingleParamAlternative': """ Creates an alternative for fixture union `param_union_name`, to handle single parameter value argvalue = argvalues[i] in @parametrize. @@ -383,12 +378,12 @@ class MultiParamAlternative(ParamAlternative): __slots__ = 'param_index_from', 'param_index_to' def __init__(self, - union_name, # type: str - alternative_name, # type: str - argnames, # type: Sequence[str] - param_index_from, # type: int - param_index_to, # type: int - decorated # type: Callable + union_name: str, + alternative_name: str, + argnames: Sequence[str], + param_index_from: int, + param_index_to: int, + decorated: Callable ): """ @@ -419,19 +414,18 @@ def get_alternative_id(self): @classmethod def create(cls, - new_fixture_host, # type: Union[Type, ModuleType] - test_func, # type: Callable - param_union_name, # type: str - argnames, # type: Sequence[str] - from_i, # type: int - to_i, # type: int - argvalues, # type: Any - ids, # type: Union[Sequence[str], Callable] - scope="function", # type: str - hook=None, # type: Callable - debug=False # type: bool - ): - # type: (...) -> MultiParamAlternative + new_fixture_host: Union[Type, ModuleType], + test_func: Callable, + param_union_name: str, + argnames: Sequence[str], + from_i: int, + to_i: int, + argvalues: Any, + ids: Union[Sequence[str], Callable], + scope: str = "function", + hook: Callable = None, + debug: bool = False + ) -> 'MultiParamAlternative': """ Creates an alternative for fixture union `param_union_name`, to handle a group of consecutive parameters argvalues[from_i:to_i] in @parametrize. Note that here the received `argvalues` should be already sliced @@ -509,12 +503,12 @@ class FixtureParamAlternative(SingleParamAlternative): """alternative class for a single parameter containing a fixture ref""" def __init__(self, - union_name, # type: str - fixture_ref, # type: fixture_ref - argnames, # type: Sequence[str] - param_index, # type: int - id, # type: Optional[str] - decorated # type: Callable + union_name: str, + fixture_ref: fixture_ref, + argnames: Sequence[str], + param_index: int, + id: Optional[str], + decorated: Callable ): """ :param union_name: the name of the union fixture created by @parametrize to switch between param alternatives @@ -609,7 +603,7 @@ class ParamIdMakers(UnionIdMakers): """ @classmethod def nostyle(cls, - param # type: ParamAlternative + param: ParamAlternative ): if isinstance(param, MultiParamAlternative): # make an empty minimal id since the parameter themselves will appear as ids separately @@ -620,7 +614,7 @@ def nostyle(cls, # @classmethod # def explicit(cls, - # param # type: ParamAlternative + # param: ParamAlternative # ): # """Same than parent but display the argnames as prefix instead of the fixture union name generated by # @parametrize, because the latter is too complex (for unicity reasons)""" @@ -630,18 +624,17 @@ def nostyle(cls, _IDGEN = object() -def parametrize(argnames=None, # type: Union[str, Tuple[str], List[str]] - argvalues=None, # type: Iterable[Any] - indirect=False, # type: bool - ids=None, # type: Union[Callable, Iterable[str]] - idstyle=None, # type: Union[str, Callable] - idgen=_IDGEN, # type: Union[str, Callable] - auto_refs=True, # type: bool - scope=None, # type: str - hook=None, # type: Callable[[Callable], Callable] - debug=False, # type: bool - **args): - # type: (...) -> Callable[[T], T] +def parametrize(argnames: Union[str, tuple[str, ...], list[str]] = None, + argvalues: Iterable[Any] = None, + indirect: bool = False, + ids: Union[Callable, Iterable[str]] = None, + idstyle: Union[str, Callable] = None, + idgen: Union[str, Callable] = _IDGEN, + auto_refs: bool = True, + scope: str = None, + hook: Callable[[Callable], Callable] = None, + debug: bool = False, + **args) -> Callable[[T], T]: """ Equivalent to `@pytest.mark.parametrize` but also supports @@ -740,18 +733,17 @@ def __repr__(self): % (self.idgen, self.params, self.caught.__class__, self.caught) -def _parametrize_plus(argnames=None, # type: Union[str, Tuple[str], List[str]] - argvalues=None, # type: Iterable[Any] - indirect=False, # type: bool - ids=None, # type: Union[Callable, Iterable[str]] - idstyle=None, # type: Optional[Union[str, Callable]] - idgen=_IDGEN, # type: Union[str, Callable] - auto_refs=True, # type: bool - scope=None, # type: str - hook=None, # type: Callable[[Callable], Callable] - debug=False, # type: bool - **args): - # type: (...) -> Tuple[Callable[[T], T], bool] +def _parametrize_plus(argnames: Union[str, tuple[str, ...], list[str]] = None, + argvalues: Iterable[Any] = None, + indirect: bool = False, + ids: Union[Callable, Iterable[str]] = None, + idstyle: Optional[Union[str, Callable]] = None, + idgen: Union[str, Callable] = _IDGEN, + auto_refs: bool = True, + scope: str = None, + hook: Callable[[Callable], Callable] = None, + debug: bool = False, + **args) -> tuple[Callable[[T], T], bool]: """ :return: a tuple (decorator, needs_inject) where needs_inject is True if decorator has signature (f, host) @@ -808,8 +800,7 @@ def _make_ids(**args): return _decorator, False else: # wrap the decorator to check if the test function has the parameters as arguments - def _apply(test_func): - # type: (...) -> Callable[[T], T] + def _apply(test_func) -> Callable[[T], T]: if not safe_isclass(test_func): # a Function: raise a proper error message if improper use s = signature(test_func) @@ -944,8 +935,7 @@ def _create_fixture_ref_product(fh, union_name, i, fixture_ref_positions, test_f return p_fix_alt # Then create the decorator per se - def parametrize_plus_decorate(test_func, fixtures_dest): - # type: (...) -> Callable[[T], T] + def parametrize_plus_decorate(test_func, fixtures_dest) -> Callable[[T], T]: """ A decorator that wraps the test function so that instead of receiving the parameter names, it receives the new fixture. All other decorations are unchanged. @@ -1134,8 +1124,8 @@ def wrapped_test_func(*args, **kwargs): # noqa def _get_argnames_argvalues( - argnames=None, # type: Union[str, Tuple[str], List[str]] - argvalues=None, # type: Iterable[Any] + argnames: Union[str, tuple[str, ...], list[str]] = None, + argvalues: Iterable[Any] = None, **args ): """ diff --git a/src/pytest_cases/plugin.py b/src/pytest_cases/plugin.py index 907ebb1d..02389f3a 100644 --- a/src/pytest_cases/plugin.py +++ b/src/pytest_cases/plugin.py @@ -5,6 +5,7 @@ from collections import OrderedDict, namedtuple from copy import copy from functools import partial +from typing import Union, Iterable, MutableMapping, Mapping, Optional from warnings import warn try: @@ -13,19 +14,16 @@ from collections import MutableSequence import pytest +from _pytest.python import CallSpec2 +from _pytest.config import Config +from _pytest.fixtures import FixtureDef + try: # python 3.3+ from inspect import signature except ImportError: from funcsigs import signature # noqa -try: # python 3.3+ type hints - from typing import List, Tuple, Union, Iterable, MutableMapping, Mapping, Optional # noqa - from _pytest.python import CallSpec2 - from _pytest.config import Config -except ImportError: - pass - from .common_mini_six import string_types from .common_pytest_lazy_values import get_lazy_args from .common_pytest_marks import PYTEST35_OR_GREATER, PYTEST46_OR_GREATER, PYTEST37_OR_GREATER, PYTEST7_OR_GREATER, PYTEST8_OR_GREATER @@ -125,8 +123,8 @@ class FixtureClosureNode(object): 'fixture_defs', 'split_fixture_name', 'split_fixture_alternatives', 'children' def __init__(self, - fixture_defs_mgr=None, # type: FixtureDefsCache - parent_node=None # type: FixtureClosureNode + fixture_defs_mgr: FixtureDefsCache = None, + parent_node: 'FixtureClosureNode' = None ): if fixture_defs_mgr is None: if parent_node is None: @@ -139,11 +137,11 @@ def __init__(self, self.parent = parent_node # these will be set after closure has been built - self.fixture_defs = None # type: OrderedDict - self.split_fixture_name = None # type: str + self.fixture_defs: OrderedDict = None + self.split_fixture_name: str = None self.split_fixture_alternatives = [] # we do not use a dict any more as several children can use the same union value (doubled unions) - self.children = [] # type: List[FixtureClosureNode] + self.children: list[FixtureClosureNode] = [] # ------ tree ------------------ @@ -234,7 +232,7 @@ def gen_all_fixture_defs(self, drop_fake_fixtures=True): # ---- utils to build the closure def build_closure(self, - initial_fixture_names, # type: Iterable[str] + initial_fixture_names: Iterable[str], ignore_args=() ): """ @@ -265,8 +263,8 @@ def already_knows_fixture(self, fixture_name): return self.parent.already_knows_fixture(fixture_name) def _build_closure(self, - fixture_defs_mgr, # type: FixtureDefsCache - initial_fixture_names, # type: Iterable[str] + fixture_defs_mgr: FixtureDefsCache, + initial_fixture_names: Iterable[str], ignore_args ): """ @@ -414,11 +412,11 @@ def add_required_fixture(self, new_fixture_name, new_fixture_defs): c.add_required_fixture(new_fixture_name, new_fixture_defs) def split_and_build(self, - fixture_defs_mgr, # type: FixtureDefsCache - split_fixture_name, # type: str - split_fixture_defs, # type: Tuple[FixtureDefinition] # noqa - alternative_fixture_names, # type: List[str] - pending_fixtures_list, # + fixture_defs_mgr: FixtureDefsCache, + split_fixture_name: str, + split_fixture_defs: tuple[FixtureDef], + alternative_fixture_names: list[str], + pending_fixtures_list, ignore_args ): """ Declares that this node contains a union with alternatives (child nodes=subtrees) """ @@ -560,7 +558,7 @@ class SuperClosure(MutableSequence): __slots__ = 'tree', 'all_fixture_defs' def __init__(self, - root_node # type: FixtureClosureNode + root_node: FixtureClosureNode ): # if we wish to drop the tree - but we do not anymore to get a better paramz order # filters_list, partitions_list = root_node._get_alternatives() @@ -802,8 +800,7 @@ def create_super_closure(fm, parentnode, fixturenames, ignore_args - ): - # type: (...) -> Tuple[List, Union[List, SuperClosure], Mapping] + ) -> tuple[list, Union[list, SuperClosure], Mapping]: """ :param fm: @@ -974,13 +971,13 @@ class CallsReactor(object): def __init__(self, metafunc): self.metafunc = metafunc - self._pending = [] # type: List[Union[UnionParamz, NormalParamz]] + self._pending: list[Union[UnionParamz, NormalParamz]] = [] self._call_list = None # -- methods to provising parametrization orders without executing them -- def append(self, - parametrization # type: Union[UnionParamz, NormalParamz] + parametrization: Union[UnionParamz, NormalParamz] ): self._pending.append(parametrization) @@ -1068,8 +1065,8 @@ def create_call_list_from_pending_parametrizations(self): def get_calls_for_tree(metafunc, - fix_closure_tree, # type: FixtureClosureNode - pending_dct # type: MutableMapping[str, Union[UnionParamz, NormalParamz]] + fix_closure_tree: FixtureClosureNode, + pending_dct: MutableMapping[str, Union[UnionParamz, NormalParamz]] ): """ Creates the list of calls for `metafunc` based on @@ -1086,10 +1083,10 @@ def get_calls_for_tree(metafunc, def _cleanup_calls_list(metafunc, - fix_closure_tree, # type: FixtureClosureNode - calls, # type: List[CallSpec2] - nodes, # type: List[FixtureClosureNode] - pending_dct # type: MutableMapping[str, Union[UnionParamz, NormalParamz]] + fix_closure_tree: FixtureClosureNode, + calls: list[CallSpec2], + nodes: list[FixtureClosureNode], + pending_dct: MutableMapping[str, Union[UnionParamz, NormalParamz]] ): """ Cleans the calls list so that all calls contain a value for all parameters. This is basically @@ -1325,9 +1322,9 @@ def _parametrize_calls(metafunc, init_calls, argnames, argvalues, discard_id=Fal def _process_node(metafunc, - current_node, # type: FixtureClosureNode - pending, # type: MutableMapping[str, Union[UnionParamz, NormalParamz]] - calls # type: List[CallSpec2] + current_node: FixtureClosureNode, + pending: MutableMapping[str, Union[UnionParamz, NormalParamz]], + calls: list[CallSpec2] ): """ Routine to apply all the parametrization tasks in `pending` that are relevant to `current_node`, @@ -1489,7 +1486,7 @@ def pytest_addoption(parser): # will be loaded when the pytest_configure hook below is called -PYTEST_CONFIG = None # type: Optional[Config] +PYTEST_CONFIG: Optional[Config] = None def pytest_load_initial_conftests(early_config): From 7d192790fd85805e1d518a46e45ee53800f3f074 Mon Sep 17 00:00:00 2001 From: Bryan Borg <71280324+jammer87@users.noreply.github.com> Date: Sun, 11 Jan 2026 02:02:01 -0600 Subject: [PATCH 2/4] Fixed some incorrect type hints for tuples --- src/pytest_cases/case_funcs.py | 4 ++-- src/pytest_cases/common_pytest_marks.py | 2 +- src/pytest_cases/plugin.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pytest_cases/case_funcs.py b/src/pytest_cases/case_funcs.py index 99b2224e..b0eb0409 100644 --- a/src/pytest_cases/case_funcs.py +++ b/src/pytest_cases/case_funcs.py @@ -42,11 +42,11 @@ class _CaseInfo(object): def __init__(self, id: str = None, marks: tuple[MarkDecorator, ...] = (), - tags: tuple[Any] = () + tags: tuple[Any, ...] = () ): self.id: str = id self.marks: tuple[MarkDecorator, ...] = marks - self.tags: tuple[Any] = () + self.tags: tuple[Any, ...] = () self.add_tags(tags) def __repr__(self): diff --git a/src/pytest_cases/common_pytest_marks.py b/src/pytest_cases/common_pytest_marks.py index 721cb558..460bd774 100644 --- a/src/pytest_cases/common_pytest_marks.py +++ b/src/pytest_cases/common_pytest_marks.py @@ -117,7 +117,7 @@ def copy_pytest_marks(from_f, to_f, override=False): def filter_marks(marks: Iterable[Mark], remove: str - ) -> tuple[Mark]: + ) -> tuple[Mark, ...]: """ Returns a tuple of all marks in `marks` that do not have a 'parametrize' name. diff --git a/src/pytest_cases/plugin.py b/src/pytest_cases/plugin.py index 02389f3a..d52d1a54 100644 --- a/src/pytest_cases/plugin.py +++ b/src/pytest_cases/plugin.py @@ -414,7 +414,7 @@ def add_required_fixture(self, new_fixture_name, new_fixture_defs): def split_and_build(self, fixture_defs_mgr: FixtureDefsCache, split_fixture_name: str, - split_fixture_defs: tuple[FixtureDef], + split_fixture_defs: tuple[FixtureDef, ...], alternative_fixture_names: list[str], pending_fixtures_list, ignore_args From 4fb637dc7c0d57e948db10480c683c489c6b9089 Mon Sep 17 00:00:00 2001 From: Bryan Borg <71280324+jammer87@users.noreply.github.com> Date: Sun, 11 Jan 2026 17:42:48 -0600 Subject: [PATCH 3/4] Flake8 fixes --- src/pytest_cases/case_funcs.py | 3 +-- src/pytest_cases/case_parametrizer_new.py | 3 ++- src/pytest_cases/common_others.py | 7 +++++-- src/pytest_cases/common_pytest.py | 2 +- src/pytest_cases/common_pytest_lazy_values.py | 4 ++-- src/pytest_cases/fixture_core1_unions.py | 2 +- src/pytest_cases/fixture_parametrize_plus.py | 4 ++-- src/pytest_cases/pep380.py | 2 ++ src/pytest_cases/pep492.py | 1 + src/pytest_cases/pep525.py | 2 ++ src/pytest_cases/plugin.py | 2 +- 11 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/pytest_cases/case_funcs.py b/src/pytest_cases/case_funcs.py index b0eb0409..9d42790a 100644 --- a/src/pytest_cases/case_funcs.py +++ b/src/pytest_cases/case_funcs.py @@ -345,7 +345,7 @@ def is_case_function(f: Any, else: try: return f.__name__.startswith(prefix) if check_prefix else True - except: + except: # noqa # GH#287: safe fallback return False @@ -379,4 +379,3 @@ def _decorator(cls): case_info.add_tags(tags_to_add) return cls return _decorator - diff --git a/src/pytest_cases/case_parametrizer_new.py b/src/pytest_cases/case_parametrizer_new.py index 3ab48943..0385de32 100644 --- a/src/pytest_cases/case_parametrizer_new.py +++ b/src/pytest_cases/case_parametrizer_new.py @@ -50,6 +50,7 @@ class ThisModule(enum.Enum): """Class to allow type hints for the THIS_MODULE Singleton""" THIS_MODULE = object() + THIS_MODULE = ThisModule.THIS_MODULE """Singleton that can be used instead of a module name to indicate that the module is the current one""" @@ -700,7 +701,7 @@ def hasinit(obj): if init: return init != object.__init__ - + def hasnew(obj): new = getattr(obj, "__new__", None) if new: diff --git a/src/pytest_cases/common_others.py b/src/pytest_cases/common_others.py index c735fcc5..0fe043b7 100644 --- a/src/pytest_cases/common_others.py +++ b/src/pytest_cases/common_others.py @@ -54,8 +54,9 @@ def get_code_first_line(f): ExpectedErrorValidator = Optional[Callable[[BaseException], Optional[bool]]] -def unfold_expected_err(expected_e: ExpectedError - ) -> tuple[ExpectedErrorType, ExpectedErrorPattern, ExpectedErrorInstance, ExpectedErrorValidator]: +def unfold_expected_err( + expected_e: ExpectedError + ) -> tuple[ExpectedErrorType, ExpectedErrorPattern, ExpectedErrorInstance, ExpectedErrorValidator]: """ 'Unfolds' the expected error `expected_e` to return a tuple of - expected error type @@ -205,10 +206,12 @@ def __exit__(self, exc_type, exc_val, exc_tb): # See https://docs.python.org/2/reference/datamodel.html#object.__exit__ return True + class Auto(enum.Enum): """Class to allow type hints for the AUTO Singleton""" AUTO = object() + AUTO = Auto.AUTO """Marker for automatic defaults""" diff --git a/src/pytest_cases/common_pytest.py b/src/pytest_cases/common_pytest.py index 2fe6083a..4e264999 100644 --- a/src/pytest_cases/common_pytest.py +++ b/src/pytest_cases/common_pytest.py @@ -363,7 +363,7 @@ def make_test_ids(global_ids, id_marks, argnames=None, argvalues=None, precomput def resolve_ids(ids: Optional[Union[Callable, Iterable[str]]], argvalues: Collection[Any], - full_resolve: bool = False + full_resolve: bool = False ) -> Union[list[str], Callable]: """ Resolves the `ids` argument of a parametrized fixture. diff --git a/src/pytest_cases/common_pytest_lazy_values.py b/src/pytest_cases/common_pytest_lazy_values.py index 5092e236..d393c90a 100644 --- a/src/pytest_cases/common_pytest_lazy_values.py +++ b/src/pytest_cases/common_pytest_lazy_values.py @@ -164,7 +164,7 @@ def __hash__(self): return hash((self.__class__, self.valuegetter, self._id, self._marks)) def get_marks(self, - as_decorators: bool = False + as_decorators: bool = False ) -> Union[tuple[Mark, ...], tuple[MarkDecorator, ...]]: """ Overrides default implementation to return the marks that are on the case function @@ -480,7 +480,7 @@ def clone(self, remove_int_base=False): def lazy_value(valuegetter: Callable[[], Any], id: str = None, # noqa - marks: Union[MarkDecorator, Iterable[MarkDecorator]] = () + marks: Union[MarkDecorator, Iterable[MarkDecorator]] = () ): """ Creates a reference to a value getter, to be used in `parametrize`. diff --git a/src/pytest_cases/fixture_core1_unions.py b/src/pytest_cases/fixture_core1_unions.py index b7d92f67..b215f7f3 100644 --- a/src/pytest_cases/fixture_core1_unions.py +++ b/src/pytest_cases/fixture_core1_unions.py @@ -432,7 +432,7 @@ def _new_fixture(request, **all_fixtures): def unpack_fixture(argnames: str, fixture: Union[str, Callable], in_cls: bool = False, - hook: Callable[[Callable], Callable] = None + hook: Callable[[Callable], Callable] = None ): """ Creates several fixtures with names `argnames` from the source `fixture`. Created fixtures will correspond to diff --git a/src/pytest_cases/fixture_parametrize_plus.py b/src/pytest_cases/fixture_parametrize_plus.py index a1987d21..237980c3 100644 --- a/src/pytest_cases/fixture_parametrize_plus.py +++ b/src/pytest_cases/fixture_parametrize_plus.py @@ -314,7 +314,7 @@ def create(cls, id: Union[str, Callable], scope: str = None, hook: Callable = None, - debug: bool = False + debug: bool = False ) -> 'SingleParamAlternative': """ Creates an alternative for fixture union `param_union_name`, to handle single parameter value @@ -424,7 +424,7 @@ def create(cls, ids: Union[Sequence[str], Callable], scope: str = "function", hook: Callable = None, - debug: bool = False + debug: bool = False ) -> 'MultiParamAlternative': """ Creates an alternative for fixture union `param_union_name`, to handle a group of consecutive parameters diff --git a/src/pytest_cases/pep380.py b/src/pytest_cases/pep380.py index fc9bee57..eae6957e 100644 --- a/src/pytest_cases/pep380.py +++ b/src/pytest_cases/pep380.py @@ -20,6 +20,7 @@ def wrapped_fixture_func(*args, **kwargs): return wrapped_fixture_func + def _decorate_fixture_plus_generator_pep380(fixture_func, new_sig, map_arguments): @wraps(fixture_func, new_sig=new_sig) def wrapped_fixture_func(*_args, **_kwargs): @@ -31,6 +32,7 @@ def wrapped_fixture_func(*_args, **_kwargs): return wrapped_fixture_func + def _parametrize_plus_decorate_generator_pep380( test_func, new_sig, diff --git a/src/pytest_cases/pep492.py b/src/pytest_cases/pep492.py index 6a79f854..f2d81196 100644 --- a/src/pytest_cases/pep492.py +++ b/src/pytest_cases/pep492.py @@ -20,6 +20,7 @@ async def wrapped_fixture_func(*args, **kwargs): return wrapped_fixture_func + def _decorate_fixture_plus_coroutine_pep492(fixture_func, new_sig, map_arguments): @wraps(fixture_func, new_sig=new_sig) async def wrapped_fixture_func(*_args, **_kwargs): diff --git a/src/pytest_cases/pep525.py b/src/pytest_cases/pep525.py index 17f002e8..75ac58bf 100644 --- a/src/pytest_cases/pep525.py +++ b/src/pytest_cases/pep525.py @@ -21,6 +21,7 @@ async def wrapped_fixture_func(*args, **kwargs): return wrapped_fixture_func + def _decorate_fixture_plus_asyncgen_pep525(fixture_func, new_sig, map_arguments): @wraps(fixture_func, new_sig=new_sig) async def wrapped_fixture_func(*_args, **_kwargs): @@ -33,6 +34,7 @@ async def wrapped_fixture_func(*_args, **_kwargs): return wrapped_fixture_func + def _parametrize_plus_decorate_asyncgen_pep525( test_func, new_sig, diff --git a/src/pytest_cases/plugin.py b/src/pytest_cases/plugin.py index d52d1a54..3d7f32e0 100644 --- a/src/pytest_cases/plugin.py +++ b/src/pytest_cases/plugin.py @@ -124,7 +124,7 @@ class FixtureClosureNode(object): def __init__(self, fixture_defs_mgr: FixtureDefsCache = None, - parent_node: 'FixtureClosureNode' = None + parent_node: 'FixtureClosureNode' = None ): if fixture_defs_mgr is None: if parent_node is None: From bb011afa83f6a53e8b61a9bcb894a235060fd888 Mon Sep 17 00:00:00 2001 From: Bryan Borg <71280324+jammer87@users.noreply.github.com> Date: Sun, 11 Jan 2026 17:46:59 -0600 Subject: [PATCH 4/4] another flake8 fix --- src/pytest_cases/common_others.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pytest_cases/common_others.py b/src/pytest_cases/common_others.py index 0fe043b7..19a23c77 100644 --- a/src/pytest_cases/common_others.py +++ b/src/pytest_cases/common_others.py @@ -55,8 +55,8 @@ def get_code_first_line(f): def unfold_expected_err( - expected_e: ExpectedError - ) -> tuple[ExpectedErrorType, ExpectedErrorPattern, ExpectedErrorInstance, ExpectedErrorValidator]: + expected_e: ExpectedError +) -> tuple[ExpectedErrorType, ExpectedErrorPattern, ExpectedErrorInstance, ExpectedErrorValidator]: """ 'Unfolds' the expected error `expected_e` to return a tuple of - expected error type