1# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
2# vi: set ft=python sts=4 ts=4 sw=4 et:
3"""
4Decorators for dipy tests
5"""
6
7import re
8import os
9import platform
10
11
12SKIP_RE = re.compile("(\s*>>>.*?)(\s*)#\s*skip\s+if\s+(.*)$")
13
14
15def doctest_skip_parser(func):
16    """Decorator replaces custom skip test markup in doctests.
17
18    Say a function has a docstring::
19
20        >>> something # skip if not HAVE_AMODULE
21        >>> something + else
22        >>> something # skip if HAVE_BMODULE
23
24    This decorator will evaluate the expresssion after ``skip if``.  If this
25    evaluates to True, then the comment is replaced by ``# doctest: +SKIP``.
26    If False, then the comment is just removed. The expression is evaluated in
27    the ``globals`` scope of `func`.
28
29    For example, if the module global ``HAVE_AMODULE`` is False, and module
30    global ``HAVE_BMODULE`` is False, the returned function will have
31    docstring::
32        >>> something # doctest: +SKIP
33        >>> something + else
34        >>> something
35
36    """
37    lines = func.__doc__.split('\n')
38    new_lines = []
39    for line in lines:
40        match = SKIP_RE.match(line)
41        if match is None:
42            new_lines.append(line)
43            continue
44        code, space, expr = match.groups()
45        if eval(expr, func.__globals__):
46            code = code + space + "# doctest: +SKIP"
47        new_lines.append(code)
48    func.__doc__ = "\n".join(new_lines)
49    return func
50
51###
52# In some cases (e.g., on Travis), we want to use a virtual frame-buffer for
53# testing. The following decorator runs the tests under xvfb (mediated by
54# xvfbwrapper) conditioned on an environment variable (that we set in
55# .travis.yml for these cases):
56use_xvfb = os.environ.get('TEST_WITH_XVFB', False)
57is_windows = platform.system().lower() == "windows"
58
59
60def xvfb_it(my_test):
61    """Run a test with xvfbwrapper."""
62    # When we use verbose testing we want the name:
63    fname = my_test.__name__
64
65    def test_with_xvfb(*args, **kwargs):
66        if use_xvfb:
67            from xvfbwrapper import Xvfb
68            display = Xvfb(width=1920, height=1080)
69            display.start()
70        my_test(*args, **kwargs)
71        if use_xvfb:
72            display.stop()
73    # Plant it back in and return the new function:
74    test_with_xvfb.__name__ = fname
75    return test_with_xvfb if not is_windows else my_test
76