diff options
| -rw-r--r-- | build_scripts/setup_runner.py | 2 | ||||
| -rw-r--r-- | build_scripts/utils.py | 5 | ||||
| -rw-r--r-- | coin_build_instructions.py | 15 | ||||
| -rw-r--r-- | sources/pyside2/PySide2/templates/core_common.xml | 6 | ||||
| -rw-r--r-- | sources/shiboken2/generator/shiboken2/cppgenerator.cpp | 4 | ||||
| -rw-r--r-- | sources/shiboken2/libshiboken/pep384impl.cpp | 19 | ||||
| -rw-r--r-- | sources/shiboken2/libshiboken/pep384impl.h | 2 | ||||
| -rw-r--r-- | sources/shiboken2/libshiboken/signature.cpp | 129 | ||||
| -rw-r--r-- | sources/shiboken2/shibokenmodule/support/signature/errorhandler.py | 16 | ||||
| -rw-r--r-- | sources/shiboken2/shibokenmodule/support/signature/loader.py | 4 |
10 files changed, 156 insertions, 46 deletions
diff --git a/build_scripts/setup_runner.py b/build_scripts/setup_runner.py index 8efb2883a..0e45a13f4 100644 --- a/build_scripts/setup_runner.py +++ b/build_scripts/setup_runner.py @@ -148,7 +148,7 @@ class SetupRunner(object): for cmd in self.invocations_list: cmd_as_string = " ".join(cmd) print("\nRunning process: {}\n".format(cmd_as_string)) - exit_code = run_process(cmd, redirect_stderr_to_stdout=False) + exit_code = run_process(cmd) if exit_code != 0: msg = textwrap.dedent(""" setup.py invocation failed with exit code: {}.\n\n diff --git a/build_scripts/utils.py b/build_scripts/utils.py index 924b698dc..9500b3409 100644 --- a/build_scripts/utils.py +++ b/build_scripts/utils.py @@ -399,10 +399,9 @@ def run_process_output(args, initial_env=None): result.append(line.rstrip()) return result -def run_process(args, initial_env=None, redirect_stderr_to_stdout=True): +def run_process(args, initial_env=None): """ Run process until completion and return the process exit code. - Prints both stdout and stderr to the console. No output is captured. """ log.info("Running process in directory {0}: command {1}".format( @@ -415,8 +414,6 @@ def run_process(args, initial_env=None, redirect_stderr_to_stdout=True): kwargs = {} kwargs['env'] = initial_env - if redirect_stderr_to_stdout: - kwargs['stderr'] = subprocess.STDOUT exit_code = subprocess.call(args, **kwargs) return exit_code diff --git a/coin_build_instructions.py b/coin_build_instructions.py index 969b9272b..db021470f 100644 --- a/coin_build_instructions.py +++ b/coin_build_instructions.py @@ -122,21 +122,6 @@ def call_setup(python_ver): cmd += ["--package-timestamp=" + CI_INTEGRATION_ID] env = os.environ - if CI_HOST_OS == "MacOS": - # On Python 3, setuptools.dist.handle_display_options does some - # weird sys.stdout.detach-ing if the stdout encoding is - # different from utf-8. This causes issues when running - # subprocess.call() because that access the original stdout - # object stored in sys.__stdout__ which was detached, and - # results in an exception being thrown. - # The Coin macOS locale by default is US-ASCII, and that - # triggers the above issue. Set the encoding to UTF-8 which - # makes sure to skip over the detach-ing code. - # Relevant links to the issue: - # https://bugs.python.org/issue15216 - # https://bitbucket.org/tarek/distribute/issues/334/fix-for-311-breaks-packages-that-use - # https://github.com/pypa/virtualenv/issues/359 - env['LC_CTYPE'] = 'UTF-8' run_instruction(cmd, "Failed to run setup.py", initial_env=env) def run_build_instructions(): diff --git a/sources/pyside2/PySide2/templates/core_common.xml b/sources/pyside2/PySide2/templates/core_common.xml index 4f715ee1f..4984cb21a 100644 --- a/sources/pyside2/PySide2/templates/core_common.xml +++ b/sources/pyside2/PySide2/templates/core_common.xml @@ -278,8 +278,10 @@ if (PySequence_Check(%PYARG_0) && (PySequence_Size(%PYARG_0) == 2)) { Shiboken::AutoDecRef pyItem(PySequence_GetItem(%PYARG_0, 0)); %out = %CONVERTTOCPP[bool](pyItem); - Shiboken::AutoDecRef pyResultItem(PySequence_GetItem(pyResult, 1)); - *result = %CONVERTTOCPP[long](pyResultItem); + if (result) { + Shiboken::AutoDecRef pyResultItem(PySequence_GetItem(pyResult, 1)); + *result = %CONVERTTOCPP[long](pyResultItem); + } } </template> diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 3d87fcff0..ea0f43170 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -2704,8 +2704,8 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s, } else if (!injectCodeCallsFunc && !func->isUserAdded() && !hasConversionRule) { // When an argument is removed from a method signature and no other means of calling // the method are provided (as with code injection) the generator must abort. - qFatal(qPrintable(QString::fromLatin1("No way to call '%1::%2' with the modifications described in the type system.") - .arg(func->ownerClass()->name(), func->signature()))); + qFatal("No way to call '%s::%s' with the modifications described in the type system.", + qPrintable(func->ownerClass()->name()), qPrintable(func->signature())); } removedArgs++; continue; diff --git a/sources/shiboken2/libshiboken/pep384impl.cpp b/sources/shiboken2/libshiboken/pep384impl.cpp index 7cca03c84..7b333f4ff 100644 --- a/sources/shiboken2/libshiboken/pep384impl.cpp +++ b/sources/shiboken2/libshiboken/pep384impl.cpp @@ -77,17 +77,22 @@ static struct PyMethodDef probe_methoddef[] = { {0} }; +static PyGetSetDef probe_getseters[] = { + {0} /* Sentinel */ +}; + #define probe_tp_call make_dummy(1) #define probe_tp_str make_dummy(2) #define probe_tp_traverse make_dummy(3) #define probe_tp_clear make_dummy(4) #define probe_tp_methods probe_methoddef -#define probe_tp_descr_get make_dummy(6) -#define probe_tp_init make_dummy(7) -#define probe_tp_alloc make_dummy(8) -#define probe_tp_new make_dummy(9) -#define probe_tp_free make_dummy(10) -#define probe_tp_is_gc make_dummy(11) +#define probe_tp_getset probe_getseters +#define probe_tp_descr_get make_dummy(7) +#define probe_tp_init make_dummy(8) +#define probe_tp_alloc make_dummy(9) +#define probe_tp_new make_dummy(10) +#define probe_tp_free make_dummy(11) +#define probe_tp_is_gc make_dummy(12) #define probe_tp_name "type.probe" #define probe_tp_basicsize make_dummy_int(42) @@ -98,6 +103,7 @@ static PyType_Slot typeprobe_slots[] = { {Py_tp_traverse, probe_tp_traverse}, {Py_tp_clear, probe_tp_clear}, {Py_tp_methods, probe_tp_methods}, + {Py_tp_getset, probe_tp_getset}, {Py_tp_descr_get, probe_tp_descr_get}, {Py_tp_init, probe_tp_init}, {Py_tp_alloc, probe_tp_alloc}, @@ -138,6 +144,7 @@ check_PyTypeObject_valid(void) || probe_tp_clear != check->tp_clear || probe_tp_weakrefoffset != typetype->tp_weaklistoffset || probe_tp_methods != check->tp_methods + || probe_tp_getset != check->tp_getset || probe_tp_base != typetype->tp_base || !PyDict_Check(check->tp_dict) || !PyDict_GetItemString(check->tp_dict, "dummy") diff --git a/sources/shiboken2/libshiboken/pep384impl.h b/sources/shiboken2/libshiboken/pep384impl.h index bfa8f38a7..d883677ce 100644 --- a/sources/shiboken2/libshiboken/pep384impl.h +++ b/sources/shiboken2/libshiboken/pep384impl.h @@ -113,7 +113,7 @@ typedef struct _typeobject { void *X26; // iternextfunc tp_iternext; struct PyMethodDef *tp_methods; void *X28; // struct PyMemberDef *tp_members; - void *X29; // struct PyGetSetDef *tp_getset; + struct PyGetSetDef *tp_getset; struct _typeobject *tp_base; PyObject *tp_dict; descrgetfunc tp_descr_get; diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp index a8874e2e0..da9c56c62 100644 --- a/sources/shiboken2/libshiboken/signature.cpp +++ b/sources/shiboken2/libshiboken/signature.cpp @@ -75,6 +75,7 @@ typedef struct safe_globals_struc { PyObject *sigparse_func; PyObject *createsig_func; PyObject *seterror_argument_func; + PyObject *make_helptext_func; } safe_globals_struc, *safe_globals; static safe_globals pyside_globals = 0; @@ -136,13 +137,15 @@ _get_class_of_cf(PyObject *ob_cf) // This must be an overloaded function that we handled special. Shiboken::AutoDecRef special(Py_BuildValue("(Os)", ob_cf, "overload")); selftype = PyDict_GetItem(pyside_globals->map_dict, special); + if (selftype == nullptr) { + // This is probably a module function. We will return type(None). + selftype = Py_None; + } } } - assert(selftype); PyObject *typemod = (PyType_Check(selftype) || PyModule_Check(selftype)) ? selftype : (PyObject *)Py_TYPE(selftype); - // do we support module functions? Py_INCREF(typemod); return typemod; } @@ -514,6 +517,9 @@ init_phase_2(safe_globals_struc *p, PyMethodDef *methods) p->seterror_argument_func = PyObject_GetAttrString(p->helper_module, "seterror_argument"); if (p->seterror_argument_func == NULL) goto error; + p->make_helptext_func = PyObject_GetAttrString(p->helper_module, "make_helptext"); + if (p->make_helptext_func == NULL) + goto error; return 0; error: @@ -524,20 +530,50 @@ error: } static int -add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp) +_fixup_getset(PyTypeObject *type, const char *name, PyGetSetDef *new_gsp) { + PyGetSetDef *gsp = type->tp_getset; + if (gsp != nullptr) { + for (; gsp->name != NULL; gsp++) { + if (strcmp(gsp->name, name) == 0) { + new_gsp->set = gsp->set; + new_gsp->doc = gsp->doc; + new_gsp->closure = gsp->closure; + return 1; + } + } + } + // staticmethod has just a __doc__ in the class + assert(strcmp(type->tp_name, "staticmethod") == 0); + return 0; +} + +static int +add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **old_descr) +{ + /* + * This function is used to assign a new __signature__ attribute, + * and also to override a __doc__ attribute. + */ assert(PyType_Check(type)); PyType_Ready(type); PyObject *dict = type->tp_dict; for (; gsp->name != NULL; gsp++) { - if (PyDict_GetItemString(dict, gsp->name)) - continue; + PyObject *have_descr = PyDict_GetItemString(dict, gsp->name); + if (have_descr != nullptr) { + assert(strcmp(gsp->name, "__doc__") == 0); + Py_INCREF(have_descr); + *old_descr = have_descr; + if (!_fixup_getset(type, gsp->name, gsp)) + continue; + } Shiboken::AutoDecRef descr(PyDescr_NewGetSet(type, gsp)); if (descr.isNull()) return -1; if (PyDict_SetItemString(dict, gsp->name, descr) < 0) return -1; } + PyType_Modified(type); return 0; } @@ -553,28 +589,91 @@ add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp) // Please note that in fact we are modifying 'type', the metaclass of all // objects, because we add new functionality. // +// Addendum 2019-01-12: We now also compute a docstring from the signature. +// + +// keep the original __doc__ functions +static PyObject *old_cf_doc_descr = 0; +static PyObject *old_sm_doc_descr = 0; +static PyObject *old_md_doc_descr = 0; +static PyObject *old_tp_doc_descr = 0; +static PyObject *old_wd_doc_descr = 0; + +static int handle_doc_in_progress = 0; + +static PyObject * +handle_doc(PyObject *ob, PyObject *old_descr) +{ + init_module_1(); + init_module_2(); + Shiboken::AutoDecRef ob_type(GetClassOfFunc(ob)); + PyTypeObject *type = reinterpret_cast<PyTypeObject *>(ob_type.object()); + if (handle_doc_in_progress || strncmp(type->tp_name, "PySide2.", 8) != 0) + return PyObject_CallMethod(old_descr, const_cast<char *>("__get__"), const_cast<char *>("(O)"), ob); + handle_doc_in_progress++; + PyObject *res = PyObject_CallFunction( + pyside_globals->make_helptext_func, + const_cast<char *>("(O)"), ob); + handle_doc_in_progress--; + if (res == nullptr) { + PyErr_Print(); + Py_FatalError("handle_doc did not receive a result"); + } + return res; +} + +static PyObject * +pyside_cf_get___doc__(PyObject *cf) { + return handle_doc(cf, old_cf_doc_descr); +} + +static PyObject * +pyside_sm_get___doc__(PyObject *sm) { + return handle_doc(sm, old_sm_doc_descr); +} + +static PyObject * +pyside_md_get___doc__(PyObject *md) { + return handle_doc(md, old_md_doc_descr); +} + +static PyObject * +pyside_tp_get___doc__(PyObject *tp) { + return handle_doc(tp, old_tp_doc_descr); +} + +static PyObject * +pyside_wd_get___doc__(PyObject *wd) { + return handle_doc(wd, old_wd_doc_descr); +} + static PyGetSetDef new_PyCFunction_getsets[] = { - {(char *) "__signature__", (getter)pyside_cf_get___signature__}, + {const_cast<char *>("__signature__"), (getter)pyside_cf_get___signature__}, + {const_cast<char *>("__doc__"), (getter)pyside_cf_get___doc__}, {0} }; static PyGetSetDef new_PyStaticMethod_getsets[] = { - {(char *) "__signature__", (getter)pyside_sm_get___signature__}, + {const_cast<char *>("__signature__"), (getter)pyside_sm_get___signature__}, + {const_cast<char *>("__doc__"), (getter)pyside_sm_get___doc__}, {0} }; static PyGetSetDef new_PyMethodDescr_getsets[] = { - {(char *) "__signature__", (getter)pyside_md_get___signature__}, + {const_cast<char *>("__signature__"), (getter)pyside_md_get___signature__}, + {const_cast<char *>("__doc__"), (getter)pyside_md_get___doc__}, {0} }; static PyGetSetDef new_PyType_getsets[] = { - {(char *) "__signature__", (getter)pyside_tp_get___signature__}, + {const_cast<char *>("__signature__"), (getter)pyside_tp_get___signature__}, + {const_cast<char *>("__doc__"), (getter)pyside_tp_get___doc__}, {0} }; static PyGetSetDef new_PyWrapperDescr_getsets[] = { - {(char *) "__signature__", (getter)pyside_wd_get___signature__}, + {const_cast<char *>("__signature__"), (getter)pyside_wd_get___signature__}, + {const_cast<char *>("__doc__"), (getter)pyside_wd_get___doc__}, {0} }; @@ -655,11 +754,11 @@ PySide_PatchTypes(void) Shiboken::AutoDecRef wd(PyObject_GetAttrString((PyObject *)Py_TYPE(Py_True), "__add__")); // wrapper-descriptor if (md.isNull() || wd.isNull() || PyType_Ready(Py_TYPE(md)) < 0 - || add_more_getsets(PepMethodDescr_TypePtr, new_PyMethodDescr_getsets) < 0 - || add_more_getsets(&PyCFunction_Type, new_PyCFunction_getsets) < 0 - || add_more_getsets(PepStaticMethod_TypePtr, new_PyStaticMethod_getsets) < 0 - || add_more_getsets(&PyType_Type, new_PyType_getsets) < 0 - || add_more_getsets(Py_TYPE(wd), new_PyWrapperDescr_getsets) < 0 + || add_more_getsets(PepMethodDescr_TypePtr, new_PyMethodDescr_getsets, &old_md_doc_descr) < 0 + || add_more_getsets(&PyCFunction_Type, new_PyCFunction_getsets, &old_cf_doc_descr) < 0 + || add_more_getsets(PepStaticMethod_TypePtr, new_PyStaticMethod_getsets, &old_sm_doc_descr) < 0 + || add_more_getsets(&PyType_Type, new_PyType_getsets, &old_tp_doc_descr) < 0 + || add_more_getsets(Py_TYPE(wd), new_PyWrapperDescr_getsets, &old_wd_doc_descr) < 0 ) return -1; #ifndef _WIN32 diff --git a/sources/shiboken2/shibokenmodule/support/signature/errorhandler.py b/sources/shiboken2/shibokenmodule/support/signature/errorhandler.py index 902bb05af..df24234e3 100644 --- a/sources/shiboken2/shibokenmodule/support/signature/errorhandler.py +++ b/sources/shiboken2/shibokenmodule/support/signature/errorhandler.py @@ -121,4 +121,20 @@ def seterror_argument(args, func_name): # We don't raise the error here, to avoid the loader in the traceback. return TypeError, msg + +def make_helptext(func): + existing_doc = func.__doc__ + sigs = get_signature(func) + if not sigs: + return existing_doc + if type(sigs) != list: + sigs = [sigs] + try: + func_name = func.__name__ + except AttribureError: + func_name = func.__func__.__name__ + sigtext = "\n".join(func_name + str(sig) for sig in sigs) + msg = sigtext + "\n\n" + existing_doc if existing_doc else sigtext + return msg + # end of file diff --git a/sources/shiboken2/shibokenmodule/support/signature/loader.py b/sources/shiboken2/shibokenmodule/support/signature/loader.py index be30483fe..8c7739d9a 100644 --- a/sources/shiboken2/shibokenmodule/support/signature/loader.py +++ b/sources/shiboken2/shibokenmodule/support/signature/loader.py @@ -201,4 +201,8 @@ def create_signature(props, key): def seterror_argument(args, func_name): return errorhandler.seterror_argument(args, func_name) +# name used in signature.cpp +def make_helptext(func): + return errorhandler.make_helptext(func) + # end of file |
