Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
BSD 3-Clause License

Copyright (c) 2018-2021, Sylvain Marié, Schneider Electric Industries
Copyright (c) 2018-2025, Sylvain Marié, Schneider Electric Industries
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Expand Down
8 changes: 7 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
# Changelog

### 3.8.7 - compatibility with pytest 8.6.0
### 3.9.0 - support for python 3.14 and pytest 8.6

- Fixed `AttributeError: 'MiniMetafunc' object has no attribute '_params_directness'` when a case function is
parametrized or requires a fixtures, with pytest 8.4.0. Fixed
[#365](https://github.com/smarie/python-pytest-cases/issues/365)
- Fixed `ValueError: The provided fixture function does not seem to be a fixture` with `@fixture_ref` with pytest
8.4.0. Fixed [#364](https://github.com/smarie/python-pytest-cases/issues/364)
- Dropped support for `python<3.9` and `pytest<6`. Fixes
[#362](https://github.com/smarie/python-pytest-cases/issues/362) and fixes
[#186](https://github.com/smarie/python-pytest-cases/issues/186)
- Fixed test suite for python 3.14, officializing the support for this version.

### 3.8.6 - compatibility fix

Expand Down
15 changes: 12 additions & 3 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,26 @@ class Folders:


ENVS = {
# python 3.14 - numpy is not available in precompiled version for this python version yet
# (PY314, "pytest-latest"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": ""}},
# python 3.14
(PY314, "pytest-latest"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": ""}},
(PY314, "pytest7.x"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": "<8"}},
(PY314, "pytest6.x"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": "<7"}},
# python 3.13
(PY313, "pytest-latest"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": ""}},
(PY313, "pytest7.x"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": "<8"}},
(PY313, "pytest6.x"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": "<7"}},
# python 3.12
(PY312, "pytest-latest"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": ""}},
(PY312, "pytest7.x"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": "<8"}},
(PY312, "pytest6.x"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": "<7"}},
# python 3.11
# We'll run this last for coverage
# We'll run 'pytest-latest' this last for coverage
(PY311, "pytest7.x"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": "<8"}},
(PY311, "pytest6.x"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": "<7"}},
# python 3.10
(PY310, "pytest-latest"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": ""}},
(PY310, "pytest7.x"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": "<8"}},
(PY310, "pytest6.x"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": "<7"}},
# python 3.9
(PY39, "pytest-latest"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": ""}},
(PY39, "pytest7.x"): {"coverage": False, "pkg_specs": {"pip": ">19", "pytest": "<8"}},
Expand Down
84 changes: 68 additions & 16 deletions src/pytest_cases/case_parametrizer_new.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,9 @@ def case_to_argvalues(host_class_or_module, # type: Union[Type, ModuleType]
If `case_fun` requires at least on fixture, a fixture will be created if not yet present, and a `fixture_ref` will
be returned.

If `case_fun` is a parametrized case, one `lazy_value` with a partialized version will be created for each parameter
combination.
If `case_fun` is a parametrized case, (NEW since 3.0.0) a fixture will be created if not yet present,
and a `fixture_ref` will be returned. (OLD < 3.0.0) one `lazy_value` with a partialized version will be created
for each parameter combination.

Otherwise, `case_fun` represents a single case: in that case a single `lazy_value` is returned.

Expand Down Expand Up @@ -734,12 +735,27 @@ def extract_cases_from_class(cls,
):
# type: (...) -> List[Callable]
"""
Collects all case functions (methods matching ``case_fun_prefix``) in class ``cls``.

:param cls:
:param check_name:
:param case_fun_prefix:
:param _case_param_factory:
:return:
Parameters
----------
cls : Type
A class where to look for case functions. All methods matching ``prefix`` will be returned.

check_name : bool
If this is ``True`` and class name does not contain the string ``Case``, the class will not be inspected and
an empty list will be returned.

case_fun_prefix : str
A prefix that case functions (class methods) must match to be collected.

_case_param_factory :
Legacy. Not used.

Returns
-------
cases_lst : List[Callable]
A list of collected case functions (class methods).
"""
if is_case_class(cls, check_name=check_name):
# see from _pytest.python import pytest_pycollect_makeitem
Expand Down Expand Up @@ -769,7 +785,7 @@ def extract_cases_from_class(cls,
return []


def extract_cases_from_module(module, # type: ModuleRef
def extract_cases_from_module(module, # type: Union[str, ModuleRef]
package_name=None, # type: str
case_fun_prefix=CASE_PREFIX_FUN, # type: str
_case_param_factory=None
Expand All @@ -782,10 +798,27 @@ def extract_cases_from_module(module, # type: ModuleRe
See also `_pytest.python.PyCollector.collect` and `_pytest.python.PyCollector._makeitem` and
`_pytest.python.pytest_pycollect_makeitem`: we could probably do this in a better way in pytest_pycollect_makeitem

:param module:
:param package_name:
:param _case_param_factory:
:return:
Parameters
----------
module : Union[str, ModuleRef]
A module where to look for case functions. All functions in the module matching ``prefix`` will be
returned. In addition, all classes in the module with ``Case`` in their name will be inspected. For each of
them, all methods matching ``prefix`` will be returned too.

package_name : Optional[str], default: None
If ``module`` is provided as a string, this is a mandatory package full qualified name (e.g. ``a.b.c``) where
to import the module from.

case_fun_prefix : str
A prefix that case functions (including class methods) must match to be collected.

_case_param_factory :
Legacy. Not used.

Returns
-------
cases : List[Callable]
A list of case functions
"""
# optionally import module if passed as module name string
if isinstance(module, string_types):
Expand All @@ -805,12 +838,30 @@ def _extract_cases_from_module_or_class(module=None, # type
cls=None, # type: Type
case_fun_prefix=CASE_PREFIX_FUN, # type: str
_case_param_factory=None
):
): # type: (...) -> List[Callable]
"""
Extracts all case functions from `module` or `cls` (only one non-None must be provided).

:param module:
:param _case_param_factory:
:return:
Parameters
----------
module : Optional[ModuleRef], default: None
A module where to look for case functions. All functions in the module matching ``prefix`` will be
returned. In addition, all classes in the module with ``Case`` in their name will be inspected. For each of
them, all methods matching ``prefix`` will be returned too.

cls : Optional[Type], default: None
A class where to look for case functions. All methods matching ``prefix`` will be returned.

case_fun_prefix : str
A prefix that case functions (including class methods) must match to be collected.

_case_param_factory :
Legacy. Not used.

Returns
-------
cases : List[Callable]
A list of case functions
"""
if not ((cls is None) ^ (module is None)):
raise ValueError("Only one of cls or module should be provided")
Expand Down Expand Up @@ -897,6 +948,7 @@ def _of_interest(x): # noqa
% (m, cases_dct[co_firstlineno]))
cases_dct[co_firstlineno] = m
else:
# Not used anymore
# Legacy usage where the cases generators were expanded here and inserted with a virtual line no
_case_param_factory(m, co_firstlineno, cases_dct)

Expand Down
Loading
Loading