mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Move getting module source to util.
This commit is contained in:
parent
cc35b402d9
commit
177e0d19ee
@ -46,3 +46,11 @@ class ExtensionError(SphinxError):
|
|||||||
|
|
||||||
class ThemeError(SphinxError):
|
class ThemeError(SphinxError):
|
||||||
category = 'Theme error'
|
category = 'Theme error'
|
||||||
|
|
||||||
|
|
||||||
|
class PycodeError(Exception):
|
||||||
|
def __str__(self):
|
||||||
|
res = self.args[0]
|
||||||
|
if len(self.args) > 1:
|
||||||
|
res += ' (exception was: %r)' % self.args[1]
|
||||||
|
return res
|
||||||
|
@ -14,8 +14,10 @@ import sys
|
|||||||
from os import path
|
from os import path
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
|
|
||||||
|
from sphinx.errors import PycodeError
|
||||||
from sphinx.pycode import nodes
|
from sphinx.pycode import nodes
|
||||||
from sphinx.pycode.pgen2 import driver, token, tokenize, parse, literals
|
from sphinx.pycode.pgen2 import driver, token, tokenize, parse, literals
|
||||||
|
from sphinx.util import get_module_source
|
||||||
from sphinx.util.docstrings import prepare_docstring, prepare_commentdoc
|
from sphinx.util.docstrings import prepare_docstring, prepare_commentdoc
|
||||||
|
|
||||||
|
|
||||||
@ -136,14 +138,6 @@ class AttrDocVisitor(nodes.NodeVisitor):
|
|||||||
self.collected[namespace, name] = docstring
|
self.collected[namespace, name] = docstring
|
||||||
|
|
||||||
|
|
||||||
class PycodeError(Exception):
|
|
||||||
def __str__(self):
|
|
||||||
res = self.args[0]
|
|
||||||
if len(self.args) > 1:
|
|
||||||
res += ' (exception was: %r)' % self.args[1]
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleAnalyzer(object):
|
class ModuleAnalyzer(object):
|
||||||
# cache for analyzer objects -- caches both by module and file name
|
# cache for analyzer objects -- caches both by module and file name
|
||||||
cache = {}
|
cache = {}
|
||||||
@ -173,33 +167,11 @@ class ModuleAnalyzer(object):
|
|||||||
return entry
|
return entry
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if modname not in sys.modules:
|
type, source = get_module_source(modname)
|
||||||
try:
|
if type == 'string':
|
||||||
__import__(modname)
|
|
||||||
except ImportError, err:
|
|
||||||
raise PycodeError('error importing %r' % modname, err)
|
|
||||||
mod = sys.modules[modname]
|
|
||||||
if hasattr(mod, '__loader__'):
|
|
||||||
try:
|
|
||||||
source = mod.__loader__.get_source(modname)
|
|
||||||
except Exception, err:
|
|
||||||
raise PycodeError('error getting source for %r' % modname,
|
|
||||||
err)
|
|
||||||
obj = cls.for_string(source, modname)
|
obj = cls.for_string(source, modname)
|
||||||
cls.cache['module', modname] = obj
|
else:
|
||||||
return obj
|
obj = cls.for_file(source, modname)
|
||||||
filename = getattr(mod, '__file__', None)
|
|
||||||
if filename is None:
|
|
||||||
raise PycodeError('no source found for module %r' % modname)
|
|
||||||
filename = path.normpath(path.abspath(filename))
|
|
||||||
lfilename = filename.lower()
|
|
||||||
if lfilename.endswith('.pyo') or lfilename.endswith('.pyc'):
|
|
||||||
filename = filename[:-1]
|
|
||||||
elif not lfilename.endswith('.py'):
|
|
||||||
raise PycodeError('source is not a .py file: %r' % filename)
|
|
||||||
if not path.isfile(filename):
|
|
||||||
raise PycodeError('source file is not present: %r' % filename)
|
|
||||||
obj = cls.for_file(filename, modname)
|
|
||||||
except PycodeError, err:
|
except PycodeError, err:
|
||||||
cls.cache['module', modname] = err
|
cls.cache['module', modname] = err
|
||||||
raise
|
raise
|
||||||
@ -214,6 +186,11 @@ class ModuleAnalyzer(object):
|
|||||||
# file-like object yielding source lines
|
# file-like object yielding source lines
|
||||||
self.source = source
|
self.source = source
|
||||||
|
|
||||||
|
# cache the source code as well
|
||||||
|
pos = self.source.tell()
|
||||||
|
self.code = self.source.read()
|
||||||
|
self.source.seek(pos)
|
||||||
|
|
||||||
# will be filled by tokenize()
|
# will be filled by tokenize()
|
||||||
self.tokens = None
|
self.tokens = None
|
||||||
# will be filled by parse()
|
# will be filled by parse()
|
||||||
|
@ -508,6 +508,38 @@ def make_refnode(builder, fromdocname, todocname, targetid, child, title=None):
|
|||||||
return node
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
def get_module_source(modname):
|
||||||
|
"""Try to find the source code for a module.
|
||||||
|
|
||||||
|
Can return ('file', 'filename') in which case the source is in the given
|
||||||
|
file, or ('string', 'source') which which case the source is the string.
|
||||||
|
"""
|
||||||
|
if modname not in sys.modules:
|
||||||
|
try:
|
||||||
|
__import__(modname)
|
||||||
|
except Exception, err:
|
||||||
|
raise PycodeError('error importing %r' % modname, err)
|
||||||
|
mod = sys.modules[modname]
|
||||||
|
if hasattr(mod, '__loader__'):
|
||||||
|
try:
|
||||||
|
source = mod.__loader__.get_source(modname)
|
||||||
|
except Exception, err:
|
||||||
|
raise PycodeError('error getting source for %r' % modname, err)
|
||||||
|
return 'string', source
|
||||||
|
filename = getattr(mod, '__file__', None)
|
||||||
|
if filename is None:
|
||||||
|
raise PycodeError('no source found for module %r' % modname)
|
||||||
|
filename = path.normpath(path.abspath(filename))
|
||||||
|
lfilename = filename.lower()
|
||||||
|
if lfilename.endswith('.pyo') or lfilename.endswith('.pyc'):
|
||||||
|
filename = filename[:-1]
|
||||||
|
elif not lfilename.endswith('.py'):
|
||||||
|
raise PycodeError('source is not a .py file: %r' % filename)
|
||||||
|
if not path.isfile(filename):
|
||||||
|
raise PycodeError('source file is not present: %r' % filename)
|
||||||
|
return 'file', filename
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
any = any
|
any = any
|
||||||
except NameError:
|
except NameError:
|
||||||
|
Loading…
Reference in New Issue
Block a user