/usr/lib/python2.7/dist-packages/nose2/plugins/loader/discovery.py is in python-nose2 0.5.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | """
Discovery-based test loader.
This plugin implements nose2's automatic test module discovery. It
looks for test modules in packages and directories whose names start
with 'test', then fires the :func:`loadTestsFromModule` hook for each
one to allow other plugins to load the actual tests.
It also fires :func:`handleFile` for every file that it sees, and
:func:`matchPath` for every python module, to allow other plugins to
load tests from other kinds of files and to influence which modules
are examined for tests.
"""
# Adapted from unittest2/loader.py from the unittest2 plugins branch.
# This module contains some code copied from unittest2/loader.py and other
# code developed in reference to that module and others within unittest2.
# unittest2 is Copyright (c) 2001-2010 Python Software Foundation; All
# Rights Reserved. See: http://docs.python.org/license.html
from fnmatch import fnmatch
import logging
import os
import sys
from nose2 import events, util
__unittest = True
log = logging.getLogger(__name__)
class DirectoryHandler(object):
def __init__(self, session):
self.session = session
self.event_handled = False
def handle_dir(self, event, full_path, top_level):
dirname = os.path.basename(full_path)
pattern = self.session.testFilePattern
evt = events.HandleFileEvent(
event.loader, dirname, full_path, pattern, top_level)
result = self.session.hooks.handleDir(evt)
if evt.extraTests:
for test in evt.extraTests:
yield test
if evt.handled:
if result:
yield result
self.event_handled = True
return
evt = events.MatchPathEvent(dirname, full_path, pattern)
result = self.session.hooks.matchDirPath(evt)
if evt.handled and not result:
self.event_handled = True
class Discoverer(object):
def loadTestsFromName(self, event):
"""Load tests from module named by event.name"""
# turn name into path or module name
# fire appropriate hooks (handle file or load from module)
if event.module:
return
name = event.name
module = None
_, top_level_dir = self._getStartDirs()
try:
# try name as a dotted module name first
__import__(name)
module = sys.modules[name]
except ImportError:
# if that fails, try it as a file or directory
event.extraTests.extend(
self._find_tests(event, name, top_level_dir))
else:
event.extraTests.extend(
self._find_tests_in_module(event, module, top_level_dir))
def loadTestsFromNames(self, event):
"""Discover tests if no test names specified"""
log.debug("Received event %s", event)
if event.names or event.module:
return
event.handled = True # I will handle discovery
return self._discover(event)
def _checkIfPathIsOK(self, start_dir):
if not os.path.isdir(os.path.abspath(start_dir)):
raise OSError("%s is not a directory" % os.path.abspath(start_dir))
def _getStartDirs(self):
start_dir = self.session.startDir
top_level_dir = self.session.topLevelDir
if start_dir is None:
start_dir = '.'
if top_level_dir is None:
top_level_dir = start_dir
self._checkIfPathIsOK(start_dir)
is_not_importable = False
start_dir = os.path.abspath(start_dir)
top_level_dir = os.path.abspath(top_level_dir)
if start_dir != top_level_dir:
is_not_importable = not os.path.isfile(
os.path.join(start_dir, '__init__.py'))
if is_not_importable:
raise ImportError(
'Start directory is not importable: %r' % start_dir)
# this is redundant in some cases, but that's ok
self.session.prepareSysPath()
return start_dir, top_level_dir
def _discover(self, event):
loader = event.loader
try:
start_dir, top_level_dir = self._getStartDirs()
except (OSError, ImportError):
_, ev, _ = sys.exc_info()
return loader.suiteClass(
loader.failedLoadTests(self.session.startDir, ev))
log.debug("_discover in %s (%s)", start_dir, top_level_dir)
tests = list(self._find_tests(event, start_dir, top_level_dir))
return loader.suiteClass(tests)
def _find_tests(self, event, start, top_level):
"""Used by discovery. Yields test suites it loads."""
log.debug('_find_tests(%r, %r)', start, top_level)
if start == top_level:
full_path = start
else:
full_path = os.path.join(top_level, start)
if os.path.isdir(start):
for test in self._find_tests_in_dir(
event, full_path, top_level):
yield test
elif os.path.isfile(start):
for test in self._find_tests_in_file(
event, start, full_path, top_level):
yield test
def _find_tests_in_dir(self, event, full_path, top_level):
if not os.path.isdir(full_path):
return
log.debug("find in dir %s (%s)", full_path, top_level)
dir_handler = DirectoryHandler(self.session)
for test in dir_handler.handle_dir(event, full_path, top_level):
yield test
if dir_handler.event_handled:
return
for path in os.listdir(full_path):
entry_path = os.path.join(full_path, path)
if os.path.isfile(entry_path):
for test in self._find_tests_in_file(
event, path, entry_path, top_level):
yield test
elif os.path.isdir(entry_path):
if ('test' in path.lower()
or util.ispackage(entry_path)
or path in self.session.libDirs):
for test in self._find_tests(event, entry_path, top_level):
yield test
def _find_tests_in_file(self, event, filename, full_path, top_level, module_name=None):
log.debug("find in file %s (%s)", full_path, top_level)
pattern = self.session.testFilePattern
loader = event.loader
evt = events.HandleFileEvent(
loader, filename, full_path, pattern, top_level)
result = self.session.hooks.handleFile(evt)
if evt.extraTests:
yield loader.suiteClass(evt.extraTests)
if evt.handled:
if result:
yield result
return
if not util.valid_module_name(filename):
# valid Python identifiers only
return
evt = events.MatchPathEvent(filename, full_path, pattern)
result = self.session.hooks.matchPath(evt)
if evt.handled:
if not result:
return
elif not self._match_path(filename, full_path, pattern):
return
if module_name is None:
module_name = util.name_from_path(full_path)
try:
module = util.module_from_name(module_name)
except:
yield loader.failedImport(module_name)
else:
mod_file = os.path.abspath(
getattr(module, '__file__', full_path))
realpath = os.path.splitext(mod_file)[0]
fullpath_noext = os.path.splitext(full_path)[0]
if realpath.lower() != fullpath_noext.lower():
module_dir = os.path.dirname(realpath)
mod_name = os.path.splitext(os.path.basename(full_path))[0]
expected_dir = os.path.dirname(full_path)
msg = ("%r module incorrectly imported from %r. "
"Expected %r. Is this module globally installed?"
)
raise ImportError(
msg % (mod_name, module_dir, expected_dir))
yield loader.loadTestsFromModule(module)
def _find_tests_in_module(self, event, module, top_level_dir):
# only called from loadTestsFromName
yield event.loader.loadTestsFromModule(module)
# may be a package; recurse into __path__ if so
pkgpath = getattr(module, '__path__', None)
if pkgpath:
for entry in pkgpath:
full_path = os.path.abspath(os.path.join(top_level_dir, entry))
for test in self._find_tests_in_dir(
event, full_path, top_level_dir):
yield test
def _match_path(self, path, full_path, pattern):
# override this method to use alternative matching strategy
return fnmatch(path, pattern)
class DiscoveryLoader(events.Plugin, Discoverer):
"""Loader plugin that can discover tests"""
alwaysOn = True
configSection = 'discovery'
def registerInSubprocess(self, event):
event.pluginClasses.append(self.__class__)
def loadTestsFromName(self, event):
"""Load tests from module named by event.name"""
return Discoverer.loadTestsFromName(self, event)
def loadTestsFromNames(self, event):
"""Discover tests if no test names specified"""
return Discoverer.loadTestsFromNames(self, event)
|