mirror of https://github.com/swig/swig
Merge branch 'master' into fix_1792
This commit is contained in:
commit
3a37288e06
|
@ -129,8 +129,13 @@ jobs:
|
|||
VER: '3.13-dbg'
|
||||
CSTD: gnu99
|
||||
- SWIGLANG: python
|
||||
VER: '3.13t' # no-gil testing
|
||||
VER: '3.13'
|
||||
CSTD: gnu99
|
||||
SWIG_FEATURES: -nogil # Test that -nogil has no effect on non-free-threading Python
|
||||
- SWIGLANG: python
|
||||
VER: '3.13t'
|
||||
CSTD: gnu99
|
||||
SWIG_FEATURES: -nogil
|
||||
- SWIGLANG: python
|
||||
VER: '3.14'
|
||||
PY_ABI_VER: '3.14'
|
||||
|
|
|
@ -7,6 +7,20 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
|||
Version 4.4.0 (in progress)
|
||||
===========================
|
||||
|
||||
2025-07-18: crusaderky
|
||||
[Python] #3215 Added -nogil flag to mark modules as free-threading compatible.
|
||||
|
||||
2025-07-18: jim-easterbrook
|
||||
[Python] #3219 Python builtin heap types buffer support via the
|
||||
"python:bf_getbuffer" and "python:bf_releasebuffer" features improvement.
|
||||
Add workarounds/fixes for python-3.9 and earlier and ignore when using
|
||||
the limited API for versions prior to python-3.11 instead of generating
|
||||
code that won't compile.
|
||||
|
||||
2025-07-09: timfel
|
||||
[Python] #3217 Fix undefined behaviour in SwigPyObject_richcompare and
|
||||
SwigPyObject_compare.
|
||||
|
||||
2025-06-27: wsfulton
|
||||
[Python] Raise an AttributeError instead of TypeError when there are internal
|
||||
and unexpected coding errors around member variable wrappers.
|
||||
|
|
|
@ -213,6 +213,7 @@ SWIGGO_CGO Defined when using Go for cgo
|
|||
SWIGGO_GCCGO Defined when using Go for gccgo
|
||||
SWIGGO_INTGO_SIZE Size of the Go type int when using Go (32 or 64)
|
||||
SWIGPYTHON_BUILTIN Defined when using Python with -builtin
|
||||
SWIGPYTHON_NOGIL Defined when using Python with -nogil
|
||||
SWIG_RUBY_AUTORENAME Defined when using Ruby with -autorename
|
||||
</pre></div>
|
||||
|
||||
|
|
|
@ -963,6 +963,7 @@ swig -python -help
|
|||
<tr><td>-interface <mod></td><td>Set low-level C/C++ module name to <mod> (default: module name prefixed by '_')</td></tr>
|
||||
<tr><td>-keyword </td><td>Use keyword arguments</td></tr>
|
||||
<tr><td>-nofastunpack </td><td>Use traditional UnpackTuple method to parse the argument functions</td></tr>
|
||||
<tr><td>-nogil </td><td>Enable free-threading if supported by the Python interpreter</td></tr>
|
||||
<tr><td>-noh </td><td>Don't generate the output header file</td></tr>
|
||||
<tr><td>-noproxy </td><td>Don't generate proxy classes</td></tr>
|
||||
<tr><td>-nortti </td><td>Disable the use of the native C++ RTTI with directors</td></tr>
|
||||
|
@ -7641,10 +7642,12 @@ will not be able to run any other threads, even if the wrapped C/C++ code is wai
|
|||
<a href="https://docs.python.org/3/howto/free-threading-python.html">Free threading Python</a>
|
||||
disables the Global Interpreter Lock (GIL) for improved parallel execution or multi-threaded
|
||||
execution.
|
||||
Python free threading was first released with experimental support for Python 3.13 and requires a special build of Python where the GIL can be disabled.
|
||||
SWIG supports free threading Python; just use a free threading build of Python.
|
||||
In particular, the Python header files from the free threading build of Python must be used
|
||||
when compiling the SWIG generated code.
|
||||
Python free threading was first released with experimental support for Python 3.13 and requires a
|
||||
special build of Python where the GIL can be disabled.
|
||||
SWIG support for free threading Python is opt-in; you must pass the <tt>-nogil</tt> flag to swig to
|
||||
indicate that the wrapped code is thread-safe. The flag has no effect on Python builds that don't
|
||||
support free threading. In particular, the Python header files from the free threading build of
|
||||
Python must be used when compiling the SWIG generated code.
|
||||
This is needed for the C/C++ compiler to be aware of the <tt>Py_GIL_DISABLED</tt> Python macro,
|
||||
which identifies the free threading build, and is used by the SWIG generated code.
|
||||
Please see the <a href="https://py-free-threading.github.io/">Python free-threading guide</a>
|
||||
|
@ -7659,6 +7662,14 @@ Users must also write thread-safe code and prevent unsafe shared mutation using
|
|||
Python code or using C/C++ native locking.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that free-threading support is separate to the standard multithreading support described
|
||||
in the previous section. For example, one can still declare that functions should or shouldn't
|
||||
release the GIL, but that will only have an effect when and if the GIL is available in the
|
||||
Python interpreter to begin with. If your wrapped code is thread-unsafe, you should use
|
||||
an explicit locking system for it and should not rely on the GIL to protect it.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Compatibility Note:</b> Support for free threading Python was added in SWIG-4.4.0.
|
||||
</p>
|
||||
|
|
|
@ -1303,8 +1303,7 @@ else
|
|||
PYTHON_SO = @PYTHON_SO@
|
||||
endif
|
||||
|
||||
PYNOGIL = @PYNOGIL@
|
||||
PYFLAGS = -Walways
|
||||
PYFLAGS = -Werror
|
||||
PYCODESTYLE = @PYCODESTYLE@
|
||||
PYCODESTYLE_FLAGS = --ignore=E252,E30,E402,E501,E731,W291,W391
|
||||
PYABI3AUDIT = @PYABI3AUDIT@
|
||||
|
@ -1368,7 +1367,7 @@ python_run: $(PYSCRIPT)
|
|||
ifneq (,$(PYCODESTYLE))
|
||||
$(COMPILETOOL) $(PYCODESTYLE) $(PYCODESTYLE_FLAGS) $(PYSCRIPT)
|
||||
endif
|
||||
env PYTHONPATH=$$PWD $(RUNTOOL) $(PYTHON) $(PYNOGIL) $(PYFLAGS) $(PYSCRIPT) $(RUNPIPE)
|
||||
env PYTHONPATH=$$PWD $(RUNTOOL) $(PYTHON) $(PYFLAGS) $(PYSCRIPT) $(RUNPIPE)
|
||||
|
||||
ifneq (,$(SRCDIR))
|
||||
$(RUNME).py: $(SRCDIR)$(RUNME).py
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
%module pyabi311_bufferinterface
|
||||
|
||||
%begin %{
|
||||
#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 < 0x030b0000
|
||||
// Examples/tests-suite/python/Makefile should only run this test with Py_LIMITED_API >= 3.11
|
||||
#error testcase misconfiguration - Py_buffer is not defined in Py_LIMITED_API < 3.11
|
||||
#endif
|
||||
%}
|
||||
|
||||
#ifdef SWIGPYTHON_BUILTIN
|
||||
%feature("python:bf_getbuffer", functype="getbufferproc") ReadOnlyData "ReadOnlyData::getbuffer";
|
||||
%feature("python:bf_releasebuffer", functype="releasebufferproc") ReadOnlyData "ReadOnlyData::releasebuffer";
|
||||
|
||||
%feature("python:bf_getbuffer", functype="getbufferproc") ReadWriteData "ReadWriteData::getbuffer";
|
||||
%feature("python:bf_releasebuffer", functype="releasebufferproc") ReadWriteData "ReadWriteData::releasebuffer";
|
||||
#endif
|
||||
|
||||
/* swig Python objects can only "expose" a Python buffer if the following
|
||||
* conditions are met:
|
||||
* 1/ SWIGPYTHON_BUILTIN is set
|
||||
* and
|
||||
* 2a/ Py_LIMITED_API is not set
|
||||
* or
|
||||
* 2b/ Py_LIMITED_API is 3.11 or greater
|
||||
*
|
||||
* or
|
||||
*
|
||||
* 1/ SWIGPYTHON_BUILTIN is not set
|
||||
* and
|
||||
* 2/ Python version is 3.12 or higher
|
||||
*/
|
||||
%inline %{
|
||||
#ifdef SWIGPYTHON_BUILTIN
|
||||
#ifdef Py_LIMITED_API
|
||||
#if Py_LIMITED_API+0 >= 0x030b0000
|
||||
bool buffers_supported() { return true; }
|
||||
#else
|
||||
bool buffers_supported() { return false; }
|
||||
#endif
|
||||
#else // Py_LIMITED_API
|
||||
bool buffers_supported() { return true; }
|
||||
#endif // Py_LIMITED_API
|
||||
#else // SWIGPYTHON_BUILTIN
|
||||
#if PY_VERSION_HEX >= 0x030c0000
|
||||
bool buffers_supported() { return true; }
|
||||
#else
|
||||
bool buffers_supported() { return false; }
|
||||
#endif
|
||||
#endif // SWIGPYTHON_BUILTIN
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
class BaseClassData {
|
||||
private:
|
||||
char data[1024];
|
||||
public:
|
||||
bool released; // public so runme.py can use it as a diagnostic
|
||||
BaseClassData() {
|
||||
released = true;
|
||||
strcpy(data, "This string represents a large block of memory.");
|
||||
};
|
||||
#ifdef SWIGPYTHON_BUILTIN
|
||||
static int getbuffer(PyObject *exporter, Py_buffer *view, int flags, bool readonly) {
|
||||
#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 < 0x030b0000
|
||||
goto fail;
|
||||
#endif
|
||||
BaseClassData *self = 0;
|
||||
if (!SWIG_IsOK(SWIG_ConvertPtr(exporter, (void**)&self, SWIGTYPE_p_BaseClassData, 0)))
|
||||
goto fail;
|
||||
self->released = false;
|
||||
return PyBuffer_FillInfo(view, exporter, &self->data, sizeof(self->data), readonly ? 1 : 0, flags);
|
||||
fail:
|
||||
PyErr_SetNone(PyExc_BufferError);
|
||||
view->obj = NULL;
|
||||
return -1;
|
||||
};
|
||||
static void releasebuffer(PyObject *exporter, Py_buffer *view) {
|
||||
BaseClassData *self = 0;
|
||||
if (!SWIG_IsOK(SWIG_ConvertPtr(exporter, (void**)&self, SWIGTYPE_p_BaseClassData, 0)))
|
||||
return;
|
||||
self->released = true;
|
||||
};
|
||||
#else
|
||||
PyObject* __buffer__(int flags, bool readonly) {
|
||||
Py_buffer view;
|
||||
if (PyBuffer_FillInfo(&view, NULL, data, sizeof(data), readonly ? 1 : 0, flags)) {
|
||||
PyErr_SetNone(PyExc_BufferError);
|
||||
return NULL;
|
||||
}
|
||||
released = false;
|
||||
return PyMemoryView_FromBuffer(&view);
|
||||
};
|
||||
void __release_buffer__(PyObject* buffer) {
|
||||
released = true;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
class ReadOnlyData: public BaseClassData {
|
||||
public:
|
||||
#ifdef SWIGPYTHON_BUILTIN
|
||||
static int getbuffer(PyObject *exporter, Py_buffer *view, int flags) {
|
||||
return BaseClassData::getbuffer(exporter, view, flags, true);
|
||||
};
|
||||
#else
|
||||
PyObject* __buffer__(int flags) {
|
||||
return BaseClassData::__buffer__(flags, true);
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
class ReadWriteData: public BaseClassData {
|
||||
public:
|
||||
#ifdef SWIGPYTHON_BUILTIN
|
||||
static int getbuffer(PyObject *exporter, Py_buffer *view, int flags) {
|
||||
return BaseClassData::getbuffer(exporter, view, flags, false);
|
||||
};
|
||||
#else
|
||||
PyObject* __buffer__(int flags) {
|
||||
return BaseClassData::__buffer__(flags, false);
|
||||
};
|
||||
#endif
|
||||
};
|
||||
%}
|
|
@ -9,8 +9,7 @@ else
|
|||
endif
|
||||
|
||||
LANGUAGE = python
|
||||
PYNOGIL = @PYNOGIL@
|
||||
PYFLAGS = -Walways
|
||||
PYFLAGS = -Werror
|
||||
SCRIPTSUFFIX = _runme.py
|
||||
PYCODESTYLE = @PYCODESTYLE@
|
||||
PYCODESTYLE_FLAGS = --ignore=E252,E30,E402,E501,E731,E741,W291,W391
|
||||
|
@ -81,6 +80,7 @@ CPP_TEST_CASES += \
|
|||
python_strict_unicode \
|
||||
python_threads \
|
||||
python_typemap_macro \
|
||||
python_various \
|
||||
simutry \
|
||||
std_containers \
|
||||
swigobject \
|
||||
|
@ -88,6 +88,19 @@ CPP_TEST_CASES += \
|
|||
|
||||
# director_profile
|
||||
|
||||
ifeq (,$(PY_ABI_VER))
|
||||
PY_ABI_311:=1
|
||||
else
|
||||
PY_ABI_VER_INTEGER:=$(shell printf "%d%02d" $(subst ., ,$(PY_ABI_VER)))
|
||||
PY_ABI_311:=$(shell test $(PY_ABI_VER_INTEGER) -ge 311 && echo "1")
|
||||
endif
|
||||
|
||||
# Test requiring python-3.11 minimum if using Py_LIMITED_API
|
||||
ifeq (1,$(PY_ABI_311))
|
||||
CPP_TEST_CASES += pyabi311_bufferinterface
|
||||
endif
|
||||
|
||||
|
||||
CPP11_TEST_CASES = \
|
||||
cpp11_hash_tables \
|
||||
cpp11_shared_ptr_const \
|
||||
|
@ -171,7 +184,7 @@ endif
|
|||
# a file is found which has _runme.py appended after the testcase name.
|
||||
run_testcase = \
|
||||
if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \
|
||||
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PYTHONPATH=.:$(srcdir):$$PYTHONPATH $(RUNTOOL) $(PYTHON) $(PYNOGIL) $(PYFLAGS) $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \
|
||||
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PYTHONPATH=.:$(srcdir):$$PYTHONPATH $(RUNTOOL) $(PYTHON) $(PYFLAGS) $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \
|
||||
fi
|
||||
|
||||
# Clean: remove the generated .py file
|
||||
|
@ -194,5 +207,5 @@ hugemod:
|
|||
perl hugemod.pl $(hugemod_runme)
|
||||
$(MAKE) hugemod_a.cpptest
|
||||
$(MAKE) hugemod_b.cpptest
|
||||
time $(PYTHON) $(PYNOGIL) $(PYFLAGS) $(hugemod_runme)
|
||||
time $(PYTHON) $(PYNOGIL) $(PYFLAGS) $(hugemod_runme)
|
||||
time $(PYTHON) $(PYFLAGS) $(hugemod_runme)
|
||||
time $(PYTHON) $(PYFLAGS) $(hugemod_runme)
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import sys
|
||||
|
||||
# don't bother with Python 2
|
||||
if sys.version_info < (3,0):
|
||||
exit(0)
|
||||
|
||||
import pyabi311_bufferinterface
|
||||
|
||||
def check(what, expected, actual):
|
||||
if expected != actual:
|
||||
raise RuntimeError(
|
||||
"Failed: ", what, " Expected: ", expected, " Actual: ", actual)
|
||||
|
||||
# test not relevant unless certain conditions are met (builtin, limited API)
|
||||
if not pyabi311_bufferinterface.buffers_supported():
|
||||
exit(0)
|
||||
|
||||
data = pyabi311_bufferinterface.ReadOnlyData()
|
||||
view = memoryview(data)
|
||||
check('readonly', view.readonly, True)
|
||||
check('read data', view[:10], b"This string represents"[:10])
|
||||
check('not released', data.released, False)
|
||||
view.release()
|
||||
check('released', data.released, True)
|
||||
|
||||
data = pyabi311_bufferinterface.ReadWriteData()
|
||||
view = memoryview(data)
|
||||
check('readonly', view.readonly, False)
|
||||
text = b'Lorem ipsum dolor sit amet'
|
||||
view[:len(text)] = b'Lorem ipsum dolor sit amet'
|
||||
check('read data', view[:len(text)], text)
|
||||
check('not released', data.released, False)
|
||||
view.release()
|
||||
check('released', data.released, True)
|
||||
|
||||
view = memoryview(data)
|
||||
check('written data', view[:len(text)], text)
|
||||
check('not released', data.released, False)
|
||||
del view
|
||||
check('released', data.released, True)
|
|
@ -83,6 +83,10 @@ if (a1 == 42) :
|
|||
if not (a1 != 42) :
|
||||
raise RuntimeError("Comparing class (with overloaded operator ==) to incompatible type, != returned False")
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
if a1.__eq__(None) is not NotImplemented:
|
||||
raise RuntimeError("Comparing to incompatible type should return NotImplemented")
|
||||
|
||||
# Check inequalities
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
from python_various import *
|
||||
import datetime
|
||||
import sys
|
||||
|
||||
class MyClass:
|
||||
pass
|
||||
|
||||
# Only implemented for python 3
|
||||
if sys.version_info[0:2] < (3, 0):
|
||||
exit(0)
|
||||
|
||||
type = GetFullyQualifiedName(1234) # Test builtins type
|
||||
if type != "int":
|
||||
raise RuntimeError("wrong type {}".format(type))
|
||||
|
||||
type = GetFullyQualifiedName(MyClass()) # Test __main__ type
|
||||
if type != "MyClass":
|
||||
raise RuntimeError("wrong type {}".format(type))
|
||||
|
||||
type = GetFullyQualifiedName(WrappedClass()) # Test a SWIG wrapped class
|
||||
if type != "python_various.WrappedClass":
|
||||
raise RuntimeError("wrong type {}".format(type))
|
||||
|
||||
type = GetFullyQualifiedName(datetime.date(2020, 1, 20)) # Test a Python standard library class
|
||||
if type != "datetime.date":
|
||||
raise RuntimeError("wrong type {}".format(type))
|
|
@ -0,0 +1,14 @@
|
|||
%module python_various
|
||||
|
||||
%inline %{
|
||||
struct WrappedClass {};
|
||||
|
||||
// A unit test for SWIG_PyType_GetFullyQualifiedName
|
||||
PyObject *GetFullyQualifiedName(PyObject *type) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
return SWIG_PyType_GetFullyQualifiedName(Py_TYPE(type));
|
||||
#else
|
||||
return type;
|
||||
#endif
|
||||
}
|
||||
%}
|
|
@ -32,7 +32,13 @@ SWIG_PyNumber_AsPyHash(PyObject *obj) {
|
|||
|
||||
SWIGINTERN int
|
||||
SwigPyBuiltin_BadInit(PyObject *self, PyObject *SWIGUNUSEDPARM(args), PyObject *SWIGUNUSEDPARM(kwds)) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(self));
|
||||
PyErr_Format(PyExc_TypeError, "Cannot create new instances of type '%S'", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_TypeError, "Cannot create new instances of type '%s'", Py_TYPE(self)->tp_name);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -40,7 +46,13 @@ SWIGINTERN void
|
|||
SwigPyBuiltin_BadDealloc(PyObject *obj) {
|
||||
SwigPyObject *sobj = (SwigPyObject *)obj;
|
||||
if (sobj->own) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(obj));
|
||||
PyErr_Format(PyExc_TypeError, "Swig detected a memory leak in type '%S': no callable destructor found.", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_TypeError, "Swig detected a memory leak in type '%s': no callable destructor found.", Py_TYPE(obj)->tp_name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,12 +99,24 @@ SwigPyBuiltin_SetterClosure (PyObject *obj, PyObject *val, void *closure) {
|
|||
return -1;
|
||||
}
|
||||
if (!val) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(obj));
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable deletion in type '%S'", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable deletion in type '%s'", Py_TYPE(obj)->tp_name);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
getset = (SwigPyGetSet *)closure;
|
||||
if (!getset->set) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(obj));
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable assignment in type '%S'", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable assignment in type '%s'", Py_TYPE(obj)->tp_name);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
tuple = PyTuple_New(1);
|
||||
|
@ -114,12 +138,24 @@ SwigPyBuiltin_FunpackSetterClosure (PyObject *obj, PyObject *val, void *closure)
|
|||
return -1;
|
||||
}
|
||||
if (!val) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(obj));
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable deletion in type '%S'", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable deletion in type '%s'", Py_TYPE(obj)->tp_name);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
getset = (SwigPyGetSet *)closure;
|
||||
if (!getset->set) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(obj));
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable assignment in type '%S'", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "Illegal member variable assignment in type '%s'", Py_TYPE(obj)->tp_name);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
result = (*getset->set)(obj, val);
|
||||
|
@ -138,7 +174,6 @@ SwigPyStaticVar_dealloc(PyDescrObject *descr) {
|
|||
SWIGINTERN PyObject *
|
||||
SwigPyStaticVar_repr(PyGetSetDescrObject *descr) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
|
||||
return PyUnicode_FromFormat("<class attribute '%S' of type '%s'>", PyDescr_NAME(descr), PyDescr_TYPE(descr)->tp_name);
|
||||
#else
|
||||
return PyString_FromFormat("<class attribute '%s' of type '%s'>", PyString_AsString(PyDescr_NAME(descr)), PyDescr_TYPE(descr)->tp_name);
|
||||
|
@ -181,24 +216,29 @@ SWIGINTERN int
|
|||
SwigPyObjectType_setattro(PyObject *typeobject, PyObject *name, PyObject *value) {
|
||||
PyObject *attribute;
|
||||
PyTypeObject *type;
|
||||
descrsetfunc local_set;
|
||||
|
||||
assert(PyType_Check(typeobject));
|
||||
type = (PyTypeObject *)typeobject;
|
||||
attribute = _PyType_Lookup(type, name);
|
||||
if (attribute != NULL) {
|
||||
/* Implement descriptor functionality, if any */
|
||||
local_set = Py_TYPE(attribute)->tp_descr_set;
|
||||
if (local_set != NULL)
|
||||
return local_set(attribute, (PyObject *)type, value);
|
||||
descrsetfunc local_set = Py_TYPE(attribute)->tp_descr_set;
|
||||
if (local_set == NULL) {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyErr_Format(PyExc_AttributeError, "cannot modify read-only attribute '%s.%S'", type->tp_name, name);
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(type);
|
||||
PyErr_Format(PyExc_AttributeError, "cannot modify read-only attribute '%S.%S'", tpname, name);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "cannot modify read-only attribute '%s.%s'", type->tp_name, PyString_AS_STRING(name));
|
||||
PyErr_Format(PyExc_AttributeError, "cannot modify read-only attribute '%s.%s'", type->tp_name, PyString_AS_STRING(name));
|
||||
#endif
|
||||
} else {
|
||||
return local_set(attribute, (PyObject *)type, value);
|
||||
}
|
||||
} else {
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyErr_Format(PyExc_AttributeError, "type '%s' has no attribute '%S'", type->tp_name, name);
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(type);
|
||||
PyErr_Format(PyExc_AttributeError, "type '%S' has no attribute '%S'", tpname, name);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "type '%s' has no attribute '%s'", type->tp_name, PyString_AS_STRING(name));
|
||||
#endif
|
||||
|
|
|
@ -66,7 +66,7 @@ SWIG_PyUnicode_AsUTF8AndSize(PyObject *str, Py_ssize_t *psize, PyObject **pbytes
|
|||
#endif
|
||||
}
|
||||
|
||||
SWIGINTERN PyObject*
|
||||
SWIGINTERN PyObject *
|
||||
SWIG_Python_str_FromChar(const char *c)
|
||||
{
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
|
@ -132,3 +132,31 @@ SWIG_Python_str_FromChar(const char *c)
|
|||
# define SWIG_Py_DECREF Py_DECREF
|
||||
# define SWIG_Py_XDECREF Py_XDECREF
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
SWIGINTERN PyObject *
|
||||
SWIG_PyType_GetFullyQualifiedName(PyTypeObject *type) {
|
||||
#if PY_VERSION_HEX >= 0x030d0000
|
||||
return PyType_GetFullyQualifiedName(type);
|
||||
#else
|
||||
PyObject *result = NULL;
|
||||
PyObject *qualname = PyObject_GetAttrString((PyObject *)type, "__qualname__");
|
||||
if (qualname) {
|
||||
PyObject *mod = PyObject_GetAttrString((PyObject *)type, "__module__");
|
||||
if (mod) {
|
||||
if (PyUnicode_Check(mod) && PyUnicode_CompareWithASCIIString(mod, "builtins") && PyUnicode_CompareWithASCIIString(mod, "__main__")) {
|
||||
result = PyUnicode_FromFormat("%U%c%U", mod, '.', qualname);
|
||||
SWIG_Py_DECREF(qualname);
|
||||
} else {
|
||||
result = qualname;
|
||||
}
|
||||
SWIG_Py_DECREF(mod);
|
||||
} else {
|
||||
result = qualname;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -206,6 +206,11 @@ SWIG_init(void) {
|
|||
#if PY_VERSION_HEX >= 0x03000000
|
||||
static PyModuleDef_Slot SwigSlots[] = {
|
||||
{ Py_mod_exec, (void *)SWIG_mod_exec },
|
||||
#ifdef SWIGPYTHON_NOGIL
|
||||
#ifdef Py_GIL_DISABLED
|
||||
{ Py_mod_gil, Py_MOD_GIL_NOT_USED },
|
||||
#endif
|
||||
#endif
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -723,26 +723,33 @@ SwigPyObject_repr2(PyObject *v, PyObject *SWIGUNUSEDPARM(args))
|
|||
}
|
||||
|
||||
SWIGRUNTIME int
|
||||
SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w)
|
||||
SwigPyObject_compare(PyObject *v, PyObject *w)
|
||||
{
|
||||
void *i = v->ptr;
|
||||
void *j = w->ptr;
|
||||
/* tp_compare is only called when both objects have the same type, so
|
||||
* the casts are guaranteed to be ok. */
|
||||
void *i = ((SwigPyObject *)v)->ptr;
|
||||
void *j = ((SwigPyObject *)w)->ptr;
|
||||
return (i < j) ? -1 : ((i > j) ? 1 : 0);
|
||||
}
|
||||
|
||||
SWIGRUNTIMEINLINE int SwigPyObject_Check(PyObject *);
|
||||
|
||||
/* Added for Python 3.x, would it also be useful for Python 2.x? */
|
||||
SWIGRUNTIME PyObject*
|
||||
SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op)
|
||||
SwigPyObject_richcompare(PyObject *v, PyObject *w, int op)
|
||||
{
|
||||
PyObject* res = NULL;
|
||||
if (!PyErr_Occurred()) {
|
||||
if (op != Py_EQ && op != Py_NE) {
|
||||
/* Per https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_richcompare
|
||||
* the first argument is guaranteed to be an instance of SwigPyObject, but the
|
||||
* second is not, so we typecheck that one. */
|
||||
if ((op != Py_EQ && op != Py_NE) || !SwigPyObject_Check(w)) {
|
||||
SWIG_Py_INCREF(Py_NotImplemented);
|
||||
return Py_NotImplemented;
|
||||
}
|
||||
res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0);
|
||||
}
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
@ -776,23 +783,22 @@ SwigPyObject_Check(PyObject *op) {
|
|||
return PyType_IsSubtype(op_type, target_tp);
|
||||
#else
|
||||
/* Check for an exact match to SwigPyObject */
|
||||
# ifdef Py_LIMITED_API
|
||||
int cmp;
|
||||
PyObject *tp_name;
|
||||
#endif
|
||||
if (op_type == target_tp)
|
||||
if (op_type == target_tp) {
|
||||
return 1;
|
||||
# ifdef Py_LIMITED_API
|
||||
/* Fallback for multiple modules */
|
||||
tp_name = PyObject_GetAttrString((PyObject *)op_type, "__name__");
|
||||
if (!tp_name)
|
||||
return 0;
|
||||
cmp = PyUnicode_CompareWithASCIIString(tp_name, "SwigPyObject");
|
||||
SWIG_Py_DECREF(tp_name);
|
||||
return cmp == 0;
|
||||
# else
|
||||
return (strcmp(op_type->tp_name, SWIG_RUNTIME_MODULE ".SwigPyObject") == 0);
|
||||
# endif
|
||||
} else {
|
||||
/* Fallback for multiple modules */
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
int cmp;
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(op_type);
|
||||
if (!tpname)
|
||||
return 0;
|
||||
cmp = PyUnicode_CompareWithASCIIString(tpname, SWIG_RUNTIME_MODULE ".SwigPyObject");
|
||||
SWIG_Py_DECREF(tpname);
|
||||
return cmp == 0;
|
||||
#else
|
||||
return strcmp(op_type->tp_name, SWIG_RUNTIME_MODULE ".SwigPyObject") == 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1100,7 +1106,7 @@ SwigPyObject_TypeOnce(void) {
|
|||
};
|
||||
PyObject *pytype = PyType_FromSpec(&spec);
|
||||
PyObject *runtime_data_module = SWIG_runtime_data_module();
|
||||
# if !defined(Py_LIMITED_API)
|
||||
#if !defined(Py_LIMITED_API)
|
||||
/* While this __dictoffset__ is only used with the builtin wrappers, SwigPyObject ought to be
|
||||
identical when created for use by proxy class wrappers in case it is shared across multiple modules. */
|
||||
#if PY_VERSION_HEX < 0x03090000
|
||||
|
@ -1193,23 +1199,22 @@ SwigPyPacked_Check(PyObject *op) {
|
|||
PyTypeObject *target_tp = SwigPyPacked_Type();
|
||||
PyTypeObject *op_type = Py_TYPE(op);
|
||||
/* Check for an exact match to SwigPyPacked */
|
||||
#ifdef Py_LIMITED_API
|
||||
int cmp;
|
||||
PyObject *tp_name;
|
||||
#endif
|
||||
if (op_type == target_tp)
|
||||
if (op_type == target_tp) {
|
||||
return 1;
|
||||
#ifdef Py_LIMITED_API
|
||||
/* Fallback for multiple modules */
|
||||
tp_name = PyObject_GetAttrString((PyObject *)op_type, "__name__");
|
||||
if (!tp_name)
|
||||
return 0;
|
||||
cmp = PyUnicode_CompareWithASCIIString(tp_name, "SwigPyPacked");
|
||||
SWIG_Py_DECREF(tp_name);
|
||||
return cmp == 0;
|
||||
} else {
|
||||
/* Fallback for multiple modules */
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
int cmp;
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(op_type);
|
||||
if (!tpname)
|
||||
return 0;
|
||||
cmp = PyUnicode_CompareWithASCIIString(tpname, SWIG_RUNTIME_MODULE ".SwigPyPacked");
|
||||
SWIG_Py_DECREF(tpname);
|
||||
return cmp == 0;
|
||||
#else
|
||||
return (strcmp(op_type->tp_name, SWIG_RUNTIME_MODULE ".SwigPyPacked") == 0);
|
||||
return strcmp(op_type->tp_name, SWIG_RUNTIME_MODULE ".SwigPyPacked") == 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SWIGRUNTIME void
|
||||
|
@ -2009,49 +2014,6 @@ SwigPyObject_GetDesc(PyObject *self)
|
|||
return ty ? ty->str : "";
|
||||
}
|
||||
|
||||
SWIGRUNTIME void
|
||||
SWIG_Python_TypeError(const char *type, PyObject *obj)
|
||||
{
|
||||
(void) obj;
|
||||
if (type) {
|
||||
#if defined(SWIG_COBJECT_TYPES)
|
||||
if (obj && SwigPyObject_Check(obj)) {
|
||||
const char *otype = (const char *) SwigPyObject_GetDesc(obj);
|
||||
if (otype) {
|
||||
PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received",
|
||||
type, otype);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#ifndef Py_LIMITED_API
|
||||
/* tp_name is not accessible */
|
||||
const char *otype = (obj ? Py_TYPE(obj)->tp_name : 0);
|
||||
if (otype) {
|
||||
PyObject *str = PyObject_Str(obj);
|
||||
PyObject *bytes = NULL;
|
||||
const char *cstr = str ? SWIG_PyUnicode_AsUTF8AndSize(str, NULL, &bytes) : 0;
|
||||
if (cstr) {
|
||||
PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received",
|
||||
type, otype, cstr);
|
||||
} else {
|
||||
PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received",
|
||||
type, otype);
|
||||
}
|
||||
SWIG_Py_XDECREF(bytes);
|
||||
SWIG_Py_XDECREF(str);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
PyErr_Format(PyExc_TypeError, "a '%s' is expected", type);
|
||||
} else {
|
||||
PyErr_Format(PyExc_TypeError, "unexpected type is received");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Convert a pointer value, signal an exception on a type mismatch */
|
||||
SWIGRUNTIME void *
|
||||
SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) {
|
||||
|
@ -2081,7 +2043,13 @@ SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
|
|||
if (!PyString_Check(name))
|
||||
# endif
|
||||
{
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(Py_TYPE(name));
|
||||
PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%S'", tpname);
|
||||
SWIG_Py_DECREF(tpname);
|
||||
#else
|
||||
PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%s'", Py_TYPE(name)->tp_name);
|
||||
#endif
|
||||
return -1;
|
||||
} else {
|
||||
SWIG_Py_INCREF(name);
|
||||
|
@ -2105,7 +2073,15 @@ SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
|
|||
if (!encoded_name)
|
||||
goto done;
|
||||
}
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
{
|
||||
PyObject *tpname = SWIG_PyType_GetFullyQualifiedName(tp);
|
||||
PyErr_Format(PyExc_AttributeError, "'%S' object has no attribute '%s'", tpname, PyString_AsString(encoded_name));
|
||||
SWIG_Py_DECREF(tpname);
|
||||
}
|
||||
#else
|
||||
PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", tp->tp_name, PyString_AsString(encoded_name));
|
||||
#endif
|
||||
SWIG_Py_DECREF(encoded_name);
|
||||
} else {
|
||||
res = f(descr, obj, value);
|
||||
|
|
|
@ -92,6 +92,7 @@ static int extranative = 0;
|
|||
static int nortti = 0;
|
||||
static int relativeimport = 0;
|
||||
static int flat_static_method = 0;
|
||||
static int nogil = 0;
|
||||
|
||||
/* flags for the make_autodoc function */
|
||||
namespace {
|
||||
|
@ -123,6 +124,7 @@ Python Options (available with -python)\n\
|
|||
-keyword - Use keyword arguments\n";
|
||||
static const char *usage2 = "\
|
||||
-nofastunpack - Use traditional UnpackTuple method to parse the argument functions\n\
|
||||
-nogil - Enable free-threading if supported by the Python interpreter\n\
|
||||
-noh - Don't generate the output header file\n";
|
||||
static const char *usage3 = "\
|
||||
-noproxy - Don't generate proxy classes\n\
|
||||
|
@ -414,6 +416,10 @@ public:
|
|||
builtin = 1;
|
||||
Preprocessor_define("SWIGPYTHON_BUILTIN", 0);
|
||||
Swig_mark_arg(i);
|
||||
} else if (strcmp(argv[i], "-nogil") == 0) {
|
||||
nogil = 1;
|
||||
Preprocessor_define("SWIGPYTHON_NOGIL", 0);
|
||||
Swig_mark_arg(i);
|
||||
} else if (strcmp(argv[i], "-relativeimport") == 0) {
|
||||
relativeimport = 1;
|
||||
Swig_mark_arg(i);
|
||||
|
@ -644,6 +650,10 @@ public:
|
|||
Printf(f_runtime, "#define SWIGPYTHON_FASTPROXY\n");
|
||||
}
|
||||
|
||||
if (nogil) {
|
||||
Printf(f_runtime, "#define SWIGPYTHON_NOGIL\n");
|
||||
}
|
||||
|
||||
Printf(f_runtime, "\n");
|
||||
|
||||
Printf(f_header, "#ifdef SWIG_TypeQuery\n");
|
||||
|
@ -4096,7 +4106,7 @@ public:
|
|||
Delete(richcompare_list);
|
||||
Printv(f, " if (!result && !PyErr_Occurred()) {\n", NIL);
|
||||
Printv(f, " if (SwigPyObject_Check(self) && SwigPyObject_Check(other)) {\n", NIL);
|
||||
Printv(f, " result = SwigPyObject_richcompare((SwigPyObject *)self, (SwigPyObject *)other, op);\n", NIL);
|
||||
Printv(f, " result = SwigPyObject_richcompare(self, other, op);\n", NIL);
|
||||
Printv(f, " } else {\n", NIL);
|
||||
Printv(f, " result = Py_NotImplemented;\n", NIL);
|
||||
Printv(f, " SWIG_Py_INCREF(result);\n", NIL);
|
||||
|
@ -4522,8 +4532,14 @@ public:
|
|||
printHeapTypesSlot(f, getHeapTypesSlot(n, "feature:python:sq_inplace_repeat"), "sq_inplace_repeat", "ssizeargfunc");
|
||||
|
||||
// buffer slots
|
||||
printHeapTypesSlot(f, getHeapTypesSlot(n, "feature:python:bf_getbuffer"), "bf_getbuffer", "getbufferproc");
|
||||
printHeapTypesSlot(f, getHeapTypesSlot(n, "feature:python:bf_releasebuffer"), "bf_releasebuffer", "releasebufferproc");
|
||||
String *bf_getbuffer = Getattr(n, "feature:python:bf_getbuffer");
|
||||
String *bf_releasebuffer = Getattr(n, "feature:python:bf_releasebuffer");
|
||||
if (bf_getbuffer || bf_releasebuffer) {
|
||||
Printv(f, "#if !defined(Py_LIMITED_API) && PY_VERSION_HEX >= 0x03090000 || Py_LIMITED_API+0 >= 0x030b0000\n", NIL);
|
||||
printHeapTypesSlot(f, getHeapTypesSlot(n, "feature:python:bf_getbuffer"), "bf_getbuffer", "getbufferproc");
|
||||
printHeapTypesSlot(f, getHeapTypesSlot(n, "feature:python:bf_releasebuffer"), "bf_releasebuffer", "releasebufferproc");
|
||||
Printv(f, "#endif\n", NIL);
|
||||
}
|
||||
|
||||
Printf(f, " { 0, NULL }\n");
|
||||
Printf(f, " };\n");
|
||||
|
@ -4536,6 +4552,16 @@ public:
|
|||
Printf(f, " };\n");
|
||||
Printv(f, " PyObject *tuple_bases = SwigPyBuiltin_InitBases(bases);\n", NIL);
|
||||
Printf(f, " PyTypeObject *pytype = (PyTypeObject *)PyType_FromSpecWithBases(&spec, tuple_bases);\n");
|
||||
if (bf_getbuffer || bf_releasebuffer) {
|
||||
Printv(f, "#if !defined(Py_LIMITED_API) && PY_VERSION_HEX < 0x03090000\n", NIL);
|
||||
Printf(f, " if (pytype) {\n");
|
||||
if (bf_getbuffer)
|
||||
Printf(f, " pytype->tp_as_buffer->bf_getbuffer = %s;\n", getSlot(n, "feature:python:bf_getbuffer"));
|
||||
if (bf_releasebuffer)
|
||||
Printf(f, " pytype->tp_as_buffer->bf_releasebuffer = %s;\n", getSlot(n, "feature:python:bf_releasebuffer"));
|
||||
Printf(f, " }\n");
|
||||
Printv(f, "#endif\n", NIL);
|
||||
}
|
||||
Printf(f, " if (pytype) {\n");
|
||||
Printf(f, " if (PyDict_Merge(pytype->tp_dict, dict, 1) == 0) {\n");
|
||||
Printv(f, " SwigPyBuiltin_SetMetaType(pytype, type);\n", NIL);
|
||||
|
|
|
@ -2050,13 +2050,6 @@ else
|
|||
if test -z "$PYVER"; then
|
||||
PYVER=0
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([if $PYTHON3 GIL can be disabled])
|
||||
PYGIL=`($PYTHON3 -c "import sysconfig; print('yes' if bool(sysconfig.get_config_var('Py_GIL_DISABLED')) else 'no')") 2>/dev/null`
|
||||
AC_MSG_RESULT($PYGIL)
|
||||
if test x"$PYGIL" = x"yes"; then
|
||||
PYNOGIL="-X gil=0"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $PYVER -ge 3; then
|
||||
|
@ -2185,7 +2178,6 @@ else
|
|||
*)PYTHON3DYNAMICLINKING="";;
|
||||
esac
|
||||
|
||||
AC_SUBST(PYNOGIL)
|
||||
AC_SUBST(PY3INCLUDE)
|
||||
AC_SUBST(PY3LIB)
|
||||
AC_SUBST(PY3LINK)
|
||||
|
|
Loading…
Reference in New Issue