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