Skip to content
Permalink
Browse files

* Fix scanning extension modules for docstrings

* Support documenting classes that are in a package's __init__ module
  • Loading branch information...
Robin Dunn authored and RobinD42 committed Aug 9, 2019
1 parent defa946 commit fa4683d8f7c70a60aa839e8c820d6ac448a2a2e8
Showing with 75 additions and 41 deletions.
  1. +1 −1 build.py
  2. +48 −25 sphinxtools/librarydescription.py
  3. +26 −15 sphinxtools/modulehunter.py
@@ -1092,7 +1092,7 @@ def cmd_sphinx(options, args):
def cmd_wxlib(options, args):
from sphinxtools.modulehunter import ModuleHunter

cmdTimer = CommandTimer('wx.lib')
cmdTimer = CommandTimer('wxlib')
pwd = pushDir(phoenixDir())

for wx_pkg in ['lib', 'py', 'svg', 'tools']:
@@ -43,23 +43,33 @@ def generic_summary(libraryItem, stream):
if libraryItem.kind in [object_types.LIBRARY, object_types.PACKAGE]:
list1 = libraryItem.GetItemByKind(object_types.PACKAGE)
list2 = libraryItem.GetItemByKind(object_types.PY_MODULE, object_types.PYW_MODULE)

templ = [templates.TEMPLATE_PACKAGE_SUMMARY, templates.TEMPLATE_MODULE_SUMMARY]
refs = ['mod', 'mod']
list3 = libraryItem.GetItemByKind(object_types.FUNCTION)
list4 = libraryItem.GetItemByKind(object_types.KLASS, recurse=True)

all_lists = [list1, list2, list3, list4]
templ = [ templates.TEMPLATE_PACKAGE_SUMMARY,
templates.TEMPLATE_MODULE_SUMMARY,
templates.TEMPLATE_STD_FUNCTION_SUMMARY,
templates.TEMPLATE_STD_CLASS_SUMMARY
]
refs = ['mod', 'mod', 'func', 'ref']
add_tilde = [True, True, True, True]

elif libraryItem.kind in range(object_types.PY_MODULE, object_types.PYW_MODULE+1):
list1 = libraryItem.GetItemByKind(object_types.FUNCTION)
list2 = libraryItem.GetItemByKind(object_types.KLASS, recurse=True)

all_lists = [list1, list2]
templ = [templates.TEMPLATE_STD_FUNCTION_SUMMARY, templates.TEMPLATE_STD_CLASS_SUMMARY]
refs = ['func', 'ref']
add_tilde = [True, True]

elif libraryItem.kind == object_types.KLASS:
write_toc = False
list1 = libraryItem.GetItemByKind(object_types.METHOD, object_types.INSTANCE_METHOD)
list1 = libraryItem.GetItemByKind(object_types.METHOD, object_types.BUILTIN_FUNCTION)
list2 = libraryItem.GetItemByKind(object_types.PROPERTY)

all_lists = [list1, list2]
templ = [templates.TEMPLATE_METHOD_SUMMARY, templates.TEMPLATE_PROPERTY_SUMMARY]
refs = ['meth', 'attr']
add_tilde = [True, True]
@@ -69,7 +79,7 @@ def generic_summary(libraryItem, stream):

toctree = ''

for index, sub_list in enumerate([list1, list2]):
for index, sub_list in enumerate(all_lists):
table = []
for item in sub_list:

@@ -739,7 +749,7 @@ def ToRest(self, class_summary):

stream.write(docs + '\n\n')

methods = self.GetItemByKind(object_types.METHOD, object_types.INSTANCE_METHOD)
methods = self.GetItemByKind(object_types.METHOD, object_types.BUILTIN_FUNCTION)
properties = self.GetItemByKind(object_types.PROPERTY)

for meth in methods:
@@ -776,16 +786,16 @@ def Save(self):

self.signature = self.signature.strip()

if len(self.signature) < 2:
self.is_redundant = True
# if len(self.signature) < 2: # ???
# self.is_redundant = True

if self.GetShortName().startswith('__test') or '.extern.' in self.name:
self.is_redundant = True

if self.is_redundant:
return

methods = self.GetItemByKind(object_types.METHOD, object_types.INSTANCE_METHOD)
methods = self.GetItemByKind(object_types.METHOD, object_types.BUILTIN_FUNCTION)
method_list = []

for meth in methods:
@@ -901,7 +911,18 @@ def Save(self):
self.signature = self.signature.replace('*', r'\*')

if not self.signature.strip():
self.is_redundant = True
# if there is no signature, then check if the first line of
# docstring looks like it might be it
lines = self.docs.split('\n')
first = lines[0]
rest = '\n'.join(lines[1:]) if len(lines) > 1 else ''
sig_start = self.GetShortName() + '('
if sig_start in first:
self.signature = first[first.find(sig_start):]
self.docs = rest.strip()

# if not self.signature.strip(): # ???
# self.is_redundant = True


def Write(self, stream):
@@ -944,21 +965,23 @@ def __init__(self, name, item):

self.getter = self.setter = self.deleter = ''

try:
if item.fget:
self.getter = item.fget.__name__
if item.fset:
self.setter = item.fset.__name__
if item.fdel:
self.deleter = item.fdel.__name__
except AttributeError:
# Thank you for screwing it up, Cython...
if item.fget:
self.getter = item.fget.__class__.__name__
if item.fset:
self.setter = item.fset.__class__.__name__
if item.fdel:
self.deleter = item.fdel.__class__.__name__
# is it a real property?
if isinstance(item, property):
try:
if item.fget:
self.getter = item.fget.__name__
if item.fset:
self.setter = item.fset.__name__
if item.fdel:
self.deleter = item.fdel.__name__
except AttributeError:
# Thank you for screwing it up, Cython...
if item.fget:
self.getter = item.fget.__class__.__name__
if item.fset:
self.setter = item.fset.__class__.__name__
if item.fdel:
self.deleter = item.fdel.__class__.__name__

self.docs = getdoc(item)
self.comments = getcomments(item)
@@ -7,7 +7,6 @@
import os
import sys
import types
import importlib
import traceback
import pkgutil

@@ -219,12 +218,14 @@ def inspect_source(method_class, obj, source):
def is_classmethod(instancemethod):
""" Determine if an instancemethod is a classmethod. """

attribute = (isPython3() and ['__self__'] or ['im_self'])[0]
# attribute = (isPython3() and ['__self__'] or ['im_self'])[0]
# if hasattr(instancemethod, attribute):
# return getattr(instancemethod, attribute) is not None
# return False

if hasattr(instancemethod, attribute):
return getattr(instancemethod, attribute) is not None

return False
return isinstance(
instancemethod,
(classmethod, types.MethodType, types.ClassMethodDescriptorType))


def describe_func(obj, parent_class, module_name):
@@ -279,7 +280,10 @@ def describe_func(obj, parent_class, module_name):
klass.number_lines = '%d' % len(source_code.split('\n'))

if isinstance(obj, staticmethod):
klass.method = method = object_types.STATIC_METHOD
klass.kind = method = object_types.STATIC_METHOD

if is_classmethod(obj):
klass.kind = method = object_types.CLASS_METHOD

try:
code = None
@@ -338,7 +342,8 @@ def describe_class(obj, module_class, module_name, constants):
continue

try:
item = getattr(obj, name)
# item = getattr(obj, name) # ????
item = obj_dict.get(name)
except AttributeError:
# Thanks to ReportLab for this funny exception...
continue
@@ -351,21 +356,18 @@ def describe_class(obj, module_class, module_name, constants):
if ismodule(item):
continue

if ismemberdescriptor(item) or isgetsetdescriptor(item):
continue

if isbuiltin(item):
count += 1
elif ismethod(item) or isfunction(item) or ismethoddescriptor(item) or \
isinstance(item, types.MethodType):
isinstance(item, (classmethod, types.MethodType, types.ClassMethodDescriptorType)):
count += 1
describe_func(item, klass, module_name)
elif isclass(item):
count += 1
describe_class(item, klass, module_name, constants)
else:
name = class_name + '.' + name
if isinstance(item, property):
if isinstance(item, property) or isgetsetdescriptor(item):
item_class = Property(name, item)
klass.Add(item_class)

@@ -406,6 +408,12 @@ def describe_class(obj, module_class, module_name, constants):
klass.signature = description.strip()
klass.number_lines = '%d' % len(source_code.split('\n'))

if not klass.signature:
if klass.superClasses:
klass.signature = '{}({})'.format(obj.__name__, ','.join(klass.superClasses))
else:
klass.signature = '{}(object)'.format(obj.__name__)


def describe_module(module, kind, constants=[]):
"""
@@ -478,7 +486,9 @@ def Import(init_name, import_name, full_process=True):
sys.path.insert(0, dirname)

try:
mainmod = importlib.import_module(import_name)
#mainmod = importlib.import_module(import_name)
terminal_module = import_name.split('.')[-1]
mainmod = __import__(import_name, globals(), fromlist=[terminal_module])
except (ImportError, NameError):
message = format_traceback()
print('Error: %s' % message)
@@ -527,7 +537,8 @@ def FindModuleType(filename):
def SubImport(import_string, module, parent_class, ispkg):

try:
submod = importlib.import_module(import_string)
#submod = importlib.import_module(import_string)
submod = __import__(import_string, globals(), fromlist=[module])
except:
# pubsub and Editra can be funny sometimes...
message = "Unable to import module/package '%s.%s'.\n Exception was: %s"%(import_string, module, format_traceback())

0 comments on commit fa4683d

Please sign in to comment.
You can’t perform that action at this time.