From c8e25b79e1374f6e5e5046097443d0f395a7c8a8 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Tue, 5 Jan 2021 10:56:42 -0800 Subject: [PATCH] Run SIP via its Python interface rather than as a separate subprocess --- build.py | 50 ++-- buildtools/config.py | 2 - buildtools/wxpysip.py | 110 +++++++++ wscript | 7 - wx/include/wxPython/sip.h | 463 ++++++-------------------------------- 5 files changed, 209 insertions(+), 423 deletions(-) create mode 100644 buildtools/wxpysip.py diff --git a/build.py b/build.py index 34038cc32..9ffd520b6 100755 --- a/build.py +++ b/build.py @@ -45,6 +45,7 @@ getVcsRev, runcmd, textfile_open, getSipFiles, \ getVisCVersion, getToolsPlatformName, updateLicenseFiles, \ TemporaryDirectory +from buildtools.wxpysip import sip_runner import buildtools.version as version @@ -87,14 +88,6 @@ # Some tools will be downloaded for the builds. These are the versions and # MD5s of the tool binaries currently in use. -sipCurrentVersion = '4.19.24' -sipMD5 = { - 'darwin' : '2a22cb7a35eb14384b0829593a366c29', - 'win32' : '49e0aa36397d7629fea95418452961fb', - 'linux32' : 'ea773f6fd92d5f23530730428a86df2f', - 'linux64' : 'b44a45191f5f84db10e2ba1c4cecd8ff', -} - wafCurrentVersion = '2.0.19' wafMD5 = 'ac362b60111a59ab2df63513018d5ad8' @@ -638,15 +631,6 @@ def _error_msg(txt): # The download and MD5 check only needs to happen once per run, cache the sip # cmd value here the first time through. -_sipCmd = None -def getSipCmd(): - global _sipCmd - if _sipCmd is None: - _sipCmd = getTool('sip', sipCurrentVersion, sipMD5, 'SIP', True, True) - return _sipCmd - - -# Same thing for WAF _wafCmd = None def getWafCmd(): global _wafCmd @@ -1285,15 +1269,31 @@ def cmd_sip(options, args): if not newer_group(sipFiles, sbf) and os.path.exists(pycode): continue - # leave this turned off for now... - # typehint = '-y {}'.format(posixjoin(cfg.PKGDIR, base[1:]) + '.pyi') - typehint = '' + # Leave it turned off for now. TODO: Experiment with this... + # pyi_extract = posixjoin(cfg.PKGDIR, base[1:]) + '.pyi' + pyi_extract = None + + # SIP extracts are used to pull python snippets and put them into the + # module's .py file + pycode = 'pycode'+base+':'+pycode + + sip_runner(src_name, + abi_version = '12.8', # siplib abi version + warnings = True, # enable warning messages + docstrings = True, # enable the automatic generation of docstrings + release_gil = True, # always release and reacquire the GIL + sip_module = 'wx.siplib', # the fully qualified name of the sip module + sbf_file=sbf, # File to write the generated file lists to + exceptions = False, # enable support for exceptions + tracing = False, # generate code with tracing enabled + sources_dir = tmpdir, # the name of the code directory + extracts = [pycode], # add to the list of extracts to generate + pyi_extract=pyi_extract, # the name of the .pyi stub file + include_dirs = [ + os.path.join(phoenixDir(), 'src'), + os.path.join(phoenixDir(), 'sip', 'gen'), + ]) - pycode = '-X pycode'+base+':'+pycode - sip = getSipCmd() - cmd = '%s %s -c %s -b %s %s %s %s' % \ - (sip, cfg.SIPOPTS, tmpdir, sbf, pycode, typehint, src_name) - runcmd(cmd) classesNeedingClassInfo = { 'sip_corewxTreeCtrl.cpp' : 'wxTreeCtrl', } diff --git a/buildtools/config.py b/buildtools/config.py index 99a1a2258..a7c2a0d59 100644 --- a/buildtools/config.py +++ b/buildtools/config.py @@ -169,8 +169,6 @@ def finishSetup(self, wx_config=None, debug=None): ('WXUSINGDLL', '1'), ('ISOLATION_AWARE_ENABLED', None), #('NDEBUG',), # using a 1-tuple makes it do an undef - ('SIP_MODULE_NAME', 'wx.siplib'), - ('SIP_MODULE_BASENAME', 'siplib'), ] if int(getVisCVersion()) > 100: self.defines += [ ('wxUSE_RC_MANIFEST', '1'), diff --git a/buildtools/wxpysip.py b/buildtools/wxpysip.py new file mode 100644 index 000000000..c58102b84 --- /dev/null +++ b/buildtools/wxpysip.py @@ -0,0 +1,110 @@ +#---------------------------------------------------------------------- +# Name: buildtools.wxpysip +# Purpose: Code to help migrate to SIP 5 with as little disruption +# as possible. +# +# Author: Robin Dunn +# +# Created: 4-Jan-2021 +# Copyright: (c) 2021 by Total Control Software +# License: wxWindows License +#---------------------------------------------------------------------- + +# NOTE: This code is mostly copied, adapted, and extended from the +# sipbuild.legacy.sip5 module. The main intent is to make it easy to run +# sip the same way as the legacy sip5 entry point, but without needing to +# run a subprocess, and to also add a little missing sip 4 functionality +# that we were depending on with the old SIP. +import os + +from sipbuild.code_generator import (set_globals, parse, generateCode, + generateExtracts, generateAPI, generateXML, generateTypeHints) +from sipbuild.exceptions import handle_exception, UserException +from sipbuild.module import resolve_abi_version +from sipbuild.version import SIP_VERSION, SIP_VERSION_STR + + +def sip_runner( + specification, # the name of the specification file [default stdin] + sources_dir=None, # the name of the code output directory [default not generated] + include_dirs=[], # add to the list of directories to search when importing or including .sip files + warnings=False, # enable warning messages [default disabled] + docstrings=False, # enable the automatic generation of docstrings [default disabled] + release_gil=False, # always release and reacquire the GIL [default only when specified] + sip_module=None, # the fully qualified name of the sip module + api_extract=None, # the name of the QScintilla API file [default not generated + exceptions=False, # enable support for C++ exceptions [default disabled] + tracing=False, # generate code with tracing enabled [default disabled] + extracts=[], # add to the list of extracts to generate + pyi_extract=None, # the name of the .pyi stub file [default not generated] + sbf_file=None, # File to write the generated file lists to [default not generated] + abi_version=None, # the sip ABI version + backstops=[], # add to the list of timeline backstops + py_debug=False, # generate code for a debug build of Python + warnings_are_errors=False, # warnings are handled as errors + parts=0, # split the generated code into files [default 1 per class] + xml_extract=None, # file to write sip xml to + protected_is_public=False, # enable the protected/public hack [default disabled] + source_suffix=None, # the suffix to use for C or C++ source files [default \".c\" or \".cpp\"] + tags=[], # add to the list of versions/platforms to generate code for + disabled_features=[], # add to the list of disabled features + ): + + print("Running SIP code generator on: {}".format(specification)) + + generated_files = [] + try: + # The code generator requires the name of the sip module. + if sources_dir is not None and sip_module is None: + raise UserException("the name of the sip module must be given") + + # Check the ABI version. + abi_major, abi_minor = resolve_abi_version(abi_version).split('.') + + # Set the globals. + set_globals(SIP_VERSION, SIP_VERSION_STR, int(abi_major), int(abi_minor), + UserException, include_dirs) + + # Parse the input file. + pt, _, _, _, tags, disabled_features = parse(specification, + (xml_extract is None), tags, backstops, disabled_features, + protected_is_public) + + # Generate the bindings. + if sources_dir is not None: + generated_files = generateCode(pt, sources_dir, source_suffix, + exceptions, tracing, release_gil, parts, tags, + disabled_features, docstrings, py_debug, sip_module) + + if sbf_file is not None: + generateBuildFile(sbf_file, generated_files) + + # Generate any extracts. + generateExtracts(pt, extracts) + + # Generate the API file. + if api_extract is not None: + generateAPI(pt, api_extract) + + # Generate the type hints file. + if pyi_extract is not None: + generateTypeHints(pt, pyi_extract) + + # Generate the XML file. + if xml_extract is not None: + generateXML(pt, xml_extract) + + except Exception as e: + handle_exception(e) + + return generated_files + + +def generateBuildFile(sbf_file, generated_files): + header, sources = generated_files + header = os.path.basename(header) + sources = [os.path.basename(n) for n in sources] + with open(sbf_file, 'w') as f: + f.write("sources = {}\n".format(' '.join(sources))) + f.write("headers = {}\n".format(header)) + diff --git a/wscript b/wscript index 1e143be67..7fc4f7ca8 100644 --- a/wscript +++ b/wscript @@ -323,13 +323,6 @@ def configure(conf): conf.env.CFLAGS_WXPY.append('-UNDEBUG') conf.env.CXXFLAGS_WXPY.append('-UNDEBUG') - # set the name of our siplib module - conf.env.CFLAGS_WXPY.append('-DSIP_MODULE_NAME=wx.siplib') - conf.env.CXXFLAGS_WXPY.append('-DSIP_MODULE_NAME=wx.siplib') - - conf.env.CFLAGS_WXPY.append('-DSIP_MODULE_BASENAME=siplib') - conf.env.CXXFLAGS_WXPY.append('-DSIP_MODULE_BASENAME=siplib') - # Add basic debug info for all builds conf.env.CFLAGS_WXPY.append('-g') conf.env.CXXFLAGS_WXPY.append('-g') diff --git a/wx/include/wxPython/sip.h b/wx/include/wxPython/sip.h index ad9036373..aa911aee7 100644 --- a/wx/include/wxPython/sip.h +++ b/wx/include/wxPython/sip.h @@ -21,22 +21,11 @@ #define _SIP_H -/* - * This gets round a problem with Qt's moc and Python v2.3. Strictly speaking - * it's a Qt problem but later versions of Python include a fix for it so we - * might as well too. - */ -#undef slots - - #include -/* - * There is a mis-feature somewhere with the Borland compiler. This works - * around it. - */ -#if defined(__BORLANDC__) -#include +/* Sanity check on the Python version. */ +#if PY_VERSION_HEX < 0x03050000 +#error "This version of SIP requires Python v3.5 or later" #endif @@ -45,238 +34,35 @@ extern "C" { #endif -/* Sanity check on the Python version. */ -#if PY_VERSION_HEX < 0x02030000 -#error "This version of SIP requires Python v2.3 or later" -#endif +/* The patch version of this implementation of the ABI. */ +#define SIP_MODULE_PATCH_VERSION 1 /* - * Define the SIP version number. + * The changes to this version of the ABI. + * + * Preserve any current exception in the wrapper tp_dealloc functions. */ -#define SIP_VERSION 0x041318 -#define SIP_VERSION_STR "4.19.24" -/* - * Define the current API version number. SIP must handle modules with the - * same major number and with the same or earlier minor number. Whenever - * members are added to non-embedded data structures they must be appended and - * the minor number incremented. Whenever data structure members are removed - * or their offset changed then the major number must be incremented and the - * minor number set * to 0. - * - * History: - * - * 12.7 Added sip_api_visit_wrappers() to the public API. - * Added sip_api_register_exit_notifier() to the public API. - * sip_api_is_owned_by_python() is now part of the public API. - * - * 12.6 Added sip_api_long_as_size_t() to the public API. - * Added the '=' format character to sip_api_build_result(). - * Added the '=' format character to sip_api_parse_result_ex(). - * - * 12.5 Replaced the sipConvertFromSliceObject() macro with - * sip_api_convert_from_slice_object() in the public API. - * - * 12.4 Added sip_api_instance_destroyed_ex() to the private API. - * - * 12.3 Added SIP_TYPE_SCOPED_ENUM to the sipTypeDef flags. - * Added sip_api_convert_to_enum() to the public API. - * Added sip_api_convert_to_bool() to the public API. - * Added sip_api_long_as_char(), sip_api_long_as_signed_char(), - * sip_api_long_as_unsigned_char(), sip_api_long_as_short(), - * sip_api_long_as_unsigned_short(), sip_api_long_as_int(), - * sip_api_long_as_unsigned_int(), sip_api_long_as_long(), - * sip_api_long_as_unsigned_long(), sip_api_long_as_long_long(), - * sip_api_long_as_unsigned_long_long() to the public API. - * Deprecated sip_api_can_convert_to_enum(). - * - * 12.2 Added sip_api_print_object() to the public API. - * Renamed sip_api_common_dtor() to sip_api_instance_destroyed() and added - * it to the public API. - * Added sipEventType and sip_api_register_event_handler() to the public - * API. - * - * 12.1 Added sip_api_enable_gc() to the public API. - * - * 12.0 Added SIP_TYPE_LIMITED_API to the sipTypeDef flags. - * Added sip_api_py_type_dict() and sip_api_py_type_name() to the public - * API. - * Added sip_api_set_new_user_type_handler() to the public API. - * Added sip_api_is_user_type() to the public API. - * Added sip_api_set_type_user_data() and sip_api_get_type_user_data() to - * the public API. - * Added sip_api_set_user_object() and sip_api_get_user_object() to the - * public API. - * Added sip_api_get_method() and sip_api_from_method() to the public API. - * Added sip_api_get_c_function() to the public API. - * Added sip_api_get_date() and sip_api_from_date() to the public API. - * Added sip_api_get_datetime() and sip_api_from_datetime() to the public - * API. - * Added sip_api_get_time() and sip_api_from_time() to the public API. - * Added sip_api_get_frame() to the public API. - * Added sip_api_check_plugin_for_type() to the public API. - * Added sip_api_unicode_new(), sip_api_unicode_write() and - * sip_api_unicode_data() to the public API. - * Added sip_api_get_buffer_info() and sip_api_relese_buffer_info() to the - * public API. - * Added sip_api_call_procedure_method() to the public API. - * Added sip_api_is_owned_by_python() to the private API. - * Added sip_api_is_derived_class() to the private API. - * Removed the im_version member from sipImportedModuleDef. - * Removed the im_module member from sipImportedModuleDef. - * Removed the em_version member from sipExportedModuleDef. - * Removed the em_virthandlers member from sipExportedModuleDef. - * Re-ordered the API functions. - * - * 11.3 Added sip_api_get_interpreter() to the public API. - * - * 11.2 Added sip_api_get_reference() to the private API. - * - * 11.1 Added sip_api_invoke_slot_ex(). - * - * 11.0 Added the pyqt5QtSignal and pyqt5ClassTypeDef structures. - * Removed qt_interface from pyqt4ClassTypeDef. - * Added hack to pyqt4QtSignal. - * - * 10.1 Added ctd_final to sipClassTypeDef. - * Added ctd_init_mixin to sipClassTypeDef. - * Added sip_api_get_mixin_address() to the public API. - * Added sip_api_convert_from_new_pytype() to the public API. - * Added sip_api_convert_to_array() to the public API. - * Added sip_api_convert_to_typed_array() to the public API. - * Added sip_api_register_proxy_resolver() to the public API. - * Added sip_api_init_mixin() to the private API. - * Added qt_interface to pyqt4ClassTypeDef. - * - * 10.0 Added sip_api_set_destroy_on_exit(). - * Added sip_api_enable_autoconversion(). - * Removed sip_api_call_error_handler_old(). - * Removed sip_api_start_thread(). - * - * 9.2 Added sip_gilstate_t and SIP_RELEASE_GIL to the public API. - * Renamed sip_api_call_error_handler() to - * sip_api_call_error_handler_old(). - * Added the new sip_api_call_error_handler() to the private API. - * - * 9.1 Added the capsule type. - * Added the 'z' format character to sip_api_build_result(). - * Added the 'z', '!' and '$' format characters to - * sip_api_parse_result_ex(). - * - * 9.0 Changed the sipVariableGetterFunc signature. - * Added sip_api_parse_result_ex() to the private API. - * Added sip_api_call_error_handler() to the private API. - * Added em_virterrorhandlers to sipExportedModuleDef. - * Re-ordered the API functions. - * - * 8.1 Revised the sipVariableDef structure. - * sip_api_get_address() is now part of the public API. - * - * 8.0 Changed the size of the sipSimpleWrapper structure. - * Added sip_api_get_address(). - * - * 7.1 Added the 'H' format character to sip_api_parse_result(). - * Deprecated the 'D' format character of sip_api_parse_result(). - * - * 7.0 Added sip_api_parse_kwd_args(). - * Added sipErrorState, sip_api_add_exception(). - * The type initialisation function is now passed a dictionary of keyword - * arguments. - * All argument parsers now update a set of error messages rather than an - * argument count. - * The signatures of sip_api_no_function() and sip_api_no_method() have - * changed. - * Added ctd_docstring to sipClassTypeDef. - * Added vf_docstring to sipVersionedFunctionDef. - * - * 6.0 Added the sipContainerDef structure to define the contents of a class - * or mapped type. Restructured sipClassDef and sipMappedTypeDef - * accordingly. - * Added the 'r' format character to sip_api_parse_args(). - * Added the 'r' format character to sip_api_call_method() and - * sip_api_build_result(). - * Added the assignment, array and copy allocation helpers. - * - * 5.0 Added sip_api_is_api_enabled(). - * Renamed the td_version_nr member of sipTypeDef to be int and where -1 - * indicates it is not versioned. - * Added the em_versions member to sipExportedModuleDef. - * Added the em_versioned_functions member to sipExportedModuleDef. - * - * 4.0 Much refactoring. - * - * 3.8 Added sip_api_register_qt_metatype() and sip_api_deprecated(). - * Added qt_register_meta_type() to the Qt support API. - * The C/C++ names of enums and types are now always defined in the - * relevant structures and don't default to the Python name. - * Added the 'XE' format characters to sip_api_parse_args(). - * - * 3.7 Added sip_api_convert_from_const_void_ptr(), - * sip_api_convert_from_void_ptr_and_size() and - * sip_api_convert_from_const_void_ptr_and_size(). - * Added the 'g' and 'G' format characters (to replace the now deprecated - * 'a' and 'A' format characters) to sip_api_build_result(), - * sip_api_call_method() and sip_api_parse_result(). - * Added the 'k' and 'K' format characters (to replace the now deprecated - * 'a' and 'A' format characters) to sip_api_parse_args(). - * Added sip_api_invoke_slot(). - * Added sip_api_parse_type(). - * Added sip_api_is_exact_wrapped_type(). - * Added the td_assign and td_qt fields to the sipTypeDef structure. - * Added the mt_assign field to the sipMappedType structure. - * - * 3.6 Added the 'g' format character to sip_api_parse_args(). - * - * 3.5 Added the td_pickle field to the sipTypeDef structure. - * Added sip_api_transfer_break(). - * - * 3.4 Added qt_find_connection() to the Qt support API. - * Added sip_api_string_as_char(), sip_api_unicode_as_wchar(), - * sip_api_unicode_as_wstring(), sip_api_find_class(), - * sip_api_find_named_enum() and sip_api_parse_signature(). - * Added the 'A', 'w' and 'x' format characters to sip_api_parse_args(), - * sip_api_parse_result(), sip_api_build_result() and - * sip_api_call_method(). - * - * 3.3 Added sip_api_register_int_types(). - * - * 3.2 Added sip_api_export_symbol() and sip_api_import_symbol(). - * - * 3.1 Added sip_api_add_mapped_type_instance(). - * - * 3.0 Moved the Qt support out of the sip module and into PyQt. This is - * such a dramatic change that there is no point in attempting to maintain - * backwards compatibility. - * - * 2.0 Added the td_flags field to the sipTypeDef structure. - * Added the first_child, sibling_next, sibling_prev and parent fields to - * the sipWrapper structure. - * Added the td_traverse and td_clear fields to the sipTypeDef structure. - * Added the em_api_minor field to the sipExportedModuleDef structure. - * Added sip_api_bad_operator_arg(). - * Added sip_api_wrapper_check(). - * - * 1.1 Added support for __pos__ and __abs__. - * - * 1.0 Removed all deprecated parts of the API. - * Removed the td_proxy field from the sipTypeDef structure. - * Removed the create proxy function from the 'q' and 'y' format - * characters to sip_api_parse_args(). - * Removed sip_api_emit_to_slot(). - * Reworked the enum related structures. - * - * 0.2 Added the 'H' format character to sip_api_parse_args(). - * - * 0.1 Added sip_api_add_class_instance(). - * Added the 't' format character to sip_api_parse_args(). - * Deprecated the 'J' and 'K' format characters to sip_api_parse_result(). - * - * 0.0 Original version. - */ -#define SIP_API_MAJOR_NR 12 -#define SIP_API_MINOR_NR 7 +/* The ABI version implemented. */ +#define SIP_ABI_MAJOR_VERSION 12 +#define SIP_ABI_MINOR_VERSION 8 + +/* The version of the code generator. */ +#define SIP_VERSION 0x50500 +#define SIP_VERSION_STR "5.5.0" + +/* These are all dependent on the user-specified name of the sip module. */ +#define _SIP_MODULE_FQ_NAME "wx.siplib" +#define _SIP_MODULE_NAME "siplib" +#define _SIP_MODULE_SHARED 1 +#define _SIP_MODULE_ENTRY PyInit_siplib +#define _SIP_MODULE_LEGACY 0 + +/* Support the historical names. */ +#define SIP_API_MAJOR_NR SIP_ABI_MAJOR_VERSION +#define SIP_API_MINOR_NR SIP_ABI_MINOR_VERSION /* @@ -324,29 +110,16 @@ typedef unsigned int uint; #endif -/* Some Python compatibility stuff. */ -#if PY_VERSION_HEX >= 0x02050000 - -#define SIP_SSIZE_T Py_ssize_t -#define SIP_SSIZE_T_FORMAT "%zd" - -#define SIP_MLNAME_CAST(s) (s) -#define SIP_MLDOC_CAST(s) (s) -#define SIP_TPNAME_CAST(s) (s) - -#else - -#define SIP_SSIZE_T int -#define SIP_SSIZE_T_FORMAT "%d" - -#define SIP_MLNAME_CAST(s) ((char *)(s)) -#define SIP_MLDOC_CAST(s) ((char *)(s)) -#define SIP_TPNAME_CAST(s) ((char *)(s)) - -#endif - -#if PY_MAJOR_VERSION >= 3 +/* Remove in v5.1. */ +#define SIP_SSIZE_T Py_ssize_t +#define SIP_SSIZE_T_FORMAT "%zd" +#define SIP_USE_PYCAPSULE +#define SIP_MODULE_RETURN(v) return (v) +/* + * Remove in v5.1. These are undocumented and can be removed when PyQt5 drops + * support for Python v2. + */ #define SIPLong_Check PyLong_Check #define SIPLong_FromLong PyLong_FromLong #define SIPLong_AsLong PyLong_AsLong @@ -359,57 +132,6 @@ typedef unsigned int uint; #define SIPBytes_AS_STRING PyBytes_AS_STRING #define SIPBytes_GET_SIZE PyBytes_GET_SIZE -#if PY_MINOR_VERSION >= 1 -#define SIP_USE_PYCAPSULE -#endif - -#if PY_MINOR_VERSION < 2 -#define SIP_SUPPORT_PYCOBJECT -#endif - -#else - -#define SIPLong_Check PyInt_Check -#define SIPLong_FromLong PyInt_FromLong -#define SIPLong_AsLong PyInt_AsLong - -#define SIPBytes_Check PyString_Check -#define SIPBytes_FromString PyString_FromString -#define SIPBytes_FromStringAndSize PyString_FromStringAndSize -#define SIPBytes_AsString PyString_AsString -#define SIPBytes_Size PyString_Size -#define SIPBytes_AS_STRING PyString_AS_STRING -#define SIPBytes_GET_SIZE PyString_GET_SIZE - -#if PY_MINOR_VERSION >= 7 -#define SIP_USE_PYCAPSULE -#endif - -#define SIP_SUPPORT_PYCOBJECT - -#endif - -#if !defined(Py_REFCNT) -#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt) -#endif - -#if !defined(Py_TYPE) -#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) -#endif - -#if !defined(PyVarObject_HEAD_INIT) -#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, -#endif - - -#if defined(SIP_USE_PYCAPSULE) -#define SIPCapsule_FromVoidPtr(p, n) PyCapsule_New((p), (n), NULL) -#define SIPCapsule_AsVoidPtr(p, n) PyCapsule_GetPointer((p), (n)) -#else -#define SIPCapsule_FromVoidPtr(p, n) sipConvertFromVoidPtr((p)) -#define SIPCapsule_AsVoidPtr(p, n) sipConvertToVoidPtr((p)) -#endif - /* * The mask that can be passed to sipTrace(). @@ -512,17 +234,12 @@ typedef int (*sipFinalFunc)(PyObject *, void *, PyObject *, PyObject **); typedef void *(*sipAccessFunc)(sipSimpleWrapper *, AccessFuncOp); typedef int (*sipTraverseFunc)(void *, visitproc, void *); typedef int (*sipClearFunc)(void *); -#if PY_MAJOR_VERSION >= 3 typedef int (*sipGetBufferFuncLimited)(PyObject *, void *, sipBufferDef *); typedef void (*sipReleaseBufferFuncLimited)(PyObject *, void *); #if !defined(Py_LIMITED_API) typedef int (*sipGetBufferFunc)(PyObject *, void *, Py_buffer *, int); typedef void (*sipReleaseBufferFunc)(PyObject *, void *, Py_buffer *); #endif -#else -typedef SIP_SSIZE_T (*sipBufferFunc)(PyObject *, void *, SIP_SSIZE_T, void **); -typedef SIP_SSIZE_T (*sipSegCountFunc)(PyObject *, void *, SIP_SSIZE_T *); -#endif typedef void (*sipDeallocFunc)(sipSimpleWrapper *); typedef void *(*sipCastFunc)(void *, const sipTypeDef *); typedef const sipTypeDef *(*sipSubClassConvertFunc)(void **); @@ -531,9 +248,9 @@ typedef PyObject *(*sipConvertFromFunc)(void *, PyObject *); typedef void (*sipVirtErrorHandlerFunc)(sipSimpleWrapper *, sip_gilstate_t); typedef int (*sipVirtHandlerFunc)(sip_gilstate_t, sipVirtErrorHandlerFunc, sipSimpleWrapper *, PyObject *, ...); -typedef void (*sipAssignFunc)(void *, SIP_SSIZE_T, void *); -typedef void *(*sipArrayFunc)(SIP_SSIZE_T); -typedef void *(*sipCopyFunc)(const void *, SIP_SSIZE_T); +typedef void (*sipAssignFunc)(void *, Py_ssize_t, void *); +typedef void *(*sipArrayFunc)(Py_ssize_t); +typedef void *(*sipCopyFunc)(const void *, Py_ssize_t); typedef void (*sipReleaseFunc)(void *, int); typedef PyObject *(*sipPickleFunc)(void *); typedef int (*sipAttrGetterFunc)(const sipTypeDef *, PyObject *); @@ -544,7 +261,7 @@ typedef int (*sipNewUserTypeFunc)(sipWrapperType *); typedef void (*sipWrapperVisitorFunc)(sipSimpleWrapper *, void *); -#if !defined(Py_LIMITED_API) || PY_VERSION_HEX < 0x03020000 +#if !defined(Py_LIMITED_API) /* * The meta-type of a wrapper type. */ @@ -638,6 +355,7 @@ struct _sipWrapper { /* + * Removed in v5.1. * The meta-type of an enum type. (This is exposed only to support the * deprecated sipConvertFromNamedEnum() macro.) */ @@ -761,7 +479,7 @@ struct _sipBufferDef { void *bd_buffer; /* The length of the buffer. */ - SIP_SSIZE_T bd_length; + Py_ssize_t bd_length; /* Set if the buffer is read-only. */ int bd_readonly; @@ -782,7 +500,7 @@ struct _sipBufferInfoDef { PyObject *bi_obj; /* The length of the buffer in bytes. */ - SIP_SSIZE_T bi_len; + Py_ssize_t bi_len; /* The number of dimensions. */ int bi_ndim; @@ -813,11 +531,6 @@ struct _sipMethodDef { /* The bound object. */ PyObject *pm_self; - -#if PY_MAJOR_VERSION < 3 - /* The class. */ - PyObject *pm_class; -#endif }; @@ -871,9 +584,6 @@ typedef enum { typedef enum { str_slot, /* __str__ */ int_slot, /* __int__ */ -#if PY_MAJOR_VERSION < 3 - long_slot, /* __long__ */ -#endif float_slot, /* __float__ */ len_slot, /* __len__ */ contains_slot, /* __contains__ */ @@ -916,18 +626,13 @@ typedef enum { ne_slot, /* __ne__ */ gt_slot, /* __gt__ */ ge_slot, /* __ge__ */ -#if PY_MAJOR_VERSION < 3 - cmp_slot, /* __cmp__ */ -#endif bool_slot, /* __bool__, __nonzero__ */ neg_slot, /* __neg__ */ repr_slot, /* __repr__ */ hash_slot, /* __hash__ */ pos_slot, /* __pos__ */ abs_slot, /* __abs__ */ -#if PY_VERSION_HEX >= 0x02050000 index_slot, /* __index__ */ -#endif iter_slot, /* __iter__ */ next_slot, /* __next__ */ setattr_slot, /* __setattr__, __delattr__ */ @@ -1039,14 +744,8 @@ struct _sipTypeDef { /* The C/C++ name of the type. */ int td_cname; - /* - * The Python type object. This needs to be a union until we remove the - * deprecated sipClass_* macros. - */ - union { - PyTypeObject *td_py_type; - sipWrapperType *td_wrapper_type; - } u; + /* The Python type object. */ + PyTypeObject *td_py_type; /* Any additional fixed data generated by a plugin. */ void *td_plugin_data; @@ -1130,7 +829,6 @@ typedef struct _sipClassTypeDef { /* The clear function. */ sipClearFunc ctd_clear; -#if PY_MAJOR_VERSION >= 3 /* The get buffer function. */ #if defined(Py_LIMITED_API) sipGetBufferFuncLimited ctd_getbuffer; @@ -1144,19 +842,6 @@ typedef struct _sipClassTypeDef { #else sipReleaseBufferFunc ctd_releasebuffer; #endif -#else - /* The read buffer function. */ - sipBufferFunc ctd_readbuffer; - - /* The write buffer function. */ - sipBufferFunc ctd_writebuffer; - - /* The segment count function. */ - sipSegCountFunc ctd_segcount; - - /* The char buffer function. */ - sipBufferFunc ctd_charbuffer; -#endif /* The deallocation function. */ sipDeallocFunc ctd_dealloc; @@ -1257,6 +942,7 @@ typedef struct _sipExternalTypeDef { /* + * Remove in v5.1. * The information describing a mapped class. This (and anything that uses it) * is deprecated. */ @@ -1625,8 +1311,9 @@ typedef struct _sipTypeInstanceDef { /* + * Remove in v5.1. * Define a mapping between a wrapped type identified by a string and the - * corresponding Python type. This is deprecated. + * corresponding Python type. */ typedef struct _sipStringTypeClassMap { /* The type as a string. */ @@ -1638,8 +1325,9 @@ typedef struct _sipStringTypeClassMap { /* + * Remove in v5.1. * Define a mapping between a wrapped type identified by an integer and the - * corresponding Python type. This is deprecated. + * corresponding Python type. */ typedef struct _sipIntTypeClassMap { /* The type as an integer. */ @@ -1660,11 +1348,6 @@ typedef struct _sipPyMethod { /* Self if it is a bound method. */ PyObject *mself; - -#if PY_MAJOR_VERSION < 3 - /* The class. */ - PyObject *mclass; -#endif } sipPyMethod; @@ -1707,7 +1390,7 @@ typedef struct _sipAPIDef { PyTypeObject *api_voidptr_type; void (*api_bad_catcher_result)(PyObject *method); - void (*api_bad_length_for_slice)(SIP_SSIZE_T seqlen, SIP_SSIZE_T slicelen); + void (*api_bad_length_for_slice)(Py_ssize_t seqlen, Py_ssize_t slicelen); PyObject *(*api_build_result)(int *isErr, const char *fmt, ...); PyObject *(*api_call_method)(int *isErr, PyObject *method, const char *fmt, ...); @@ -1715,8 +1398,8 @@ typedef struct _sipAPIDef { sipSimpleWrapper *, PyObject *, const char *, ...); PyObject *(*api_connect_rx)(PyObject *txObj, const char *sig, PyObject *rxObj, const char *slot, int type); - SIP_SSIZE_T (*api_convert_from_sequence_index)(SIP_SSIZE_T idx, - SIP_SSIZE_T len); + Py_ssize_t (*api_convert_from_sequence_index)(Py_ssize_t idx, + Py_ssize_t len); int (*api_can_convert_to_type)(PyObject *pyObj, const sipTypeDef *td, int flags); void *(*api_convert_to_type)(PyObject *pyObj, const sipTypeDef *td, @@ -1754,9 +1437,9 @@ typedef struct _sipAPIDef { PyObject *(*api_convert_from_void_ptr)(void *val); PyObject *(*api_convert_from_const_void_ptr)(const void *val); PyObject *(*api_convert_from_void_ptr_and_size)(void *val, - SIP_SSIZE_T size); + Py_ssize_t size); PyObject *(*api_convert_from_const_void_ptr_and_size)(const void *val, - SIP_SSIZE_T size); + Py_ssize_t size); void *(*api_convert_to_void_ptr)(PyObject *obj); int (*api_export_symbol)(const char *name, void *sym); void *(*api_import_symbol)(const char *name); @@ -1777,12 +1460,12 @@ typedef struct _sipAPIDef { PyObject *(*api_convert_from_new_pytype)(void *cpp, PyTypeObject *py_type, sipWrapper *owner, sipSimpleWrapper **selfp, const char *fmt, ...); PyObject *(*api_convert_to_typed_array)(void *data, const sipTypeDef *td, - const char *format, size_t stride, SIP_SSIZE_T len, int flags); + const char *format, size_t stride, Py_ssize_t len, int flags); PyObject *(*api_convert_to_array)(void *data, const char *format, - SIP_SSIZE_T len, int flags); + Py_ssize_t len, int flags); int (*api_register_proxy_resolver)(const sipTypeDef *td, sipProxyResolverFunc resolver); - PyInterpreterState *(*api_get_interpreter)(); + PyInterpreterState *(*api_get_interpreter)(void); sipNewUserTypeFunc (*api_set_new_user_type_handler)(const sipTypeDef *, sipNewUserTypeFunc); void (*api_set_type_user_data)(sipWrapperType *, void *); @@ -1801,9 +1484,9 @@ typedef struct _sipAPIDef { int (*api_is_user_type)(const sipWrapperType *); struct _frame *(*api_get_frame)(int); int (*api_check_plugin_for_type)(const sipTypeDef *, const char *); - PyObject *(*api_unicode_new)(SIP_SSIZE_T, unsigned, int *, void **); + PyObject *(*api_unicode_new)(Py_ssize_t, unsigned, int *, void **); void (*api_unicode_write)(int, void *, int, unsigned); - void *(*api_unicode_data)(PyObject *, int *, SIP_SSIZE_T *); + void *(*api_unicode_data)(PyObject *, int *, Py_ssize_t *); int (*api_get_buffer_info)(PyObject *, sipBufferInfoDef *); void (*api_release_buffer_info)(sipBufferInfoDef *); PyObject *(*api_get_user_object)(const sipSimpleWrapper *); @@ -1948,14 +1631,22 @@ typedef struct _sipAPIDef { /* * The following are part of the public API. */ - int (*api_convert_from_slice_object)(PyObject *slice, SIP_SSIZE_T length, - SIP_SSIZE_T *start, SIP_SSIZE_T *stop, SIP_SSIZE_T *step, - SIP_SSIZE_T *slicelength); + int (*api_convert_from_slice_object)(PyObject *slice, Py_ssize_t length, + Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, + Py_ssize_t *slicelength); size_t (*api_long_as_size_t)(PyObject *o); void (*api_visit_wrappers)(sipWrapperVisitorFunc visitor, void *closure); int (*api_register_exit_notifier)(PyMethodDef *md); + + /* + * The following are not part of the public API. + */ + PyObject *(*api_is_py_method_12_8)(sip_gilstate_t *gil, char *pymc, + sipSimpleWrapper **sipSelfp, const char *cname, const char *mname); } sipAPIDef; +const sipAPIDef *sip_init_library(PyObject *mod_dict); + /* * The API implementing the optional Qt support. @@ -2020,7 +1711,7 @@ typedef struct _sipQtAPI { #define SIP_ACCFUNC 0x0008 /* If there is an access function. */ #define SIP_NOT_IN_MAP 0x0010 /* If Python object is not in the map. */ -#if !defined(Py_LIMITED_API) || PY_VERSION_HEX < 0x03020000 +#if !defined(Py_LIMITED_API) #define SIP_PY_OWNED 0x0020 /* If owned by Python. */ #define SIP_SHARE_MAP 0x0040 /* If the map slot might be occupied. */ #define SIP_CPP_HAS_REF 0x0080 /* If C/C++ has a reference. */ @@ -2068,22 +1759,16 @@ typedef struct _sipQtAPI { #define sipTypeIsMapped(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_MAPPED) #define sipTypeIsEnum(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_ENUM) #define sipTypeIsScopedEnum(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_SCOPED_ENUM) -#define sipTypeAsPyTypeObject(td) ((td)->u.td_py_type) +#define sipTypeAsPyTypeObject(td) ((td)->td_py_type) #define sipTypeName(td) sipNameFromPool((td)->td_module, (td)->td_cname) #define sipTypePluginData(td) ((td)->td_plugin_data) /* - * Note that this was never actually documented as being part of the public - * API. It is now deprecated. sipIsUserType() should be used instead. - */ -#define sipIsExactWrappedType(wt) (sipTypeAsPyTypeObject((wt)->wt_td) == (PyTypeObject *)(wt)) - - -/* - * The following are deprecated parts of the public API. + * Remove in v5.1. */ #define sipClassName(w) PyString_FromString(Py_TYPE(w)->tp_name) +#define sipIsExactWrappedType(wt) (sipTypeAsPyTypeObject((wt)->wt_td) == (PyTypeObject *)(wt)) /* From c385873d705581260e3f9f22524062a3045fec00 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Tue, 5 Jan 2021 11:11:26 -0800 Subject: [PATCH] Add SIP_ABI to the config object --- build.py | 2 +- buildtools/config.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/build.py b/build.py index 9ffd520b6..1db1b92ae 100755 --- a/build.py +++ b/build.py @@ -1278,7 +1278,7 @@ def cmd_sip(options, args): pycode = 'pycode'+base+':'+pycode sip_runner(src_name, - abi_version = '12.8', # siplib abi version + abi_version = cfg.SIP_ABI, # siplib abi version warnings = True, # enable warning messages docstrings = True, # enable the automatic generation of docstrings release_gil = True, # always release and reacquire the GIL diff --git a/buildtools/config.py b/buildtools/config.py index a7c2a0d59..e9b865dd7 100644 --- a/buildtools/config.py +++ b/buildtools/config.py @@ -85,6 +85,8 @@ class Configuration(object): PKGDIR = 'wx' # The name of the top-level package + SIP_ABI = '12.8' + # --------------------------------------------------------------- # Basic initialization and configuration code From 224630cf647341bc719d5fbde08e42e99317aab6 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Thu, 7 Jan 2021 13:43:11 -0800 Subject: [PATCH] Add Config.SIP_TRACE flag --- build.py | 2 +- buildtools/config.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build.py b/build.py index 1db1b92ae..73e5d5018 100755 --- a/build.py +++ b/build.py @@ -1285,7 +1285,7 @@ def cmd_sip(options, args): sip_module = 'wx.siplib', # the fully qualified name of the sip module sbf_file=sbf, # File to write the generated file lists to exceptions = False, # enable support for exceptions - tracing = False, # generate code with tracing enabled + tracing = cfg.SIP_TRACE, # generate code with tracing enabled sources_dir = tmpdir, # the name of the code directory extracts = [pycode], # add to the list of extracts to generate pyi_extract=pyi_extract, # the name of the .pyi stub file diff --git a/buildtools/config.py b/buildtools/config.py index e9b865dd7..c6d94da12 100644 --- a/buildtools/config.py +++ b/buildtools/config.py @@ -86,6 +86,7 @@ class Configuration(object): # The name of the top-level package SIP_ABI = '12.8' + SIP_TRACE = False # --------------------------------------------------------------- # Basic initialization and configuration code