Show More
@@ -261,6 +261,16 b' def call_tip(oinfo, format_call=True):' | |||||
261 |
|
261 | |||
262 | return call_line, doc |
|
262 | return call_line, doc | |
263 |
|
263 | |||
|
264 | def safe_hasattr(obj, attr): | |||
|
265 | """In recent versions of Python, hasattr() only catches AttributeError. | |||
|
266 | This catches all errors. | |||
|
267 | """ | |||
|
268 | try: | |||
|
269 | getattr(obj, attr) | |||
|
270 | return True | |||
|
271 | except: | |||
|
272 | return False | |||
|
273 | ||||
264 |
|
274 | |||
265 | def find_file(obj): |
|
275 | def find_file(obj): | |
266 | """Find the absolute path to the file where an object was defined. |
|
276 | """Find the absolute path to the file where an object was defined. | |
@@ -279,7 +289,7 b' def find_file(obj):' | |||||
279 | The absolute path to the file where the object was defined. |
|
289 | The absolute path to the file where the object was defined. | |
280 | """ |
|
290 | """ | |
281 | # get source if obj was decorated with @decorator |
|
291 | # get source if obj was decorated with @decorator | |
282 | if hasattr(obj, '__wrapped__'): |
|
292 | if safe_hasattr(obj, '__wrapped__'): | |
283 | obj = obj.__wrapped__ |
|
293 | obj = obj.__wrapped__ | |
284 |
|
294 | |||
285 | fname = None |
|
295 | fname = None | |
@@ -316,7 +326,7 b' def find_source_lines(obj):' | |||||
316 | The line number where the object definition starts. |
|
326 | The line number where the object definition starts. | |
317 | """ |
|
327 | """ | |
318 | # get source if obj was decorated with @decorator |
|
328 | # get source if obj was decorated with @decorator | |
319 | if hasattr(obj, '__wrapped__'): |
|
329 | if safe_hasattr(obj, '__wrapped__'): | |
320 | obj = obj.__wrapped__ |
|
330 | obj = obj.__wrapped__ | |
321 |
|
331 | |||
322 | try: |
|
332 | try: | |
@@ -779,7 +789,7 b' class Inspector:' | |||||
779 | out['init_docstring'] = init_ds |
|
789 | out['init_docstring'] = init_ds | |
780 |
|
790 | |||
781 | # Call form docstring for callable instances |
|
791 | # Call form docstring for callable instances | |
782 | if hasattr(obj, '__call__'): |
|
792 | if safe_hasattr(obj, '__call__'): | |
783 | call_def = self._getdef(obj.__call__, oname) |
|
793 | call_def = self._getdef(obj.__call__, oname) | |
784 | if call_def is not None: |
|
794 | if call_def is not None: | |
785 | out['call_def'] = self.format(call_def) |
|
795 | out['call_def'] = self.format(call_def) |
@@ -158,6 +158,11 b' class SimpleMagics(Magics):' | |||||
158 | "A class-based line/cell magic" |
|
158 | "A class-based line/cell magic" | |
159 |
|
159 | |||
160 |
|
160 | |||
|
161 | class Awkward(object): | |||
|
162 | def __getattr__(self, name): | |||
|
163 | raise Exception(name) | |||
|
164 | ||||
|
165 | ||||
161 | def check_calltip(obj, name, call, docstring): |
|
166 | def check_calltip(obj, name, call, docstring): | |
162 | """Generic check pattern all calltip tests will use""" |
|
167 | """Generic check pattern all calltip tests will use""" | |
163 | info = inspector.info(obj, name) |
|
168 | info = inspector.info(obj, name) | |
@@ -261,6 +266,10 b' def test_info():' | |||||
261 | nt.assert_equal(i['type_name'], 'instance') |
|
266 | nt.assert_equal(i['type_name'], 'instance') | |
262 | nt.assert_equal(i['docstring'], OldStyle.__doc__) |
|
267 | nt.assert_equal(i['docstring'], OldStyle.__doc__) | |
263 |
|
268 | |||
|
269 | def test_info_awkward(): | |||
|
270 | # Just test that this doesn't throw an error. | |||
|
271 | i = inspector.info(Awkward()) | |||
|
272 | ||||
264 | def test_getdoc(): |
|
273 | def test_getdoc(): | |
265 | class A(object): |
|
274 | class A(object): | |
266 | """standard docstring""" |
|
275 | """standard docstring""" |
General Comments 0
You need to be logged in to leave comments.
Login now