Unverified Commit 4a956a72 authored by Peter Eastman's avatar Peter Eastman Committed by GitHub
Browse files

Convert C++ types to Python types in API docs (#5036)

* Convert C++ types to Python types in API docs

* Translate some more types

* Convert return types that are STL containers
parent 2af004b6
...@@ -72,8 +72,46 @@ def process_docstring(app, what, name, obj, options, lines): ...@@ -72,8 +72,46 @@ def process_docstring(app, what, name, obj, options, lines):
lines[:] = [(l if not l.isspace() else '') for l in joined.split(linesep)] lines[:] = [(l if not l.isspace() else '') for l in joined.split(linesep)]
substitutions = {'double':'float', 'long long':'int', 'string':'str',
'pairii':'tuple[int, int]',
'vectord':'tuple[float, ...]',
'vectorvectorvectord':'tuple[tuple[tuple[float, ...], ...], ...]',
'vectori':'tuple[int, ...]',
'vectorvectori':'tuple[tuple[int, ...], ...]',
'vectorpairii':'tuple[tuple[int, int], ...]',
'vectorstring':'tuple[str, ...]',
'mapstringstring':'Mapping[str, str]',
'mapstringdouble':'Mapping[str, float]',
'mapii':'Mapping[int, int]',
'seti':'set[int]'
}
def convert_type(type):
if type in substitutions:
type = substitutions[type]
if '<' in type:
match = re.match('vector<(.*?),.*>', type)
if match is not None:
type = f'tuple[{convert_type(match[1])}]'
match = re.match('map<(.*?),(.*?),.*>', type)
if match is not None:
type = f'Mapping[{convert_type(match[1])}, {convert_type(match[2])}]'
return type
def process_signature(app, what, name, obj, options, signature, return_annotation):
if return_annotation is not None:
# Convert C++ types to Python types
if return_annotation.startswith('std::'):
return_annotation = return_annotation[5:]
if return_annotation.endswith(' const &'):
return_annotation = return_annotation[:-8]
return_annotation = convert_type(return_annotation)
return (signature, return_annotation)
def setup(app): def setup(app):
app.connect('autodoc-process-docstring', process_docstring) app.connect('autodoc-process-docstring', process_docstring)
app.connect('autodoc-process-signature', process_signature)
def test(): def test():
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
namespace std { namespace std {
%template(pairii) pair<int,int>; %template(pairii) pair<int,int>;
%template(vectord) vector<double>; %template(vectord) vector<double>;
%template(vectorddd) vector< vector< vector<double> > >; %template(vectorvectorvectord) vector< vector< vector<double> > >;
%template(vectori) vector<int>; %template(vectori) vector<int>;
%template(vectorii) vector < vector<int> >; %template(vectorvectori) vector < vector<int> >;
%template(vectorpairii) vector< pair<int,int> >; %template(vectorpairii) vector< pair<int,int> >;
%template(vectorstring) vector<string>; %template(vectorstring) vector<string>;
%template(mapstringstring) map<string,string>; %template(mapstringstring) map<string,string>;
......
...@@ -19,6 +19,11 @@ except ImportError: ...@@ -19,6 +19,11 @@ except ImportError:
INDENT = " " INDENT = " "
docTags = {'emphasis':'i', 'bold':'b', 'itemizedlist':'ul', 'listitem':'li', 'preformatted':'pre', 'computeroutput':'tt', docTags = {'emphasis':'i', 'bold':'b', 'itemizedlist':'ul', 'listitem':'li', 'preformatted':'pre', 'computeroutput':'tt',
'superscript': 'sup', 'subscript':'sub', 'verbatim': 'verbatim'} 'superscript': 'sup', 'subscript':'sub', 'verbatim': 'verbatim'}
typeSubstitutions = {'double':'float', 'long long':'int', 'string':'str'}
vectorPattern = re.compile("vector\<(.*)>")
setPattern = re.compile("set\<(.*)>")
mapPattern = re.compile("map\<(.*)\,(.*)>")
pairPattern = re.compile("pair\<(.*)\,(.*)>")
def is_method_abstract(argstring): def is_method_abstract(argstring):
return argstring.split(")")[-1].find("=0") >= 0 return argstring.split(")")[-1].find("=0") >= 0
...@@ -158,13 +163,29 @@ def docstringTypemap(cpptype): ...@@ -158,13 +163,29 @@ def docstringTypemap(cpptype):
This doesn't need to be perfectly accurate -- it's not used for generating This doesn't need to be perfectly accurate -- it's not used for generating
the actual swig wrapper code. It's only used for generating the docstrings. the actual swig wrapper code. It's only used for generating the docstrings.
""" """
pytype = cpptype pytype = cpptype.strip()
if pytype.startswith('const '): if pytype.startswith('const '):
pytype = pytype[6:] pytype = pytype[6:]
if pytype.startswith('std::'): if pytype.startswith('std::'):
pytype = pytype[5:] pytype = pytype[5:]
pytype = pytype.strip('&') pytype = pytype.strip('&')
return pytype.strip() pytype = pytype.strip('*')
pytype = pytype.strip()
if pytype in typeSubstitutions:
pytype = typeSubstitutions[pytype]
match = vectorPattern.match(pytype)
if match is not None:
pytype = f'Sequence[{docstringTypemap(match[1])}]'
match = setPattern.match(pytype)
if match is not None:
pytype = f'set[{docstringTypemap(match[1])}]'
match = mapPattern.match(pytype)
if match is not None:
pytype = f'Mapping[{docstringTypemap(match[1])}, {docstringTypemap(match[2])}]'
match = pairPattern.match(pytype)
if match is not None:
pytype = f'tuple[{docstringTypemap(match[1])}, {docstringTypemap(match[2])}]'
return pytype
class SwigInputBuilder: class SwigInputBuilder:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment