1"""Tests for the decorators we've created for IPython.
2"""
3from __future__ import print_function
4
5# Module imports
6# Std lib
7import inspect
8import sys
9
10# Third party
11import nose.tools as nt
12
13# Our own
14from IPython.testing import decorators as dec
15
16#-----------------------------------------------------------------------------
17# Utilities
18
19# Note: copied from OInspect, kept here so the testing stuff doesn't create
20# circular dependencies and is easier to reuse.
21def getargspec(obj):
22    """Get the names and default values of a function's arguments.
23
24    A tuple of four things is returned: (args, varargs, varkw, defaults).
25    'args' is a list of the argument names (it may contain nested lists).
26    'varargs' and 'varkw' are the names of the * and ** arguments or None.
27    'defaults' is an n-tuple of the default values of the last n arguments.
28
29    Modified version of inspect.getargspec from the Python Standard
30    Library."""
31
32    if inspect.isfunction(obj):
33        func_obj = obj
34    elif inspect.ismethod(obj):
35        func_obj = obj.__func__
36    else:
37        raise TypeError('arg is not a Python function')
38    args, varargs, varkw = inspect.getargs(func_obj.__code__)
39    return args, varargs, varkw, func_obj.__defaults__
40
41#-----------------------------------------------------------------------------
42# Testing functions
43
44@dec.as_unittest
45def trivial():
46    """A trivial test"""
47    pass
48
49
50@dec.skip
51def test_deliberately_broken():
52    """A deliberately broken test - we want to skip this one."""
53    1/0
54
55@dec.skip('Testing the skip decorator')
56def test_deliberately_broken2():
57    """Another deliberately broken test - we want to skip this one."""
58    1/0
59
60
61# Verify that we can correctly skip the doctest for a function at will, but
62# that the docstring itself is NOT destroyed by the decorator.
63def doctest_bad(x,y=1,**k):
64    """A function whose doctest we need to skip.
65
66    >>> 1+1
67    3
68    """
69    print('x:',x)
70    print('y:',y)
71    print('k:',k)
72
73
74def call_doctest_bad():
75    """Check that we can still call the decorated functions.
76
77    >>> doctest_bad(3,y=4)
78    x: 3
79    y: 4
80    k: {}
81    """
82    pass
83
84
85def test_skip_dt_decorator():
86    """Doctest-skipping decorator should preserve the docstring.
87    """
88    # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring!
89    check = """A function whose doctest we need to skip.
90
91    >>> 1+1
92    3
93    """
94    # Fetch the docstring from doctest_bad after decoration.
95    val = doctest_bad.__doc__
96
97    nt.assert_equal(check,val,"doctest_bad docstrings don't match")
98
99
100# Doctest skipping should work for class methods too
101class FooClass(object):
102    """FooClass
103
104    Example:
105
106    >>> 1+1
107    2
108    """
109
110    def __init__(self,x):
111        """Make a FooClass.
112
113        Example:
114
115        >>> f = FooClass(3)
116        junk
117        """
118        print('Making a FooClass.')
119        self.x = x
120
121    def bar(self,y):
122        """Example:
123
124        >>> ff = FooClass(3)
125        >>> ff.bar(0)
126        boom!
127        >>> 1/0
128        bam!
129        """
130        return 1/y
131
132    def baz(self,y):
133        """Example:
134
135        >>> ff2 = FooClass(3)
136        Making a FooClass.
137        >>> ff2.baz(3)
138        True
139        """
140        return self.x==y
141
142
143def test_skip_dt_decorator2():
144    """Doctest-skipping decorator should preserve function signature.
145    """
146    # Hardcoded correct answer
147    dtargs = (['x', 'y'], None, 'k', (1,))
148    # Introspect out the value
149    dtargsr = getargspec(doctest_bad)
150    assert dtargsr==dtargs, \
151           "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,)
152
153
154@dec.skip_linux
155def test_linux():
156    nt.assert_false(sys.platform.startswith('linux'),"This test can't run under linux")
157
158@dec.skip_win32
159def test_win32():
160    nt.assert_not_equal(sys.platform,'win32',"This test can't run under windows")
161
162@dec.skip_osx
163def test_osx():
164    nt.assert_not_equal(sys.platform,'darwin',"This test can't run under osx")
165
166