diff --git a/CHANGES.rst b/CHANGES.rst index 267d4a70..81129fe5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -124,6 +124,7 @@ Changes in this release include the following: * Removed wx.lib.floatbar, which has been deprecated forever and probably hasn't been working in nearly as long. (#976) +* Updated SIP to version 4.19.13. diff --git a/bin/build-sip-posix b/bin/build-sip-posix index f6b03048..e74183b2 100755 --- a/bin/build-sip-posix +++ b/bin/build-sip-posix @@ -21,7 +21,7 @@ SIPVER=`$PYTHON configure.py --version | grep -v "This is SIP"` if [ "$PLATFORM" = "darwin" ]; then # try to ensure compatibility back to 10.6 if we can xcode=$(xcode-select -print-path) - for v in 6 7 8 9 10 11 12; do + for v in 7 8 9 10 11 12 13 14 15; do if [ -d $xcode/SDKs/MacOSX10.$v.sdk ]; then SDK=$xcode/SDKs/MacOSX10.$v.sdk break @@ -32,7 +32,7 @@ if [ "$PLATFORM" = "darwin" ]; then done $PYTHON configure.py \ - --deployment-target=10.6 \ + --deployment-target=10.7 \ --sdk=$SDK \ --arch=i386 \ --universal \ diff --git a/build.py b/build.py index 3cd5b828..caa08801 100755 --- a/build.py +++ b/build.py @@ -75,12 +75,12 @@ wxICON = 'docs/sphinx/_static/images/sphinxdocs/mondrian.png' # Some tools will be downloaded for the builds. These are the versions and # MD5s of the tool binaries currently in use. -sipCurrentVersion = '4.19.7' +sipCurrentVersion = '4.19.13' sipMD5 = { - 'darwin' : 'd30ca1ffb09c0dbb6326e99d012c55b8', - 'win32' : 'dbb882f4f95b1a7419a436280407899c', - 'linux32' : '56a763acdf7c0b5725b31a71a9a56160', - 'linux64' : 'b349127a4d46452936e4181d96b12c2d', + 'darwin' : '2d2958a6f4cceebe5e4facb0114f9b0c', + 'win32' : '83cad605ae09a42440afdf89358c7f82', + 'linux32' : 'd9d2f8d1e897d2f238a5c49532d55933', + 'linux64' : '19f59f0bceb60dfd9b41f8e63b002492', } wafCurrentVersion = '2.0.8' @@ -1370,8 +1370,10 @@ def copyWxDlls(options): cairo_root = os.path.join(phoenixDir(), 'packaging', 'cairo-msw') dlls += glob.glob(os.path.join(cairo_root, arch, 'bin', '*.dll')) - # For Python 3.5 and 3.6 builds we also need to copy some VC14 redist DLLs - if PYVER in ['3.5', '3.6']: + # For Python 3.5 and 3.6 builds we also need to copy some VC14 redist DLLs. + # NOTE: Do it for 3.7 too for now. But when we fully switch over to VS 2017 + # this may need to change. See notes in wscript about it. + if PYVER in ['3.5', '3.6', '3.7']: redist_dir = os.path.join( phoenixDir(), 'packaging', 'Py3.5', 'vcredist', arch, 'Microsoft.VC140.CRT', '*.dll') diff --git a/buildtools/config.py b/buildtools/config.py index e3cc2f0c..299d4cf7 100644 --- a/buildtools/config.py +++ b/buildtools/config.py @@ -1,4 +1,5 @@ #---------------------------------------------------------------------- +#---------------------------------------------------------------------- # Name: buildtools.config # Purpose: Code to set and validate platform options and etc. for # the wxPython build. Moved to their own module and @@ -119,8 +120,9 @@ class Configuration(object): '-w', # enable warnings '-o', # turn on auto-docstrings '-g', # turn on acquire/release of GIL for everything + '-n', 'wx.siplib', # name of the module containing the siplib #'-e', # turn on exceptions support - #'-T', # turn off writing the timestamp to the generated files '-g', # always release and reaquire the GIL + #'-T', # turn off writing the timestamp to the generated files #'-r', # turn on function call tracing '-I', os.path.join(phoenixDir(), 'src'), '-I', os.path.join(phoenixDir(), 'sip', 'gen'), @@ -166,6 +168,8 @@ class Configuration(object): ('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'), ] self.libs = [] diff --git a/sip/siplib/array.c b/sip/siplib/array.c index de590864..c157d938 100644 --- a/sip/siplib/array.c +++ b/sip/siplib/array.c @@ -1,7 +1,7 @@ /* * This file implements the API for the array type. * - * Copyright (c) 2016 Riverbank Computing Limited + * Copyright (c) 2018 Riverbank Computing Limited * * This file is part of SIP. * @@ -238,7 +238,7 @@ static PyObject *sipArray_subscript(PyObject *self, PyObject *key) { Py_ssize_t start, stop, step, slicelength; - if (sipConvertFromSliceObject(key, array->len, &start, &stop, &step, &slicelength) < 0) + if (sip_api_convert_from_slice_object(key, array->len, &start, &stop, &step, &slicelength) < 0) return NULL; if (step != 1) @@ -293,7 +293,7 @@ static int sipArray_ass_subscript(PyObject *self, PyObject *key, { Py_ssize_t stop, step; - if (sipConvertFromSliceObject(key, array->len, &start, &stop, &step, &len) < 0) + if (sip_api_convert_from_slice_object(key, array->len, &start, &stop, &step, &len) < 0) return -1; if (step != 1) diff --git a/sip/siplib/sip.h b/sip/siplib/sip.h index 6f15aa2f..e2c01622 100644 --- a/sip/siplib/sip.h +++ b/sip/siplib/sip.h @@ -1,7 +1,7 @@ /* * The SIP module interface. * - * Copyright (c) 2017 Riverbank Computing Limited + * Copyright (c) 2018 Riverbank Computing Limited * * This file is part of SIP. * @@ -54,8 +54,8 @@ extern "C" { /* * Define the SIP version number. */ -#define SIP_VERSION 0x041307 -#define SIP_VERSION_STR "4.19.7" +#define SIP_VERSION 0x04130d +#define SIP_VERSION_STR "4.19.13" /* @@ -68,6 +68,11 @@ extern "C" { * * History: * + * 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. @@ -263,11 +268,7 @@ extern "C" { * 0.0 Original version. */ #define SIP_API_MAJOR_NR 12 -#define SIP_API_MINOR_NR 3 - - -/* The name of the sip module. */ -#define SIP_MODULE_NAME "wx.siplib" +#define SIP_API_MINOR_NR 5 /* @@ -1886,6 +1887,18 @@ typedef struct _sipAPIDef { void *api_long_as_long_long; void *api_long_as_unsigned_long_long; #endif + + /* + * The following are not part of the public API. + */ + void (*api_instance_destroyed_ex)(sipSimpleWrapper **sipSelfp); + + /* + * 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); } sipAPIDef; @@ -2004,20 +2017,13 @@ typedef struct _sipQtAPI { #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)) -#if PY_VERSION_HEX >= 0x03020000 -#define sipConvertFromSliceObject PySlice_GetIndicesEx -#else -#define sipConvertFromSliceObject(o, len, start, stop, step, slen) \ - PySlice_GetIndicesEx((PySliceObject *)(o), (len), (start), (stop), \ - (step), (slen)) -#endif - /* * The following are deprecated parts of the public API. diff --git a/sip/siplib/sipint.h b/sip/siplib/sipint.h index def8e42c..17951cfa 100644 --- a/sip/siplib/sipint.h +++ b/sip/siplib/sipint.h @@ -150,6 +150,9 @@ PyObject *sip_api_invoke_slot_ex(const sipSlot *slot, PyObject *sigargs, void *sip_api_convert_rx(sipWrapper *txSelf, const char *sigargs, PyObject *rxObj, const char *slot, const char **memberp, int flags); int sip_api_save_slot(sipSlot *sp, PyObject *rxObj, const char *slot); +int sip_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); /* diff --git a/sip/siplib/siplib.c b/sip/siplib/siplib.c index be69dbe2..5071ec47 100644 --- a/sip/siplib/siplib.c +++ b/sip/siplib/siplib.c @@ -1,7 +1,7 @@ /* * SIP library code. * - * Copyright (c) 2017 Riverbank Computing Limited + * Copyright (c) 2018 Riverbank Computing Limited * * This file is part of SIP. * @@ -38,6 +38,24 @@ #endif +/* + * The qualified and base names of the sip module. These should be defined in + * the compiler invocation when creating a package-specific copy. + */ +#if !defined(SIP_MODULE_NAME) +#define SIP_MODULE_NAME sip +#endif + +#if !defined(SIP_MODULE_BASENAME) +#define SIP_MODULE_BASENAME sip +#endif + +#define STRINGIFY_EX(s) #s +#define STRINGIFY(s) STRINGIFY_EX(s) + +#define SIP_MODULE_NAME_STR STRINGIFY(SIP_MODULE_NAME) +#define SIP_MODULE_BASENAME_STR STRINGIFY(SIP_MODULE_BASENAME) + /* * The Python metatype for a C++ wrapper type. We inherit everything from the * standard Python metatype except the init and getattro methods and the size @@ -438,6 +456,7 @@ static int sip_api_enable_gc(int enable); static void sip_api_print_object(PyObject *o); static int sip_api_register_event_handler(sipEventType type, const sipTypeDef *td, void *handler); +static void sip_api_instance_destroyed_ex(sipSimpleWrapper **sipSelfp); /* @@ -620,6 +639,14 @@ static const sipAPIDef sip_api = { 0, 0, #endif + /* + * The following are not part of the public API. + */ + sip_api_instance_destroyed_ex, + /* + * The following are part of the public API. + */ + sip_api_convert_from_slice_object, }; @@ -722,6 +749,7 @@ typedef struct _sipEventHandler { *****************************************************************************/ static PyObject *sipEnumType_alloc(PyTypeObject *self, SIP_SSIZE_T nitems); +static PyObject *sipEnumType_getattro(PyObject *self, PyObject *name); /* @@ -746,7 +774,7 @@ static PyTypeObject sipEnumType_Type = { 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ - 0, /* tp_getattro */ + sipEnumType_getattro, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ @@ -1004,19 +1032,24 @@ static int long_as_nonoverflow_int(PyObject *val_obj); * The Python module initialisation function. */ #if PY_MAJOR_VERSION >= 3 -#define SIP_MODULE_ENTRY PyInit_siplib +#define SIP_MODULE_ENTRY_PREFIX PyInit_ #define SIP_MODULE_TYPE PyObject * #define SIP_MODULE_DISCARD(m) Py_DECREF(m) #define SIP_FATAL(s) return NULL #define SIP_MODULE_RETURN(m) return (m) #else -#define SIP_MODULE_ENTRY initsiplib +#define SIP_MODULE_ENTRY_PREFIX init #define SIP_MODULE_TYPE void #define SIP_MODULE_DISCARD(m) #define SIP_FATAL(s) Py_FatalError(s) #define SIP_MODULE_RETURN(m) #endif +#define CONCAT_EX(PREFIX, NAME) PREFIX ## NAME +#define CONCAT(PREFIX, NAME) CONCAT_EX(PREFIX, NAME) + +#define SIP_MODULE_ENTRY CONCAT(SIP_MODULE_ENTRY_PREFIX, SIP_MODULE_BASENAME) + #if defined(SIP_STATIC_MODULE) SIP_MODULE_TYPE SIP_MODULE_ENTRY(void) #else @@ -1050,7 +1083,7 @@ PyMODINIT_FUNC SIP_MODULE_ENTRY(void) #if PY_MAJOR_VERSION >= 3 static PyModuleDef module_def = { PyModuleDef_HEAD_INIT, - SIP_MODULE_NAME, /* m_name */ + SIP_MODULE_NAME_STR, /* m_name */ NULL, /* m_doc */ -1, /* m_size */ methods, /* m_methods */ @@ -1080,13 +1113,13 @@ PyMODINIT_FUNC SIP_MODULE_ENTRY(void) sipWrapperType_Type.tp_base = &PyType_Type; if (PyType_Ready(&sipWrapperType_Type) < 0) - SIP_FATAL(SIP_MODULE_NAME ": Failed to initialise sip.wrappertype type"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to initialise sip.wrappertype type"); if (PyType_Ready((PyTypeObject *)&sipSimpleWrapper_Type) < 0) - SIP_FATAL(SIP_MODULE_NAME ": Failed to initialise sip.simplewrapper type"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to initialise sip.simplewrapper type"); if (sip_api_register_py_type((PyTypeObject *)&sipSimpleWrapper_Type) < 0) - SIP_FATAL(SIP_MODULE_NAME ": Failed to register sip.simplewrapper type"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to register sip.simplewrapper type"); #if defined(STACKLESS) sipWrapper_Type.super.tp_base = (PyTypeObject *)&sipSimpleWrapper_Type; @@ -1097,33 +1130,33 @@ PyMODINIT_FUNC SIP_MODULE_ENTRY(void) #endif if (PyType_Ready((PyTypeObject *)&sipWrapper_Type) < 0) - SIP_FATAL(SIP_MODULE_NAME ": Failed to initialise sip.wrapper type"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to initialise sip.wrapper type"); if (PyType_Ready(&sipMethodDescr_Type) < 0) - SIP_FATAL(SIP_MODULE_NAME ": Failed to initialise sip.methoddescriptor type"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to initialise sip.methoddescriptor type"); if (PyType_Ready(&sipVariableDescr_Type) < 0) - SIP_FATAL(SIP_MODULE_NAME ": Failed to initialise sip.variabledescriptor type"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to initialise sip.variabledescriptor type"); sipEnumType_Type.tp_base = &PyType_Type; if (PyType_Ready(&sipEnumType_Type) < 0) - SIP_FATAL(SIP_MODULE_NAME ": Failed to initialise sip.enumtype type"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to initialise sip.enumtype type"); if (PyType_Ready(&sipVoidPtr_Type) < 0) - SIP_FATAL(SIP_MODULE_NAME ": Failed to initialise sip.voidptr type"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to initialise sip.voidptr type"); if (PyType_Ready(&sipArray_Type) < 0) - SIP_FATAL(SIP_MODULE_NAME ": Failed to initialise sip.array type"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to initialise sip.array type"); #if PY_MAJOR_VERSION >= 3 mod = PyModule_Create(&module_def); #else - mod = Py_InitModule(SIP_MODULE_NAME, methods); + mod = Py_InitModule(SIP_MODULE_NAME_STR, methods); #endif if (mod == NULL) - SIP_FATAL(SIP_MODULE_NAME ": Failed to initialise sip module"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to initialise sip module"); mod_dict = PyModule_GetDict(mod); @@ -1134,12 +1167,12 @@ PyMODINIT_FUNC SIP_MODULE_ENTRY(void) if (type_unpickler == NULL || enum_unpickler == NULL) { SIP_MODULE_DISCARD(mod); - SIP_FATAL(SIP_MODULE_NAME ": Failed to get pickle helpers"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to get pickle helpers"); } /* Publish the SIP API. */ #if defined(SIP_USE_PYCAPSULE) - obj = PyCapsule_New((void *)&sip_api, SIP_MODULE_NAME "._C_API", NULL); + obj = PyCapsule_New((void *)&sip_api, SIP_MODULE_NAME_STR "._C_API", NULL); #else obj = PyCObject_FromVoidPtr((void *)&sip_api, NULL); #endif @@ -1147,7 +1180,7 @@ PyMODINIT_FUNC SIP_MODULE_ENTRY(void) if (obj == NULL) { SIP_MODULE_DISCARD(mod); - SIP_FATAL(SIP_MODULE_NAME ": Failed to create _C_API object"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to create _C_API object"); } rc = PyDict_SetItemString(mod_dict, "_C_API", obj); @@ -1156,20 +1189,20 @@ PyMODINIT_FUNC SIP_MODULE_ENTRY(void) if (rc < 0) { SIP_MODULE_DISCARD(mod); - SIP_FATAL(SIP_MODULE_NAME ": Failed to add _C_API object to module dictionary"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to add _C_API object to module dictionary"); } /* These will always be needed. */ if (objectify("__init__", &init_name) < 0) { SIP_MODULE_DISCARD(mod); - SIP_FATAL(SIP_MODULE_NAME ": Failed to objectify '__init__'"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to objectify '__init__'"); } if ((empty_tuple = PyTuple_New(0)) == NULL) { SIP_MODULE_DISCARD(mod); - SIP_FATAL(SIP_MODULE_NAME ": Failed to create empty tuple"); + SIP_FATAL(SIP_MODULE_NAME_STR ": Failed to create empty tuple"); } /* Add the SIP version number, but don't worry about errors. */ @@ -1225,6 +1258,18 @@ PyMODINIT_FUNC SIP_MODULE_ENTRY(void) /* Make sure we are notified when starting to exit. */ register_exit_notifier(); + /* + * Also install the package-specific module at the top level for backwards + * compatibility. + */ + if (strcmp(SIP_MODULE_NAME_STR, "sip") != 0 && strcmp(SIP_MODULE_BASENAME_STR, "sip") == 0) + { + PyObject *modules = PySys_GetObject("modules"); + + if (modules != NULL) + PyDict_SetItemString(modules, "sip", mod); + } + SIP_MODULE_RETURN(mod); } @@ -5373,11 +5418,11 @@ static int parsePass1(PyObject **parseErrp, sipSimpleWrapper **selfp, else { #if PY_MAJOR_VERSION >= 3 - PyErr_Format(PyExc_OverflowError, "argument '%d' overflowed: %S", - failure.arg_nr, failure.detail_obj); + PyErr_Format(PyExc_OverflowError, "argument '%s' overflowed: %S", + failure.arg_name, failure.detail_obj); #else - PyErr_Format(PyExc_OverflowError, "argument '%d' overflowed: %s", - failure.arg_nr, exc_str); + PyErr_Format(PyExc_OverflowError, "argument '%s' overflowed: %s", + failure.arg_name, exc_str); #endif } @@ -5999,17 +6044,28 @@ static PyObject *convertToSequence(void *array, SIP_SSIZE_T nr_elem, } +/* + * Perform housekeeping after a C++ instance has been destroyed. + */ +void sip_api_instance_destroyed(sipSimpleWrapper *sw) +{ + sip_api_instance_destroyed_ex(&sw); +} + + /* * Carry out actions common to all dtors. */ -void sip_api_instance_destroyed(sipSimpleWrapper *sipSelf) +static void sip_api_instance_destroyed_ex(sipSimpleWrapper **sipSelfp) { + SIP_BLOCK_THREADS + + sipSimpleWrapper *sipSelf = *sipSelfp; + if (sipSelf != NULL && sipInterpreter != NULL) { PyObject *xtype, *xvalue, *xtb; - SIP_BLOCK_THREADS - /* We may be tidying up after an exception so preserve it. */ PyErr_Fetch(&xtype, &xvalue, &xtb); callPyDtor(sipSelf); @@ -6017,7 +6073,11 @@ void sip_api_instance_destroyed(sipSimpleWrapper *sipSelf) sipOMRemoveObject(&cppPyMap, sipSelf); - /* This no longer points to anything useful. */ + /* + * This no longer points to anything useful. Actually it might do as + * the partialy destroyed C++ instance may still be trying to invoke + * reimplemented virtuals. + */ clear_access_func(sipSelf); /* @@ -6030,10 +6090,20 @@ void sip_api_instance_destroyed(sipSimpleWrapper *sipSelf) Py_DECREF(sipSelf); } else if (PyObject_TypeCheck((PyObject *)sipSelf, (PyTypeObject *)&sipWrapper_Type)) + { removeFromParent((sipWrapper *)sipSelf); - - SIP_UNBLOCK_THREADS + } } + + /* + * Normally this is done in the generated dealloc function. However this + * is only called if the pointer/access function has not been reset (which + * it has). It acts as a guard to prevent any further invocations of + * reimplemented virtuals. + */ + *sipSelfp = NULL; + + SIP_UNBLOCK_THREADS } @@ -6245,14 +6315,22 @@ static PyObject *createContainerType(sipContainerDef *cod, sipTypeDef *td, PyObject *type_dict, sipExportedModuleDef *client) { PyObject *py_type, *scope_dict, *name, *args; + sipTypeDef *scope_td; /* Get the dictionary to place the type in. */ if (cod->cod_scope.sc_flag) { + scope_td = NULL; scope_dict = mod_dict; } - else if ((scope_dict = getScopeDict(getGeneratedType(&cod->cod_scope, client), mod_dict, client)) == NULL) - goto reterr; + else + { + scope_td = getGeneratedType(&cod->cod_scope, client); + scope_dict = getScopeDict(scope_td, mod_dict, client); + + if (scope_dict == NULL) + goto reterr; + } /* Create an object corresponding to the type name. */ #if PY_MAJOR_VERSION >= 3 @@ -6283,6 +6361,23 @@ static PyObject *createContainerType(sipContainerDef *cod, sipTypeDef *td, if (py_type == NULL) goto relargs; +#if PY_VERSION_HEX >= 0x03030000 + /* Fix __qualname__ if there is a scope. */ + if (scope_td != NULL) + { + PyHeapTypeObject *ht; + PyObject *qualname = get_qualname(scope_td, name); + + if (qualname == NULL) + goto reltype; + + ht = (PyHeapTypeObject *)py_type; + + Py_CLEAR(ht->ht_qualname); + ht->ht_qualname = qualname; + } +#endif + /* Add the type to the "parent" dictionary. */ if (PyDict_SetItem(scope_dict, name, py_type) < 0) goto reltype; @@ -6378,6 +6473,16 @@ static int createClassType(sipExportedModuleDef *client, sipClassTypeDef *ctd, Py_INCREF(st); PyTuple_SET_ITEM(bases, i, st); + + /* + * Inherit any garbage collector code rather than look for it each + * time it is needed. + */ + if (ctd->ctd_traverse == NULL) + ctd->ctd_traverse = ((sipClassTypeDef *)sup_td)->ctd_traverse; + + if (ctd->ctd_clear == NULL) + ctd->ctd_clear = ((sipClassTypeDef *)sup_td)->ctd_clear; } } @@ -7167,9 +7272,7 @@ static int add_lazy_container_attrs(sipTypeDef *td, sipContainerDef *cod, sipVariableDef *vd; /* Do the methods. */ - pmd = cod->cod_methods; - - for (i = 0; i < cod->cod_nrmethods; ++i) + for (pmd = cod->cod_methods, i = 0; i < cod->cod_nrmethods; ++i, ++pmd) { /* Non-lazy methods will already have been handled. */ if (!sipTypeHasNonlazyMethod(td) || !isNonlazyMethod(pmd)) @@ -7177,14 +7280,10 @@ static int add_lazy_container_attrs(sipTypeDef *td, sipContainerDef *cod, if (addMethod(dict, pmd) < 0) return -1; } - - ++pmd; } /* Do the unscoped enum members. */ - enm = cod->cod_enummembers; - - for (i = 0; i < cod->cod_nrenummembers; ++i) + for (enm = cod->cod_enummembers, i = 0; i < cod->cod_nrenummembers; ++i, ++enm) { int rc; PyObject *val; @@ -7217,14 +7316,10 @@ static int add_lazy_container_attrs(sipTypeDef *td, sipContainerDef *cod, if (rc < 0) return -1; - - ++enm; } /* Do the variables. */ - vd = cod->cod_variables; - - for (i = 0; i < cod->cod_nrvariables; ++i) + for (vd = cod->cod_variables, i = 0; i < cod->cod_nrvariables; ++i, ++vd) { int rc; PyObject *descr; @@ -7243,8 +7338,6 @@ static int add_lazy_container_attrs(sipTypeDef *td, sipContainerDef *cod, if (rc < 0) return -1; - - ++vd; } return 0; @@ -10935,25 +11028,11 @@ static int sipSimpleWrapper_traverse(sipSimpleWrapper *self, visitproc visit, void *ptr; const sipClassTypeDef *ctd; - /* Call the nearest handwritten traverse code in the class hierachy. */ + /* Call any handwritten traverse code. */ if ((ptr = getPtrTypeDef(self, &ctd)) != NULL) - { - const sipClassTypeDef *sup_ctd = ctd; - - if (ctd->ctd_traverse == NULL) - { - const sipEncodedTypeDef *sup; - - if ((sup = ctd->ctd_supers) != NULL) - do - sup_ctd = sipGetGeneratedClassType(sup, ctd); - while (sup_ctd->ctd_traverse == NULL && !sup++->sc_flag); - } - - if (sup_ctd->ctd_traverse != NULL) - if ((vret = sup_ctd->ctd_traverse(ptr, visit, arg)) != 0) + if (ctd->ctd_traverse != NULL) + if ((vret = ctd->ctd_traverse(ptr, visit, arg)) != 0) return vret; - } if (self->dict != NULL) if ((vret = visit(self->dict, arg)) != 0) @@ -10985,24 +11064,10 @@ static int sipSimpleWrapper_clear(sipSimpleWrapper *self) const sipClassTypeDef *ctd; PyObject *tmp; - /* Call the nearest handwritten clear code in the class hierachy. */ + /* Call any handwritten clear code. */ if ((ptr = getPtrTypeDef(self, &ctd)) != NULL) - { - const sipClassTypeDef *sup_ctd = ctd; - - if (ctd->ctd_clear == NULL) - { - sipEncodedTypeDef *sup; - - if ((sup = ctd->ctd_supers) != NULL) - do - sup_ctd = sipGetGeneratedClassType(sup, ctd); - while (sup_ctd->ctd_clear == NULL && !sup++->sc_flag); - } - - if (sup_ctd->ctd_clear != NULL) - vret = sup_ctd->ctd_clear(ptr); - } + if (ctd->ctd_clear != NULL) + vret = ctd->ctd_clear(ptr); /* Remove the instance dictionary. */ tmp = self->dict; @@ -12545,10 +12610,25 @@ static int parseBytes_AsCharArray(PyObject *obj, const char **ap, a = SIPBytes_AS_STRING(obj); asz = SIPBytes_GET_SIZE(obj); } +#if PY_MAJOR_VERSION >= 3 + else + { + Py_buffer view; + + if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) + return -1; + + a = view.buf; + asz = view.len; + + PyBuffer_Release(&view); + } +#else else if (PyObject_AsCharBuffer(obj, &a, &asz) < 0) { return -1; } +#endif if (ap != NULL) *ap = a; @@ -12573,10 +12653,25 @@ static int parseBytes_AsChar(PyObject *obj, char *ap) chp = SIPBytes_AS_STRING(obj); sz = SIPBytes_GET_SIZE(obj); } +#if PY_MAJOR_VERSION >= 3 + else + { + Py_buffer view; + + if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) + return -1; + + chp = view.buf; + sz = view.len; + + PyBuffer_Release(&view); + } +#else else if (PyObject_AsCharBuffer(obj, &chp, &sz) < 0) { return -1; } +#endif if (sz != 1) return -1; @@ -12953,6 +13048,88 @@ static PyObject *sipEnumType_alloc(PyTypeObject *self, SIP_SSIZE_T nitems) } +/* + * The enum type getattro slot. + */ +static PyObject *sipEnumType_getattro(PyObject *self, PyObject *name) +{ + PyObject *res; + sipEnumTypeDef *etd; + sipExportedModuleDef *client; + const sipEnumMemberDef *enm, *emd; + int enum_nr, nr_members, m; + const char *name_str; + + /* + * Try a generic lookup first. This has the side effect of checking the + * type of the name object. + */ + if ((res = PyObject_GenericGetAttr(self, name)) != NULL) + return res; + + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + return NULL; + + PyErr_Clear(); + + /* Get the member name. */ +#if PY_VERSION_HEX >= 0x03030000 + name_str = PyUnicode_AsUTF8(name); +#elif PY_MAJOR_VERSION >= 3 + name_str = _PyUnicode_AsString(name); +#else + /* We don't handle Unicode names. */ + if (!PyString_Check(name)) + { + PyErr_Format(PyExc_TypeError, + "attribute name must be string, not '%.200s'", + Py_TYPE(name)->tp_name); + name_str = NULL; + } + else + { + name_str = PyString_AS_STRING(name); + } +#endif + + if (name_str == NULL) + return NULL; + + etd = (sipEnumTypeDef *)((sipEnumTypeObject *)self)->type; + client = ((sipTypeDef *)etd)->td_module; + + /* Find the number of this enum. */ + for (enum_nr = 0; enum_nr < client->em_nrtypes; ++enum_nr) + if (client->em_types[enum_nr] == (sipTypeDef *)etd) + break; + + /* Get the enum members in the same scope. */ + if (etd->etd_scope < 0) + { + nr_members = client->em_nrenummembers; + enm = client->em_enummembers; + } + else + { + const sipContainerDef *cod = get_container(client->em_types[etd->etd_scope]); + + nr_members = cod->cod_nrenummembers; + enm = cod->cod_enummembers; + } + + /* Find the enum member. */ + for (emd = enm, m = 0; m < nr_members; ++m, ++emd) + if (emd->em_enum == enum_nr && strcmp(emd->em_name, name_str) == 0) + return sip_api_convert_from_enum(emd->em_val, (sipTypeDef *)etd); + + PyErr_Format(PyExc_AttributeError, + "sip.enumtype object '%s' has no member '%s'", + sipPyNameOfEnum(etd), name_str); + + return NULL; +} + + /* * Check if an object is of the right type to convert to an encoded string. */ @@ -12967,8 +13144,24 @@ static int check_encoded_string(PyObject *obj) if (SIPBytes_Check(obj)) return 0; +#if PY_MAJOR_VERSION >= 3 + { + Py_buffer view; + + if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) + { + PyErr_Clear(); + } + else + { + PyBuffer_Release(&view); + return 0; + } + } +#else if (PyObject_CheckReadBuffer(obj)) return 0; +#endif return -1; } @@ -13965,3 +14158,26 @@ static PyObject *get_qualname(const sipTypeDef *td, PyObject *name) ((PyHeapTypeObject *)scope_type)->ht_qualname, name); } #endif + + +/* + * Implement PySlice_GetIndicesEx() (or its subsequent replacement). + */ +int sip_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) +{ +#if PY_VERSION_HEX >= 0x03070000 + if (PySlice_Unpack(slice, start, stop, step) < 0) + return -1; + + *slicelength = PySlice_AdjustIndices(length, start, stop, *step); + + return 0; +#elif PY_VERSION_HEX >= 0x03020000 + return PySlice_GetIndicesEx(slice, length, start, stop, step, slicelength); +#else + return PySlice_GetIndicesEx((PySliceObject *)slice, length, start, stop, + step, slicelength); +#endif +} diff --git a/sip/siplib/voidptr.c b/sip/siplib/voidptr.c index 6a1d30dd..58633490 100644 --- a/sip/siplib/voidptr.c +++ b/sip/siplib/voidptr.c @@ -1,7 +1,7 @@ /* * SIP library code. * - * Copyright (c) 2016 Riverbank Computing Limited + * Copyright (c) 2018 Riverbank Computing Limited * * This file is part of SIP. * @@ -476,7 +476,7 @@ static PyObject *sipVoidPtr_subscript(PyObject *self, PyObject *key) { Py_ssize_t start, stop, step, slicelength; - if (sipConvertFromSliceObject(key, v->size, &start, &stop, &step, &slicelength) < 0) + if (sip_api_convert_from_slice_object(key, v->size, &start, &stop, &step, &slicelength) < 0) return NULL; if (step != 1) @@ -533,7 +533,7 @@ static int sipVoidPtr_ass_subscript(PyObject *self, PyObject *key, { Py_ssize_t stop, step; - if (sipConvertFromSliceObject(key, v->size, &start, &stop, &step, &size) < 0) + if (sip_api_convert_from_slice_object(key, v->size, &start, &stop, &step, &size) < 0) return -1; if (step != 1) diff --git a/src/core_ex.cpp b/src/core_ex.cpp index bb6def49..f39b2829 100644 --- a/src/core_ex.cpp +++ b/src/core_ex.cpp @@ -203,6 +203,11 @@ void wxPyCoreModuleInject(PyObject* moduleDict) _AddInfoString("autoidman"); #endif + wxString sip_version = wxString("sip-") + wxString(SIP_VERSION_STR); + obj = wx2PyString(sip_version); + PyList_Append(PlatformInfo, obj); + Py_DECREF(obj); + #undef _AddInfoString PyObject* PlatformInfoTuple = PyList_AsTuple(PlatformInfo); diff --git a/wscript b/wscript index 0c8a2f66..1e6ce538 100644 --- a/wscript +++ b/wscript @@ -67,7 +67,7 @@ def configure(conf): import distutils.msvc9compiler msvc_version = str( distutils.msvc9compiler.get_build_version() ) - # When building for Python 3.7 the msvc_version returned will be + # When building for Python 3.7 the msvc_version returned will be # "14.1" as that is the version of the BasePlatformToolkit that stock # Python 3.7 was built with, a.k.a v141, which is the default in # Visual Studio 2017. However, waf is using "msvc 15.0" to designate @@ -75,7 +75,7 @@ def configure(conf): # fix up the msvc_version accordingly. if msvc_version == "14.1" and sys.version_info >= (3,7): ##msvc_version = '15.0' - + # On the other hand, microsoft says that v141 and v140 (Visual # Studio 2015) are binary compatible, so for now let's just drop # it back to "14.0" until I get all the details worked out for @@ -158,6 +158,7 @@ def configure(conf): # ** Add code for new modules here (and below for non-MSW) + # tweak the PYEXT compile and link flags if making a --debug build if conf.env.debug: for listname in ['CFLAGS_PYEXT', 'CXXFLAGS_PYEXT']: @@ -291,6 +292,13 @@ 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') @@ -313,7 +321,7 @@ def configure(conf): # Python's lib, which we don't want as that could tie us to that # specific Python instance instead of the one that is loading the # wxPython extension modules. That's okay for PYEMBED but not for PYEXT - # configs. + # configs. conf.env.LIBPATH_PYEXT = [] conf.env.LIB_PYEXT = []