Added support for detecting Python exceptions (#147)

Closes #145
This commit is contained in:
Ashley Whetter 2018-07-31 16:57:24 -07:00 committed by GitHub
parent 6b8ccf62ae
commit d8f4847a5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 3 deletions

View File

@ -3,11 +3,18 @@ try:
except ImportError:
import __builtin__ as builtins
import re
import sys
import astroid
import astroid.nodes
if sys.version_info < (3,):
_EXCEPTIONS_MODULE = "exceptions"
else:
_EXCEPTIONS_MODULE = "builtins"
def resolve_import_alias(name, import_names):
"""Resolve a name from an aliased import to its original name.
@ -230,3 +237,24 @@ def is_constructor(node):
and isinstance(node.parent.scope(), astroid.nodes.ClassDef)
and node.name == '__init__'
)
def is_exception(node):
"""Check if a class is an exception.
:param node: The node to check.
:type node: astroid.nodes.ClassDef
:returns: True if the class is an exception, False otherwise.
:rtype: bool
"""
if (node.name in ('Exception', 'BaseException')
and node.root().name == _EXCEPTIONS_MODULE):
return True
if not hasattr(node, 'ancestors'):
return False
return any(
is_exception(parent) for parent in node.ancestors(recurs=True)
)

View File

@ -81,7 +81,7 @@ class PythonSphinxMapper(SphinxMapperBase):
obj_map = dict((cls.type, cls) for cls
in [PythonClass, PythonFunction, PythonModule,
PythonMethod, PythonPackage, PythonAttribute,
PythonData])
PythonData, PythonException])
try:
cls = obj_map[data['type']]
except KeyError:
@ -357,6 +357,10 @@ class PythonClass(PythonPythonMapper):
return docstring
class PythonException(PythonClass):
type = 'exception'
class Parser(object):
def parse_file(self, file_path):
directory, filename = os.path.split(file_path)
@ -400,6 +404,10 @@ class Parser(object):
return [data]
def parse_classdef(self, node, data=None):
type_ = 'class'
if astroid_utils.is_exception(node):
type_ = 'exception'
args = ''
try:
constructor = node.lookup('__init__')[1]
@ -412,7 +420,7 @@ class Parser(object):
basenames = list(astroid_utils.get_full_basenames(node.bases, node.basenames))
data = {
'type': 'class',
'type': type_,
'name': node.name,
'args': args,
'bases': basenames,

View File

@ -1,6 +1,6 @@
{%- if obj.display %}
.. py:class:: {{ obj.short_name }}{% if obj.args %}({{ obj.args }}){% endif %}
.. py:{{ obj.type }}:: {{ obj.short_name }}{% if obj.args %}({{ obj.args }}){% endif %}
{%- if obj.bases %}

View File

@ -0,0 +1 @@
{% extends "python/class.rst" %}