Skip to content

Commit 217fab5

Browse files
author
deathaxe
authored
Refactor generator detection (#252)
Use `isinstance(obj, Iterable)` to detect generator functions in python 3.3 environment and `isinstance(obj, Generator)` on python 3.8.
1 parent d9807b4 commit 217fab5

11 files changed

+60
-56
lines changed

tests/test_3141596.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
from functools import wraps
77
from unittest import skipIf
88
from unittesting import AWAIT_WORKER
9+
from unittesting import DeferrableMethod
910
from unittesting import DeferrableTestCase
10-
from unittesting.utils import isiterable
1111

1212
BASEDIR = os.path.dirname(os.path.abspath(__file__))
1313

@@ -83,7 +83,7 @@ def condition():
8383
txt = f.read()
8484

8585
deferred = func(self, txt)
86-
if isiterable(deferred):
86+
if isinstance(deferred, DeferrableMethod):
8787
yield from deferred
8888

8989
yield

unittesting/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from .core import AWAIT_WORKER
2+
from .core import DeferrableMethod
23
from .core import DeferrableTestCase
34
from .core import expectedFailure
45
from .helpers import DeferrableViewTestCase
@@ -10,6 +11,7 @@
1011

1112
__all__ = [
1213
"AWAIT_WORKER",
14+
"DeferrableMethod",
1315
"DeferrableTestCase",
1416
"expectedFailure",
1517
"run_scheduler",

unittesting/core/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import sys
22

33
if sys.version_info >= (3, 8):
4+
from .py38.case import DeferrableMethod
45
from .py38.case import DeferrableTestCase
56
from .py38.case import expectedFailure
67
from .py38.runner import AWAIT_WORKER
78
from .py38.runner import DeferringTextTestRunner
89
from .py38.suite import DeferrableTestSuite
910
else:
11+
from .py33.case import DeferrableMethod
1012
from .py33.case import DeferrableTestCase
1113
from .py33.case import expectedFailure
1214
from .py33.runner import AWAIT_WORKER
@@ -17,6 +19,7 @@
1719

1820
__all__ = [
1921
"AWAIT_WORKER",
22+
"DeferrableMethod",
2023
"DeferrableTestCase",
2124
"DeferrableTestSuite",
2225
"DeferringTextTestRunner",

unittesting/core/py33/case.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import sys
22
import warnings
33

4+
from collections.abc import Iterable as DeferrableMethod
45
from functools import wraps
56
from unittest import TestCase
67
from unittest.case import _ExpectedFailure
78
from unittest.case import _Outcome
89
from unittest.case import _UnexpectedSuccess
910
from unittest.case import SkipTest
1011

11-
from ...utils import isiterable
12+
1213
from .runner import defer
1314

1415
__all__ = [
@@ -22,7 +23,7 @@ def expectedFailure(func):
2223
def wrapper(*args, **kwargs):
2324
try:
2425
deferred = func(*args, **kwargs)
25-
if isiterable(deferred):
26+
if isinstance(deferred, DeferrableMethod):
2627
yield from deferred
2728
except Exception:
2829
raise _ExpectedFailure(sys.exc_info())
@@ -35,7 +36,7 @@ class DeferrableTestCase(TestCase):
3536
def _executeTestPart(self, function, outcome, isTest=False):
3637
try:
3738
deferred = function()
38-
if isiterable(deferred):
39+
if isinstance(deferred, DeferrableMethod):
3940
yield from deferred
4041
except KeyboardInterrupt:
4142
raise

unittesting/core/py33/suite.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from unittest.suite import _isnotsuite
55
from unittest.suite import TestSuite
66

7-
from ...utils import isiterable
7+
from .case import DeferrableMethod
88

99

1010
class DeferrableTestSuite(TestSuite):
@@ -20,13 +20,13 @@ def run(self, result, debug=False):
2020

2121
if _isnotsuite(test):
2222
deferred = self._tearDownPreviousClass(test, result)
23-
if isiterable(deferred):
23+
if isinstance(deferred, DeferrableMethod):
2424
yield from deferred
2525
yield
2626
self._handleModuleFixture(test, result)
2727
yield
2828
deferred = self._handleClassSetUp(test, result)
29-
if isiterable(deferred):
29+
if isinstance(deferred, DeferrableMethod):
3030
yield from deferred
3131
yield
3232
result._previousTestClass = test.__class__
@@ -40,14 +40,14 @@ def run(self, result, debug=False):
4040
else:
4141
deferred = test.debug()
4242

43-
if isiterable(deferred):
43+
if isinstance(deferred, DeferrableMethod):
4444
yield from deferred
4545

4646
yield
4747

4848
if topLevel:
4949
deferred = self._tearDownPreviousClass(None, result)
50-
if isiterable(deferred):
50+
if isinstance(deferred, DeferrableMethod):
5151
yield from deferred
5252
yield
5353
yield
@@ -77,7 +77,7 @@ def _handleClassSetUp(self, test, result):
7777
_call_if_exists(result, '_setupStdout')
7878
try:
7979
deferred = setUpClass()
80-
if isiterable(deferred):
80+
if isinstance(deferred, DeferrableMethod):
8181
yield from deferred
8282
except Exception as e:
8383
if isinstance(result, _DebugResult):
@@ -106,7 +106,7 @@ def _tearDownPreviousClass(self, test, result):
106106
_call_if_exists(result, '_setupStdout')
107107
try:
108108
deferred = tearDownClass()
109-
if isiterable(deferred):
109+
if isinstance(deferred, DeferrableMethod):
110110
yield from deferred
111111
except Exception as e:
112112
if isinstance(result, _DebugResult):

unittesting/core/py38/case.py

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import sys
22

3+
from collections.abc import Generator as DeferrableMethod
34
from unittest import TestCase
45
from unittest.case import _Outcome
56
from unittest.case import expectedFailure
67

7-
from ...utils import isiterable
88
from .runner import defer
99

1010
__all__ = [
@@ -17,22 +17,22 @@ class DeferrableTestCase(TestCase):
1717

1818
def _callSetUp(self):
1919
deferred = self.setUp()
20-
if isiterable(deferred):
20+
if isinstance(deferred, DeferrableMethod):
2121
yield from deferred
2222

2323
def _callTestMethod(self, method):
2424
deferred = method()
25-
if isiterable(deferred):
25+
if isinstance(deferred, DeferrableMethod):
2626
yield from deferred
2727

2828
def _callTearDown(self):
2929
deferred = self.tearDown()
30-
if isiterable(deferred):
30+
if isinstance(deferred, DeferrableMethod):
3131
yield from deferred
3232

3333
def _callCleanup(self, function, *args, **kwargs):
3434
deferred = function(*args, **kwargs)
35-
if isiterable(deferred):
35+
if isinstance(deferred, DeferrableMethod):
3636
yield from deferred
3737

3838
@staticmethod
@@ -71,22 +71,22 @@ def run(self, result=None):
7171

7272
with outcome.testPartExecutor(self):
7373
deferred = self._callSetUp()
74-
if isiterable(deferred):
74+
if isinstance(deferred, DeferrableMethod):
7575
yield from deferred
7676
if outcome.success:
7777
outcome.expecting_failure = expecting_failure
7878
with outcome.testPartExecutor(self, isTest=True):
7979
deferred = self._callTestMethod(testMethod)
80-
if isiterable(deferred):
80+
if isinstance(deferred, DeferrableMethod):
8181
yield from deferred
8282
outcome.expecting_failure = False
8383
with outcome.testPartExecutor(self):
8484
deferred = self._callTearDown()
85-
if isiterable(deferred):
85+
if isinstance(deferred, DeferrableMethod):
8686
yield from deferred
8787

8888
deferred = self.doCleanups()
89-
if isiterable(deferred):
89+
if isinstance(deferred, DeferrableMethod):
9090
yield from deferred
9191
for test, reason in outcome.skipped:
9292
self._addSkip(result, test, reason)
@@ -123,7 +123,7 @@ def doCleanups(self):
123123
function, args, kwargs = self._cleanups.pop()
124124
with outcome.testPartExecutor(self):
125125
deferred = self._callCleanup(function, *args, **kwargs)
126-
if isiterable(deferred):
126+
if isinstance(deferred, DeferrableMethod):
127127
yield from deferred
128128

129129
# return this for backwards compatibility
@@ -138,14 +138,14 @@ def doClassCleanups(cls):
138138
function, args, kwargs = cls._class_cleanups.pop()
139139
try:
140140
deferred = function(*args, **kwargs)
141-
if isiterable(deferred):
141+
if isinstance(deferred, DeferrableMethod):
142142
yield from deferred
143143
except Exception:
144144
cls.tearDown_exceptions.append(sys.exc_info())
145145

146146
def __call__(self, *args, **kwds):
147147
deferred = self.run(*args, **kwds)
148-
if isiterable(deferred):
148+
if isinstance(deferred, DeferrableMethod):
149149
yield from deferred
150150
else:
151151
return deferred

unittesting/core/py38/suite.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from unittest.suite import _isnotsuite
55
from unittest.suite import TestSuite
66

7-
from ...utils import isiterable
7+
from .case import DeferrableMethod
88

99

1010
class DeferrableTestSuite(TestSuite):
@@ -20,13 +20,13 @@ def run(self, result, debug=False):
2020

2121
if _isnotsuite(test):
2222
deferred = self._tearDownPreviousClass(test, result)
23-
if isiterable(deferred):
23+
if isinstance(deferred, DeferrableMethod):
2424
yield from deferred
2525
yield
2626
self._handleModuleFixture(test, result)
2727
yield
2828
deferred = self._handleClassSetUp(test, result)
29-
if isiterable(deferred):
29+
if isinstance(deferred, DeferrableMethod):
3030
yield from deferred
3131
yield
3232
result._previousTestClass = test.__class__
@@ -43,14 +43,14 @@ def run(self, result, debug=False):
4343
if self._cleanup:
4444
self._removeTestAtIndex(index)
4545

46-
if isiterable(deferred):
46+
if isinstance(deferred, DeferrableMethod):
4747
yield from deferred
4848

4949
yield
5050

5151
if topLevel:
5252
deferred = self._tearDownPreviousClass(None, result)
53-
if isiterable(deferred):
53+
if isinstance(deferred, DeferrableMethod):
5454
yield from deferred
5555
yield
5656
yield
@@ -80,7 +80,7 @@ def _handleClassSetUp(self, test, result):
8080
_call_if_exists(result, '_setupStdout')
8181
try:
8282
deferred = setUpClass()
83-
if isiterable(deferred):
83+
if isinstance(deferred, DeferrableMethod):
8484
yield from deferred
8585
except Exception as e:
8686
if isinstance(result, _DebugResult):
@@ -94,7 +94,7 @@ def _handleClassSetUp(self, test, result):
9494
_call_if_exists(result, '_restoreStdout')
9595
if currentClass._classSetupFailed is True:
9696
deferred = currentClass.doClassCleanups()
97-
if isiterable(deferred):
97+
if isinstance(deferred, DeferrableMethod):
9898
yield from deferred
9999
if len(currentClass.tearDown_exceptions) > 0:
100100
for exc in currentClass.tearDown_exceptions:
@@ -119,7 +119,7 @@ def _tearDownPreviousClass(self, test, result):
119119
_call_if_exists(result, '_setupStdout')
120120
try:
121121
deferred = tearDownClass()
122-
if isiterable(deferred):
122+
if isinstance(deferred, DeferrableMethod):
123123
yield from deferred
124124
except Exception as e:
125125
if isinstance(result, _DebugResult):
@@ -131,7 +131,7 @@ def _tearDownPreviousClass(self, test, result):
131131
finally:
132132
_call_if_exists(result, '_restoreStdout')
133133
deferred = previousClass.doClassCleanups()
134-
if isiterable(deferred):
134+
if isinstance(deferred, DeferrableMethod):
135135
yield from deferred
136136
if len(previousClass.tearDown_exceptions) > 0:
137137
for exc in previousClass.tearDown_exceptions:

unittesting/helpers/override_preferences_test_cast.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import shutil
44
import sublime
55

6+
from ..core import DeferrableMethod
67
from ..core import DeferrableTestCase
78

89

@@ -32,9 +33,9 @@ def setUpClass(cls):
3233
yield 500
3334
s.clear_on_change(on_change_key)
3435

35-
x = super().setUpClass()
36-
if hasattr(x, '__iter__'):
37-
yield from x
36+
deferred = super().setUpClass()
37+
if isinstance(deferred, DeferrableMethod):
38+
yield from deferred
3839

3940
@classmethod
4041
def tearDownClass(cls):
@@ -49,6 +50,6 @@ def tearDownClass(cls):
4950
except Exception:
5051
pass
5152

52-
x = super().tearDownClass()
53-
if hasattr(x, '__iter__'):
54-
yield from x
53+
deferred = super().tearDownClass()
54+
if isinstance(deferred, DeferrableMethod):
55+
yield from deferred

0 commit comments

Comments
 (0)