mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-9795 First attempt to run output of Napoleon through rest_formatter.py to render docstring
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import sys
|
||||
|
||||
from sphinxcontrib.napoleon.docstring import GoogleDocstring
|
||||
|
||||
import rest_formatter
|
||||
|
||||
|
||||
def main(text=None):
|
||||
try:
|
||||
src = sys.stdin.read() if text is None else text
|
||||
import textwrap
|
||||
rest_formatter.main(str(GoogleDocstring(textwrap.dedent(src))))
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
sys.stderr.write("Error calculating docstring: " + str(exc_value))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -188,30 +188,35 @@ def parse_docstring(docstring, errors, **options):
|
||||
return MyParsedRstDocstring(writer.document)
|
||||
|
||||
|
||||
try:
|
||||
src = sys.stdin.read()
|
||||
def main(text=None):
|
||||
try:
|
||||
src = sys.stdin.read() if text is None else text
|
||||
|
||||
errors = []
|
||||
errors = []
|
||||
|
||||
class EmptyLinker(DocstringLinker):
|
||||
def translate_indexterm(self, indexterm):
|
||||
return ""
|
||||
class EmptyLinker(DocstringLinker):
|
||||
def translate_indexterm(self, indexterm):
|
||||
return ""
|
||||
|
||||
def translate_identifier_xref(self, identifier, label=None):
|
||||
return identifier
|
||||
def translate_identifier_xref(self, identifier, label=None):
|
||||
return identifier
|
||||
|
||||
docstring = parse_docstring(src, errors)
|
||||
html = docstring.to_html(EmptyLinker())
|
||||
docstring = parse_docstring(src, errors)
|
||||
html = docstring.to_html(EmptyLinker())
|
||||
|
||||
if errors and not html:
|
||||
sys.stderr.write("Error parsing docstring:\n")
|
||||
for error in errors:
|
||||
sys.stderr.write(str(error) + "\n")
|
||||
if errors and not html:
|
||||
sys.stderr.write("Error parsing docstring:\n")
|
||||
for error in errors:
|
||||
sys.stderr.write(str(error) + "\n")
|
||||
sys.exit(1)
|
||||
|
||||
sys.stdout.write(html)
|
||||
sys.stdout.flush()
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
sys.stderr.write("Error calculating docstring: " + str(exc_value))
|
||||
sys.exit(1)
|
||||
|
||||
sys.stdout.write(html)
|
||||
sys.stdout.flush()
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
sys.stderr.write("Error calculating docstring: " + str(exc_value))
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -0,0 +1,838 @@
|
||||
"""Utilities for writing code that runs on Python 2 and 3"""
|
||||
|
||||
# Copyright (c) 2010-2015 Benjamin Peterson
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import functools
|
||||
import itertools
|
||||
import operator
|
||||
import sys
|
||||
import types
|
||||
|
||||
__author__ = "Benjamin Peterson <benjamin@python.org>"
|
||||
__version__ = "1.9.0"
|
||||
|
||||
|
||||
# Useful for very coarse version differentiation.
|
||||
PY2 = sys.version_info[0] == 2
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3:
|
||||
string_types = str,
|
||||
integer_types = int,
|
||||
class_types = type,
|
||||
text_type = str
|
||||
binary_type = bytes
|
||||
|
||||
MAXSIZE = sys.maxsize
|
||||
else:
|
||||
string_types = basestring,
|
||||
integer_types = (int, long)
|
||||
class_types = (type, types.ClassType)
|
||||
text_type = unicode
|
||||
binary_type = str
|
||||
|
||||
if sys.platform.startswith("java"):
|
||||
# Jython always uses 32 bits.
|
||||
MAXSIZE = int((1 << 31) - 1)
|
||||
else:
|
||||
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
|
||||
class X(object):
|
||||
def __len__(self):
|
||||
return 1 << 31
|
||||
try:
|
||||
len(X())
|
||||
except OverflowError:
|
||||
# 32-bit
|
||||
MAXSIZE = int((1 << 31) - 1)
|
||||
else:
|
||||
# 64-bit
|
||||
MAXSIZE = int((1 << 63) - 1)
|
||||
del X
|
||||
|
||||
|
||||
def _add_doc(func, doc):
|
||||
"""Add documentation to a function."""
|
||||
func.__doc__ = doc
|
||||
|
||||
|
||||
def _import_module(name):
|
||||
"""Import module, returning the module after the last dot."""
|
||||
__import__(name)
|
||||
return sys.modules[name]
|
||||
|
||||
|
||||
class _LazyDescr(object):
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def __get__(self, obj, tp):
|
||||
result = self._resolve()
|
||||
setattr(obj, self.name, result) # Invokes __set__.
|
||||
try:
|
||||
# This is a bit ugly, but it avoids running this again by
|
||||
# removing this descriptor.
|
||||
delattr(obj.__class__, self.name)
|
||||
except AttributeError:
|
||||
pass
|
||||
return result
|
||||
|
||||
|
||||
class MovedModule(_LazyDescr):
|
||||
|
||||
def __init__(self, name, old, new=None):
|
||||
super(MovedModule, self).__init__(name)
|
||||
if PY3:
|
||||
if new is None:
|
||||
new = name
|
||||
self.mod = new
|
||||
else:
|
||||
self.mod = old
|
||||
|
||||
def _resolve(self):
|
||||
return _import_module(self.mod)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
_module = self._resolve()
|
||||
value = getattr(_module, attr)
|
||||
setattr(self, attr, value)
|
||||
return value
|
||||
|
||||
|
||||
class _LazyModule(types.ModuleType):
|
||||
|
||||
def __init__(self, name):
|
||||
super(_LazyModule, self).__init__(name)
|
||||
self.__doc__ = self.__class__.__doc__
|
||||
|
||||
def __dir__(self):
|
||||
attrs = ["__doc__", "__name__"]
|
||||
attrs += [attr.name for attr in self._moved_attributes]
|
||||
return attrs
|
||||
|
||||
# Subclasses should override this
|
||||
_moved_attributes = []
|
||||
|
||||
|
||||
class MovedAttribute(_LazyDescr):
|
||||
|
||||
def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
|
||||
super(MovedAttribute, self).__init__(name)
|
||||
if PY3:
|
||||
if new_mod is None:
|
||||
new_mod = name
|
||||
self.mod = new_mod
|
||||
if new_attr is None:
|
||||
if old_attr is None:
|
||||
new_attr = name
|
||||
else:
|
||||
new_attr = old_attr
|
||||
self.attr = new_attr
|
||||
else:
|
||||
self.mod = old_mod
|
||||
if old_attr is None:
|
||||
old_attr = name
|
||||
self.attr = old_attr
|
||||
|
||||
def _resolve(self):
|
||||
module = _import_module(self.mod)
|
||||
return getattr(module, self.attr)
|
||||
|
||||
|
||||
class _SixMetaPathImporter(object):
|
||||
"""
|
||||
A meta path importer to import six.moves and its submodules.
|
||||
|
||||
This class implements a PEP302 finder and loader. It should be compatible
|
||||
with Python 2.5 and all existing versions of Python3
|
||||
"""
|
||||
def __init__(self, six_module_name):
|
||||
self.name = six_module_name
|
||||
self.known_modules = {}
|
||||
|
||||
def _add_module(self, mod, *fullnames):
|
||||
for fullname in fullnames:
|
||||
self.known_modules[self.name + "." + fullname] = mod
|
||||
|
||||
def _get_module(self, fullname):
|
||||
return self.known_modules[self.name + "." + fullname]
|
||||
|
||||
def find_module(self, fullname, path=None):
|
||||
if fullname in self.known_modules:
|
||||
return self
|
||||
return None
|
||||
|
||||
def __get_module(self, fullname):
|
||||
try:
|
||||
return self.known_modules[fullname]
|
||||
except KeyError:
|
||||
raise ImportError("This loader does not know module " + fullname)
|
||||
|
||||
def load_module(self, fullname):
|
||||
try:
|
||||
# in case of a reload
|
||||
return sys.modules[fullname]
|
||||
except KeyError:
|
||||
pass
|
||||
mod = self.__get_module(fullname)
|
||||
if isinstance(mod, MovedModule):
|
||||
mod = mod._resolve()
|
||||
else:
|
||||
mod.__loader__ = self
|
||||
sys.modules[fullname] = mod
|
||||
return mod
|
||||
|
||||
def is_package(self, fullname):
|
||||
"""
|
||||
Return true, if the named module is a package.
|
||||
|
||||
We need this method to get correct spec objects with
|
||||
Python 3.4 (see PEP451)
|
||||
"""
|
||||
return hasattr(self.__get_module(fullname), "__path__")
|
||||
|
||||
def get_code(self, fullname):
|
||||
"""Return None
|
||||
|
||||
Required, if is_package is implemented"""
|
||||
self.__get_module(fullname) # eventually raises ImportError
|
||||
return None
|
||||
get_source = get_code # same as get_code
|
||||
|
||||
_importer = _SixMetaPathImporter(__name__)
|
||||
|
||||
|
||||
class _MovedItems(_LazyModule):
|
||||
"""Lazy loading of moved objects"""
|
||||
__path__ = [] # mark as package
|
||||
|
||||
|
||||
_moved_attributes = [
|
||||
MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
|
||||
MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
|
||||
MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
|
||||
MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
|
||||
MovedAttribute("intern", "__builtin__", "sys"),
|
||||
MovedAttribute("map", "itertools", "builtins", "imap", "map"),
|
||||
MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
|
||||
MovedAttribute("reload_module", "__builtin__", "imp", "reload"),
|
||||
MovedAttribute("reduce", "__builtin__", "functools"),
|
||||
MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
|
||||
MovedAttribute("StringIO", "StringIO", "io"),
|
||||
MovedAttribute("UserDict", "UserDict", "collections"),
|
||||
MovedAttribute("UserList", "UserList", "collections"),
|
||||
MovedAttribute("UserString", "UserString", "collections"),
|
||||
MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
|
||||
MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
|
||||
MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
|
||||
|
||||
MovedModule("builtins", "__builtin__"),
|
||||
MovedModule("configparser", "ConfigParser"),
|
||||
MovedModule("copyreg", "copy_reg"),
|
||||
MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
|
||||
MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"),
|
||||
MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
|
||||
MovedModule("http_cookies", "Cookie", "http.cookies"),
|
||||
MovedModule("html_entities", "htmlentitydefs", "html.entities"),
|
||||
MovedModule("html_parser", "HTMLParser", "html.parser"),
|
||||
MovedModule("http_client", "httplib", "http.client"),
|
||||
MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
|
||||
MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
|
||||
MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
|
||||
MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
|
||||
MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
|
||||
MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
|
||||
MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
|
||||
MovedModule("cPickle", "cPickle", "pickle"),
|
||||
MovedModule("queue", "Queue"),
|
||||
MovedModule("reprlib", "repr"),
|
||||
MovedModule("socketserver", "SocketServer"),
|
||||
MovedModule("_thread", "thread", "_thread"),
|
||||
MovedModule("tkinter", "Tkinter"),
|
||||
MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
|
||||
MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
|
||||
MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
|
||||
MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
|
||||
MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
|
||||
MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
|
||||
MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
|
||||
MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
|
||||
MovedModule("tkinter_colorchooser", "tkColorChooser",
|
||||
"tkinter.colorchooser"),
|
||||
MovedModule("tkinter_commondialog", "tkCommonDialog",
|
||||
"tkinter.commondialog"),
|
||||
MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
|
||||
MovedModule("tkinter_font", "tkFont", "tkinter.font"),
|
||||
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
|
||||
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
|
||||
"tkinter.simpledialog"),
|
||||
MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
|
||||
MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
|
||||
MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
|
||||
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
|
||||
MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
|
||||
MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
|
||||
MovedModule("winreg", "_winreg"),
|
||||
]
|
||||
for attr in _moved_attributes:
|
||||
setattr(_MovedItems, attr.name, attr)
|
||||
if isinstance(attr, MovedModule):
|
||||
_importer._add_module(attr, "moves." + attr.name)
|
||||
del attr
|
||||
|
||||
_MovedItems._moved_attributes = _moved_attributes
|
||||
|
||||
moves = _MovedItems(__name__ + ".moves")
|
||||
_importer._add_module(moves, "moves")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_parse(_LazyModule):
|
||||
"""Lazy loading of moved objects in six.moves.urllib_parse"""
|
||||
|
||||
|
||||
_urllib_parse_moved_attributes = [
|
||||
MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urljoin", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urlparse", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("quote", "urllib", "urllib.parse"),
|
||||
MovedAttribute("quote_plus", "urllib", "urllib.parse"),
|
||||
MovedAttribute("unquote", "urllib", "urllib.parse"),
|
||||
MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
|
||||
MovedAttribute("urlencode", "urllib", "urllib.parse"),
|
||||
MovedAttribute("splitquery", "urllib", "urllib.parse"),
|
||||
MovedAttribute("splittag", "urllib", "urllib.parse"),
|
||||
MovedAttribute("splituser", "urllib", "urllib.parse"),
|
||||
MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("uses_params", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("uses_query", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
|
||||
]
|
||||
for attr in _urllib_parse_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_parse, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
|
||||
"moves.urllib_parse", "moves.urllib.parse")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_error(_LazyModule):
|
||||
"""Lazy loading of moved objects in six.moves.urllib_error"""
|
||||
|
||||
|
||||
_urllib_error_moved_attributes = [
|
||||
MovedAttribute("URLError", "urllib2", "urllib.error"),
|
||||
MovedAttribute("HTTPError", "urllib2", "urllib.error"),
|
||||
MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
|
||||
]
|
||||
for attr in _urllib_error_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_error, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
|
||||
"moves.urllib_error", "moves.urllib.error")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_request(_LazyModule):
|
||||
"""Lazy loading of moved objects in six.moves.urllib_request"""
|
||||
|
||||
|
||||
_urllib_request_moved_attributes = [
|
||||
MovedAttribute("urlopen", "urllib2", "urllib.request"),
|
||||
MovedAttribute("install_opener", "urllib2", "urllib.request"),
|
||||
MovedAttribute("build_opener", "urllib2", "urllib.request"),
|
||||
MovedAttribute("pathname2url", "urllib", "urllib.request"),
|
||||
MovedAttribute("url2pathname", "urllib", "urllib.request"),
|
||||
MovedAttribute("getproxies", "urllib", "urllib.request"),
|
||||
MovedAttribute("Request", "urllib2", "urllib.request"),
|
||||
MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
|
||||
MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
|
||||
MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("FileHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
|
||||
MovedAttribute("urlretrieve", "urllib", "urllib.request"),
|
||||
MovedAttribute("urlcleanup", "urllib", "urllib.request"),
|
||||
MovedAttribute("URLopener", "urllib", "urllib.request"),
|
||||
MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
|
||||
MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
|
||||
]
|
||||
for attr in _urllib_request_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_request, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
|
||||
"moves.urllib_request", "moves.urllib.request")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_response(_LazyModule):
|
||||
"""Lazy loading of moved objects in six.moves.urllib_response"""
|
||||
|
||||
|
||||
_urllib_response_moved_attributes = [
|
||||
MovedAttribute("addbase", "urllib", "urllib.response"),
|
||||
MovedAttribute("addclosehook", "urllib", "urllib.response"),
|
||||
MovedAttribute("addinfo", "urllib", "urllib.response"),
|
||||
MovedAttribute("addinfourl", "urllib", "urllib.response"),
|
||||
]
|
||||
for attr in _urllib_response_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_response, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
|
||||
"moves.urllib_response", "moves.urllib.response")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_robotparser(_LazyModule):
|
||||
"""Lazy loading of moved objects in six.moves.urllib_robotparser"""
|
||||
|
||||
|
||||
_urllib_robotparser_moved_attributes = [
|
||||
MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
|
||||
]
|
||||
for attr in _urllib_robotparser_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
|
||||
"moves.urllib_robotparser", "moves.urllib.robotparser")
|
||||
|
||||
|
||||
class Module_six_moves_urllib(types.ModuleType):
|
||||
"""Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
|
||||
__path__ = [] # mark as package
|
||||
parse = _importer._get_module("moves.urllib_parse")
|
||||
error = _importer._get_module("moves.urllib_error")
|
||||
request = _importer._get_module("moves.urllib_request")
|
||||
response = _importer._get_module("moves.urllib_response")
|
||||
robotparser = _importer._get_module("moves.urllib_robotparser")
|
||||
|
||||
def __dir__(self):
|
||||
return ['parse', 'error', 'request', 'response', 'robotparser']
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
|
||||
"moves.urllib")
|
||||
|
||||
|
||||
def add_move(move):
|
||||
"""Add an item to six.moves."""
|
||||
setattr(_MovedItems, move.name, move)
|
||||
|
||||
|
||||
def remove_move(name):
|
||||
"""Remove item from six.moves."""
|
||||
try:
|
||||
delattr(_MovedItems, name)
|
||||
except AttributeError:
|
||||
try:
|
||||
del moves.__dict__[name]
|
||||
except KeyError:
|
||||
raise AttributeError("no such move, %r" % (name,))
|
||||
|
||||
|
||||
if PY3:
|
||||
_meth_func = "__func__"
|
||||
_meth_self = "__self__"
|
||||
|
||||
_func_closure = "__closure__"
|
||||
_func_code = "__code__"
|
||||
_func_defaults = "__defaults__"
|
||||
_func_globals = "__globals__"
|
||||
else:
|
||||
_meth_func = "im_func"
|
||||
_meth_self = "im_self"
|
||||
|
||||
_func_closure = "func_closure"
|
||||
_func_code = "func_code"
|
||||
_func_defaults = "func_defaults"
|
||||
_func_globals = "func_globals"
|
||||
|
||||
|
||||
try:
|
||||
advance_iterator = next
|
||||
except NameError:
|
||||
def advance_iterator(it):
|
||||
return it.next()
|
||||
next = advance_iterator
|
||||
|
||||
|
||||
try:
|
||||
callable = callable
|
||||
except NameError:
|
||||
def callable(obj):
|
||||
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
|
||||
|
||||
|
||||
if PY3:
|
||||
def get_unbound_function(unbound):
|
||||
return unbound
|
||||
|
||||
create_bound_method = types.MethodType
|
||||
|
||||
Iterator = object
|
||||
else:
|
||||
def get_unbound_function(unbound):
|
||||
return unbound.im_func
|
||||
|
||||
def create_bound_method(func, obj):
|
||||
return types.MethodType(func, obj, obj.__class__)
|
||||
|
||||
class Iterator(object):
|
||||
|
||||
def next(self):
|
||||
return type(self).__next__(self)
|
||||
|
||||
callable = callable
|
||||
_add_doc(get_unbound_function,
|
||||
"""Get the function out of a possibly unbound function""")
|
||||
|
||||
|
||||
get_method_function = operator.attrgetter(_meth_func)
|
||||
get_method_self = operator.attrgetter(_meth_self)
|
||||
get_function_closure = operator.attrgetter(_func_closure)
|
||||
get_function_code = operator.attrgetter(_func_code)
|
||||
get_function_defaults = operator.attrgetter(_func_defaults)
|
||||
get_function_globals = operator.attrgetter(_func_globals)
|
||||
|
||||
|
||||
if PY3:
|
||||
def iterkeys(d, **kw):
|
||||
return iter(d.keys(**kw))
|
||||
|
||||
def itervalues(d, **kw):
|
||||
return iter(d.values(**kw))
|
||||
|
||||
def iteritems(d, **kw):
|
||||
return iter(d.items(**kw))
|
||||
|
||||
def iterlists(d, **kw):
|
||||
return iter(d.lists(**kw))
|
||||
|
||||
viewkeys = operator.methodcaller("keys")
|
||||
|
||||
viewvalues = operator.methodcaller("values")
|
||||
|
||||
viewitems = operator.methodcaller("items")
|
||||
else:
|
||||
def iterkeys(d, **kw):
|
||||
return iter(d.iterkeys(**kw))
|
||||
|
||||
def itervalues(d, **kw):
|
||||
return iter(d.itervalues(**kw))
|
||||
|
||||
def iteritems(d, **kw):
|
||||
return iter(d.iteritems(**kw))
|
||||
|
||||
def iterlists(d, **kw):
|
||||
return iter(d.iterlists(**kw))
|
||||
|
||||
viewkeys = operator.methodcaller("viewkeys")
|
||||
|
||||
viewvalues = operator.methodcaller("viewvalues")
|
||||
|
||||
viewitems = operator.methodcaller("viewitems")
|
||||
|
||||
_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
|
||||
_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
|
||||
_add_doc(iteritems,
|
||||
"Return an iterator over the (key, value) pairs of a dictionary.")
|
||||
_add_doc(iterlists,
|
||||
"Return an iterator over the (key, [values]) pairs of a dictionary.")
|
||||
|
||||
|
||||
if PY3:
|
||||
def b(s):
|
||||
return s.encode("latin-1")
|
||||
def u(s):
|
||||
return s
|
||||
unichr = chr
|
||||
if sys.version_info[1] <= 1:
|
||||
def int2byte(i):
|
||||
return bytes((i,))
|
||||
else:
|
||||
# This is about 2x faster than the implementation above on 3.2+
|
||||
int2byte = operator.methodcaller("to_bytes", 1, "big")
|
||||
byte2int = operator.itemgetter(0)
|
||||
indexbytes = operator.getitem
|
||||
iterbytes = iter
|
||||
import io
|
||||
StringIO = io.StringIO
|
||||
BytesIO = io.BytesIO
|
||||
_assertCountEqual = "assertCountEqual"
|
||||
_assertRaisesRegex = "assertRaisesRegex"
|
||||
_assertRegex = "assertRegex"
|
||||
else:
|
||||
def b(s):
|
||||
return s
|
||||
# Workaround for standalone backslash
|
||||
def u(s):
|
||||
return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
|
||||
unichr = unichr
|
||||
int2byte = chr
|
||||
def byte2int(bs):
|
||||
return ord(bs[0])
|
||||
def indexbytes(buf, i):
|
||||
return ord(buf[i])
|
||||
iterbytes = functools.partial(itertools.imap, ord)
|
||||
import StringIO
|
||||
StringIO = BytesIO = StringIO.StringIO
|
||||
_assertCountEqual = "assertItemsEqual"
|
||||
_assertRaisesRegex = "assertRaisesRegexp"
|
||||
_assertRegex = "assertRegexpMatches"
|
||||
_add_doc(b, """Byte literal""")
|
||||
_add_doc(u, """Text literal""")
|
||||
|
||||
|
||||
def assertCountEqual(self, *args, **kwargs):
|
||||
return getattr(self, _assertCountEqual)(*args, **kwargs)
|
||||
|
||||
|
||||
def assertRaisesRegex(self, *args, **kwargs):
|
||||
return getattr(self, _assertRaisesRegex)(*args, **kwargs)
|
||||
|
||||
|
||||
def assertRegex(self, *args, **kwargs):
|
||||
return getattr(self, _assertRegex)(*args, **kwargs)
|
||||
|
||||
|
||||
if PY3:
|
||||
exec_ = getattr(moves.builtins, "exec")
|
||||
|
||||
|
||||
def reraise(tp, value, tb=None):
|
||||
if value is None:
|
||||
value = tp()
|
||||
if value.__traceback__ is not tb:
|
||||
raise value.with_traceback(tb)
|
||||
raise value
|
||||
|
||||
else:
|
||||
def exec_(_code_, _globs_=None, _locs_=None):
|
||||
"""Execute code in a namespace."""
|
||||
if _globs_ is None:
|
||||
frame = sys._getframe(1)
|
||||
_globs_ = frame.f_globals
|
||||
if _locs_ is None:
|
||||
_locs_ = frame.f_locals
|
||||
del frame
|
||||
elif _locs_ is None:
|
||||
_locs_ = _globs_
|
||||
exec("""exec _code_ in _globs_, _locs_""")
|
||||
|
||||
|
||||
exec_("""def reraise(tp, value, tb=None):
|
||||
raise tp, value, tb
|
||||
""")
|
||||
|
||||
|
||||
if sys.version_info[:2] == (3, 2):
|
||||
exec_("""def raise_from(value, from_value):
|
||||
if from_value is None:
|
||||
raise value
|
||||
raise value from from_value
|
||||
""")
|
||||
elif sys.version_info[:2] > (3, 2):
|
||||
exec_("""def raise_from(value, from_value):
|
||||
raise value from from_value
|
||||
""")
|
||||
else:
|
||||
def raise_from(value, from_value):
|
||||
raise value
|
||||
|
||||
|
||||
print_ = getattr(moves.builtins, "print", None)
|
||||
if print_ is None:
|
||||
def print_(*args, **kwargs):
|
||||
"""The new-style print function for Python 2.4 and 2.5."""
|
||||
fp = kwargs.pop("file", sys.stdout)
|
||||
if fp is None:
|
||||
return
|
||||
def write(data):
|
||||
if not isinstance(data, basestring):
|
||||
data = str(data)
|
||||
# If the file has an encoding, encode unicode with it.
|
||||
if (isinstance(fp, file) and
|
||||
isinstance(data, unicode) and
|
||||
fp.encoding is not None):
|
||||
errors = getattr(fp, "errors", None)
|
||||
if errors is None:
|
||||
errors = "strict"
|
||||
data = data.encode(fp.encoding, errors)
|
||||
fp.write(data)
|
||||
want_unicode = False
|
||||
sep = kwargs.pop("sep", None)
|
||||
if sep is not None:
|
||||
if isinstance(sep, unicode):
|
||||
want_unicode = True
|
||||
elif not isinstance(sep, str):
|
||||
raise TypeError("sep must be None or a string")
|
||||
end = kwargs.pop("end", None)
|
||||
if end is not None:
|
||||
if isinstance(end, unicode):
|
||||
want_unicode = True
|
||||
elif not isinstance(end, str):
|
||||
raise TypeError("end must be None or a string")
|
||||
if kwargs:
|
||||
raise TypeError("invalid keyword arguments to print()")
|
||||
if not want_unicode:
|
||||
for arg in args:
|
||||
if isinstance(arg, unicode):
|
||||
want_unicode = True
|
||||
break
|
||||
if want_unicode:
|
||||
newline = unicode("\n")
|
||||
space = unicode(" ")
|
||||
else:
|
||||
newline = "\n"
|
||||
space = " "
|
||||
if sep is None:
|
||||
sep = space
|
||||
if end is None:
|
||||
end = newline
|
||||
for i, arg in enumerate(args):
|
||||
if i:
|
||||
write(sep)
|
||||
write(arg)
|
||||
write(end)
|
||||
if sys.version_info[:2] < (3, 3):
|
||||
_print = print_
|
||||
def print_(*args, **kwargs):
|
||||
fp = kwargs.get("file", sys.stdout)
|
||||
flush = kwargs.pop("flush", False)
|
||||
_print(*args, **kwargs)
|
||||
if flush and fp is not None:
|
||||
fp.flush()
|
||||
|
||||
_add_doc(reraise, """Reraise an exception.""")
|
||||
|
||||
if sys.version_info[0:2] < (3, 4):
|
||||
def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
|
||||
updated=functools.WRAPPER_UPDATES):
|
||||
def wrapper(f):
|
||||
f = functools.wraps(wrapped, assigned, updated)(f)
|
||||
f.__wrapped__ = wrapped
|
||||
return f
|
||||
return wrapper
|
||||
else:
|
||||
wraps = functools.wraps
|
||||
|
||||
def with_metaclass(meta, *bases):
|
||||
"""Create a base class with a metaclass."""
|
||||
# This requires a bit of explanation: the basic idea is to make a dummy
|
||||
# metaclass for one level of class instantiation that replaces itself with
|
||||
# the actual metaclass.
|
||||
class metaclass(meta):
|
||||
def __new__(cls, name, this_bases, d):
|
||||
return meta(name, bases, d)
|
||||
return type.__new__(metaclass, 'temporary_class', (), {})
|
||||
|
||||
|
||||
def add_metaclass(metaclass):
|
||||
"""Class decorator for creating a class with a metaclass."""
|
||||
def wrapper(cls):
|
||||
orig_vars = cls.__dict__.copy()
|
||||
slots = orig_vars.get('__slots__')
|
||||
if slots is not None:
|
||||
if isinstance(slots, str):
|
||||
slots = [slots]
|
||||
for slots_var in slots:
|
||||
orig_vars.pop(slots_var)
|
||||
orig_vars.pop('__dict__', None)
|
||||
orig_vars.pop('__weakref__', None)
|
||||
return metaclass(cls.__name__, cls.__bases__, orig_vars)
|
||||
return wrapper
|
||||
|
||||
|
||||
def python_2_unicode_compatible(klass):
|
||||
"""
|
||||
A decorator that defines __unicode__ and __str__ methods under Python 2.
|
||||
Under Python 3 it does nothing.
|
||||
|
||||
To support Python 2 and 3 with a single code base, define a __str__ method
|
||||
returning text and apply this decorator to the class.
|
||||
"""
|
||||
if PY2:
|
||||
if '__str__' not in klass.__dict__:
|
||||
raise ValueError("@python_2_unicode_compatible cannot be applied "
|
||||
"to %s because it doesn't define __str__()." %
|
||||
klass.__name__)
|
||||
klass.__unicode__ = klass.__str__
|
||||
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
|
||||
return klass
|
||||
|
||||
|
||||
# Complete the moves implementation.
|
||||
# This code is at the end of this module to speed up module loading.
|
||||
# Turn this module into a package.
|
||||
__path__ = [] # required for PEP 302 and PEP 451
|
||||
__package__ = __name__ # see PEP 366 @ReservedAssignment
|
||||
if globals().get("__spec__") is not None:
|
||||
__spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable
|
||||
# Remove other six meta path importers, since they cause problems. This can
|
||||
# happen if six is removed from sys.modules and then reloaded. (Setuptools does
|
||||
# this for some reason.)
|
||||
if sys.meta_path:
|
||||
for i, importer in enumerate(sys.meta_path):
|
||||
# Here's some real nastiness: Another "instance" of the six module might
|
||||
# be floating around. Therefore, we can't use isinstance() to check for
|
||||
# the six meta path importer, since the other six instance will have
|
||||
# inserted an importer with different class.
|
||||
if (type(importer).__name__ == "_SixMetaPathImporter" and
|
||||
importer.name == __name__):
|
||||
del sys.meta_path[i]
|
||||
break
|
||||
del i, importer
|
||||
# Finally, add the importer to the meta path import hook.
|
||||
sys.meta_path.append(_importer)
|
||||
@@ -0,0 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
sphinxcontrib
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
This package is a namespace package that contains all extensions
|
||||
distributed in the ``sphinx-contrib`` distribution.
|
||||
|
||||
:copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
__import__('pkg_resources').declare_namespace(__name__)
|
||||
@@ -0,0 +1,387 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2014 Rob Ruana
|
||||
# Licensed under the BSD License, see LICENSE file for details.
|
||||
|
||||
"""Sphinx napoleon extension -- support for NumPy and Google style docstrings.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from six import iteritems
|
||||
from sphinxcontrib.napoleon.docstring import GoogleDocstring, NumpyDocstring
|
||||
from sphinxcontrib.napoleon._version import __version__
|
||||
assert __version__ # silence pyflakes
|
||||
|
||||
|
||||
class Config(object):
|
||||
"""Sphinx napoleon extension settings in `conf.py`.
|
||||
|
||||
Listed below are all the settings used by napoleon and their default
|
||||
values. These settings can be changed in the Sphinx `conf.py` file. Make
|
||||
sure that both "sphinx.ext.autodoc" and "sphinxcontrib.napoleon" are
|
||||
enabled in `conf.py`::
|
||||
|
||||
# conf.py
|
||||
|
||||
# Add any Sphinx extension module names here, as strings
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinxcontrib.napoleon']
|
||||
|
||||
# Napoleon settings
|
||||
napoleon_google_docstring = True
|
||||
napoleon_numpy_docstring = True
|
||||
napoleon_include_private_with_doc = False
|
||||
napoleon_include_special_with_doc = True
|
||||
napoleon_use_admonition_for_examples = False
|
||||
napoleon_use_admonition_for_notes = False
|
||||
napoleon_use_admonition_for_references = False
|
||||
napoleon_use_ivar = False
|
||||
napoleon_use_param = True
|
||||
napoleon_use_rtype = True
|
||||
|
||||
.. _Google style:
|
||||
http://google.github.io/styleguide/pyguide.html
|
||||
.. _NumPy style:
|
||||
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
|
||||
|
||||
Attributes
|
||||
----------
|
||||
napoleon_google_docstring : bool, defaults to True
|
||||
True to parse `Google style`_ docstrings. False to disable support
|
||||
for Google style docstrings.
|
||||
napoleon_numpy_docstring : bool, defaults to True
|
||||
True to parse `NumPy style`_ docstrings. False to disable support
|
||||
for NumPy style docstrings.
|
||||
napoleon_include_private_with_doc : bool, defaults to False
|
||||
True to include private members (like ``_membername``) with docstrings
|
||||
in the documentation. False to fall back to Sphinx's default behavior.
|
||||
|
||||
**If True**::
|
||||
|
||||
def _included(self):
|
||||
\"\"\"
|
||||
This will be included in the docs because it has a docstring
|
||||
\"\"\"
|
||||
pass
|
||||
|
||||
def _skipped(self):
|
||||
# This will NOT be included in the docs
|
||||
pass
|
||||
|
||||
napoleon_include_special_with_doc : bool, defaults to True
|
||||
True to include special members (like ``__membername__``) with
|
||||
docstrings in the documentation. False to fall back to Sphinx's
|
||||
default behavior.
|
||||
|
||||
**If True**::
|
||||
|
||||
def __str__(self):
|
||||
\"\"\"
|
||||
This will be included in the docs because it has a docstring
|
||||
\"\"\"
|
||||
return unicode(self).encode('utf-8')
|
||||
|
||||
def __unicode__(self):
|
||||
# This will NOT be included in the docs
|
||||
return unicode(self.__class__.__name__)
|
||||
|
||||
napoleon_use_admonition_for_examples : bool, defaults to False
|
||||
True to use the ``.. admonition::`` directive for the **Example** and
|
||||
**Examples** sections. False to use the ``.. rubric::`` directive
|
||||
instead. One may look better than the other depending on what HTML
|
||||
theme is used.
|
||||
|
||||
This `NumPy style`_ snippet will be converted as follows::
|
||||
|
||||
Example
|
||||
-------
|
||||
This is just a quick example
|
||||
|
||||
**If True**::
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
This is just a quick example
|
||||
|
||||
**If False**::
|
||||
|
||||
.. rubric:: Example
|
||||
|
||||
This is just a quick example
|
||||
|
||||
napoleon_use_admonition_for_notes : bool, defaults to False
|
||||
True to use the ``.. admonition::`` directive for **Notes** sections.
|
||||
False to use the ``.. rubric::`` directive instead.
|
||||
|
||||
Note
|
||||
----
|
||||
The singular **Note** section will always be converted to a
|
||||
``.. note::`` directive.
|
||||
|
||||
See Also
|
||||
--------
|
||||
:attr:`napoleon_use_admonition_for_examples`
|
||||
|
||||
napoleon_use_admonition_for_references : bool, defaults to False
|
||||
True to use the ``.. admonition::`` directive for **References**
|
||||
sections. False to use the ``.. rubric::`` directive instead.
|
||||
|
||||
See Also
|
||||
--------
|
||||
:attr:`napoleon_use_admonition_for_examples`
|
||||
|
||||
napoleon_use_ivar : bool, defaults to False
|
||||
True to use the ``:ivar:`` role for instance variables. False to use
|
||||
the ``.. attribute::`` directive instead.
|
||||
|
||||
This `NumPy style`_ snippet will be converted as follows::
|
||||
|
||||
Attributes
|
||||
----------
|
||||
attr1 : int
|
||||
Description of `attr1`
|
||||
|
||||
**If True**::
|
||||
|
||||
:ivar attr1: Description of `attr1`
|
||||
:vartype attr1: int
|
||||
|
||||
**If False**::
|
||||
|
||||
.. attribute:: attr1
|
||||
|
||||
*int*
|
||||
|
||||
Description of `attr1`
|
||||
|
||||
napoleon_use_param : bool, defaults to True
|
||||
True to use a ``:param:`` role for each function parameter. False to
|
||||
use a single ``:parameters:`` role for all the parameters.
|
||||
|
||||
This `NumPy style`_ snippet will be converted as follows::
|
||||
|
||||
Parameters
|
||||
----------
|
||||
arg1 : str
|
||||
Description of `arg1`
|
||||
arg2 : int, optional
|
||||
Description of `arg2`, defaults to 0
|
||||
|
||||
**If True**::
|
||||
|
||||
:param arg1: Description of `arg1`
|
||||
:type arg1: str
|
||||
:param arg2: Description of `arg2`, defaults to 0
|
||||
:type arg2: int, optional
|
||||
|
||||
**If False**::
|
||||
|
||||
:parameters: * **arg1** (*str*) --
|
||||
Description of `arg1`
|
||||
* **arg2** (*int, optional*) --
|
||||
Description of `arg2`, defaults to 0
|
||||
|
||||
napoleon_use_rtype : bool, defaults to True
|
||||
True to use the ``:rtype:`` role for the return type. False to output
|
||||
the return type inline with the description.
|
||||
|
||||
This `NumPy style`_ snippet will be converted as follows::
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
True if successful, False otherwise
|
||||
|
||||
**If True**::
|
||||
|
||||
:returns: True if successful, False otherwise
|
||||
:rtype: bool
|
||||
|
||||
**If False**::
|
||||
|
||||
:returns: *bool* -- True if successful, False otherwise
|
||||
|
||||
"""
|
||||
_config_values = {
|
||||
'napoleon_google_docstring': (True, 'env'),
|
||||
'napoleon_numpy_docstring': (True, 'env'),
|
||||
'napoleon_include_private_with_doc': (False, 'env'),
|
||||
'napoleon_include_special_with_doc': (True, 'env'),
|
||||
'napoleon_use_admonition_for_examples': (False, 'env'),
|
||||
'napoleon_use_admonition_for_notes': (False, 'env'),
|
||||
'napoleon_use_admonition_for_references': (False, 'env'),
|
||||
'napoleon_use_ivar': (False, 'env'),
|
||||
'napoleon_use_param': (True, 'env'),
|
||||
'napoleon_use_rtype': (True, 'env'),
|
||||
}
|
||||
|
||||
def __init__(self, **settings):
|
||||
for name, (default, rebuild) in iteritems(self._config_values):
|
||||
setattr(self, name, default)
|
||||
for name, value in iteritems(settings):
|
||||
setattr(self, name, value)
|
||||
|
||||
|
||||
def setup(app):
|
||||
"""Sphinx extension setup function.
|
||||
|
||||
When the extension is loaded, Sphinx imports this module and executes
|
||||
the ``setup()`` function, which in turn notifies Sphinx of everything
|
||||
the extension offers.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
app : sphinx.application.Sphinx
|
||||
Application object representing the Sphinx process
|
||||
|
||||
See Also
|
||||
--------
|
||||
`The Sphinx documentation on Extensions
|
||||
<http://sphinx-doc.org/extensions.html>`_
|
||||
|
||||
`The Extension Tutorial <http://sphinx-doc.org/extdev/tutorial.html>`_
|
||||
|
||||
`The Extension API <http://sphinx-doc.org/extdev/appapi.html>`_
|
||||
|
||||
|
||||
"""
|
||||
from sphinx.application import Sphinx
|
||||
if not isinstance(app, Sphinx):
|
||||
return # probably called by tests
|
||||
|
||||
app.connect('autodoc-process-docstring', _process_docstring)
|
||||
app.connect('autodoc-skip-member', _skip_member)
|
||||
|
||||
for name, (default, rebuild) in iteritems(Config._config_values):
|
||||
app.add_config_value(name, default, rebuild)
|
||||
|
||||
|
||||
def _process_docstring(app, what, name, obj, options, lines):
|
||||
"""Process the docstring for a given python object.
|
||||
|
||||
Called when autodoc has read and processed a docstring. `lines` is a list
|
||||
of docstring lines that `_process_docstring` modifies in place to change
|
||||
what Sphinx outputs.
|
||||
|
||||
The following settings in conf.py control what styles of docstrings will
|
||||
be parsed:
|
||||
|
||||
* ``napoleon_google_docstring`` -- parse Google style docstrings
|
||||
* ``napoleon_numpy_docstring`` -- parse NumPy style docstrings
|
||||
|
||||
Parameters
|
||||
----------
|
||||
app : sphinx.application.Sphinx
|
||||
Application object representing the Sphinx process.
|
||||
what : str
|
||||
A string specifying the type of the object to which the docstring
|
||||
belongs. Valid values: "module", "class", "exception", "function",
|
||||
"method", "attribute".
|
||||
name : str
|
||||
The fully qualified name of the object.
|
||||
obj : module, class, exception, function, method, or attribute
|
||||
The object to which the docstring belongs.
|
||||
options : sphinx.ext.autodoc.Options
|
||||
The options given to the directive: an object with attributes
|
||||
inherited_members, undoc_members, show_inheritance and noindex that
|
||||
are True if the flag option of same name was given to the auto
|
||||
directive.
|
||||
lines : list of str
|
||||
The lines of the docstring, see above.
|
||||
|
||||
.. note:: `lines` is modified *in place*
|
||||
|
||||
"""
|
||||
result_lines = lines
|
||||
if app.config.napoleon_numpy_docstring:
|
||||
docstring = NumpyDocstring(result_lines, app.config, app, what, name,
|
||||
obj, options)
|
||||
result_lines = docstring.lines()
|
||||
if app.config.napoleon_google_docstring:
|
||||
docstring = GoogleDocstring(result_lines, app.config, app, what, name,
|
||||
obj, options)
|
||||
result_lines = docstring.lines()
|
||||
lines[:] = result_lines[:]
|
||||
|
||||
|
||||
def _skip_member(app, what, name, obj, skip, options):
|
||||
"""Determine if private and special class members are included in docs.
|
||||
|
||||
The following settings in conf.py determine if private and special class
|
||||
members are included in the generated documentation:
|
||||
|
||||
* ``napoleon_include_private_with_doc`` --
|
||||
include private members if they have docstrings
|
||||
* ``napoleon_include_special_with_doc`` --
|
||||
include special members if they have docstrings
|
||||
|
||||
Parameters
|
||||
----------
|
||||
app : sphinx.application.Sphinx
|
||||
Application object representing the Sphinx process
|
||||
what : str
|
||||
A string specifying the type of the object to which the member
|
||||
belongs. Valid values: "module", "class", "exception", "function",
|
||||
"method", "attribute".
|
||||
name : str
|
||||
The name of the member.
|
||||
obj : module, class, exception, function, method, or attribute.
|
||||
For example, if the member is the __init__ method of class A, then
|
||||
`obj` will be `A.__init__`.
|
||||
skip : bool
|
||||
A boolean indicating if autodoc will skip this member if `_skip_member`
|
||||
does not override the decision
|
||||
options : sphinx.ext.autodoc.Options
|
||||
The options given to the directive: an object with attributes
|
||||
inherited_members, undoc_members, show_inheritance and noindex that
|
||||
are True if the flag option of same name was given to the auto
|
||||
directive.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
True if the member should be skipped during creation of the docs,
|
||||
False if it should be included in the docs.
|
||||
|
||||
"""
|
||||
has_doc = getattr(obj, '__doc__', False)
|
||||
is_member = (what == 'class' or what == 'exception' or what == 'module')
|
||||
if name != '__weakref__' and name != '__init__' and has_doc and is_member:
|
||||
cls_is_owner = False
|
||||
if what == 'class' or what == 'exception':
|
||||
if sys.version_info[0] < 3:
|
||||
cls = getattr(obj, 'im_class', getattr(obj, '__objclass__',
|
||||
None))
|
||||
cls_is_owner = (cls and hasattr(cls, name) and
|
||||
name in cls.__dict__)
|
||||
elif sys.version_info[1] >= 3:
|
||||
qualname = getattr(obj, '__qualname__', '')
|
||||
cls_path, _, _ = qualname.rpartition('.')
|
||||
if cls_path:
|
||||
try:
|
||||
if '.' in cls_path:
|
||||
import importlib
|
||||
import functools
|
||||
|
||||
mod = importlib.import_module(obj.__module__)
|
||||
mod_path = cls_path.split('.')
|
||||
cls = functools.reduce(getattr, mod_path, mod)
|
||||
else:
|
||||
cls = obj.__globals__[cls_path]
|
||||
except:
|
||||
cls_is_owner = False
|
||||
else:
|
||||
cls_is_owner = (cls and hasattr(cls, name) and
|
||||
name in cls.__dict__)
|
||||
else:
|
||||
cls_is_owner = False
|
||||
else:
|
||||
cls_is_owner = True
|
||||
|
||||
if what == 'module' or cls_is_owner:
|
||||
is_special = name.startswith('__') and name.endswith('__')
|
||||
is_private = not is_special and name.startswith('_')
|
||||
inc_special = app.config.napoleon_include_special_with_doc
|
||||
inc_private = app.config.napoleon_include_private_with_doc
|
||||
if (is_special and inc_special) or (is_private and inc_private):
|
||||
return False
|
||||
return skip
|
||||
@@ -0,0 +1,8 @@
|
||||
# Package versioning solution originally found here:
|
||||
# http://stackoverflow.com/q/458550
|
||||
|
||||
# Store the version here so:
|
||||
# 1) we don't load dependencies by storing it in __init__.py
|
||||
# 2) we can import it in setup.py for the same reason
|
||||
# 3) we can import it into your module
|
||||
__version__ = '0.3.11'
|
||||
@@ -0,0 +1,928 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2014 Rob Ruana
|
||||
# Licensed under the BSD License, see LICENSE file for details.
|
||||
|
||||
"""Classes for docstring parsing and formatting."""
|
||||
|
||||
import collections
|
||||
import inspect
|
||||
import re
|
||||
import sys
|
||||
|
||||
from pockets import modify_iter
|
||||
from six import string_types
|
||||
from six.moves import range
|
||||
|
||||
|
||||
_directive_regex = re.compile(r'\.\. \S+::')
|
||||
_google_section_regex = re.compile(r'^(\s|\w)+:\s*$')
|
||||
_google_typed_arg_regex = re.compile(r'\s*(.+?)\s*\(\s*(.+?)\s*\)')
|
||||
_numpy_section_regex = re.compile(r'^[=\-`:\'"~^_*+#<>]{2,}\s*$')
|
||||
_xref_regex = re.compile(r'(:\w+:\S+:`.+?`|:\S+:`.+?`|`.+?`)')
|
||||
|
||||
|
||||
class GoogleDocstring(object):
|
||||
"""Convert Google style docstrings to reStructuredText.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
docstring : str or List[str]
|
||||
The docstring to parse, given either as a string or split into
|
||||
individual lines.
|
||||
config : Optional[sphinxcontrib.napoleon.Config or sphinx.config.Config]
|
||||
The configuration settings to use. If not given, defaults to the
|
||||
config object on `app`; or if `app` is not given defaults to the
|
||||
a new `sphinxcontrib.napoleon.Config` object.
|
||||
|
||||
See Also
|
||||
--------
|
||||
:class:`sphinxcontrib.napoleon.Config`
|
||||
|
||||
Other Parameters
|
||||
----------------
|
||||
app : Optional[sphinx.application.Sphinx]
|
||||
Application object representing the Sphinx process.
|
||||
what : Optional[str]
|
||||
A string specifying the type of the object to which the docstring
|
||||
belongs. Valid values: "module", "class", "exception", "function",
|
||||
"method", "attribute".
|
||||
name : Optional[str]
|
||||
The fully qualified name of the object.
|
||||
obj : module, class, exception, function, method, or attribute
|
||||
The object to which the docstring belongs.
|
||||
options : Optional[sphinx.ext.autodoc.Options]
|
||||
The options given to the directive: an object with attributes
|
||||
inherited_members, undoc_members, show_inheritance and noindex that
|
||||
are True if the flag option of same name was given to the auto
|
||||
directive.
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> from sphinxcontrib.napoleon import Config
|
||||
>>> config = Config(napoleon_use_param=True, napoleon_use_rtype=True)
|
||||
>>> docstring = '''One line summary.
|
||||
...
|
||||
... Extended description.
|
||||
...
|
||||
... Args:
|
||||
... arg1(int): Description of `arg1`
|
||||
... arg2(str): Description of `arg2`
|
||||
... Returns:
|
||||
... str: Description of return value.
|
||||
... '''
|
||||
>>> print(GoogleDocstring(docstring, config))
|
||||
One line summary.
|
||||
<BLANKLINE>
|
||||
Extended description.
|
||||
<BLANKLINE>
|
||||
:param arg1: Description of `arg1`
|
||||
:type arg1: int
|
||||
:param arg2: Description of `arg2`
|
||||
:type arg2: str
|
||||
<BLANKLINE>
|
||||
:returns: Description of return value.
|
||||
:rtype: str
|
||||
<BLANKLINE>
|
||||
|
||||
"""
|
||||
def __init__(self, docstring, config=None, app=None, what='', name='',
|
||||
obj=None, options=None):
|
||||
self._config = config
|
||||
self._app = app
|
||||
|
||||
if not self._config:
|
||||
from sphinxcontrib.napoleon import Config
|
||||
self._config = self._app and self._app.config or Config()
|
||||
|
||||
if not what:
|
||||
if inspect.isclass(obj):
|
||||
what = 'class'
|
||||
elif inspect.ismodule(obj):
|
||||
what = 'module'
|
||||
elif isinstance(obj, collections.Callable):
|
||||
what = 'function'
|
||||
else:
|
||||
what = 'object'
|
||||
|
||||
self._what = what
|
||||
self._name = name
|
||||
self._obj = obj
|
||||
self._opt = options
|
||||
if isinstance(docstring, string_types):
|
||||
docstring = docstring.splitlines()
|
||||
self._lines = docstring
|
||||
self._line_iter = modify_iter(docstring, modifier=lambda s: s.rstrip())
|
||||
self._parsed_lines = []
|
||||
self._is_in_section = False
|
||||
self._section_indent = 0
|
||||
if not hasattr(self, '_directive_sections'):
|
||||
self._directive_sections = []
|
||||
if not hasattr(self, '_sections'):
|
||||
self._sections = {
|
||||
'args': self._parse_parameters_section,
|
||||
'arguments': self._parse_parameters_section,
|
||||
'attributes': self._parse_attributes_section,
|
||||
'example': self._parse_examples_section,
|
||||
'examples': self._parse_examples_section,
|
||||
'keyword args': self._parse_keyword_arguments_section,
|
||||
'keyword arguments': self._parse_keyword_arguments_section,
|
||||
'methods': self._parse_methods_section,
|
||||
'note': self._parse_note_section,
|
||||
'notes': self._parse_notes_section,
|
||||
'other parameters': self._parse_other_parameters_section,
|
||||
'parameters': self._parse_parameters_section,
|
||||
'return': self._parse_returns_section,
|
||||
'returns': self._parse_returns_section,
|
||||
'raises': self._parse_raises_section,
|
||||
'references': self._parse_references_section,
|
||||
'see also': self._parse_see_also_section,
|
||||
'warning': self._parse_warning_section,
|
||||
'warnings': self._parse_warning_section,
|
||||
'warns': self._parse_warns_section,
|
||||
'yield': self._parse_yields_section,
|
||||
'yields': self._parse_yields_section,
|
||||
}
|
||||
self._parse()
|
||||
|
||||
def __str__(self):
|
||||
"""Return the parsed docstring in reStructuredText format.
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
UTF-8 encoded version of the docstring.
|
||||
|
||||
"""
|
||||
if sys.version_info[0] >= 3:
|
||||
return self.__unicode__()
|
||||
else:
|
||||
return self.__unicode__().encode('utf8')
|
||||
|
||||
def __unicode__(self):
|
||||
"""Return the parsed docstring in reStructuredText format.
|
||||
|
||||
Returns
|
||||
-------
|
||||
unicode
|
||||
Unicode version of the docstring.
|
||||
|
||||
"""
|
||||
return u'\n'.join(self.lines())
|
||||
|
||||
def lines(self):
|
||||
"""Return the parsed lines of the docstring in reStructuredText format.
|
||||
|
||||
Returns
|
||||
-------
|
||||
List[str]
|
||||
The lines of the docstring in a list.
|
||||
|
||||
"""
|
||||
return self._parsed_lines
|
||||
|
||||
def _consume_indented_block(self, indent=1):
|
||||
lines = []
|
||||
line = self._line_iter.peek()
|
||||
while(not self._is_section_break() and
|
||||
(not line or self._is_indented(line, indent))):
|
||||
lines.append(next(self._line_iter))
|
||||
line = self._line_iter.peek()
|
||||
return lines
|
||||
|
||||
def _consume_contiguous(self):
|
||||
lines = []
|
||||
while (self._line_iter.has_next() and
|
||||
self._line_iter.peek() and
|
||||
not self._is_section_header()):
|
||||
lines.append(next(self._line_iter))
|
||||
return lines
|
||||
|
||||
def _consume_empty(self):
|
||||
lines = []
|
||||
line = self._line_iter.peek()
|
||||
while self._line_iter.has_next() and not line:
|
||||
lines.append(next(self._line_iter))
|
||||
line = self._line_iter.peek()
|
||||
return lines
|
||||
|
||||
def _consume_field(self, parse_type=True, prefer_type=False):
|
||||
line = next(self._line_iter)
|
||||
|
||||
before, colon, after = self._partition_field_on_colon(line)
|
||||
_name, _type, _desc = before, '', after
|
||||
|
||||
if parse_type:
|
||||
match = _google_typed_arg_regex.match(before)
|
||||
if match:
|
||||
_name = match.group(1)
|
||||
_type = match.group(2)
|
||||
|
||||
if _name[:2] == '**':
|
||||
_name = r'\*\*'+_name[2:]
|
||||
elif _name[:1] == '*':
|
||||
_name = r'\*'+_name[1:]
|
||||
|
||||
if prefer_type and not _type:
|
||||
_type, _name = _name, _type
|
||||
indent = self._get_indent(line) + 1
|
||||
_desc = [_desc] + self._dedent(self._consume_indented_block(indent))
|
||||
_desc = self.__class__(_desc, self._config).lines()
|
||||
return _name, _type, _desc
|
||||
|
||||
def _consume_fields(self, parse_type=True, prefer_type=False):
|
||||
self._consume_empty()
|
||||
fields = []
|
||||
while not self._is_section_break():
|
||||
_name, _type, _desc = self._consume_field(parse_type, prefer_type)
|
||||
if _name or _type or _desc:
|
||||
fields.append((_name, _type, _desc,))
|
||||
return fields
|
||||
|
||||
def _consume_inline_attribute(self):
|
||||
line = next(self._line_iter)
|
||||
_type, colon, _desc = self._partition_field_on_colon(line)
|
||||
if not colon:
|
||||
_type, _desc = _desc, _type
|
||||
_desc = [_desc] + self._dedent(self._consume_to_end())
|
||||
_desc = self.__class__(_desc, self._config).lines()
|
||||
return _type, _desc
|
||||
|
||||
def _consume_returns_section(self):
|
||||
lines = self._dedent(self._consume_to_next_section())
|
||||
if lines:
|
||||
before, colon, after = self._partition_field_on_colon(lines[0])
|
||||
_name, _type, _desc = '', '', lines
|
||||
|
||||
if colon:
|
||||
if after:
|
||||
_desc = [after] + lines[1:]
|
||||
else:
|
||||
_desc = lines[1:]
|
||||
|
||||
match = _google_typed_arg_regex.match(before)
|
||||
if match:
|
||||
_name = match.group(1)
|
||||
_type = match.group(2)
|
||||
else:
|
||||
_type = before
|
||||
|
||||
_desc = self.__class__(_desc, self._config).lines()
|
||||
return [(_name, _type, _desc,)]
|
||||
else:
|
||||
return []
|
||||
|
||||
def _consume_usage_section(self):
|
||||
lines = self._dedent(self._consume_to_next_section())
|
||||
return lines
|
||||
|
||||
def _consume_section_header(self):
|
||||
section = next(self._line_iter)
|
||||
stripped_section = section.strip(':')
|
||||
if stripped_section.lower() in self._sections:
|
||||
section = stripped_section
|
||||
return section
|
||||
|
||||
def _consume_to_end(self):
|
||||
lines = []
|
||||
while self._line_iter.has_next():
|
||||
lines.append(next(self._line_iter))
|
||||
return lines
|
||||
|
||||
def _consume_to_next_section(self):
|
||||
self._consume_empty()
|
||||
lines = []
|
||||
while not self._is_section_break():
|
||||
lines.append(next(self._line_iter))
|
||||
return lines + self._consume_empty()
|
||||
|
||||
def _dedent(self, lines, full=False):
|
||||
if full:
|
||||
return [line.lstrip() for line in lines]
|
||||
else:
|
||||
min_indent = self._get_min_indent(lines)
|
||||
return [line[min_indent:] for line in lines]
|
||||
|
||||
def _format_admonition(self, admonition, lines):
|
||||
lines = self._strip_empty(lines)
|
||||
if len(lines) == 1:
|
||||
return ['.. %s:: %s' % (admonition, lines[0].strip()), '']
|
||||
elif lines:
|
||||
lines = self._indent(self._dedent(lines), 3)
|
||||
return ['.. %s::' % admonition, ''] + lines + ['']
|
||||
else:
|
||||
return ['.. %s::' % admonition, '']
|
||||
|
||||
def _format_block(self, prefix, lines, padding=None):
|
||||
if lines:
|
||||
if padding is None:
|
||||
padding = ' ' * len(prefix)
|
||||
result_lines = []
|
||||
for i, line in enumerate(lines):
|
||||
if i == 0:
|
||||
result_lines.append((prefix + line).rstrip())
|
||||
elif line:
|
||||
result_lines.append(padding + line)
|
||||
else:
|
||||
result_lines.append('')
|
||||
return result_lines
|
||||
else:
|
||||
return [prefix]
|
||||
|
||||
def _format_field(self, _name, _type, _desc):
|
||||
_desc = self._strip_empty(_desc)
|
||||
has_desc = any(_desc)
|
||||
separator = has_desc and ' -- ' or ''
|
||||
if _name:
|
||||
if _type:
|
||||
if '`' in _type:
|
||||
field = '**%s** (%s)%s' % (_name, _type, separator)
|
||||
else:
|
||||
field = '**%s** (*%s*)%s' % (_name, _type, separator)
|
||||
else:
|
||||
field = '**%s**%s' % (_name, separator)
|
||||
elif _type:
|
||||
if '`' in _type:
|
||||
field = '%s%s' % (_type, separator)
|
||||
else:
|
||||
field = '*%s*%s' % (_type, separator)
|
||||
else:
|
||||
field = ''
|
||||
|
||||
if has_desc:
|
||||
return [field + _desc[0]] + _desc[1:]
|
||||
else:
|
||||
return [field]
|
||||
|
||||
def _format_fields(self, field_type, fields):
|
||||
field_type = ':%s:' % field_type.strip()
|
||||
padding = ' ' * len(field_type)
|
||||
multi = len(fields) > 1
|
||||
lines = []
|
||||
for _name, _type, _desc in fields:
|
||||
field = self._format_field(_name, _type, _desc)
|
||||
if multi:
|
||||
if lines:
|
||||
lines.extend(self._format_block(padding + ' * ', field))
|
||||
else:
|
||||
lines.extend(self._format_block(field_type + ' * ', field))
|
||||
else:
|
||||
lines.extend(self._format_block(field_type + ' ', field))
|
||||
if lines and lines[-1]:
|
||||
lines.append('')
|
||||
return lines
|
||||
|
||||
def _get_current_indent(self, peek_ahead=0):
|
||||
line = self._line_iter.peek(peek_ahead + 1)[peek_ahead]
|
||||
while line != self._line_iter.sentinel:
|
||||
if line:
|
||||
return self._get_indent(line)
|
||||
peek_ahead += 1
|
||||
line = self._line_iter.peek(peek_ahead + 1)[peek_ahead]
|
||||
return 0
|
||||
|
||||
def _get_indent(self, line):
|
||||
for i, s in enumerate(line):
|
||||
if not s.isspace():
|
||||
return i
|
||||
return len(line)
|
||||
|
||||
def _get_min_indent(self, lines):
|
||||
min_indent = None
|
||||
for line in lines:
|
||||
if line:
|
||||
indent = self._get_indent(line)
|
||||
if min_indent is None:
|
||||
min_indent = indent
|
||||
elif indent < min_indent:
|
||||
min_indent = indent
|
||||
return min_indent or 0
|
||||
|
||||
def _indent(self, lines, n=4):
|
||||
return [(' ' * n) + line for line in lines]
|
||||
|
||||
def _is_indented(self, line, indent=1):
|
||||
for i, s in enumerate(line):
|
||||
if i >= indent:
|
||||
return True
|
||||
elif not s.isspace():
|
||||
return False
|
||||
return False
|
||||
|
||||
def _is_section_header(self):
|
||||
section = self._line_iter.peek().lower()
|
||||
match = _google_section_regex.match(section)
|
||||
if match and section.strip(':') in self._sections:
|
||||
header_indent = self._get_indent(section)
|
||||
section_indent = self._get_current_indent(peek_ahead=1)
|
||||
return section_indent > header_indent
|
||||
elif self._directive_sections:
|
||||
if _directive_regex.match(section):
|
||||
for directive_section in self._directive_sections:
|
||||
if section.startswith(directive_section):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _is_section_break(self):
|
||||
line = self._line_iter.peek()
|
||||
return (not self._line_iter.has_next() or
|
||||
self._is_section_header() or
|
||||
(self._is_in_section and
|
||||
line and
|
||||
not self._is_indented(line, self._section_indent)))
|
||||
|
||||
def _parse(self):
|
||||
self._parsed_lines = self._consume_empty()
|
||||
|
||||
if self._name and (self._what == 'attribute' or self._what == 'data'):
|
||||
self._parsed_lines.extend(self._parse_attribute_docstring())
|
||||
return
|
||||
|
||||
while self._line_iter.has_next():
|
||||
if self._is_section_header():
|
||||
try:
|
||||
section = self._consume_section_header()
|
||||
self._is_in_section = True
|
||||
self._section_indent = self._get_current_indent()
|
||||
if _directive_regex.match(section):
|
||||
lines = [section] + self._consume_to_next_section()
|
||||
else:
|
||||
lines = self._sections[section.lower()](section)
|
||||
finally:
|
||||
self._is_in_section = False
|
||||
self._section_indent = 0
|
||||
else:
|
||||
if not self._parsed_lines:
|
||||
lines = self._consume_contiguous() + self._consume_empty()
|
||||
else:
|
||||
lines = self._consume_to_next_section()
|
||||
self._parsed_lines.extend(lines)
|
||||
|
||||
def _parse_attribute_docstring(self):
|
||||
_type, _desc = self._consume_inline_attribute()
|
||||
return self._format_field('', _type, _desc)
|
||||
|
||||
def _parse_attributes_section(self, section):
|
||||
lines = []
|
||||
for _name, _type, _desc in self._consume_fields():
|
||||
if self._config.napoleon_use_ivar:
|
||||
field = ':ivar %s: ' % _name
|
||||
lines.extend(self._format_block(field, _desc))
|
||||
if _type:
|
||||
lines.append(':vartype %s: %s' % (_name, _type))
|
||||
else:
|
||||
lines.extend(['.. attribute:: ' + _name, ''])
|
||||
field = self._format_field('', _type, _desc)
|
||||
lines.extend(self._indent(field, 3))
|
||||
lines.append('')
|
||||
if self._config.napoleon_use_ivar:
|
||||
lines.append('')
|
||||
return lines
|
||||
|
||||
def _parse_examples_section(self, section):
|
||||
use_admonition = self._config.napoleon_use_admonition_for_examples
|
||||
return self._parse_generic_section(section, use_admonition)
|
||||
|
||||
def _parse_usage_section(self, section):
|
||||
header = ['.. rubric:: Usage:', '']
|
||||
block = ['.. code-block:: python', '']
|
||||
lines = self._consume_usage_section()
|
||||
lines = self._indent(lines, 3)
|
||||
return header + block + lines + ['']
|
||||
|
||||
def _parse_generic_section(self, section, use_admonition):
|
||||
lines = self._strip_empty(self._consume_to_next_section())
|
||||
lines = self._dedent(lines)
|
||||
if use_admonition:
|
||||
header = '.. admonition:: %s' % section
|
||||
lines = self._indent(lines, 3)
|
||||
else:
|
||||
header = '.. rubric:: %s' % section
|
||||
if lines:
|
||||
return [header, ''] + lines + ['']
|
||||
else:
|
||||
return [header, '']
|
||||
|
||||
def _parse_keyword_arguments_section(self, section):
|
||||
return self._format_fields('Keyword Arguments', self._consume_fields())
|
||||
|
||||
def _parse_methods_section(self, section):
|
||||
lines = []
|
||||
for _name, _, _desc in self._consume_fields(parse_type=False):
|
||||
lines.append('.. method:: %s' % _name)
|
||||
if _desc:
|
||||
lines.extend([''] + self._indent(_desc, 3))
|
||||
lines.append('')
|
||||
return lines
|
||||
|
||||
def _parse_note_section(self, section):
|
||||
lines = self._consume_to_next_section()
|
||||
return self._format_admonition('note', lines)
|
||||
|
||||
def _parse_notes_section(self, section):
|
||||
use_admonition = self._config.napoleon_use_admonition_for_notes
|
||||
return self._parse_generic_section('Notes', use_admonition)
|
||||
|
||||
def _parse_other_parameters_section(self, section):
|
||||
return self._format_fields('Other Parameters', self._consume_fields())
|
||||
|
||||
def _parse_parameters_section(self, section):
|
||||
fields = self._consume_fields()
|
||||
if self._config.napoleon_use_param:
|
||||
lines = []
|
||||
for _name, _type, _desc in fields:
|
||||
field = ':param %s: ' % _name
|
||||
lines.extend(self._format_block(field, _desc))
|
||||
if _type:
|
||||
lines.append(':type %s: %s' % (_name, _type))
|
||||
return lines + ['']
|
||||
else:
|
||||
return self._format_fields('Parameters', fields)
|
||||
|
||||
def _parse_raises_section(self, section):
|
||||
fields = self._consume_fields(parse_type=False, prefer_type=True)
|
||||
field_type = ':raises:'
|
||||
padding = ' ' * len(field_type)
|
||||
multi = len(fields) > 1
|
||||
lines = []
|
||||
for _, _type, _desc in fields:
|
||||
_desc = self._strip_empty(_desc)
|
||||
has_desc = any(_desc)
|
||||
separator = has_desc and ' -- ' or ''
|
||||
if _type:
|
||||
has_refs = '`' in _type or ':' in _type
|
||||
has_space = any(c in ' \t\n\v\f ' for c in _type)
|
||||
|
||||
if not has_refs and not has_space:
|
||||
_type = ':exc:`%s`%s' % (_type, separator)
|
||||
elif has_desc and has_space:
|
||||
_type = '*%s*%s' % (_type, separator)
|
||||
else:
|
||||
_type = '%s%s' % (_type, separator)
|
||||
|
||||
if has_desc:
|
||||
field = [_type + _desc[0]] + _desc[1:]
|
||||
else:
|
||||
field = [_type]
|
||||
else:
|
||||
field = _desc
|
||||
if multi:
|
||||
if lines:
|
||||
lines.extend(self._format_block(padding + ' * ', field))
|
||||
else:
|
||||
lines.extend(self._format_block(field_type + ' * ', field))
|
||||
else:
|
||||
lines.extend(self._format_block(field_type + ' ', field))
|
||||
if lines and lines[-1]:
|
||||
lines.append('')
|
||||
return lines
|
||||
|
||||
def _parse_references_section(self, section):
|
||||
use_admonition = self._config.napoleon_use_admonition_for_references
|
||||
return self._parse_generic_section('References', use_admonition)
|
||||
|
||||
def _parse_returns_section(self, section):
|
||||
fields = self._consume_returns_section()
|
||||
multi = len(fields) > 1
|
||||
if multi:
|
||||
use_rtype = False
|
||||
else:
|
||||
use_rtype = self._config.napoleon_use_rtype
|
||||
|
||||
lines = []
|
||||
for _name, _type, _desc in fields:
|
||||
if use_rtype:
|
||||
field = self._format_field(_name, '', _desc)
|
||||
else:
|
||||
field = self._format_field(_name, _type, _desc)
|
||||
|
||||
if multi:
|
||||
if lines:
|
||||
lines.extend(self._format_block(' * ', field))
|
||||
else:
|
||||
lines.extend(self._format_block(':returns: * ', field))
|
||||
else:
|
||||
lines.extend(self._format_block(':returns: ', field))
|
||||
if _type and use_rtype:
|
||||
lines.extend([':rtype: %s' % _type, ''])
|
||||
if lines and lines[-1]:
|
||||
lines.append('')
|
||||
return lines
|
||||
|
||||
def _parse_see_also_section(self, section):
|
||||
lines = self._consume_to_next_section()
|
||||
return self._format_admonition('seealso', lines)
|
||||
|
||||
def _parse_warning_section(self, section):
|
||||
lines = self._consume_to_next_section()
|
||||
return self._format_admonition('warning', lines)
|
||||
|
||||
def _parse_warns_section(self, section):
|
||||
return self._format_fields('Warns', self._consume_fields())
|
||||
|
||||
def _parse_yields_section(self, section):
|
||||
fields = self._consume_returns_section()
|
||||
return self._format_fields('Yields', fields)
|
||||
|
||||
def _partition_field_on_colon(self, line):
|
||||
before_colon = []
|
||||
after_colon = []
|
||||
colon = ''
|
||||
found_colon = False
|
||||
for i, source in enumerate(_xref_regex.split(line)):
|
||||
if found_colon:
|
||||
after_colon.append(source)
|
||||
else:
|
||||
if (i % 2) == 0 and ":" in source:
|
||||
found_colon = True
|
||||
before, colon, after = source.partition(":")
|
||||
before_colon.append(before)
|
||||
after_colon.append(after)
|
||||
else:
|
||||
before_colon.append(source)
|
||||
|
||||
return ("".join(before_colon).strip(),
|
||||
colon,
|
||||
"".join(after_colon).strip())
|
||||
|
||||
def _strip_empty(self, lines):
|
||||
if lines:
|
||||
start = -1
|
||||
for i, line in enumerate(lines):
|
||||
if line:
|
||||
start = i
|
||||
break
|
||||
if start == -1:
|
||||
lines = []
|
||||
end = -1
|
||||
for i in reversed(range(len(lines))):
|
||||
line = lines[i]
|
||||
if line:
|
||||
end = i
|
||||
break
|
||||
if start > 0 or end + 1 < len(lines):
|
||||
lines = lines[start:end + 1]
|
||||
return lines
|
||||
|
||||
|
||||
class NumpyDocstring(GoogleDocstring):
|
||||
"""Convert NumPy style docstrings to reStructuredText.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
docstring : str or List[str]
|
||||
The docstring to parse, given either as a string or split into
|
||||
individual lines.
|
||||
config : Optional[sphinxcontrib.napoleon.Config or sphinx.config.Config]
|
||||
The configuration settings to use. If not given, defaults to the
|
||||
config object on `app`; or if `app` is not given defaults to the
|
||||
a new `sphinxcontrib.napoleon.Config` object.
|
||||
|
||||
See Also
|
||||
--------
|
||||
:class:`sphinxcontrib.napoleon.Config`
|
||||
|
||||
Other Parameters
|
||||
----------------
|
||||
app : Optional[sphinx.application.Sphinx]
|
||||
Application object representing the Sphinx process.
|
||||
what : Optional[str]
|
||||
A string specifying the type of the object to which the docstring
|
||||
belongs. Valid values: "module", "class", "exception", "function",
|
||||
"method", "attribute".
|
||||
name : Optional[str]
|
||||
The fully qualified name of the object.
|
||||
obj : module, class, exception, function, method, or attribute
|
||||
The object to which the docstring belongs.
|
||||
options : Optional[sphinx.ext.autodoc.Options]
|
||||
The options given to the directive: an object with attributes
|
||||
inherited_members, undoc_members, show_inheritance and noindex that
|
||||
are True if the flag option of same name was given to the auto
|
||||
directive.
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> from sphinxcontrib.napoleon import Config
|
||||
>>> config = Config(napoleon_use_param=True, napoleon_use_rtype=True)
|
||||
>>> docstring = '''One line summary.
|
||||
...
|
||||
... Extended description.
|
||||
...
|
||||
... Parameters
|
||||
... ----------
|
||||
... arg1 : int
|
||||
... Description of `arg1`
|
||||
... arg2 : str
|
||||
... Description of `arg2`
|
||||
... Returns
|
||||
... -------
|
||||
... str
|
||||
... Description of return value.
|
||||
... '''
|
||||
>>> print(NumpyDocstring(docstring, config))
|
||||
One line summary.
|
||||
<BLANKLINE>
|
||||
Extended description.
|
||||
<BLANKLINE>
|
||||
:param arg1: Description of `arg1`
|
||||
:type arg1: int
|
||||
:param arg2: Description of `arg2`
|
||||
:type arg2: str
|
||||
<BLANKLINE>
|
||||
:returns: Description of return value.
|
||||
:rtype: str
|
||||
<BLANKLINE>
|
||||
|
||||
Methods
|
||||
-------
|
||||
__str__()
|
||||
Return the parsed docstring in reStructuredText format.
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
UTF-8 encoded version of the docstring.
|
||||
|
||||
__unicode__()
|
||||
Return the parsed docstring in reStructuredText format.
|
||||
|
||||
Returns
|
||||
-------
|
||||
unicode
|
||||
Unicode version of the docstring.
|
||||
|
||||
lines()
|
||||
Return the parsed lines of the docstring in reStructuredText format.
|
||||
|
||||
Returns
|
||||
-------
|
||||
List[str]
|
||||
The lines of the docstring in a list.
|
||||
|
||||
"""
|
||||
def __init__(self, docstring, config=None, app=None, what='', name='',
|
||||
obj=None, options=None):
|
||||
self._directive_sections = ['.. index::']
|
||||
super(NumpyDocstring, self).__init__(docstring, config, app, what,
|
||||
name, obj, options)
|
||||
|
||||
def _consume_field(self, parse_type=True, prefer_type=False):
|
||||
line = next(self._line_iter)
|
||||
if parse_type:
|
||||
_name, _, _type = self._partition_field_on_colon(line)
|
||||
else:
|
||||
_name, _type = line, ''
|
||||
_name, _type = _name.strip(), _type.strip()
|
||||
if prefer_type and not _type:
|
||||
_type, _name = _name, _type
|
||||
indent = self._get_indent(line)
|
||||
_desc = self._dedent(self._consume_indented_block(indent + 1))
|
||||
_desc = self.__class__(_desc, self._config).lines()
|
||||
return _name, _type, _desc
|
||||
|
||||
def _consume_returns_section(self):
|
||||
return self._consume_fields(prefer_type=True)
|
||||
|
||||
def _consume_section_header(self):
|
||||
section = next(self._line_iter)
|
||||
if not _directive_regex.match(section):
|
||||
# Consume the header underline
|
||||
next(self._line_iter)
|
||||
return section
|
||||
|
||||
def _is_section_break(self):
|
||||
line1, line2 = self._line_iter.peek(2)
|
||||
return (not self._line_iter.has_next() or
|
||||
self._is_section_header() or
|
||||
['', ''] == [line1, line2] or
|
||||
(self._is_in_section and
|
||||
line1 and
|
||||
not self._is_indented(line1, self._section_indent)))
|
||||
|
||||
def _is_section_header(self):
|
||||
section, underline = self._line_iter.peek(2)
|
||||
section = section.lower()
|
||||
if section in self._sections and isinstance(underline, string_types):
|
||||
return bool(_numpy_section_regex.match(underline))
|
||||
elif self._directive_sections:
|
||||
if _directive_regex.match(section):
|
||||
for directive_section in self._directive_sections:
|
||||
if section.startswith(directive_section):
|
||||
return True
|
||||
return False
|
||||
|
||||
_name_rgx = re.compile(r"^\s*(:(?P<role>\w+):`(?P<name>[a-zA-Z0-9_.-]+)`|"
|
||||
r" (?P<name2>[a-zA-Z0-9_.-]+))\s*", re.X)
|
||||
|
||||
def _parse_see_also_section(self, section):
|
||||
lines = self._consume_to_next_section()
|
||||
try:
|
||||
return self._parse_numpydoc_see_also_section(lines)
|
||||
except ValueError:
|
||||
return self._format_admonition('seealso', lines)
|
||||
|
||||
def _parse_numpydoc_see_also_section(self, content):
|
||||
"""
|
||||
Derived from the NumpyDoc implementation of _parse_see_also.
|
||||
|
||||
See Also
|
||||
--------
|
||||
func_name : Descriptive text
|
||||
continued text
|
||||
another_func_name : Descriptive text
|
||||
func_name1, func_name2, :meth:`func_name`, func_name3
|
||||
|
||||
"""
|
||||
items = []
|
||||
|
||||
def parse_item_name(text):
|
||||
"""Match ':role:`name`' or 'name'"""
|
||||
m = self._name_rgx.match(text)
|
||||
if m:
|
||||
g = m.groups()
|
||||
if g[1] is None:
|
||||
return g[3], None
|
||||
else:
|
||||
return g[2], g[1]
|
||||
raise ValueError("%s is not a item name" % text)
|
||||
|
||||
def push_item(name, rest):
|
||||
if not name:
|
||||
return
|
||||
name, role = parse_item_name(name)
|
||||
items.append((name, list(rest), role))
|
||||
del rest[:]
|
||||
|
||||
current_func = None
|
||||
rest = []
|
||||
|
||||
for line in content:
|
||||
if not line.strip():
|
||||
continue
|
||||
|
||||
m = self._name_rgx.match(line)
|
||||
if m and line[m.end():].strip().startswith(':'):
|
||||
push_item(current_func, rest)
|
||||
current_func, line = line[:m.end()], line[m.end():]
|
||||
rest = [line.split(':', 1)[1].strip()]
|
||||
if not rest[0]:
|
||||
rest = []
|
||||
elif not line.startswith(' '):
|
||||
push_item(current_func, rest)
|
||||
current_func = None
|
||||
if ',' in line:
|
||||
for func in line.split(','):
|
||||
if func.strip():
|
||||
push_item(func, [])
|
||||
elif line.strip():
|
||||
current_func = line
|
||||
elif current_func is not None:
|
||||
rest.append(line.strip())
|
||||
push_item(current_func, rest)
|
||||
|
||||
if not items:
|
||||
return []
|
||||
|
||||
roles = {
|
||||
'method': 'meth',
|
||||
'meth': 'meth',
|
||||
'function': 'func',
|
||||
'func': 'func',
|
||||
'class': 'class',
|
||||
'exception': 'exc',
|
||||
'exc': 'exc',
|
||||
'object': 'obj',
|
||||
'obj': 'obj',
|
||||
'module': 'mod',
|
||||
'mod': 'mod',
|
||||
'data': 'data',
|
||||
'constant': 'const',
|
||||
'const': 'const',
|
||||
'attribute': 'attr',
|
||||
'attr': 'attr'
|
||||
}
|
||||
if self._what is None:
|
||||
func_role = 'obj'
|
||||
else:
|
||||
func_role = roles.get(self._what, '')
|
||||
lines = []
|
||||
last_had_desc = True
|
||||
for func, desc, role in items:
|
||||
if role:
|
||||
link = ':%s:`%s`' % (role, func)
|
||||
elif func_role:
|
||||
link = ':%s:`%s`' % (func_role, func)
|
||||
else:
|
||||
link = "`%s`_" % func
|
||||
if desc or last_had_desc:
|
||||
lines += ['']
|
||||
lines += [link]
|
||||
else:
|
||||
lines[-1] += ", %s" % link
|
||||
if desc:
|
||||
lines += self._indent([' '.join(desc)])
|
||||
last_had_desc = True
|
||||
else:
|
||||
last_had_desc = False
|
||||
lines += ['']
|
||||
|
||||
return self._format_admonition('seealso', lines)
|
||||
@@ -19,6 +19,7 @@ import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.PathUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -33,6 +34,7 @@ public class PythonHelpersLocator {
|
||||
/**
|
||||
* @return the base directory under which various scripts, etc are stored.
|
||||
*/
|
||||
@NotNull
|
||||
public static File getHelpersRoot() {
|
||||
@NonNls String jarPath = PathUtil.getJarPathForClass(PythonHelpersLocator.class);
|
||||
if (jarPath.endsWith(".jar")) {
|
||||
@@ -55,7 +57,7 @@ public class PythonHelpersLocator {
|
||||
* @param resourceName a path relative to helper root
|
||||
* @return absolute path of the resource
|
||||
*/
|
||||
public static String getHelperPath(String resourceName) {
|
||||
public static String getHelperPath(@NotNull String resourceName) {
|
||||
return getHelperFile(resourceName).getAbsolutePath();
|
||||
}
|
||||
|
||||
@@ -64,7 +66,8 @@ public class PythonHelpersLocator {
|
||||
* @param resourceName a path relative to helper root
|
||||
* @return a file object pointing to that path; existence is not checked.
|
||||
*/
|
||||
public static File getHelperFile(String resourceName) {
|
||||
@NotNull
|
||||
public static File getHelperFile(@NotNull String resourceName) {
|
||||
return new File(getHelpersRoot(), resourceName);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,12 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
/**
|
||||
* User: catherine
|
||||
*/
|
||||
@@ -55,7 +58,16 @@ public class DocStringUtil {
|
||||
public static boolean isEpydocDocString(@NotNull String text) {
|
||||
return text.contains("@param ") || text.contains("@rtype") || text.contains("@type");
|
||||
}
|
||||
|
||||
|
||||
public static boolean isGoogleDocString(@NotNull String text) {
|
||||
final Matcher matcher = GoogleCodeStyleDocString.SECTION_HEADER_RE.matcher(text);
|
||||
if (!matcher.find()) {
|
||||
return false;
|
||||
}
|
||||
@NonNls final String foundName = matcher.group(1).trim();
|
||||
return SectionBasedDocString.SECTION_NAMES.contains(foundName.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for a doc string under given parent.
|
||||
* @param parent where to look. For classes and functions, this would be PyStatementList, for modules, PyFile.
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.regex.Pattern;
|
||||
* @author Mikhail Golubev
|
||||
*/
|
||||
public class GoogleCodeStyleDocString extends SectionBasedDocString {
|
||||
private static final Pattern SECTION_HEADER_RE = Pattern.compile("^\\s*(\\w[\\s\\w]*):\\s*$");
|
||||
public static final Pattern SECTION_HEADER_RE = Pattern.compile("^\\s*(\\w[\\s\\w]*):\\s*$");
|
||||
private static final Pattern FIELD_NAME_AND_TYPE_RE = Pattern.compile("\\s*(.+?)\\s*\\(\\s*(.+?)\\s*\\)\\s*");
|
||||
private static final Pattern SPHINX_REFERENCE_RE = Pattern.compile("(:\\w+:\\S+:`.+?`|:\\S+:`.+?`|`.+?`)");
|
||||
|
||||
|
||||
@@ -57,6 +57,10 @@ public class PyDocumentationSettings implements PersistentStateComponent<PyDocum
|
||||
public boolean isNumpyFormat(PsiFile file) {
|
||||
return isFormat(file, DocStringFormat.NUMPY);
|
||||
}
|
||||
|
||||
public boolean isGoogleFormat(PsiFile file) {
|
||||
return isFormat(file, DocStringFormat.GOOGLE);
|
||||
}
|
||||
|
||||
public boolean isPlain(PsiFile file) {
|
||||
return isFormat(file, DocStringFormat.PLAIN);
|
||||
@@ -82,7 +86,7 @@ public class PyDocumentationSettings implements PersistentStateComponent<PyDocum
|
||||
|
||||
public void setFormat(String format) {
|
||||
myDocStringFormat = format;
|
||||
}
|
||||
}
|
||||
|
||||
@Transient
|
||||
public String getFormat() {
|
||||
|
||||
@@ -67,27 +67,31 @@ public class PyStructuredDocstringFormatter {
|
||||
final String preparedDocstring = StringUtil.join(lines, "\n");
|
||||
|
||||
final String formatter;
|
||||
final TagBasedDocString structuredDocString;
|
||||
if (documentationSettings.isEpydocFormat(element.getContainingFile()) ||
|
||||
DocStringUtil.isEpydocDocString(preparedDocstring)) {
|
||||
final StructuredDocString structuredDocString;
|
||||
if (documentationSettings.isEpydocFormat(element.getContainingFile()) || DocStringUtil.isEpydocDocString(preparedDocstring)) {
|
||||
formatter = PythonHelpersLocator.getHelperPath("epydoc_formatter.py");
|
||||
structuredDocString = new EpydocString(preparedDocstring);
|
||||
result.add(formatStructuredDocString(structuredDocString));
|
||||
}
|
||||
else if (documentationSettings.isReSTFormat(element.getContainingFile()) ||
|
||||
DocStringUtil.isSphinxDocString(preparedDocstring)) {
|
||||
else if (documentationSettings.isReSTFormat(element.getContainingFile()) || DocStringUtil.isSphinxDocString(preparedDocstring)) {
|
||||
formatter = PythonHelpersLocator.getHelperPath("rest_formatter.py");
|
||||
structuredDocString = new SphinxDocString(preparedDocstring);
|
||||
}
|
||||
else if (documentationSettings.isGoogleFormat(element.getContainingFile()) || DocStringUtil.isGoogleDocString(preparedDocstring)) {
|
||||
formatter = PythonHelpersLocator.getHelperPath("google_formatter.py");
|
||||
structuredDocString = new GoogleCodeStyleDocString(preparedDocstring);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String output = runExternalTool(module, formatter, docstring);
|
||||
if (output != null)
|
||||
if (output != null) {
|
||||
result.add(0, output);
|
||||
else
|
||||
}
|
||||
else {
|
||||
result.add(0, structuredDocString.getDescription());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -28,10 +28,7 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Common base class for docstring styles supported by Napoleon Sphinx extension.
|
||||
@@ -66,9 +63,10 @@ public abstract class SectionBasedDocString implements StructuredDocString {
|
||||
.put("warnings", "warnings")
|
||||
.build();
|
||||
|
||||
private static ImmutableSet<String> SECTIONS_WITH_NAME_AND_TYPE = ImmutableSet.of("attributes", "methods",
|
||||
"parameters", "keyword arguments", "other parameters");
|
||||
private static ImmutableSet<String> SECTIONS_WITH_TYPE = ImmutableSet.of("returns", "raises", "yields");
|
||||
public static Set<String> SECTION_NAMES = SECTION_ALIASES.keySet();
|
||||
private static final ImmutableSet<String> SECTIONS_WITH_NAME_AND_TYPE =
|
||||
ImmutableSet.of("attributes", "methods", "parameters", "keyword arguments", "other parameters");
|
||||
private static final ImmutableSet<String> SECTIONS_WITH_TYPE = ImmutableSet.of("returns", "raises", "yields");
|
||||
|
||||
protected final List<Substring> myLines;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user