Skip to content

Commit 69c73e4

Browse files
author
Sylvain MARIE
committed
'case_funcs_new' and 'case_info' merged again in module 'case_funcs', and _CaseInfo made private again. Now a clearer explanation is provided about why this class is private.
1 parent bc307d6 commit 69c73e4

File tree

6 files changed

+112
-114
lines changed

6 files changed

+112
-114
lines changed

pytest_cases/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from .case_parametrizer_legacy import cases_data, CaseDataGetter, get_all_cases_legacy, \
2121
get_pytest_parametrize_args_legacy, cases_fixture
2222

23-
from .case_funcs_new import case, copy_case_info, set_case_id, get_case_id, get_case_marks, \
23+
from .case_funcs import case, copy_case_info, set_case_id, get_case_id, get_case_marks, \
2424
get_case_tags, matches_tag_query, is_case_class, is_case_function
2525
from .case_parametrizer_new import parametrize_with_cases, THIS_MODULE, get_all_cases, get_parametrize_args
2626

@@ -38,7 +38,7 @@
3838
__all__ = [
3939
'__version__',
4040
# the submodules
41-
'case_funcs_legacy', 'case_funcs_new', 'case_info',
41+
'case_funcs_legacy', 'case_funcs',
4242
'case_parametrizer_legacy', 'case_parametrizer_new',
4343
'common_mini_six', 'common_others', 'common_pytest', 'common_pytest_lazy_values', 'common_pytest_marks',
4444
'filters',

pytest_cases/case_funcs_new.py renamed to pytest_cases/case_funcs.py

Lines changed: 107 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
# + All contributors to <https://github.com/smarie/python-pytest-cases>
33
#
44
# License: 3-clause BSD, <https://github.com/smarie/python-pytest-cases/blob/master/LICENSE>
5+
from copy import copy
56
from decopatch import function_decorator, DECORATED
67

7-
from .case_info import CaseInfo, _tags_match_query
8-
98
try: # python 3.5+
109
from typing import Type, Callable, Union, Optional, Any, Tuple, Dict, Iterable, List, Set
1110
except ImportError:
1211
pass
1312

13+
from .common_mini_six import string_types
1414
from .common_pytest import safe_isclass
1515
from .common_pytest_marks import get_pytest_marks_on_function, markdecorators_as_tuple, markdecorators_to_markinfos
1616

@@ -28,18 +28,117 @@
2828
"""Prefix used by default to identify case functions within a module"""
2929

3030

31+
CASE_FIELD = '_pytestcase'
32+
33+
34+
class _CaseInfo(object):
35+
"""
36+
Contains all information available about a case.
37+
It is attached to a case function as an attribute.
38+
39+
Currently we do not wish to export an object-oriented API for this but rather a set of functions.
40+
This is why this class remains private. Public functions to access the various elements in this class
41+
are provided below (`get_case_id`, `get_case_tags` and `get_case_marks`). This is a safeguard to allow us
42+
to change this class design later while easily guaranteeing retrocompatibility.
43+
"""
44+
__slots__ = ('id', 'marks', 'tags')
45+
46+
def __init__(self,
47+
id=None, # type: str
48+
marks=(), # type: Tuple[MarkDecorator, ...]
49+
tags=() # type: Tuple[Any]
50+
):
51+
self.id = id
52+
self.marks = marks
53+
self.tags = ()
54+
self.add_tags(tags)
55+
56+
def __repr__(self):
57+
return "_CaseInfo(id=%r,marks=%r,tags=%r)" % (self.id, self.marks, self.tags)
58+
59+
@classmethod
60+
def get_from(cls,
61+
case_func, # type: Callable
62+
create_if_missing=False # type: bool
63+
):
64+
""" Return the _CaseInfo associated with case_fun or None
65+
66+
:param case_func:
67+
:param create_if_missing: if no case information is present on the function, by default None is returned. If
68+
this flag is set to True, a new _CaseInfo will be created and attached on the function, and returned.
69+
"""
70+
ci = getattr(case_func, CASE_FIELD, None)
71+
if ci is None and create_if_missing:
72+
ci = cls()
73+
ci.attach_to(case_func)
74+
return ci
75+
76+
def attach_to(self,
77+
case_func # type: Callable
78+
):
79+
"""attach this case_info to the given case function"""
80+
setattr(case_func, CASE_FIELD, self)
81+
82+
def add_tags(self,
83+
tags # type: Union[Any, Union[List, Set, Tuple]]
84+
):
85+
"""add the given tag or tags"""
86+
if tags:
87+
if isinstance(tags, string_types) or not isinstance(tags, (set, list, tuple)):
88+
# a single tag, create a tuple around it
89+
tags = (tags,)
90+
91+
self.tags += tuple(tags)
92+
93+
def matches_tag_query(self,
94+
has_tag=None, # type: Union[str, Iterable[str]]
95+
):
96+
"""
97+
Returns True if the case function with this case_info is selected by the query
98+
99+
:param has_tag:
100+
:return:
101+
"""
102+
return _tags_match_query(self.tags, has_tag)
103+
104+
@classmethod
105+
def copy_info(cls,
106+
from_case_func,
107+
to_case_func):
108+
case_info = cls.get_from(from_case_func)
109+
if case_info is not None:
110+
# there is something to copy: do it
111+
cp = copy(case_info)
112+
cp.attach_to(to_case_func)
113+
114+
115+
def _tags_match_query(tags, # type: Iterable[str]
116+
has_tag # type: Optional[Union[str, Iterable[str]]]
117+
):
118+
"""Internal routine to determine is all tags in `has_tag` are persent in `tags`
119+
Note that `has_tag` can be a single tag, or none
120+
"""
121+
if has_tag is None:
122+
return True
123+
124+
if not isinstance(has_tag, (tuple, list, set)):
125+
has_tag = (has_tag,)
126+
127+
return all(t in tags for t in has_tag)
128+
129+
31130
def copy_case_info(from_fun, # type: Callable
32131
to_fun # type: Callable
33132
):
34133
"""Copy all information from case function `from_fun` to `to_fun`."""
35-
CaseInfo.copy_info(from_fun, to_fun)
134+
_CaseInfo.copy_info(from_fun, to_fun)
36135

37136

38137
def set_case_id(id, # type: str
39138
case_func # type: Callable
40139
):
41140
"""Set an explicit id on case function `case_func`."""
42-
ci = CaseInfo.get_from(case_func, create_if_missing=True)
141+
ci = _CaseInfo.get_from(case_func, create_if_missing=True)
43142
ci.id = id
44143

45144

@@ -57,7 +156,7 @@ def get_case_id(case_func, # type: Callable
57156
case id.
58157
:return:
59158
"""
60-
_ci = CaseInfo.get_from(case_func)
159+
_ci = _CaseInfo.get_from(case_func)
61160
_id = _ci.id if _ci is not None else None
62161

63162
if _id is None:
@@ -95,7 +194,7 @@ def get_case_marks(case_func, # type: Callable
95194
returned. Otherwise (default) the marks are returned as is.
96195
:return:
97196
"""
98-
_ci = CaseInfo.get_from(case_func)
197+
_ci = _CaseInfo.get_from(case_func)
99198
if _ci is None:
100199
_ci_marks = None
101200
else:
@@ -119,7 +218,7 @@ def get_case_marks(case_func, # type: Callable
119218
def get_case_tags(case_func # type: Callable
120219
):
121220
"""Return the tags on this case function or an empty tuple"""
122-
ci = CaseInfo.get_from(case_func)
221+
ci = _CaseInfo.get_from(case_func)
123222
return ci.tags if ci is not None else ()
124223

125224

@@ -198,7 +297,7 @@ def case_hi():
198297
:return:
199298
"""
200299
marks = markdecorators_as_tuple(marks)
201-
case_info = CaseInfo(id, marks, tags)
300+
case_info = _CaseInfo(id, marks, tags)
202301
case_info.attach_to(case_func)
203302
return case_func
204303

pytest_cases/case_funcs_legacy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
except ImportError:
2020
pass
2121

22-
from .case_funcs_new import case
22+
from .case_funcs import case
2323

2424

2525
@function_decorator

pytest_cases/case_info.py

Lines changed: 0 additions & 101 deletions
This file was deleted.

pytest_cases/case_parametrizer_legacy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from .common_pytest_marks import get_pytest_marks_on_function, make_marked_parameter_value
3535

3636
from .case_funcs_legacy import is_case_generator, get_case_generator_details
37-
from .case_funcs_new import matches_tag_query
37+
from .case_funcs import matches_tag_query
3838
from .case_parametrizer_new import THIS_MODULE, extract_cases_from_module
3939

4040
from .fixture_core2 import fixture_plus

pytest_cases/case_parametrizer_new.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from .common_pytest import safe_isclass, MiniMetafunc, is_fixture, get_fixture_name, inject_host, add_fixture_params
2424

2525
from . import fixture
26-
from .case_funcs_new import matches_tag_query, is_case_function, is_case_class, CASE_PREFIX_FUN, copy_case_info, \
26+
from .case_funcs import matches_tag_query, is_case_function, is_case_class, CASE_PREFIX_FUN, copy_case_info, \
2727
get_case_id, get_case_marks, GEN_BY_US
2828
from .fixture__creation import check_name_available, CHANGE
2929
from .fixture_parametrize_plus import fixture_ref, _parametrize_plus

0 commit comments

Comments
 (0)