-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
move the keyword/mark matching to the "legacy" module
- Loading branch information
1 parent
de2de00
commit cef0423
Showing
2 changed files
with
94 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
""" | ||
this is a place where we put datastructures used by legacy apis | ||
we hope ot remove | ||
""" | ||
import attr | ||
import keyword | ||
|
||
from . import MarkInfo, MarkDecorator | ||
|
||
from _pytest.config import UsageError | ||
|
||
|
||
@attr.s | ||
class MarkMapping(object): | ||
"""Provides a local mapping for markers where item access | ||
resolves to True if the marker is present. """ | ||
|
||
own_mark_names = attr.ib() | ||
|
||
@classmethod | ||
def from_keywords(cls, keywords): | ||
mark_names = set() | ||
for key, value in keywords.items(): | ||
if isinstance(value, MarkInfo) or isinstance(value, MarkDecorator): | ||
mark_names.add(key) | ||
return cls(mark_names) | ||
|
||
def __getitem__(self, name): | ||
return name in self.own_mark_names | ||
|
||
|
||
class KeywordMapping(object): | ||
"""Provides a local mapping for keywords. | ||
Given a list of names, map any substring of one of these names to True. | ||
""" | ||
|
||
def __init__(self, names): | ||
self._names = names | ||
|
||
def __getitem__(self, subname): | ||
for name in self._names: | ||
if subname in name: | ||
return True | ||
return False | ||
|
||
|
||
python_keywords_allowed_list = ["or", "and", "not"] | ||
|
||
|
||
def matchmark(colitem, markexpr): | ||
"""Tries to match on any marker names, attached to the given colitem.""" | ||
return eval(markexpr, {}, MarkMapping.from_keywords(colitem.keywords)) | ||
|
||
|
||
def matchkeyword(colitem, keywordexpr): | ||
"""Tries to match given keyword expression to given collector item. | ||
Will match on the name of colitem, including the names of its parents. | ||
Only matches names of items which are either a :class:`Class` or a | ||
:class:`Function`. | ||
Additionally, matches on names in the 'extra_keyword_matches' set of | ||
any item, as well as names directly assigned to test functions. | ||
""" | ||
mapped_names = set() | ||
|
||
# Add the names of the current item and any parent items | ||
import pytest | ||
for item in colitem.listchain(): | ||
if not isinstance(item, pytest.Instance): | ||
mapped_names.add(item.name) | ||
|
||
# Add the names added as extra keywords to current or parent items | ||
for name in colitem.listextrakeywords(): | ||
mapped_names.add(name) | ||
|
||
# Add the names attached to the current function through direct assignment | ||
if hasattr(colitem, 'function'): | ||
for name in colitem.function.__dict__: | ||
mapped_names.add(name) | ||
|
||
mapping = KeywordMapping(mapped_names) | ||
if " " not in keywordexpr: | ||
# special case to allow for simple "-k pass" and "-k 1.3" | ||
return mapping[keywordexpr] | ||
elif keywordexpr.startswith("not ") and " " not in keywordexpr[4:]: | ||
return not mapping[keywordexpr[4:]] | ||
for kwd in keywordexpr.split(): | ||
if keyword.iskeyword(kwd) and kwd not in python_keywords_allowed_list: | ||
raise UsageError("Python keyword '{}' not accepted in expressions passed to '-k'".format(kwd)) | ||
try: | ||
return eval(keywordexpr, {}, mapping) | ||
except SyntaxError: | ||
raise UsageError("Wrong expression passed to '-k': {}".format(keywordexpr)) |