1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
# -*- coding: utf-8 -*-
"""
test_util_inspect
~~~~~~~~~~~~~~~
Tests util.inspect functions.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from unittest import TestCase
import sys
from six import PY3
import functools
from textwrap import dedent
import pytest
from sphinx.util import inspect
class TestGetArgSpec(TestCase):
def test_getargspec_builtin_type(self):
with pytest.raises(TypeError):
inspect.getargspec(int)
def test_getargspec_partial(self):
def fun(a, b, c=1, d=2):
pass
p = functools.partial(fun, 10, c=11)
if PY3:
# Python 3's partial is rather cleverer than Python 2's, and we
# have to jump through some hoops to define an equivalent function
# in a way that won't confuse Python 2's parser:
ns = {}
exec(dedent("""
def f_expected(b, *, c=11, d=2):
pass
"""), ns)
f_expected = ns["f_expected"]
else:
def f_expected(b, d=2):
pass
expected = inspect.getargspec(f_expected)
assert expected == inspect.getargspec(p)
def test_getargspec_bound_methods(self):
def f_expected_unbound(self, arg1, **kwargs):
pass
expected_unbound = inspect.getargspec(f_expected_unbound)
def f_expected_bound(arg1, **kwargs):
pass
expected_bound = inspect.getargspec(f_expected_bound)
class Foo:
def method(self, arg1, **kwargs):
pass
bound_method = Foo().method
@functools.wraps(bound_method)
def wrapped_bound_method(*args, **kwargs):
pass
assert expected_unbound == inspect.getargspec(Foo.method)
if PY3 and sys.version_info >= (3, 4, 4):
# On py2, the inspect functions don't properly handle bound
# methods (they include a spurious 'self' argument)
assert expected_bound == inspect.getargspec(bound_method)
# On py2, the inspect functions can't properly handle wrapped
# functions (no __wrapped__ support)
assert expected_bound == inspect.getargspec(wrapped_bound_method)
class TestSafeGetAttr(TestCase):
def test_safe_getattr_with_default(self):
class Foo(object):
def __getattr__(self, item):
raise Exception
obj = Foo()
result = inspect.safe_getattr(obj, 'bar', 'baz')
assert result == 'baz'
def test_safe_getattr_with_exception(self):
class Foo(object):
def __getattr__(self, item):
raise Exception
obj = Foo()
try:
inspect.safe_getattr(obj, 'bar')
except AttributeError as exc:
self.assertEqual(exc.args[0], 'bar')
else:
self.fail('AttributeError not raised')
def test_safe_getattr_with_property_exception(self):
class Foo(object):
@property
def bar(self):
raise Exception
obj = Foo()
try:
inspect.safe_getattr(obj, 'bar')
except AttributeError as exc:
self.assertEqual(exc.args[0], 'bar')
else:
self.fail('AttributeError not raised')
def test_safe_getattr_with___dict___override(self):
class Foo(object):
@property
def __dict__(self):
raise Exception
obj = Foo()
try:
inspect.safe_getattr(obj, 'bar')
except AttributeError as exc:
self.assertEqual(exc.args[0], 'bar')
else:
self.fail('AttributeError not raised')
class TestObjectDescription(TestCase):
def test_dictionary_sorting(self):
dictionary = {"c": 3, "a": 1, "d": 2, "b": 4}
description = inspect.object_description(dictionary)
assert description == "{'a': 1, 'b': 4, 'c': 3, 'd': 2}"
def test_dict_customtype(self):
class CustomType(object):
def __init__(self, value):
self._value = value
def __repr__(self):
return "<CustomType(%r)>" % self._value
dictionary = {CustomType(2): 2, CustomType(1): 1}
description = inspect.object_description(dictionary)
# Type is unsortable, just check that it does not crash
assert "<CustomType(2)>: 2" in description
|