Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Towards typing #150

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,6 @@
}


def autodoc_process_signature(app, what, name, obj, options, signature,
return_annotation):
from inspect import ismethod
if ismethod(obj) and obj.__doc__:
import re
pattern = r"^[ \n]*%s(\([a-z_0-9, ]+\))" % re.escape(obj.__name__)
func_match = re.match(pattern, obj.__doc__)

if func_match is not None:
signature = func_match.group(1)
elif obj.__name__ == "is_valid":
signature = "()"

return (signature, return_annotation)


def autodoc_process_docstring(app, what, name, obj, options, lines):
# clear out redundant pybind-generated member list
if any("Members" in ln for ln in lines):
Expand Down Expand Up @@ -94,4 +78,3 @@ def gen_method_string(meth_name):

def setup(app):
app.connect("autodoc-process-docstring", autodoc_process_docstring)
app.connect("autodoc-process-signature", autodoc_process_signature)
29 changes: 14 additions & 15 deletions doc/misc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,27 @@ This command should install :mod:`islpy`::

pip install islpy

You may need to run this with :command:`sudo`.
If you don't already have `pip <https://pypi.python.org/pypi/pip>`_,
run this beforehand::
For a more manual installation from source, `download the source
<http://pypi.org/project/islpy>`__, unpack it, and say::

curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py
python get-pip.py
pip install -v .

For a more manual installation, `download the source
<http://pypi.python.org/pypi/islpy>`_, unpack it, and say::
You may also clone its git repository::

python setup.py install
git clone --recursive https://github.com/inducer/islpy.git

You may also clone its git repository::
The following attempts an editable installation, however note
that this may run into various issues and is not well-supported
by the build tools::

git clone --recursive http://git.tiker.net/trees/islpy.git
git clone --recursive git://github.com/inducer/islpy
$ pip install --no-build-isolation -e .

Wiki and FAQ
============
Support
=======

A `wiki page <http://wiki.tiker.net/IslPy>`_ is also available, where install
instructions and an FAQ will grow over time.
You can try posting questions or comments at the
`Github Discussions site <https://github.com/inducer/islpy/discussions>`__
for islpy.

For a mailing list, please consider using the `isl list
<http://groups.google.com/group/isl-development>`_ until they tell us to get
Expand Down
94 changes: 46 additions & 48 deletions gen_wrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -876,10 +876,11 @@ def write_wrapper(outf, meth):
input_args = []
post_call = []
extra_ret_vals = []
extra_ret_descrs = []
extra_ret_types = []
preamble = []

arg_names = []
arg_sigs = []

checks.append("isl_ctx *islpy_ctx = nullptr;")

Expand All @@ -906,15 +907,15 @@ def write_wrapper(outf, meth):
if (meth.cls in ["ast_build", "ast_print_options"]
and meth.name.startswith("set_")):
extra_ret_vals.append(f"py_{arg.name}")
extra_ret_descrs.append("(opaque handle to "
"manage callback lifetime)")
extra_ret_types.append("CallbackLifetimeHandle ")

input_args.append(f"py::object py_{arg.name}")
passed_args.append(cb_name)
passed_args.append(f"py_{arg.name}.ptr()")

preamble.append(get_callback(cb_name, arg))

arg_sigs.append(f"{arg.name}: Callable")
docs.append(":param {name}: callback({args})".format(
name=arg.name,
args=", ".join(
Expand All @@ -931,10 +932,10 @@ def write_wrapper(outf, meth):
doc_cls = arg.base_type
if doc_cls.startswith("isl_"):
doc_cls = doc_cls[4:]
if doc_cls == "unsigned long":
else:
doc_cls = "int"

docs.append(f":param {arg.name}: :class:`{doc_cls}`")
arg_sigs.append(f"{arg.name}: {doc_cls}")

elif arg.base_type in ["char", "const char"] and arg.ptr == "*":
if arg.semantics is SEM_KEEP:
Expand All @@ -949,7 +950,7 @@ def _arg_to_const_str(arg: Argument) -> str:

input_args.append(f"{_arg_to_const_str(arg)}{arg.base_type} *{arg.name}")

docs.append(f":param {arg.name}: string")
arg_sigs.append(f"{arg.name}: str")

elif arg.base_type in ["int", "isl_bool"] and arg.ptr == "*":
if arg.name in ["exact", "tight"]:
Expand All @@ -959,16 +960,14 @@ def _arg_to_const_str(arg: Argument) -> str:
extra_ret_vals.append(f"(bool) arg_{arg.name}")
else:
extra_ret_vals.append(f"arg_{arg.name}")
extra_ret_descrs.append(
f"{arg.name} ({to_py_class(arg.base_type)})")
extra_ret_types.append(to_py_class(arg.base_type))
arg_names.pop()
else:
raise SignatureNotSupported("int *")

elif arg.base_type == "isl_val" and arg.ptr == "*" and arg_idx > 0:
# {{{ val input argument

arg_descr = f":param {arg.name}: :class:`Val`"
input_args.append(f"py::object py_{arg.name}")
checks.append("""
std::unique_ptr<val> unique_arg_%(name)s;
Expand Down Expand Up @@ -1013,18 +1012,16 @@ def _arg_to_const_str(arg: Argument) -> str:
post_call.append(f"unique_arg_{arg.name}.release();")

passed_args.append(f"unique_arg_{arg.name}->m_data")
docs.append(arg_descr)
arg_sigs.append(f"{arg.name}: Val | int")

# }}}

elif arg.base_type.startswith("isl_") and arg.ptr == "*":
# {{{ isl types input arguments

arg_cls = arg.base_type[4:]
arg_descr = f":param {arg.name}: :class:`{to_py_class(arg_cls)}`"

if arg_idx == 0 and meth.is_mutator:
arg_descr += " (mutated in-place)"
input_args.append(f"py::object py_{arg.name}")
checks.append("""
isl::%(cls)s &arg_%(name)s(
Expand All @@ -1038,7 +1035,7 @@ def _arg_to_const_str(arg: Argument) -> str:
"cls": arg_cls})
passed_args.append(f"arg_{arg.name}.m_data")
post_call.append(f"arg_{arg.name}.invalidate();")
arg_descr += " (mutated in-place)"
docs.append("..note::\n {arg.name} is mutated in-place.\n\n")

else:
if arg.semantics is None and arg.base_type != "isl_ctx":
Expand Down Expand Up @@ -1077,7 +1074,9 @@ def _arg_to_const_str(arg: Argument) -> str:
input_args.append(f"{arg_cls} &arg_{arg.name}")
post_call.append(f"arg_{arg.name}.invalidate();")
passed_args.append(f"arg_{arg.name}.m_data")
arg_descr += " (:ref:`becomes invalid <auto-invalidation>`)"
docs.append(
"..note::\n {arg.name} "
":ref:`becomes invalid <auto-invalidation>`)\n\n")
else:
passed_args.append(f"arg_{arg.name}.m_data")
input_args.append(f"{arg_cls} const &arg_{arg.name}")
Expand All @@ -1092,7 +1091,7 @@ def _arg_to_const_str(arg: Argument) -> str:
islpy_ctx = {arg.base_type}_get_ctx(arg_{arg.name}.m_data);
""")

docs.append(arg_descr)
arg_sigs.append(f"{arg.name}: {to_py_class(arg_cls)}")

# }}}

Expand All @@ -1118,8 +1117,7 @@ def _arg_to_const_str(arg: Argument) -> str:
""" % {"name": arg.name, "ret_cls": ret_cls})

extra_ret_vals.append(f"py_ret_{arg.name}")
extra_ret_descrs.append(
f"{arg.name} (:class:`{to_py_class(ret_cls)}`)")
extra_ret_types.append(to_py_class(ret_cls))

# }}}

Expand All @@ -1142,7 +1140,7 @@ def _arg_to_const_str(arg: Argument) -> str:

arg_idx += 1

processed_return_type = f"{meth.return_base_type} {meth.return_ptr}"
processed_return_type = f"{meth.return_base_type} {meth.return_ptr}".strip()

if meth.return_base_type == "void" and not meth.return_ptr:
result_capture = ""
Expand All @@ -1168,18 +1166,18 @@ def _arg_to_const_str(arg: Argument) -> str:
if meth.name.startswith("is_") or meth.name.startswith("has_"):
processed_return_type = "bool"

ret_descr = processed_return_type
ret_type = processed_return_type

if extra_ret_vals:
if len(extra_ret_vals) == 1:
processed_return_type = "py::object"
body.append(f"return py::object(result, {extra_ret_vals[0]});")
ret_descr = extra_ret_descrs[0]
ret_type, = extra_ret_types
else:
processed_return_type = "py::object"
body.append("return py::make_tuple(result, {});".format(
", ".join(extra_ret_vals)))
ret_descr = "tuple: ({})".format(", ".join(extra_ret_descrs))
ret_type = f"tuple[{', '.join(extra_ret_types)}]"
else:
body.append("return result;")

Expand All @@ -1195,18 +1193,18 @@ def _arg_to_const_str(arg: Argument) -> str:

assert not (meth.name.startswith("is_") or meth.name.startswith("has_"))

ret_descr = processed_return_type
ret_type = "None"

if extra_ret_vals:
if len(extra_ret_vals) == 1:
processed_return_type = "py::object"
body.append(f"return py::object({extra_ret_vals[0]});")
ret_descr = extra_ret_descrs[0]
ret_type, = extra_ret_types
else:
processed_return_type = "py::object"
body.append("return py::make_tuple({});".format(
", ".join(extra_ret_vals)))
ret_descr = "tuple: ({})".format(", ".join(extra_ret_descrs))
ret_type = f"tuple[{', '.join(extra_ret_types)}]"
else:
body.append("return result;")

Expand All @@ -1221,18 +1219,18 @@ def _arg_to_const_str(arg: Argument) -> str:
""")

processed_return_type = "bool"
ret_descr = "bool"
ret_type = "bool"

if extra_ret_vals:
if len(extra_ret_vals) == 1:
processed_return_type = "py::object"
body.append(f"return py::object({extra_ret_vals[0]});")
ret_descr = extra_ret_descrs[0]
ret_type, = extra_ret_types
else:
processed_return_type = "py::object"
body.append("return py::make_tuple({});".format(
", ".join(extra_ret_vals)))
ret_descr = "tuple: ({})".format(", ".join(extra_ret_descrs))
ret_type = f"tuple[{', '.join(extra_ret_types)}]"
else:
body.append("return result;")

Expand All @@ -1245,7 +1243,7 @@ def _arg_to_const_str(arg: Argument) -> str:
raise NotImplementedError("extra ret val with safe type")

body.append("return result;")
ret_descr = processed_return_type
ret_type = "int"

# }}}

Expand All @@ -1263,7 +1261,8 @@ def _arg_to_const_str(arg: Argument) -> str:
body.append(f"arg_{meth.args[0].name}.take_possession_of(result);")
body.append(f"return py_{meth.args[0].name};")

ret_descr = f":class:`{to_py_class(ret_cls)}` (self)"
ret_type = to_py_class(ret_cls)
docs.append("..note::\n Returns *self*.\n\n")
else:
processed_return_type = "py::object"
isl_obj_ret_val = \
Expand All @@ -1272,10 +1271,9 @@ def _arg_to_const_str(arg: Argument) -> str:
if extra_ret_vals:
isl_obj_ret_val = "py::make_tuple({}, {})".format(
isl_obj_ret_val, ", ".join(extra_ret_vals))
ret_descr = "tuple: (:class:`{}`, {})".format(
to_py_class(ret_cls), ", ".join(extra_ret_descrs))
ret_type = f"tuple[{', '.join(extra_ret_types)}]"
else:
ret_descr = f":class:`{to_py_class(ret_cls)}`"
ret_type = to_py_class(ret_cls)

if meth.return_semantics is None and ret_cls != "ctx":
raise Undocumented(meth)
Expand Down Expand Up @@ -1308,7 +1306,7 @@ def _arg_to_const_str(arg: Argument) -> str:
if meth.return_semantics is SEM_GIVE:
body.append("free(result);")

ret_descr = "string"
ret_type = "str"

elif (meth.return_base_type == "void"
and meth.return_ptr == "*"
Expand All @@ -1317,21 +1315,21 @@ def _arg_to_const_str(arg: Argument) -> str:
body.append("""
return py::borrow<py::object>((PyObject *) result);
""")
ret_descr = "a user-specified python object"
ret_type = "object"
processed_return_type = "py::object"

elif meth.return_base_type == "void" and not meth.return_ptr:
if extra_ret_vals:
processed_return_type = "py::object"
if len(extra_ret_vals) == 1:
body.append(f"return {extra_ret_vals[0]};")
ret_descr = extra_ret_descrs[0]
ret_type, = extra_ret_types
else:
body.append("return py::make_tuple({});".format(
", ".join(extra_ret_vals)))
ret_descr = "tuple: {}".format(", ".join(extra_ret_descrs))
ret_type = f"tuple[{', '.join(extra_ret_types)}]"
else:
ret_descr = "None"
ret_type = "None"

else:
raise SignatureNotSupported(
Expand All @@ -1351,17 +1349,16 @@ def _arg_to_const_str(arg: Argument) -> str:
inputs=", ".join(input_args),
body="\n".join(body)))

docs = (["{}({})".format(meth.name, ", ".join(arg_names)),
"", *docs, f":return: {ret_descr}"])
sig_str = f"({', '.join(arg_sigs)}) -> {ret_type}"

return arg_names, "\n".join(docs)
return arg_names, "\n".join(docs), sig_str

# }}}


# {{{ exposer generator

def write_exposer(outf, meth, arg_names, doc_str):
def write_exposer(outf, meth, arg_names, doc_str, sig_str):
func_name = f"isl::{meth.cls}_{meth.name}"
py_name = meth.name

Expand All @@ -1388,12 +1385,13 @@ def write_exposer(outf, meth, arg_names, doc_str):
"This function is not part of the officially public isl API. "
"Use at your own risk.")

doc_str_arg = ', "{}"'.format(doc_str.replace("\n", "\\n"))

wrap_class = CLASS_MAP.get(meth.cls, meth.cls)

outf.write(f'wrap_{wrap_class}.def{"_static" if meth.is_static else ""}('
f'"{py_name}", {func_name}{args_str+doc_str_arg});\n')
f'"{py_name}", {func_name}{args_str}'
f', py::sig("def {py_name}{sig_str}")'
f', "{py_name}{sig_str}\\n{doc_str.replace("\n", "\\n")}"'
');\n')

if meth.name == "read_from_str":
assert meth.is_static
Expand Down Expand Up @@ -1443,13 +1441,13 @@ def write_wrappers(expf, wrapf, methods):
continue

try:
arg_names, doc_str = write_wrapper(wrapf, meth)
write_exposer(expf, meth, arg_names, doc_str)
arg_names, doc_str, sig_str = write_wrapper(wrapf, meth)
write_exposer(expf, meth, arg_names, doc_str, sig_str)
except Undocumented:
undoc.append(str(meth))
except Retry:
arg_names, doc_str = write_wrapper(wrapf, meth)
write_exposer(expf, meth, arg_names, doc_str)
arg_names, doc_str, sig_str = write_wrapper(wrapf, meth)
write_exposer(expf, meth, arg_names, doc_str, sig_str)
except SignatureNotSupported:
_, e, _ = sys.exc_info()
print(f"SKIP (sig not supported: {e}): {meth}")
Expand Down
Loading
Loading