Skip to content

Commit

Permalink
Fixed most flake8 errors and updated documentation to use `genbadge…
Browse files Browse the repository at this point in the history
…`. Slightly improved coverage too. Fixes #223
  • Loading branch information
Sylvain MARIE committed Jun 29, 2021
1 parent 1ea6e85 commit f996f4a
Show file tree
Hide file tree
Showing 12 changed files with 95 additions and 62 deletions.
9 changes: 5 additions & 4 deletions pytest_cases/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@
from .common_pytest_lazy_values import lazy_value, is_lazy
from .common_others import unfold_expected_err, assert_exception, AUTO

AUTO2 = AUTO
"""Deprecated symbol, for retrocompatibility. Will be dropped soon."""

from .fixture_core1_unions import fixture_union, NOT_USED, unpack_fixture, ignore_unused
from .fixture_core2 import pytest_fixture_plus, fixture_plus, fixture, param_fixtures, param_fixture
from .fixture_parametrize_plus import pytest_parametrize_plus, parametrize_plus, parametrize, fixture_ref


from .case_funcs import case, copy_case_info, set_case_id, get_case_id, get_case_marks, \
get_case_tags, matches_tag_query, is_case_class, is_case_function
from .case_parametrizer_new import parametrize_with_cases, THIS_MODULE, get_all_cases, get_parametrize_args, \
Expand All @@ -29,6 +25,11 @@
from os import path as _path
__version__ = _gv(_path.join(_path.dirname(__file__), _path.pardir))


AUTO2 = AUTO
"""Deprecated symbol, for retrocompatibility. Will be dropped soon."""


__all__ = [
'__version__',
# the submodules
Expand Down
10 changes: 8 additions & 2 deletions pytest_cases/case_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from decopatch import function_decorator, DECORATED

try: # python 3.5+
from typing import Type, Callable, Union, Optional, Any, Tuple, Dict, Iterable, List, Set
from typing import Callable, Union, Optional, Any, Tuple, Iterable, List, Set
except ImportError:
pass

Expand Down Expand Up @@ -275,10 +275,16 @@ 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, Tuple[MarkDecorator, ...], List[MarkDecorator], Set[MarkDecorator]]
marks=(), # type: Union[MarkDecorator, SeveralMarkDecorators]
case_func=DECORATED # noqa
):
"""
Expand Down
19 changes: 10 additions & 9 deletions pytest_cases/case_parametrizer_new.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from .common_others import get_code_first_line, 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
get_param_argnames_as_list, Mark
from .common_pytest_lazy_values import LazyValue, LazyTuple, LazyTupleItem
from .common_pytest import safe_isclass, MiniMetafunc, is_fixture, get_fixture_name, inject_host, add_fixture_params, \
list_all_fixtures_in, get_pytest_request_and_item, safe_isinstance
Expand Down Expand Up @@ -269,8 +269,8 @@ def get_all_cases(parametrization_target, # type: Callable
for c in cases:
# load case or cases depending on type
if safe_isclass(c):
# class
new_cases = extract_cases_from_class(c, case_fun_prefix=prefix, check_name=False) # do not check name, it was explicitly passed
# class - do not check name, it was explicitly passed
new_cases = extract_cases_from_class(c, case_fun_prefix=prefix, check_name=False)
cases_funs += new_cases
elif callable(c):
# function
Expand Down Expand Up @@ -303,7 +303,7 @@ def get_parametrize_args(host_class_or_module, # type: Union[Type, ModuleType
import_fixtures=False, # type: bool
debug=False # type: bool
):
# type: (...) -> List[Union[lazy_value, fixture_ref]]
# type: (...) -> 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`:
Expand Down Expand Up @@ -387,7 +387,7 @@ def case_to_argvalues(host_class_or_module, # type: Union[Type, ModuleType]
import_fixtures=False, # type: bool
debug=False # type: bool
):
# type: (...) -> Tuple[lazy_value]
# type: (...) -> 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
Expand Down Expand Up @@ -464,7 +464,7 @@ def get_or_create_case_fixture(case_id, # type: str
import_fixtures=False, # type: bool
debug=False # type: bool
):
# type: (...) -> Tuple[str, Tuple[MarkInfo]]
# type: (...) -> 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
Expand Down Expand Up @@ -529,8 +529,8 @@ def get_or_create_case_fixture(case_id, # type: str
for f in list_all_fixtures_in(true_case_func_host, recurse_to_module=False, return_names=False):
f_name = get_fixture_name(f)
if (f_name in existing_fixture_names) or (f.__name__ in existing_fixture_names):
raise ValueError("Cannot import fixture %r from %r as it would override an existing symbol in "
"%r. Please set `@parametrize_with_cases(import_fixtures=False)`"
raise ValueError("Cannot import fixture %r from %r as it would override an existing symbol "
"in %r. Please set `@parametrize_with_cases(import_fixtures=False)`"
"" % (f, from_module, target_host))
target_host_module = target_host if not target_in_class else get_host_module(target_host)
setattr(target_host_module, f.__name__, f)
Expand Down Expand Up @@ -786,7 +786,8 @@ def _of_interest(x): # noqa
for m_name, m in getmembers(container, _of_interest):
if is_case_class(m):
co_firstlineno = get_code_first_line(m)
cls_cases = extract_cases_from_class(m, case_fun_prefix=case_fun_prefix, _case_param_factory=_case_param_factory)
cls_cases = extract_cases_from_class(m, case_fun_prefix=case_fun_prefix,
_case_param_factory=_case_param_factory)
for _i, _m_item in enumerate(cls_cases):
gen_line_nb = co_firstlineno + (_i / len(cls_cases))
cases_dct[gen_line_nb] = _m_item
Expand Down
30 changes: 15 additions & 15 deletions pytest_cases/common_mini_six.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
if PY3:
string_types = str,
else:
string_types = basestring,
string_types = basestring, # noqa


# if PY3:
Expand Down Expand Up @@ -49,17 +49,17 @@
# """)


def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
# This requires a bit of explanation: the basic idea is to make a dummy
# metaclass for one level of class instantiation that replaces itself with
# the actual metaclass.
class metaclass(type):

def __new__(cls, name, this_bases, d):
return meta(name, bases, d)

@classmethod
def __prepare__(cls, name, this_bases):
return meta.__prepare__(name, bases)
return type.__new__(metaclass, 'temporary_class', (), {})
# def with_metaclass(meta, *bases):
# """Create a base class with a metaclass."""
# # This requires a bit of explanation: the basic idea is to make a dummy
# # metaclass for one level of class instantiation that replaces itself with
# # the actual metaclass.
# class metaclass(type):
#
# def __new__(cls, name, this_bases, d):
# return meta(name, bases, d)
#
# @classmethod
# def __prepare__(cls, name, this_bases):
# return meta.__prepare__(name, bases)
# return type.__new__(metaclass, 'temporary_class', (), {})
12 changes: 9 additions & 3 deletions pytest_cases/common_others.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def get_code_first_line(f):
raise ValueError("Cannot get code information for function or class %r" % f)


# Below is the beginning of a switch from our code scanning tool above to the same one than pytest. See `case_parametrizer_new`
# Below is the beginning of a switch from our scanning code to the same one than pytest. See `case_parametrizer_new`
# from _pytest.compat import get_real_func as compat_get_real_func
#
# try:
Expand All @@ -49,13 +49,19 @@ def get_code_first_line(f):
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]]]

except: # noqa
pass


def unfold_expected_err(expected_e # type: ExpectedError
):
# type: (...) -> Tuple[Optional[Type[BaseException]], Optional[re.Pattern], Optional[BaseException], Optional[Callable[[BaseException], Optional[bool]]]]
# type: (...) -> Tuple[ExpectedErrorType, ExpectedErrorPattern, ExpectedErrorInstance, ExpectedErrorValidator]
"""
'Unfolds' the expected error `expected_e` to return a tuple of
- expected error type
Expand Down Expand Up @@ -132,7 +138,7 @@ class MyErr(ValueError):
raise TypeError()
# good repr pattern - ok
with assert_exception(r"ValueError\('hello'[,]+\)"):
with assert_exception(r"ValueError\\('hello'[,]+\\)"):
raise ValueError("hello")
# good instance equality check - ok
Expand Down
3 changes: 1 addition & 2 deletions pytest_cases/common_pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
except ImportError:
from funcsigs import signature, Parameter # noqa

from distutils.version import LooseVersion
from inspect import isgeneratorfunction, isclass

try:
from typing import Union, Callable, Any, Optional, Tuple, Type # noqa
from typing import Union, Callable, Any, Optional, Tuple, Type, Iterable, Sized, List # noqa
except ImportError:
pass

Expand Down
17 changes: 12 additions & 5 deletions pytest_cases/common_pytest_lazy_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def __eq__(self, other):
"""Default equality method based on the _field_names"""
try:
return all(getattr(self, k) == getattr(other, k) for k in self._field_names)
except:
except Exception: # noqa
return False

def __repr__(self):
Expand Down Expand Up @@ -85,7 +85,7 @@ def _unwrap(obj):
Note: maybe from inspect import unwrap could do the same?
"""
start_obj = obj
for i in range(100):
for _ in range(100):
# __pytest_wrapped__ is set by @pytest.fixture when wrapping the fixture function
# to trigger a warning if it gets called directly instead of by pytest: we don't
# want to unwrap further than this otherwise we lose useful wrappings like @mock.patch (#3774)
Expand Down Expand Up @@ -303,9 +303,16 @@ def __hash__(self):

def __repr__(self):
"""Override the inherited method to avoid infinite recursion"""

# lazy value tuple or cached tuple
if self.host.has_cached_value(raise_if_no_context=False):
tuple_to_represent = self.host.cached_value
else:
tuple_to_represent = self.host._lazyvalue # noqa

vals_to_display = (
('item', self.item), # item number first for easier debug
('tuple', self.host.cached_value if self.host.has_cached_value(raise_if_no_context=False) else self.host._lazyvalue), # lazy value tuple or cached tuple
('tuple', tuple_to_represent),
)
return "%s(%s)" % (self.__class__.__name__, ", ".join("%s=%r" % (k, v) for k, v in vals_to_display))

Expand Down Expand Up @@ -506,7 +513,7 @@ def is_lazy_value(argval):
try:
# note: we use the private and not public class here on purpose
return isinstance(argval, _LazyValue)
except:
except Exception: # noqa
return False


Expand All @@ -519,7 +526,7 @@ def is_lazy(argval):
try:
# note: we use the private and not public classes here on purpose
return isinstance(argval, (_LazyValue, LazyTuple, _LazyTupleItem))
except:
except Exception: # noqa
return False


Expand Down
4 changes: 4 additions & 0 deletions pytest_cases/filters.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Authors: Sylvain MARIE <sylvain.marie@se.com>
# + All contributors to <https://github.com/smarie/python-pytest-cases>
#
# License: 3-clause BSD, <https://github.com/smarie/python-pytest-cases/blob/master/LICENSE>
import re

from .case_funcs import get_case_id, get_case_tags
Expand Down
5 changes: 3 additions & 2 deletions pytest_cases/fixture_core2.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ def _root_fixture(**_kwargs):
def _create_fixture(_param_idx):

if debug:
print("Creating nonparametrized 'view' fixture %r returning %r[%s]" % (argname, root_fixture_name, _param_idx))
print("Creating nonparametrized 'view' fixture %r returning %r[%s]"
% (argname, root_fixture_name, _param_idx))

@fixture(name=argname, scope=scope, autouse=autouse, hook=hook, **kwargs)
@with_signature("%s(%s)" % (argname, root_fixture_name))
Expand Down Expand Up @@ -338,7 +339,7 @@ class CombinedFixtureParamValue(object):
__slots__ = 'param_defs', 'argvalues',

def __init__(self,
param_defs, # type: Iterable[FixtureParam]
param_defs, # type: Iterable[FixtureParam]
argvalues):
self.param_defs = param_defs
self.argvalues = argvalues
Expand Down
20 changes: 11 additions & 9 deletions pytest_cases/fixture_parametrize_plus.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
from collections.abc import Iterable
except ImportError: # noqa
from collections import Iterable

try:
from typing import Union, Callable, List, Any, Sequence, Optional # noqa

try:
from typing import Union, Callable, List, Any, Sequence, Optional, Type # noqa
from types import ModuleType # noqa
except ImportError:
pass

Expand Down Expand Up @@ -643,10 +643,11 @@ def parametrize(argnames=None, # type: str
(3) new possibilities in argvalues:
- one can include references to fixtures with `fixture_ref(<fixture>)` where <fixture> can be the fixture name or
fixture function. When such a fixture reference is detected in the argvalues, a new function-scope "union" fixture
will be created with a unique name, and the test function will be wrapped so as to be injected with the correct
parameters from this fixture. Special test ids will be created to illustrate the switching between the various
normal parameters and fixtures. You can see debug print messages about all fixtures created using `debug=True`
fixture function. When such a fixture reference is detected in the argvalues, a new function-scope "union"
fixture will be created with a unique name, and the test function will be wrapped so as to be injected with the
correct parameters from this fixture. Special test ids will be created to illustrate the switching between the
various normal parameters and fixtures. You can see debug print messages about all fixtures created using
`debug=True`
- one can include lazy argvalues with `lazy_value(<valuegetter>, [id=..., marks=...])`. A `lazy_value` is the same
thing than a function-scoped fixture, except that the value getter function is not a fixture and therefore can
Expand Down Expand Up @@ -762,7 +763,7 @@ def _make_ids(**args):
for n, v in args.items():
yield "%s=%s" % (n, mini_idval(val=v, argname='', idx=v))

idgen = lambda **args: "-".join(_make_ids(**args))
idgen = lambda **args: "-".join(_make_ids(**args)) # noqa

# generate id
if idgen is not None:
Expand Down Expand Up @@ -1118,7 +1119,7 @@ def _get_argnames_argvalues(argnames=None, argvalues=None, **args):
argvalues = kw_argvalues
# simplify if needed to comply with pytest.mark.parametrize
if len(argnames) == 1:
argvalues = [l[0] if not is_marked_parameter_value(l) else l for l in argvalues]
argvalues = [_l[0] if not is_marked_parameter_value(_l) else _l for _l in argvalues]
return argnames, argvalues

if isinstance(argnames, string_types):
Expand Down Expand Up @@ -1165,6 +1166,7 @@ def _gen_ids(argnames, argvalues, idgen):
raise TypeError("idgen should be a callable or a string, found: %r" % idgen)

_formatter = idgen

def gen_id_using_str_formatter(**params):
try:
# format using the idgen template
Expand Down
Loading

0 comments on commit f996f4a

Please sign in to comment.