root/galaxy-central/eggs/nose-0.11.1-py2.6.egg/nose/plugins/attrib.py @ 3

リビジョン 3, 9.6 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1"""Attribute selector plugin.
2
3Oftentimes when testing you will want to select tests based on
4criteria rather then simply by filename. For example, you might want
5to run all tests except for the slow ones. You can do this with the
6Attribute selector plugin by setting attributes on your test methods.
7Here is an example:
8
9.. code-block:: python
10
11    def test_big_download():
12        import urllib
13        # commence slowness...
14
15    test_big_download.slow = 1
16
17Once you've assigned an attribute ``slow = 1`` you can exclude that
18test and all other tests having the slow attribute by running ::
19
20    $ nosetests -a '!slow'
21
22There is also a decorator available for you that will set attributes.
23Here's how to set ``slow=1`` like above with the decorator:
24
25.. code-block:: python
26
27    from nose.plugins.attrib import attr
28    @attr('slow')
29    def test_big_download():
30        import urllib
31        # commence slowness...
32
33And here's how to set an attribute with a specific value:
34
35.. code-block:: python
36
37    from nose.plugins.attrib import attr
38    @attr(speed='slow')
39    def test_big_download():
40        import urllib
41        # commence slowness...
42
43This test could be run with ::
44
45    $ nosetests -a speed=slow
46
47Below is a reference to the different syntaxes available.
48
49Simple syntax
50-------------
51
52Examples of using the ``-a`` and ``--attr`` options:
53
54* ``nosetests -a status=stable``
55   Only runs tests with attribute "status" having value "stable"
56
57* ``nosetests -a priority=2,status=stable``
58   Runs tests having both attributes and values
59
60* ``nosetests -a priority=2 -a slow``
61   Runs tests that match either attribute
62
63* ``nosetests -a tags=http``
64   If a test's ``tags`` attribute was a list and it contained the value
65   ``http`` then it would be run
66
67* ``nosetests -a slow``
68   Runs tests with the attribute ``slow`` if its value does not equal False
69   (False, [], "", etc...)
70
71* ``nosetests -a '!slow'``
72   Runs tests that do NOT have the attribute ``slow`` or have a ``slow``
73   attribute that is equal to False
74   **NOTE**:
75   if your shell (like bash) interprets '!' as a special character make sure to
76   put single quotes around it.
77
78Expression Evaluation
79---------------------
80
81Examples using the ``-A`` and ``--eval-attr`` options:
82
83* ``nosetests -A "not slow"``
84  Evaluates the Python expression "not slow" and runs the test if True
85
86* ``nosetests -A "(priority > 5) and not slow"``
87  Evaluates a complex Python expression and runs the test if True
88
89"""
90import logging
91import os
92import sys
93from inspect import isfunction
94from nose.plugins.base import Plugin
95from nose.util import tolist
96
97log = logging.getLogger('nose.plugins.attrib')
98compat_24 = sys.version_info >= (2, 4)
99
100def attr(*args, **kwargs):
101    """Decorator that adds attributes to objects
102    for use with the Attribute (-a) plugin.
103    """
104    def wrap(func):
105        for name in args:
106            # these are just True flags:
107            setattr(func, name, 1)
108        func.__dict__.update(kwargs)
109        return func
110    return wrap
111
112class ContextHelper:
113    """Returns default values for dictionary lookups."""
114    def __init__(self, obj):
115        self.obj = obj
116
117    def __getitem__(self, name):
118        return self.obj.get(name, False)
119
120
121class AttributeGetter:
122    """Helper for looking up attributes
123
124    First we check the method, and if the attribute is not present,
125    we check the method's class.
126    """
127    missing = object()
128
129    def __init__(self, cls, method):
130        self.cls = cls
131        self.method = method
132
133    def get(self, name, default=None):
134        log.debug('Get %s from %s.%s', name, self.cls, self.method)
135        val = self.method.__dict__.get(name, self.missing)
136        if val is self.missing:
137            log.debug('No attribute %s in method, getting from class',
138                      name)
139            val = getattr(self.cls, name, default)
140            log.debug('Class attribute %s value: %s', name, val)
141        return val
142
143class AttributeSelector(Plugin):
144    """Selects test cases to be run based on their attributes.
145    """
146
147    def __init__(self):
148        Plugin.__init__(self)
149        self.attribs = []
150
151    def options(self, parser, env):
152        """Register command line options"""
153        parser.add_option("-a", "--attr",
154                          dest="attr", action="append",
155                          default=env.get('NOSE_ATTR'),
156                          metavar="ATTR",
157                          help="Run only tests that have attributes "
158                          "specified by ATTR [NOSE_ATTR]")
159        # disable in < 2.4: eval can't take needed args
160        if compat_24:
161            parser.add_option("-A", "--eval-attr",
162                              dest="eval_attr", metavar="EXPR", action="append",
163                              default=env.get('NOSE_EVAL_ATTR'),
164                              help="Run only tests for whose attributes "
165                              "the Python expression EXPR evaluates "
166                              "to True [NOSE_EVAL_ATTR]")
167
168    def configure(self, options, config):
169        """Configure the plugin and system, based on selected options.
170
171        attr and eval_attr may each be lists.
172
173        self.attribs will be a list of lists of tuples. In that list, each
174        list is a group of attributes, all of which must match for the rule to
175        match.
176        """
177        self.attribs = []
178
179        # handle python eval-expression parameter
180        if compat_24 and options.eval_attr:
181            eval_attr = tolist(options.eval_attr)
182            for attr in eval_attr:
183                # "<python expression>"
184                # -> eval(expr) in attribute context must be True
185                def eval_in_context(expr, attribs):
186                    return eval(expr, None, ContextHelper(attribs))
187                self.attribs.append([(attr, eval_in_context)])
188
189        # attribute requirements are a comma separated list of
190        # 'key=value' pairs
191        if options.attr:
192            std_attr = tolist(options.attr)
193            for attr in std_attr:
194                # all attributes within an attribute group must match
195                attr_group = []
196                for attrib in attr.strip().split(","):
197                    # don't die on trailing comma
198                    if not attrib:
199                        continue
200                    items = attrib.split("=", 1)
201                    if len(items) > 1:
202                        # "name=value"
203                        # -> 'str(obj.name) == value' must be True
204                        key, value = items
205                    else:
206                        key = items[0]
207                        if key[0] == "!":
208                            # "!name"
209                            # 'bool(obj.name)' must be False
210                            key = key[1:]
211                            value = False
212                        else:
213                            # "name"
214                            # -> 'bool(obj.name)' must be True
215                            value = True
216                    attr_group.append((key, value))
217                self.attribs.append(attr_group)
218        if self.attribs:
219            self.enabled = True
220
221    def validateAttrib(self, attribs):
222        # TODO: is there a need for case-sensitive value comparison?
223        # within each group, all must match for the group to match
224        # if any group matches, then the attribute set as a whole
225        # has matched
226        any = False
227        for group in self.attribs:
228            match = True
229            for key, value in group:
230                obj_value = attribs.get(key)
231                if callable(value):
232                    if not value(key, attribs):
233                        match = False
234                        break
235                elif value is True:
236                    # value must exist and be True
237                    if not bool(obj_value):
238                        match = False
239                        break
240                elif value is False:
241                    # value must not exist or be False
242                    if bool(obj_value):
243                        match = False
244                        break
245                elif type(obj_value) in (list, tuple):
246                    # value must be found in the list attribute
247
248                    if not str(value).lower() in [str(x).lower()
249                                                  for x in obj_value]:
250                        match = False
251                        break
252                else:
253                    # value must match, convert to string and compare
254                    if (value != obj_value
255                        and str(value).lower() != str(obj_value).lower()):
256                        match = False
257                        break
258            any = any or match
259        if any:
260            # not True because we don't want to FORCE the selection of the
261            # item, only say that it is acceptable
262            return None
263        return False
264
265    def wantClass(self, cls):
266        """Accept the class if the class or any method is wanted.
267        """
268        cls_attr = cls.__dict__
269        if self.validateAttrib(cls_attr) is not False:
270            return None
271        # Methods in __dict__.values() are functions, oddly enough.
272        methods = filter(isfunction, cls_attr.values())
273        wanted = filter(lambda m: m is not False,
274                        map(self.wantFunction, methods))
275        if wanted:
276            return None
277        return False
278
279    def wantFunction(self, function):
280        """Accept the function if its attributes match.
281        """
282        return self.validateAttrib(function.__dict__)
283
284    def wantMethod(self, method):
285        """Accept the method if its attributes match.
286        """
287        attribs = AttributeGetter(method.im_class, method)
288        return self.validateAttrib(attribs)
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。