/usr/share/pyshared/nose2/plugins/layers.py is in python-nose2 0.4.7-2.
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 | import logging
import re
import six
from nose2 import events, util
from nose2.suite import LayerSuite
from nose2.compat import unittest, OrderedDict
BRIGHT = r'\033[1m'
RESET = r'\033[0m'
__unittest = True
log = logging.getLogger(__name__)
class Layers(events.Plugin):
alwaysOn = True
def startTestRun(self, event):
event.suite = self._makeLayerSuite(event)
def _makeLayerSuite(self, event):
return self._sortByLayers(
event.suite, self.session.testLoader.suiteClass)
def _sortByLayers(self, suite, suiteClass):
top = suiteClass()
# first find all of the layers mentioned
layers = OrderedDict()
for test in self._flatten(suite):
# split tests up into buckets by layer
layer = getattr(test, 'layer', None)
if layer:
layers.setdefault(layer, LayerSuite(layer=layer)).addTest(test)
else:
top.addTest(test)
# then organize layers into a tree
remaining = list(layers.keys())
seen = set()
tree = {}
while remaining:
ly = remaining.pop()
if ly in seen:
continue
seen.add(ly)
# superclasses of this layer
if ly is None:
deps = []
else:
deps = [cls for cls in util.bases_and_mixins(ly)
if cls is not object]
deps.reverse()
if not deps:
# layer is top-level
self._addToTree(tree, ly, None)
else:
outer = ly
while deps:
inner, outer = outer, deps.pop()
self._addToTree(tree, inner, outer)
if outer not in layers:
remaining.append(outer)
layers[outer] = LayerSuite(layer=outer)
# finally build the top-level suite
self._treeToSuite(tree, None, top, layers)
# printtree(top)
return top
def _addToTree(self, tree, inner, outer):
found = False
for k, v in tree.items():
if inner in v:
found = True
if outer is not None:
v.remove(inner)
break
if outer is not None or not found:
tree.setdefault(outer, []).append(inner)
def _treeToSuite(self, tree, key, suite, layers):
mysuite = layers.get(key, None)
if mysuite:
suite.addTest(mysuite)
suite = mysuite
sublayers = tree.get(key, [])
# ensure that layers with a set order are in order
sublayers.sort(key=self._sortKey)
log.debug('sorted sublayers of %s (%s): %s', mysuite,
getattr(mysuite, 'layer', 'no layer'), sublayers)
for layer in sublayers:
self._treeToSuite(tree, layer, suite, layers)
def _flatten(self, suite):
out = []
for test in suite:
try:
out.extend(self._flatten(test))
except TypeError:
out.append(test)
return out
def _sortKey(self, layer):
pos = getattr(layer, 'position', None)
# ... lame
if pos is not None:
key = six.u("%04d") % pos
else:
key = layer.__name__
return key
class LayerReporter(events.Plugin):
commandLineSwitch = (
None, 'layer-reporter', 'Add layer information to test reports')
configSection = 'layer-reporter'
def __init__(self):
self.indent = self.config.as_str('indent', ' ')
self.colors = self.config.as_bool('colors', False)
self.highlight_words = self.config.as_list('highlight-words',
['A', 'having', 'should'])
self.highlight_re = re.compile(
r'\b(%s)\b' % '|'.join(self.highlight_words))
self.layersReported = set()
def reportStartTest(self, event):
if self.session.verbosity < 2:
return
test = event.testEvent.test
layer = getattr(test, 'layer', None)
if not layer:
return
for ix, lys in enumerate(util.ancestry(layer)):
for layer in lys:
if layer not in self.layersReported:
desc = self.describeLayer(layer)
event.stream.writeln('%s%s' % (self.indent * ix, desc))
self.layersReported.add(layer)
event.stream.write(self.indent * (ix + 1))
def describeLayer(self, layer):
return self.format(getattr(layer, 'description', layer.__name__))
def format(self, st):
if self.colors:
return self.highlight_re.sub(r'%s\1%s' % (BRIGHT, RESET), st)
return st
def describeTest(self, event):
if hasattr(event.test, 'methodDescription'):
event.description = self.format(event.test.methodDescription())
if event.errorList and hasattr(event.test, 'layer'):
# walk back layers to build full description
self.describeLayers(event)
def describeLayers(self, event):
desc = [event.description]
base = event.test.layer
for layer in (base.__mro__ + getattr(base, 'mixins', ())):
if layer is object:
continue
desc.append(self.describeLayer(layer))
desc.reverse()
event.description = ' '.join(desc)
# for debugging
def printtree(suite, indent=''):
six.print_('%s%s ->' % (indent, getattr(suite, 'layer', 'no layer')))
for test in suite:
if isinstance(test, unittest.BaseTestSuite):
printtree(test, indent + ' ')
else:
six.print_('%s %s' % (indent, test))
six.print_('%s<- %s' % (indent, getattr(suite, 'layer', 'no layer')))
|