Merge branch 'master' into doxygen

Fix the usual conflicts in autodoc unit test due to fixing the
divergences in autodoc generation between builtin and default cases in
this branch.
This commit is contained in:
Vadim Zeitlin 2017-09-19 13:54:41 +02:00
commit db65ae5aea
371 changed files with 9815 additions and 3191 deletions

View file

@ -183,7 +183,7 @@ static String *getSlot(Node *n = NULL, const char *key = NULL, String *default_s
static void printSlot(File *f, String *slotval, const char *slotname, const char *functype = NULL) {
String *slotval_override = 0;
if (functype)
if (functype && Strcmp(slotval, "0") == 0)
slotval = slotval_override = NewStringf("(%s) %s", functype, slotval);
int len = Len(slotval);
int fieldwidth = len > 41 ? (len > 61 ? 0 : 61 - len) : 41 - len;
@ -1946,6 +1946,7 @@ public:
String *new_value = convertValue(value, Getattr(p, "type"));
if (new_value)
Printf(doc, "=%s", new_value);
Delete(new_value);
}
Delete(type_str);
Delete(made_name);
@ -2031,9 +2032,9 @@ public:
Delete(rname);
} else {
if (CPlusPlus) {
Printf(doc, "Proxy of C++ %s class.", real_classname);
Printf(doc, "Proxy of C++ %s class.", SwigType_namestr(real_classname));
} else {
Printf(doc, "Proxy of C %s struct.", real_classname);
Printf(doc, "Proxy of C %s struct.", SwigType_namestr(real_classname));
}
}
}
@ -2044,7 +2045,7 @@ public:
String *paramList = make_autodocParmList(n, showTypes);
Printf(doc, "__init__(");
if (showTypes)
Printf(doc, "%s ", getClassName());
Printf(doc, "%s ", class_name);
if (Len(paramList))
Printf(doc, "self, %s) -> %s", paramList, class_name);
else
@ -2055,7 +2056,7 @@ public:
case AUTODOC_DTOR:
if (showTypes)
Printf(doc, "__del__(%s self)", getClassName());
Printf(doc, "__del__(%s self)", class_name);
else
Printf(doc, "__del__(self)");
break;
@ -2109,6 +2110,70 @@ public:
return doc;
}
/* ------------------------------------------------------------
* convertIntegerValue()
*
* Check if string v is an integer and can be represented in
* Python. If so, return an appropriate Python representation,
* otherwise (or if we are unsure), return NIL.
* ------------------------------------------------------------ */
String *convertIntegerValue(String *v, SwigType *resolved_type) {
const char *const s = Char(v);
char *end;
String *result = NIL;
// Check if this is an integer number in any base.
long value = strtol(s, &end, 0);
if (errno == ERANGE || end == s)
return NIL;
if (*end != '\0') {
// If there is a suffix after the number, we can safely ignore "l"
// and (provided the number is unsigned) "u", and also combinations of
// these, but not anything else.
for (char *p = end; *p != '\0'; ++p) {
switch (*p) {
case 'l':
case 'L':
break;
case 'u':
case 'U':
if (value < 0)
return NIL;
break;
default:
return NIL;
}
}
}
// So now we are certain that we are indeed dealing with an integer
// that has a representation as long given by value.
if (Cmp(resolved_type, "bool") == 0)
// Allow integers as the default value for a bool parameter.
return NewString(value ? "True" : "False");
if (value == 0)
return NewString(SwigType_ispointer(resolved_type) ? "None" : "0");
// v may still be octal or hexadecimal:
const char *p = s;
if (*p == '+' || *p == '-')
++p;
if (*p == '0' && *(p+1) != 'x' && *(p+1) != 'X') {
// This must have been an octal number. This is the only case we
// cannot use in Python directly, since Python 2 and 3 use non-
// compatible representations.
result = NewString(*s == '-' ? "int('-" : "int('");
String *octal_string = NewStringWithSize(p, (int) (end - p));
Append(result, octal_string);
Append(result, "', 8)");
Delete(octal_string);
return result;
}
result = *end == '\0' ? Copy(v) : NewStringWithSize(s, (int) (end - s));
return result;
}
/* ------------------------------------------------------------
* convertDoubleValue()
*
@ -2147,7 +2212,7 @@ public:
// Avoid unnecessary string allocation in the common case when we don't
// need to remove any suffix.
return *end == '\0' ? v : NewStringWithSize(s, (int)(end - s));
return *end == '\0' ? Copy(v) : NewStringWithSize(s, (int)(end - s));
}
return NIL;
@ -2157,109 +2222,24 @@ public:
* convertValue()
*
* Check if string v can be a Python value literal or a
* constant. Return NIL if it isn't.
* constant. Return an equivalent Python representation,
* or NIL if it isn't, or we are unsure.
* ------------------------------------------------------------ */
String *convertValue(String *v, SwigType *type) {
const char *const s = Char(v);
char *end;
String *result = NIL;
bool fail = false;
SwigType *resolved_type = 0;
SwigType *resolved_type = SwigType_typedef_resolve_all(type);
// Check if this is a number in any base.
long value = strtol(s, &end, 0);
(void) value;
if (end != s) {
if (errno == ERANGE) {
// There was an overflow, we could try representing the value as Python
// long integer literal, but for now don't bother with it.
fail = true;
} else {
if (*end != '\0') {
// If there is a suffix after the number, we can safely ignore any
// combination of "l" and "u", but not anything else (again, stuff like
// "LL" could be handled, but we don't bother to do it currently).
bool seen_long = false;
for (char * p = end; *p != '\0'; ++p) {
switch (*p) {
case 'l':
case 'L':
// Bail out on "LL".
if (seen_long) {
fail = true;
break;
}
seen_long = true;
break;
case 'u':
case 'U':
break;
default:
// Except that our suffix could actually be the fractional part of
// a floating point number, so we still have to check for this.
result = convertDoubleValue(v);
}
}
}
if (!fail) {
// Allow integers as the default value for a bool parameter.
resolved_type = SwigType_typedef_resolve_all(type);
if (Cmp(resolved_type, "bool") == 0) {
result = NewString(value ? "True" : "False");
} else {
// Deal with the values starting with 0 first as they can be octal or
// hexadecimal numbers or even pointers.
if (s[0] == '0') {
if (Len(v) == 1) {
// This is just a lone 0, but it needs to be represented differently
// in Python depending on whether it's a zero or a null pointer.
if (SwigType_ispointer(resolved_type))
result = NewString("None");
else
result = v;
} else if (s[1] == 'x' || s[1] == 'X') {
// This must have been a hex number, we can use it directly in Python,
// so nothing to do here.
} else {
// This must have been an octal number, we have to change its prefix
// to be "0o" in Python 3 only (and as long as we still support Python
// 2.5, this can't be done unconditionally).
if (py3) {
if (end - s > 1) {
result = NewString("0o");
Append(result, NewStringWithSize(s + 1, (int)(end - s - 1)));
}
}
}
}
// Avoid unnecessary string allocation in the common case when we don't
// need to remove any suffix.
if (!result)
result = *end == '\0' ? v : NewStringWithSize(s, (int)(end - s));
}
}
}
}
// Check if this is a floating point number (notice that it wasn't
// necessarily parsed as a long above, consider e.g. ".123").
if (!fail && !result) {
result = convertIntegerValue(v, resolved_type);
if (!result) {
result = convertDoubleValue(v);
if (!result) {
if (Strcmp(v, "true") == 0 || Strcmp(v, "TRUE") == 0)
if (Strcmp(v, "true") == 0)
result = NewString("True");
else if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0)
else if (Strcmp(v, "false") == 0)
result = NewString("False");
else if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0) {
if (!resolved_type)
resolved_type = SwigType_typedef_resolve_all(type);
else if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0)
result = SwigType_ispointer(resolved_type) ? NewString("None") : NewString("0");
}
// This could also be an enum type, default value of which could be
// representable in Python if it doesn't include any scope (which could,
// but currently is not, translated).
@ -2267,7 +2247,7 @@ public:
Node *lookup = Swig_symbol_clookup(v, 0);
if (lookup) {
if (Cmp(Getattr(lookup, "nodeType"), "enumitem") == 0)
result = Getattr(lookup, "sym:name");
result = Copy(Getattr(lookup, "sym:name"));
}
}
}
@ -2314,10 +2294,12 @@ public:
if (Getattr(p, "tmap:default"))
return false;
if (String *value = Getattr(p, "value")) {
String *type = Getattr(p, "type");
if (!convertValue(value, type))
String *value = Getattr(p, "value");
if (value) {
String *convertedValue = convertValue(value, Getattr(p, "type"));
if (!convertedValue)
return false;
Delete(convertedValue);
}
}
@ -2598,7 +2580,8 @@ public:
String *tmp = NewString("");
String *dispatch;
const char *dispatch_code = funpack ? "return %s(self, argc, argv);" : "return %s(self, args);";
const char *dispatch_code = funpack ? "return %s(self, argc, argv);" :
(builtin_ctor ? "return %s(self, args, NULL);" : "return %s(self, args);");
if (castmode) {
dispatch = Swig_overload_dispatch_cast(n, dispatch_code, &maxargs);
@ -2612,7 +2595,8 @@ public:
String *symname = Getattr(n, "sym:name");
String *wname = Swig_name_wrapper(symname);
Printv(f->def, linkage, builtin_ctor ? "int " : "PyObject *", wname, "(PyObject *self, PyObject *args) {", NIL);
const char *builtin_kwargs = builtin_ctor ? ", PyObject *SWIGUNUSEDPARM(kwargs)" : "";
Printv(f->def, linkage, builtin_ctor ? "int " : "PyObject *", wname, "(PyObject *self, PyObject *args", builtin_kwargs, ") {", NIL);
Wrapper_add_local(f, "argc", "Py_ssize_t argc");
Printf(tmp, "PyObject *argv[%d] = {0}", maxargs + 1);
@ -2620,9 +2604,14 @@ public:
if (!fastunpack) {
Wrapper_add_local(f, "ii", "Py_ssize_t ii");
if (maxargs - (add_self ? 1 : 0) > 0)
Append(f->code, "if (!PyTuple_Check(args)) SWIG_fail;\n");
Append(f->code, "argc = args ? PyObject_Length(args) : 0;\n");
if (maxargs - (add_self ? 1 : 0) > 0) {
Append(f->code, "if (!PyTuple_Check(args)) SWIG_fail;\n");
Append(f->code, "argc = PyObject_Length(args);\n");
} else {
Append(f->code, "argc = args ? PyObject_Length(args) : 0;\n");
}
if (add_self)
Append(f->code, "argv[0] = self;\n");
Printf(f->code, "for (ii = 0; (ii < %d) && (ii < argc); ii++) {\n", add_self ? maxargs - 1 : maxargs);
@ -2645,8 +2634,8 @@ public:
if (GetFlag(n, "feature:python:maybecall")) {
Append(f->code, "fail:\n");
Append(f->code, "Py_INCREF(Py_NotImplemented);\n");
Append(f->code, "return Py_NotImplemented;\n");
Append(f->code, " Py_INCREF(Py_NotImplemented);\n");
Append(f->code, " return Py_NotImplemented;\n");
} else {
Node *sibl = n;
while (Getattr(sibl, "sym:previousSibling"))
@ -2658,7 +2647,7 @@ public:
Delete(fulldecl);
} while ((sibl = Getattr(sibl, "sym:nextSibling")));
Append(f->code, "fail:\n");
Printf(f->code, "SWIG_SetErrorMsg(PyExc_NotImplementedError,"
Printf(f->code, " SWIG_SetErrorMsg(PyExc_NotImplementedError,"
"\"Wrong number or type of arguments for overloaded function '%s'.\\n\"" "\n\" Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes);
Printf(f->code, "return %s;\n", builtin_ctor ? "-1" : "0");
Delete(protoTypes);
@ -2821,9 +2810,10 @@ public:
Append(wname, overname);
}
const char *builtin_kwargs = builtin_ctor ? ", PyObject *SWIGUNUSEDPARM(kwargs)" : "";
if (!allow_kwargs || overname) {
if (!varargs) {
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL);
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL);
} else {
Printv(f->def, linkage, wrap_return, wname, "__varargs__", "(PyObject *", self_param, ", PyObject *args, PyObject *varargs) {", NIL);
}
@ -3019,17 +3009,13 @@ public:
Clear(f->def);
if (overname) {
if (noargs) {
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", int nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {", NIL);
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {", NIL);
} else {
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", int nobjs, PyObject **swig_obj) {", NIL);
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **swig_obj) {", NIL);
}
Printf(parse_args, "if ((nobjs < %d) || (nobjs > %d)) SWIG_fail;\n", num_required, num_arguments);
} else {
if (noargs) {
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL);
} else {
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL);
}
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL);
if (onearg && !builtin_ctor) {
Printf(parse_args, "if (!args) SWIG_fail;\n");
Append(parse_args, "swig_obj[0] = args;\n");
@ -3283,10 +3269,17 @@ public:
if (need_cleanup) {
Printv(f->code, cleanup, NIL);
}
if (builtin_ctor)
if (builtin_ctor) {
Printv(f->code, " return -1;\n", NIL);
else
Printv(f->code, " return NULL;\n", NIL);
} else {
if (GetFlag(n, "feature:python:maybecall")) {
Append(f->code, " PyErr_Clear();\n");
Append(f->code, " Py_INCREF(Py_NotImplemented);\n");
Append(f->code, " return Py_NotImplemented;\n");
} else {
Printv(f->code, " return NULL;\n", NIL);
}
}
if (funpack) {
@ -3323,9 +3316,10 @@ public:
DelWrapper(f);
f = NewWrapper();
if (funpack) {
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", int nobjs, PyObject **swig_obj) {", NIL);
// Note: funpack is currently always false for varargs
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **swig_obj) {", NIL);
} else {
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL);
Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL);
}
Wrapper_add_local(f, "resultobj", builtin_ctor ? "int resultobj" : "PyObject *resultobj");
Wrapper_add_local(f, "varargs", "PyObject *varargs");
@ -3435,7 +3429,7 @@ public:
closure_name = Copy(wrapper_name);
}
if (func_type) {
String *s = NewStringf("(%s) %s", func_type, closure_name);
String *s = NewStringf("%s", closure_name);
Delete(closure_name);
closure_name = s;
}
@ -5119,7 +5113,7 @@ public:
Printv(f_shadow, tab4, "__swig_destroy__ = ", module, ".", Swig_name_destroy(NSPACE_TODO, symname), "\n", NIL);
if (!have_pythonprepend(n) && !have_pythonappend(n)) {
if (proxydel) {
Printv(f_shadow, tab4, "__del__ = lambda self: None\n", NIL);
Printv(f_shadow, tab4, "def __del__(self):\n", tab8, "return None\n", NIL);
}
return SWIG_OK;
}
@ -5454,8 +5448,11 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
Delete(target);
// Get any exception classes in the throws typemap
if (Getattr(n, "noexcept")) {
Append(w->def, " noexcept");
Append(declaration, " noexcept");
}
ParmList *throw_parm_list = 0;
if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
Parm *p;
int gencomma = 0;
@ -5489,8 +5486,16 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
* if the return value is a reference or const reference, a specialized typemap must
* handle it, including declaration of c_result ($result).
*/
if (!is_void) {
if (!(ignored_method && !pure_virtual)) {
if (!is_void && (!ignored_method || pure_virtual)) {
if (!SwigType_isclass(returntype)) {
if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
Delete(construct_result);
} else {
Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
}
} else {
String *cres = SwigType_lstr(returntype, "c_result");
Printf(w->code, "%s;\n", cres);
Delete(cres);