10000 merge 3.3-slp (Stackless #114) · akruis/cpython@5dbc669 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5dbc669

Browse files
author
Anselm Kruis
committed
merge 3.3-slp (Stackless python#114)
2 parents 7a8a196 + 851b549 commit 5dbc669

File tree

4 files changed

+121
-106
lines changed

4 files changed

+121
-106
lines changed

Stackless/unittests/support.py

Lines changed: 101 additions & 27 deletions
< 8000 /tr>
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@
2929
import weakref
3030
import pickle
3131
import inspect
32-
from io import StringIO
32+
import io
3333
import contextlib
3434
import gc
3535

3636
# emit warnings about uncollectable objects
3737
gc.set_debug(gc.DEBUG_UNCOLLECTABLE)
3838
try:
39-
long
39+
long # @UndefinedVariable
4040
except NameError:
4141
long = int # @ReservedAssignment
4242

@@ -50,7 +50,7 @@
5050
@contextlib.contextmanager
5151
def captured_stderr():
5252
old = sys.stderr
53-
new = StringIO()
53+
new = io.StringIO()
5454
sys.stderr = new
5555
try:
5656
yield new
@@ -172,6 +172,77 @@ def __init__(cls, *args, **kw):
172172

173173
class StacklessTestCase(unittest.TestCase, StacklessTestCaseMixin, metaclass=StacklessTestCaseMeta):
174174

175+
@classmethod
176+
def prepare_test_method(cls, func, name):
177+
"""Called after class creation
178+
179+
This method creates the _H methods, which run without
180+
soft switching
181+
"""
182+
if hasattr(func, "enable_softswitch") and not getattr(func, "_H_created", False):
183+
return ((func, name), )
184+
185+
def wrapper_hardswitch(self, method=func):
186+
self.assertTrue(self.__setup_called, "Broken test case: it didn't call super(..., self).setUp()")
187+
self.assertFalse(stackless.enable_softswitch(None), "softswitch is enabled")
188+
return method(self)
189+
wrapper_hardswitch.enable_softswitch = False
190+
wrapper_hardswitch.__name__ = name + "_H"
191+
if func.__doc__:
192+
doc = func.__doc__
193+
if doc.startswith("(soft) "):
194+
doc = doc[7:]
195+
wrapper_hardswitch.__doc__ = "(hard) " + doc
196+
setattr(cls, wrapper_hardswitch.__name__, wrapper_hardswitch)
197+
198+
if not hasattr(func, "_H_created"):
199+
func._H_created = True
200+
func.enable_softswitch = True
201+
if func.__doc__:
202+
func.__doc__ = "(soft) " + func.__doc__
203+
return ((func, name), (wrapper_hardswitch, wrapper_hardswitch.__name__))
204+
205+
@classmethod
206+
def prepare_pickle_test_method(cls, func, name=None):
207+
"""Called after class creation
208+
209+
This method creates the Py0...n C0...n methods, which run with
210+
the Python or C implementation of the enumerated pickle protocol.
211+
212+
This method also acts as a method decorator.
213+
"""
214+
if name is None:
215+
# used as a decorator
216+
func.prepare = cls.prepare_pickle_test_method
217+
return func
218+
219+
if hasattr(func, "_pickle_created"):
220+
return StacklessTestCase.prepare_test_method.__func__(cls, func, name)
221+
setattr(cls, name, None)
222+
r = []
223+
for i in range(0, pickle.HIGHEST_PROTOCOL + 1):
224+
for p_letter in ("C", "P"):
225+
def test(self, method=func, proto=i, pickle_module=p_letter, unpickle_module=p_letter):
226+
self.assertTrue(self._StacklessTestCase__setup_called, "Broken test case: it didn't call super(..., self).setUp()")
227+
self._pickle_protocol = proto
228+
self._pickle_module = pickle_module
229+
self._unpickle_module = unpickle_module
230+
return method(self)
231+
if i == 0 and p_letter == "C":
232+
test.__name__ = name
233+
else:
234+
test.__name__ = "{:s}_{:s}{:d}".format(name, p_letter, i)
235+
test._pickle_created = True
236+
if func.__doc__:
237+
doc = func.__doc__
238+
match = re.match(r"\([PC][0-{:d}]\)".format(pickle.HIGHEST_PROTOCOL), doc)
239+
if match:
240+
doc = match.string[match.end():]
241+
test.__doc__ = "({:s}{:d}) {:s}".format(p_letter, i, doc)
242+
setattr(cls, test.__name__, test)
243+
r.extend(StacklessTestCase.prepare_test_method.__func__(cls, test, test.__name__))
244+
return r
245+
175246
@classmethod
176247
def prepare_test_methods(cls):
177248
"""Called after class creation
@@ -183,29 +254,10 @@ def prepare_test_methods(cls):
183254
for n in names:
184255
m = getattr(cls, n)
185256
if inspect.ismethod(m):
186-
m = m.im_func
187-
if hasattr(m, "enable_softswitch") and not getattr(m, "_H_created", False):
188-
continue
189-
190-
def wrapper_hardswitch(self, method=m):
191-
self.assertTrue(self.__setup_called, "Broken test case: it didn't call super(..., self).setUp()")
192-
self.assertFalse(stackless.enable_softswitch(None), "softswitch is enabled")
193-
return method(self)
194-
wrapper_hardswitch.enable_softswitch = False
195-
wrapper_hardswitch.__name__ = n + "_H"
196-
if m.__doc__:
197-
doc = m.__doc__
198-
if doc.startswith("(soft) "):
199-
doc = doc[7:]
200-
wrapper_hardswitch.__doc__ = "(hard) " + doc
201-
setattr(cls, wrapper_hardswitch.__name__, wrapper_hardswitch)
202-
203-
if hasattr(m, "_H_created"):
204-
continue
205-
m._H_created = True
206-
m.enable_softswitch = True
207-
if m.__doc__:
208-
m.__doc__ = "(soft) " + m.__doc__
257+
m = m.__func__
258+
prepare = getattr(m, "prepare", cls.prepare_test_method)
259+
for x in prepare.__func__(cls, m, n):
260+
pass
209261

210262
__setup_called = False
211263
__preexisting_threads = None
@@ -233,7 +285,7 @@ def setUpStacklessTestCase(self):
233285
234286
This method must be called from :meth:`setUp`.
235287
"""
236-
self.__setup_called = True
288+
self._StacklessTestCase__setup_called = True
237289
self.addCleanup(stackless.enable_softswitch, stackless.enable_softswitch(self.__enable_softswitch))
238290

239291
self.__active_test_cases[id(self)] = self
@@ -278,6 +330,20 @@ def tearDown(self):
278330
self.assertEqual(active_count, expected_thread_count, "Leakage from other threads, with %d threads running (%d expected)" % (active_count, expected_thread_count))
279331
gc.collect() # emits warnings about uncollectable objects after each test
280332

333+
def dumps(self, obj, protocol=None, *, fix_imports=True):
334+
if self._pickle_module == "P":
335+
return pickle._dumps(obj, protocol=protocol, fix_imports=fix_imports)
336+
elif self._pickle_module == "C":
337+
return pickle.dumps(obj, protocol=protocol, fix_imports=fix_imports)
338+
raise ValueError("Invalid pickle module")
339+
340+
def loads(self, s, *, fix_imports=True, encoding="ASCII", errors="strict"):
341+
if self._pickle_module == "P":
342+
return pickle._loads(s, fix_imports=fix_imports, encoding=encoding, errors=errors)
343+
elif self._pickle_module == "C":
344+
return pickle.loads(s, fix_imports=fix_imports, encoding=encoding, errors=errors)
345+
raise ValueError("Invalid pickle module")
346+
281347
# limited pickling support for test cases
282348
# Between setUp() and tearDown() the test-case has a
283349
# working __reduce__ method. Later the test case gets pickled by
@@ -331,6 +397,14 @@ def _addSkip(self, result, reason):
331397
del _tc
332398

333399

400+
class StacklessPickleTestCase(StacklessTestCase):
401+
"""A test case class for pickle tests"""
402+
403+
@classmethod
404+
def prepare_test_method(cls, func, name):
405+
return cls.prepare_pickle_test_method(func, name)
406+
407+
334408
def restore_testcase_from_id(id_):
335409
return StacklessTestCase.restore_testcase_from_id(id_)
336410

Stackless/unittests/test_miscell.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# import common
22

3-
import pickle
43
import unittest
54
import stackless
65
import sys
@@ -82,14 +81,16 @@ def test_aliveness1(self):
8281
t = stackless.tasklet(runtask)()
8382
self.lifecycle(t)
8483

84+
@StacklessTestCase.prepare_pickle_test_method
8585
def test_aliveness2(self):
8686
""" Same as 1, but with a pickled unrun tasklet. """
8787
t = stackless.tasklet(runtask)()
88-
t_new = pickle.loads(pickle.dumps((t)))
88+
t_new = self.loads(self.dumps((t)))
8989
t.remove()
9090
t_new.insert()
9191
self.lifecycle(t_new)
9292

93+
@StacklessTestCase.prepare_pickle_test_method
9394
def test_aliveness3(self):
9495
""" Same as 1, but with a pickled run(slightly) tasklet. """
9596

@@ -114,8 +115,8 @@ def test_aliveness3(self):
114115
self.assertEqual(t.recursion_depth, softSwitching and 1 or 2)
115116

116117
# Now save & load
117-
dumped = pickle.dumps(t)
118-
t_new = pickle.loads(dumped)
118+
dumped = self.dumps(t)
119+
t_new = self.loads(dumped)
119120

120121
# Remove and insert & swap names around a bit
121122
t.remove()

Stackless/unittests/test_pickle.py

Lines changed: 8 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import sys
22
import types
33
import unittest
4-
import pickle
54
import gc
65
import inspect
76

87
from stackless import schedule, tasklet, stackless
98

10-
from support import StacklessTestCase
9+
from support import StacklessTestCase, StacklessPickleTestCase
1110

1211

1312
# because test runner instances in the testsuite contain copies of the old stdin/stdout thingies,
@@ -244,28 +243,10 @@ def is_soft():
244243
return softswitch
245244

246245

247-
class PyPickleMixin(object):
248-
249-
def dumps(self, obj, protocol=None, *, fix_imports=True):
250-
return pickle._dumps(obj, protocol=protocol, fix_imports=fix_imports)
251-
252-
def loads(self, s, *, fix_imports=True, encoding="ASCII", errors="strict"):
253-
return pickle._loads(s, fix_imports=fix_imports, encoding=encoding, errors=errors)
254-
255-
256-
class CPickleMixin(object):
257-
258-
def dumps(self, obj, protocol=None, *, fix_imports=True):
259-
return pickle.dumps(obj, protocol=protocol, fix_imports=fix_imports)
260-
261-
def loads(self, s, *, fix_imports=True, encoding="ASCII", errors="strict"):
262-
return pickle.loads(s, fix_imports=fix_imports, encoding=encoding, errors=errors)
263-
264-
265-
class AbstractTestPickledTasklets(StacklessTestCase):
246+
class TestPickledTasklets(StacklessPickleTestCase):
266247

267248
def setUp(self):
268-
super(AbstractTestPickledTasklets, self).setUp()
249+
super(TestPickledTasklets, self).setUp()
269250
self.verbose = VERBOSE
270251

271252
def tearDown(self):
@@ -278,7 +259,7 @@ def tearDown(self):
278259
current.kill()
279260
current = next
280261

281-
super(AbstractTestPickledTasklets, self).tearDown()
262+
super(TestPickledTasklets, self).tearDown()
282263

283264
del self.verbose
284265

@@ -325,24 +306,6 @@ def run_pickled(self, func, *args):
325306
self.assertNotEqual(new_ident, old_ident)
326307
self.assertEqual(is_empty(), True)
327308

328-
# compatibility to 2.2.3
329-
global have_enumerate
330-
try:
331-
enumerate
332-
have_enumerate = True
333-
except NameError:
334-
have_enumerate = False
335-
336-
global have_fromkeys
337-
try:
338-
{}.fromkeys
339-
have_fromkeys = True
340-
except AttributeError:
341-
have_fromkeys = False
342-
343-
344-
class PickledTaskletTestCases(object):
345-
346309
def testClassPersistence(self):
347310
t1 = CustomTasklet(nothing)()
348311
s = self.dumps(t1)
@@ -382,9 +345,8 @@ def testDictIteritems(self):
382345
def testSet(self):
383346
self.run_pickled(settest, 20, 13)
384347

385-
if have_enumerate:
386-
def testEnumerate(self):
387-
self.run_pickled(enumeratetest, 20, 13)
348+
def testEnumerate(self):
349+
self.run_pickled(enumeratetest, 20, 13)
388350

389351
def testTuple(self):
390352
self.run_pickled(tupletest, 20, 13)
@@ -530,14 +492,6 @@ def testFunctionModulePreservation(self):
530492
self.assertEqual(f1.__module__, f2.__module__)
531493

532494

533-
class TestPickledTaskletsPy(AbstractTestPickledTasklets, PickledTaskletTestCases, PyPickleMixin):
534-
pass
535-
536-
537-
class TestPickledTaskletsC(AbstractTestPickledTasklets, PickledTaskletTestCases, CPickleMixin):
538-
pass
539-
540-
541495
class TestFramePickling(StacklessTestCase):
542496

543497
def testLocalplus(self):
@@ -578,7 +532,7 @@ def func(current):
578532
self.assertIs(cell.cell_contents, result)
579533

580534

581-
class DictViewPicklingTestCases(object):
535+
class TestDictViewPickling(StacklessPickleTestCase):
582536

583537
def testDictKeyViewPickling(self):
584538
# stackless python prior to 2.7.3 used to register its own __reduce__
@@ -600,15 +554,7 @@ def testDictValueViewPickling(self):
600554
self.assertEqual(list(view1), list(view2))
601555

602556

603-
class TestDictViewPicklingPy(AbstractTestPickledTasklets, DictViewPicklingTestCases, PyPickleMixin):
604-
pass
605-
606-
607-
class TestDictViewPicklingC(AbstractTestPickledTasklets, DictViewPicklingTestCases, CPickleMixin):
608-
pass
609-
610-
611-
class Traceback_TestCases(object):
557+
class TestTraceback(StacklessPickleTestCase):
612558
def testTracebackFrameLinkage(self):
613559
def a():
614560
# raise an exception
@@ -644,13 +590,6 @@ def c():
644590
self.assertListEqual([i[1:] for i in all_outerframes_orig[:l - 1]], [i[1:] for i in all_outerframes[:l - 1]])
645591

646592

647-
class TestTracebackPy(StacklessTestCase, Traceback_TestCases, PyPickleMixin):
648-
pass
649-
650-
651-
class TestTracebackC(StacklessTestCase, Traceback_TestCases, CPickleMixin):
652-
pass
653-
654593
if __name__ == '__main__':
655594
if not sys.argv[1:]:
656595
sys.argv.append('-v')

0 commit comments

Comments
 (0)
0