forked from twisted/twisted
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_nooldstyle.py
211 lines (156 loc) · 5.82 KB
/
test_nooldstyle.py
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
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Tests for L{twisted.python._oldstyle._oldStyle}.
"""
from __future__ import absolute_import, division
import types
import inspect
from twisted.python.reflect import namedAny, fullyQualifiedName
from twisted.python.modules import getModule
from twisted.python.compat import _PY3, _shouldEnableNewStyle
from twisted.trial import unittest
from twisted.python import _oldstyle
_skip = None
if _PY3:
_skip = "Not relevant on Python 3."
elif not _shouldEnableNewStyle():
_skip = "Not running with TWISTED_NEWSTYLE=1"
forbiddenModules = [
"twisted._threads",
"twisted.application",
"twisted.internet",
"twisted.logger",
"twisted.plugins",
"twisted.positioning",
"twisted.protocols.haproxy",
"twisted.python",
"twisted.script",
"twisted.tap",
"twisted.trial",
]
class SomeOldStyleClass:
"""
I am a docstring!
"""
bar = "baz"
def func(self):
"""
A function on an old style class.
@return: "hi", for testing.
"""
return "hi"
class SomeNewStyleClass(object):
"""
Some new style class!
"""
class OldStyleDecoratorTests(unittest.TestCase):
"""
Tests for L{_oldstyle._oldStyle}.
"""
def test_makesNewStyle(self):
"""
L{_oldstyle._oldStyle} wraps an old-style class and returns a new-style
class that has the same functions, attributes, etc.
"""
class SomeClassThatUsesOldStyle(SomeOldStyleClass):
pass
self.assertEqual(type(SomeClassThatUsesOldStyle), types.ClassType)
updatedClass = _oldstyle._oldStyle(SomeClassThatUsesOldStyle)
self.assertEqual(type(updatedClass), type)
self.assertEqual(updatedClass.__bases__, (SomeOldStyleClass, object))
self.assertEqual(updatedClass().func(), "hi")
self.assertEqual(updatedClass().bar, "baz")
def test_carriesAttributes(self):
"""
The class returned by L{_oldstyle._oldStyle} has the same C{__name__},
C{__module__}, and docstring (C{__doc__}) attributes as the original.
"""
updatedClass = _oldstyle._oldStyle(SomeOldStyleClass)
self.assertEqual(updatedClass.__name__, SomeOldStyleClass.__name__)
self.assertEqual(updatedClass.__doc__, SomeOldStyleClass.__doc__)
self.assertEqual(updatedClass.__module__, SomeOldStyleClass.__module__)
def test_onlyOldStyleMayBeDecorated(self):
"""
Using L{_oldstyle._oldStyle} on a new-style class on Python 2 will
raise an exception.
"""
with self.assertRaises(ValueError) as e:
_oldstyle._oldStyle(SomeNewStyleClass)
self.assertEqual(
e.exception.args[0],
("twisted.python._oldstyle._oldStyle is being used to decorate a "
"new-style class (twisted.test.test_nooldstyle.SomeNewStyleClass)"
". This should only be used to decorate old-style classes."))
def test_noOpByDefault(self):
"""
On Python 3 or on Py2 when C{TWISTED_NEWSTYLE} is not set,
L{_oldStyle._oldStyle} is a no-op.
"""
updatedClass = _oldstyle._oldStyle(SomeOldStyleClass)
self.assertEqual(type(updatedClass), type(SomeOldStyleClass))
self.assertIs(updatedClass, SomeOldStyleClass)
if _PY3:
test_onlyOldStyleMayBeDecorated.skip = "Only relevant on Py2."
if _skip:
test_makesNewStyle.skip = _skip
test_carriesAttributes.skip = _skip
else:
test_noOpByDefault.skip = ("Only relevant when not running under "
"TWISTED_NEWSTYLE=1")
class NewStyleOnly(object):
"""
A base testclass that takes a module and tests if the classes defined
in it are old-style.
CAVEATS: This is maybe slightly dumb. It doesn't look inside functions, for
classes defined there, or nested classes.
"""
skip = _skip
def test_newStyleClassesOnly(self):
"""
Test that C{self.module} has no old-style classes in it.
"""
try:
module = namedAny(self.module)
except ImportError as e:
raise unittest.SkipTest("Not importable: {}".format(e))
oldStyleClasses = []
for name, val in inspect.getmembers(module):
if hasattr(val, "__module__") \
and val.__module__ == self.module:
if isinstance(val, types.ClassType):
oldStyleClasses.append(fullyQualifiedName(val))
if oldStyleClasses:
self.todo = "Not all classes are made new-style yet. See #8243."
for x in forbiddenModules:
if self.module.startswith(x):
delattr(self, "todo")
raise unittest.FailTest(
"Old-style classes in {module}: {val}".format(
module=self.module,
val=", ".join(oldStyleClasses)))
def _buildTestClasses(_locals):
"""
Build the test classes that use L{NewStyleOnly}, one class per module.
@param _locals: The global C{locals()} dict.
"""
for x in getModule("twisted").walkModules():
ignoredModules = [
"twisted.test.reflect_helper",
"twisted.internet.test.process_",
"twisted.test.process_"
]
isIgnored = [x.name.startswith(ignored) for ignored in ignoredModules]
if True in isIgnored:
continue
class Test(NewStyleOnly, unittest.TestCase):
"""
@see: L{NewStyleOnly}
"""
module = x.name
acceptableName = x.name.replace(".", "_")
Test.__name__ = acceptableName
if hasattr(Test, "__qualname__"):
Test.__qualname__ = acceptableName
_locals.update({acceptableName: Test})
_buildTestClasses(locals())