summaryrefslogtreecommitdiffstats
path: root/scripts/external_libs/nose-1.3.4/python2/nose/selector.py
blob: c4a006a8d758fea00996eecaae01094a161be45d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
"""
Test Selection
--------------

Test selection is handled by a Selector. The test loader calls the
appropriate selector method for each object it encounters that it
thinks may be a test.
"""
import logging
import os
import unittest
from nose.config import Config
from nose.util import split_test_name, src, getfilename, getpackage, ispackage

log = logging.getLogger(__name__)

__all__ = ['Selector', 'defaultSelector', 'TestAddress']


# for efficiency and easier mocking
op_join = os.path.join
op_basename = os.path.basename
op_exists = os.path.exists
op_splitext = os.path.splitext
op_isabs = os.path.isabs
op_abspath = os.path.abspath


class Selector(object):
    """Core test selector. Examines test candidates and determines whether,
    given the specified configuration, the test candidate should be selected
    as a test.
    """
    def __init__(self, config):
        if config is None:
            config = Config()
        self.configure(config)

    def configure(self, config):
        self.config = config
        self.exclude = config.exclude
        self.ignoreFiles = config.ignoreFiles
        self.include = config.include
        self.plugins = config.plugins
        self.match = config.testMatch
        
    def matches(self, name):
        """Does the name match my requirements?

        To match, a name must match config.testMatch OR config.include
        and it must not match config.exclude
        """
        return ((self.match.search(name)
                 or (self.include and
                     filter(None,
                            [inc.search(name) for inc in self.include])))
                and ((not self.exclude)
                     or not filter(None,
                                   [exc.search(name) for exc in self.exclude])
                 ))
    
    def wantClass(self, cls):
        """Is the class a wanted test class?

        A class must be a unittest.TestCase subclass, or match test name
        requirements. Classes that start with _ are always excluded.
        """
        declared = getattr(cls, '__test__', None)
        if declared is not None:
            wanted = declared
        else:
            wanted = (not cls.__name__.startswith('_')
                      and (issubclass(cls, unittest.TestCase)
                           or self.matches(cls.__name__)))
        
        plug_wants = self.plugins.wantClass(cls)        
        if plug_wants is not None:
            log.debug("Plugin setting selection of %s to %s", cls, plug_wants)
            wanted = plug_wants
        log.debug("wantClass %s? %s", cls, wanted)
        return wanted

    def wantDirectory(self, dirname):
        """Is the directory a wanted test directory?

        All package directories match, so long as they do not match exclude. 
        All other directories must match test requirements.
        """
        tail = op_basename(dirname)
        if ispackage(dirname):
            wanted = (not self.exclude
                      or not filter(None,
                                    [exc.search(tail) for exc in self.exclude]
                                    ))
        else:
            wanted = (self.matches(tail)
                      or (self.config.srcDirs
                          and tail in self.config.srcDirs))
        plug_wants = self.plugins.wantDirectory(dirname)
        if plug_wants is not None:
            log.debug("Plugin setting selection of %s to %s",
                      dirname, plug_wants)
            wanted = plug_wants
        log.debug("wantDirectory %s? %s", dirname, wanted)
        return wanted
    
    def wantFile(self, file):
        """Is the file a wanted test file?

        The file must be a python source file and match testMatch or
        include, and not match exclude. Files that match ignore are *never*
        wanted, regardless of plugin, testMatch, include or exclude settings.
        """
        # never, ever load files that match anything in ignore
        # (.* _* and *setup*.py by default)
        base = op_basename(file)
        ignore_matches = [ ignore_this for ignore_this in self.ignoreFiles
                           if ignore_this.search(base) ]
        if ignore_matches:
            log.debug('%s matches ignoreFiles pattern; skipped',
                      base) 
            return False
        if not self.config.includeExe and os.access(file, os.X_OK):
            log.info('%s is executable; skipped', file)
            return False
        dummy, ext = op_splitext(base)
        pysrc = ext == '.py'

        wanted = pysrc and self.matches(base) 
        plug_wants = self.plugins.wantFile(file)
        if plug_wants is not None:
            log.debug("plugin setting want %s to %s", file, plug_wants)
            wanted = plug_wants
        log.debug("wantFile %s? %s", file, wanted)
        return wanted

    def wantFunction(self, function):
        """Is the function a test function?
        """
        try:
            if hasattr(function, 'compat_func_name'):
                funcname = function.compat_func_name
            else:
                funcname = function.__name__
        except AttributeError:
            # not a function
            return False
        declared = getattr(function, '__test__', None)
        if declared is not None:
            wanted = declared
        else:
            wanted = not funcname.startswith('_') and self.matches(funcname)
        plug_wants = self.plugins.wantFunction(function)
        if plug_wants is not None:
            wanted = plug_wants
        log.debug("wantFunction %s? %s", function, wanted)
        return wanted

    def wantMethod(self, method):
        """Is the method a test method?
        """
        try:
            method_name = method.__name__
        except AttributeError:
            # not a method
            return False
        if method_name.startswith('_'):
            # never collect 'private' methods
            return False
        declared = getattr(method, '__test__', None)
        if declared is not None:
            wanted = declared
        else:
            wanted = self.matches(method_name)
        plug_wants = self.plugins.wantMethod(method)
        if plug_wants is not None:
            wanted = plug_wants
        log.debug("wantMethod %s? %s", method, wanted)
        return wanted
    
    def wantModule(self, module):
        """Is the module a test module?

        The tail of the module name must match test requirements. One exception:
        we always want __main__.
        """
        declared = getattr(module, '__test__', None)
        if declared is not None:
            wanted = declared
        else:
            wanted = self.matches(module.__name__.split('.')[-1]) \
                     or module.__name__ == '__main__'
        plug_wants = self.plugins.wantModule(module)
        if plug_wants is not None:
            wanted = plug_wants
        log.debug("wantModule %s? %s", module, wanted)
        return wanted
        
defaultSelector = Selector        


class TestAddress(object):
    """A test address represents a user's request to run a particular
    test. The user may specify a filename or module (or neither),
    and/or a callable (a class, function, or method). The naming
    format for test addresses is:

    filename_or_module:callable

    Filenames that are not absolute will be made absolute relative to
    the working dir.

    The filename or module part will be considered a module name if it
    doesn't look like a file, that is, if it doesn't exist on the file
    system and it doesn't contain any directory separators and it
    doesn't end in .py.

    Callables may be a class name, function name, method name, or
    class.method specification.
    """
    def __init__(self, name, workingDir=None):
        if workingDir is None:
            workingDir = os.getcwd()
        self.name = name
        self.workingDir = workingDir
        self.filename, self.module, self.call = split_test_name(name)
        log.debug('Test name %s resolved to file %s, module %s, call %s',
                  name, self.filename, self.module, self.call)
        if self.filename is None:
            if self.module is not None:
                self.filename = getfilename(self.module, self.workingDir)
        if self.filename:
            self.filename = src(self.filename)
            if not op_isabs(self.filename):
                self.filename = op_abspath(op_join(workingDir,
                                                   self.filename))
            if self.module is None:
                self.module = getpackage(self.filename)
        log.debug(
            'Final resolution of test name %s: file %s module %s call %s',
            name, self.filename, self.module, self.call)

    def totuple(self):
        return (self.filename, self.module, self.call)
        
    def __str__(self):
        return self.name

    def __repr__(self):
        return "%s: (%s, %s, %s)" % (self.name, self.filename,
                                     self.module, self.call)