1from __future__ import absolute_import, unicode_literals
2
3import importlib
4import os
5import sys
6
7from nose import SkipTest
8
9from .utils import decorator, symbol_by_name
10
11__all__ = [
12    'todo',
13    'if_darwin', 'unless_darwin',
14    'if_environ', 'unless_environ',
15    'if_module', 'unless_module',
16    'if_jython', 'unless_jython',
17    'if_platform', 'unless_platform',
18    'if_pypy', 'unless_pypy',
19    'if_python3', 'unless_python3',
20    'if_win32', 'unless_win32',
21    'if_symbol', 'unless_symbol',
22    'if_python_version_after', 'if_python_version_before',
23]
24
25
26@decorator
27def if_python_version_before(*version, **kwargs):
28    """Skip test if Python version is less than ``*version``.
29
30    Example::
31
32        # skips test if running on Python < 3.1
33        @skip.if_python_version_before(3, 1)
34
35    """
36    if sys.version_info < version:
37        raise SkipTest('python < {0}: {1}'.format(
38            '.'.join(map(str, version)),
39            kwargs.get('reason') or 'incompatible'))
40    yield
41
42
43@decorator
44def if_python_version_after(*version, **kwargs):
45    """Skip test if Python version is greater or equal to ``*version``.
46
47    Example::
48
49        # skips test if running on Python >= 3.5
50        @skip.if_python_version_after(3, 5)
51
52    """
53    if sys.version_info >= version:
54        raise SkipTest('python >= {0}: {1}'.format(
55            '.'.join(map(str, version)),
56            kwargs.get('reason') or 'incompatible'))
57    yield
58
59
60def if_python3(*version, **kwargs):
61    """Skip test if Python version is 3 or later.
62
63    Example::
64
65        @skip.if_python3(reason='does not have buffer type')
66
67    """
68    return if_python_version_after(3, *version, **kwargs)
69
70
71def unless_python3(*version, **kwargs):
72    """Skip test if Python version is Python 2 or earlier.
73
74    Example::
75
76        @skip.unless_python3()
77
78    """
79    return if_python_version_before(3, *version, **kwargs)
80
81
82@decorator
83def if_environ(env_var_name):
84    """Skip test if environment variable ``env_var_name`` is defined.
85
86    Example::
87
88        @skip.if_environ('SKIP_SLOW_TESTS')
89
90    """
91    if os.environ.get(env_var_name):
92        raise SkipTest('envvar {0} set'.format(env_var_name))
93    yield
94
95
96@decorator
97def unless_environ(env_var_name):
98    """Skip test if environment variable ``env_var_name`` is undefined.
99
100    Example::
101
102        @skip.unless_environ('LOCALE')
103
104    """
105    if not os.environ.get(env_var_name):
106        raise SkipTest('envvar {0} not set'.format(env_var_name))
107    yield
108
109
110@decorator
111def _skip_test(reason, sign):
112    raise SkipTest('{0}: {1}'.format(sign, reason))
113
114
115def todo(reason):
116    """Skip test flagging case as TODO.
117
118    Example::
119
120        @skip.todo(reason='broken test')
121
122    """
123    return _skip_test(reason, sign='TODO')
124
125
126def skip(reason):
127    return _skip_test(reason, sign='SKIP')
128
129
130@decorator
131def if_module(module, name=None, import_errors=(ImportError,)):
132    """Skip test if ``module`` can be imported.
133
134    :param module: Module to import.
135    :keyword name: Alternative module name to use in reason.
136    :keyword import_errors: Tuple of import errors to check for.
137        Default is ``(ImportError,)``.
138
139    Example::
140
141        @skip.if_module('librabbitmq')
142
143    """
144    try:
145        importlib.import_module(module)
146    except import_errors:
147        pass
148    else:
149        raise SkipTest('module available: {0}'.format(name or module))
150    yield
151
152
153@decorator
154def unless_module(module, name=None, import_errors=(ImportError,)):
155    """Skip test if ``module`` can not be imported.
156
157    :param module: Module to import.
158    :keyword name: Alternative module name to use in reason.
159    :keyword import_errors: Tuple of import errors to check for.
160        Default is ``(ImportError,)``.
161
162    Example::
163
164        @skip.unless_module('librabbitmq')
165
166    """
167    try:
168        importlib.import_module(module)
169    except import_errors:
170        raise SkipTest('module not installed: {0}'.format(name or module))
171    yield
172
173
174@decorator
175def if_symbol(symbol, name=None,
176              import_errors=(AttributeError, ImportError)):
177    """Skip test if ``symbol`` can be imported.
178
179    :param module: Symbol to import.
180    :keyword name: Alternative symbol name to use in reason.
181    :keyword import_errors: Tuple of import errors to check for.
182        Default is ``(AttributeError, ImportError,)``.
183
184    Example::
185
186        @skip.if_symbol('django.db.transaction:on_commit')
187
188    """
189    try:
190        symbol_by_name(symbol)
191    except import_errors:
192        pass
193    else:
194        raise SkipTest('symbol exists: {0}'.format(name or symbol))
195    yield
196
197
198@decorator
199def unless_symbol(symbol, name=None,
200                  import_errors=(AttributeError, ImportError)):
201    """Skip test if ``symbol`` cannot be imported.
202
203    :param module: Symbol to import.
204    :keyword name: Alternative symbol name to use in reason.
205    :keyword import_errors: Tuple of import errors to check for.
206        Default is ``(AttributeError, ImportError,)``.
207
208    Example::
209
210        @skip.unless_symbol('django.db.transaction:on_commit')
211
212    """
213    try:
214        symbol_by_name(symbol)
215    except import_errors:
216        raise SkipTest('missing symbol: {0}'.format(name or symbol))
217    yield
218
219
220@decorator
221def if_platform(platform_name, name=None):
222    """Skip test if :data:`sys.platform` name matches ``platform_name``.
223
224    :param platform_name: Name to match with :data:`sys.platform`.
225    :keyword name: Alternative name to use in reason.
226
227    Example::
228
229        @skip.if_platform('netbsd', name='NetBSD')
230
231    """
232    if sys.platform.startswith(platform_name):
233        raise SkipTest('does not work on {0}'.format(platform_name or name))
234    yield
235
236
237def if_jython():
238    """Skip test if running under Jython.
239
240    Example::
241
242        @skip.if_jython()
243
244    """
245    return if_platform('java', name='Jython')
246
247
248def if_win32():
249    """Skip test if running under Windows.
250
251    Example::
252
253        @skip.if_win32()
254
255    """
256    return if_platform('win32', name='Windows')
257
258
259def if_darwin():
260    """Skip test if running under OS X.
261
262    Example::
263
264        @skip.if_darwin()
265
266    """
267    return if_platform('darwin', name='OS X')
268
269
270@decorator
271def unless_platform(platform_name, name=None):
272    """Skip test if :data:`sys.platform` name does not match ``platform_name``.
273
274    :param platform_name: Name to match with :data:`sys.platform`.
275    :keyword name: Alternative name to use in reason.
276
277    Example::
278
279        @skip.unless_platform('netbsd', name='NetBSD')
280
281    """
282    if not sys.platform.startswith(platform_name):
283        raise SkipTest('only applicable on {0}'.format(platform_name or name))
284    yield
285
286
287def unless_jython():
288    """Skip test if not running under Jython."""
289    return unless_platform('java', name='Jython')
290
291
292def unless_win32():
293    """Skip test if not running under Windows."""
294    return unless_platform('win32', name='Windows')
295
296
297def unless_darwin():
298    """Skip test if not running under OS X."""
299    return unless_platform('darwin', name='OS X')
300
301
302@decorator
303def if_pypy(reason='does not work on PyPy'):
304    """Skip test if running on PyPy.
305
306    Example::
307
308        @skip.if_pypy()
309
310    """
311    if getattr(sys, 'pypy_version_info', None):
312        raise SkipTest(reason)
313    yield
314
315
316@decorator
317def unless_pypy(reason='only applicable for PyPy'):
318    """Skip test if not running on PyPy.
319
320    Example::
321
322        @skip.unless_pypy()
323
324    """
325    if not hasattr(sys, 'pypy_version_info'):
326        raise SkipTest(reason)
327    yield
328