12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- """
- this is a place where we put datastructures used by legacy apis
- we hope ot remove
- """
- import attr
- import keyword
- 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_item(cls, item):
- mark_names = {mark.name for mark in item.iter_markers()}
- 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
- @classmethod
- def from_item(cls, item):
- mapped_names = set()
- # Add the names of the current item and any parent items
- import pytest
- for item in item.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 item.listextrakeywords():
- mapped_names.add(name)
- # Add the names attached to the current function through direct assignment
- if hasattr(item, "function"):
- for name in item.function.__dict__:
- mapped_names.add(name)
- return cls(mapped_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_item(colitem))
- 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.
- """
- mapping = KeywordMapping.from_item(colitem)
- 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))
|