"""Attribute selector plugin.
Simple syntax (-a, --attr) examples:
* `nosetests -a status=stable`:
Only test cases with attribute "status" having value "stable"
* `nosetests -a priority=2,status=stable`:
Both attributes must match
* `nosetests -a priority=2 -a slow`:
Either attribute must match
* `nosetests -a tags=http`:
Attribute list "tags" must contain value "http" (see test_foobar()
below for definition)
* `nosetests -a slow`:
Attribute "slow" must be defined and its value cannot equal to False
(False, [], "", etc...)
* `nosetests -a '!slow'`:
Attribute "slow" must NOT be defined or its value must be equal to False.
Note the quotes around the value -- this may be necessary if your shell
interprets `!' as a special character.
Eval expression syntax (-A, --eval-attr) examples:
* `nosetests -A "not slow"`
* `nosetests -A "(priority > 5) and not slow"`
"""
import logging
import os
import sys
from inspect import isfunction
from nose.plugins.base import Plugin
from nose.util import tolist
log = logging.getLogger('nose.plugins.attrib')
compat_24 = sys.version_info >= (2, 4)
class ContextHelper:
"""Returns default values for dictionary lookups."""
def __init__(self, obj):
self.obj = obj
def __getitem__(self, name):
return self.obj.get(name, False)
class AttributeGetter:
"""Helper for looking up attributes
First we check the method, and if the attribute is not present,
we check the method's class.
"""
missing = object()
def __init__(self, cls, method):
self.cls = cls
self.method = method
def get(self, name, default=None):
log.debug('Get %s from %s.%s', name, self.cls, self.method)
val = self.method.__dict__.get(name, self.missing)
if val is self.missing:
log.debug('No attribute %s in method, getting from class',
name)
val = getattr(self.cls, name, default)
log.debug('Class attribute %s value: %s', name, val)
return val
class AttributeSelector(Plugin):
"""Selects test cases to be run based on their attributes.
"""
def __init__(self):
Plugin.__init__(self)
self.attribs = []
def options(self, parser, env=os.environ):
"""Add command-line options for this plugin."""
parser.add_option("-a", "--attr",
dest="attr", action="append",
default=env.get('NOSE_ATTR'),
help="Run only tests that have attributes "
"specified by ATTR [NOSE_ATTR]")
# disable in < 2.4: eval can't take needed args
if compat_24:
parser.add_option("-A", "--eval-attr",
dest="eval_attr", metavar="EXPR", action="append",
default=env.get('NOSE_EVAL_ATTR'),
help="Run only tests for whose attributes "
"the Python expression EXPR evaluates "
"to True [NOSE_EVAL_ATTR]")
def configure(self, options, config):
"""Configure the plugin and system, based on selected options.
attr and eval_attr may each be lists.
self.attribs will be a list of lists of tuples. In that list, each
list is a group of attributes, all of which must match for the rule to
match.
"""
self.attribs = []
# handle python eval-expression parameter
if compat_24 and options.eval_attr:
eval_attr = tolist(options.eval_attr)
for attr in eval_attr:
# "