Merge github.com:swig/swig

# Conflicts:
#	CHANGES.current
This commit is contained in:
Andrew Rogers 2018-11-29 07:02:49 +00:00
commit 402d55da52
4 changed files with 87 additions and 59 deletions

View file

@ -7,11 +7,36 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.0.0 (in progress)
===========================
2018-11-24: adr26
2018-11-29: adr26
[Python] #1360 Leak of SWIG var link object
Fix reference counting on _SWIG_globals to allow var link to be freed on module unload.
2018-11-28: wsfulton
[Python] When using -builtin, the two step C-extension module import is now
one step and the wrapped API is only available once and not in an underlying
module attribute like it is without -builtin. To understand this, consider a
module named 'example' (using: %module example). The C-extension is compiled into
a Python module called '_example' and a pure Python module provides the actual
API from the module called 'example'. It was previously possible to additionally
access the API from the module attribute 'example._example'. The latter was an
implementation detail and is no longer available. It shouldn't have been used, but
if necessary it can be resurrected using the moduleimport attribute described in the
Python chapter of the documentation. If both modules are provided in a Python
package, try:
%module(moduleimport="from . import _example\nfrom ._example import *") example
or more generically:
%module(moduleimport="from . import $module\nfrom .$module import *") example
and if both are provided as global modules, try:
%module(moduleimport="import _example\nfrom _example import *") example
or more generically:
%module(moduleimport="import $module\nfrom $module import *") example
The module import code shown will appear in the example.py file.
2018-11-24: vadz
#1358 Fix handling of abstract base classes nested inside templates

View file

@ -6137,7 +6137,8 @@ pure Python module uses to find the C/C++ module is as follows:
<ol>
<li><p>The pure Python module, foo.py, tries to load the C/C++ module, _foo, from the same package foo.py is
located in. The package name is determined from the <tt>__name__</tt>
located in. The package name is determined from the <tt>__package__</tt>
attribute if available, see <a href="https://www.python.org/dev/peps/pep-0366/">PEP 366</a>, otherwise it is derived from the <tt>__name__</tt>
attribute given to foo.py by the Python loader that imported
foo.py. If foo.py is not in a package then _foo is loaded
as a global module.</p>

View file

@ -17,6 +17,7 @@
%include "example.h"
/* An output method that turns a complex into a short string */
%feature("python:slot", "tp_str", functype="reprfunc") Complex::__str__; // For -builtin option to use __str__ in the tp_str slot
%extend Complex {
char *__str__() {
static char temp[512];

View file

@ -693,37 +693,39 @@ public:
mod_docstring = NULL;
}
/* Import the C-extension module. This should be a relative import,
* since the shadow module may also have been imported by a relative
* import, and there is thus no guarantee that the C-extension is on
* sys.path. Relative imports must be explicitly specified from 2.6.0
* onwards (implicit relative imports raised a DeprecationWarning in 2.6,
* and fail in 2.7 onwards).
*
* First determine the shadow wrappers package based on the __name__ it
* was given by the importer that loaded it. Then construct a name for
* the module based on the package name and the module name (we know the
* module name). Use importlib to try and load it. If an attempt to
* load the module with importlib fails with an ImportError then fallback
* and try and load just the module name from the global namespace.
*/
Printv(default_import_code, "def swig_import_helper():\n", NULL);
Printv(default_import_code, tab4, "import importlib\n", NULL);
Printv(default_import_code, tab4, "pkg = __package__ if __package__ else __name__.rpartition('.')[0]\n", NULL);
Printf(default_import_code, tab4 "mname = '.'.join((pkg, '%s')).lstrip('.')\n", module);
Printv(default_import_code, tab4, "try:\n", NULL);
Printv(default_import_code, tab8, "return importlib.import_module(mname)\n", NULL);
Printv(default_import_code, tab4, "except ImportError:\n", NULL);
Printf(default_import_code, tab8 "return importlib.import_module('%s')\n", module);
Printf(default_import_code, "%s = swig_import_helper()\n", module);
Printv(default_import_code, "del swig_import_helper\n", NULL);
if (builtin) {
if (!builtin) {
/* Import the C-extension module. This should be a relative import,
* since the shadow module may also have been imported by a relative
* import, and there is thus no guarantee that the C-extension is on
* sys.path. Relative imports must be explicitly specified from 2.6.0
* onwards (implicit relative imports raised a DeprecationWarning in 2.6,
* and fail in 2.7 onwards).
*
* First check for __package__ which is available from 2.6 onwards, see PEP366.
* Next determine the shadow wrappers package based on the __name__ it
* was given by the importer that loaded it. Then construct a name for
* the module based on the package name and the module name (we know the
* module name). Use importlib to try and load it. If an attempt to
* load the module with importlib fails with an ImportError then fallback
* and try and load just the module name from the global namespace.
*/
Printv(default_import_code, "def swig_import_helper():\n", NULL);
Printv(default_import_code, tab4, "import importlib\n", NULL);
Printv(default_import_code, tab4, "pkg = __package__ if __package__ else __name__.rpartition('.')[0]\n", NULL);
Printf(default_import_code, tab4 "mname = '.'.join((pkg, '%s')).lstrip('.')\n", module);
Printv(default_import_code, tab4, "try:\n", NULL);
Printv(default_import_code, tab8, "return importlib.import_module(mname)\n", NULL);
Printv(default_import_code, tab4, "except ImportError:\n", NULL);
Printf(default_import_code, tab8 "return importlib.import_module('%s')\n", module);
Printf(default_import_code, "%s = swig_import_helper()\n", module);
Printv(default_import_code, "del swig_import_helper\n", NULL);
} else {
/*
* Pull in all the attributes from the C module.
*
* An alternative approach to doing this if/else chain was
* proposed by Michael Thon. Someone braver than I may try it out.
* proposed by Michael Thon at https://github.com/swig/swig/issues/691.
* Someone braver than I may try it out.
* I fear some current swig user may depend on some side effect
* of from _foo import *
*
@ -2599,6 +2601,7 @@ public:
builtin_self = false;
else
builtin_ctor = true;
Delete(mrename);
}
bool director_class = (getCurrentClass() && Swig_directorclass(getCurrentClass()));
bool add_self = builtin_self && (!builtin_ctor || director_class);
@ -4737,11 +4740,12 @@ public:
Delete(cname);
}
String *subfunc = Swig_name_construct(NSPACE_TODO, symname);
if (!have_constructor && handled_as_init) {
if (!builtin) {
if (Getattr(n, "feature:shadow")) {
String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), tab4, Getfile(n), Getline(n), "%feature(\"shadow\")");
String *pyaction = NewStringf("%s.%s", module, Swig_name_construct(NSPACE_TODO, symname));
String *pyaction = NewStringf("%s.%s", module, subfunc);
Replaceall(pycode, "$action", pyaction);
Delete(pyaction);
Printv(f_shadow, pycode, "\n", NIL);
@ -4771,7 +4775,7 @@ public:
if (have_pythonprepend(n))
Printv(f_shadow, indent_pythoncode(pythonprepend(n), tab8, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
Printv(f_shadow, pass_self, NIL);
Printv(f_shadow, tab8, module, ".", class_name, "_swiginit(self, ", funcCall(Swig_name_construct(NSPACE_TODO, symname), callParms), ")\n", NIL);
Printv(f_shadow, tab8, module, ".", class_name, "_swiginit(self, ", funcCall(subfunc, callParms), ")\n", NIL);
if (have_pythonappend(n))
Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n\n", NIL);
Delete(pass_self);
@ -4781,39 +4785,36 @@ public:
} else {
/* Hmmm. We seem to be creating a different constructor. We're just going to create a
function for it. */
if (Getattr(n, "feature:shadow")) {
String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), "", Getfile(n), Getline(n), "%feature(\"shadow\")");
String *pyaction = NewStringf("%s.%s", module, Swig_name_construct(NSPACE_TODO, symname));
Replaceall(pycode, "$action", pyaction);
Delete(pyaction);
Printv(f_shadow_stubs, pycode, "\n", NIL);
Delete(pycode);
} else {
String *parms = make_pyParmList(n, false, false, allow_kwargs);
String *callParms = make_pyParmList(n, false, true, allow_kwargs);
if (!builtin) {
if (Getattr(n, "feature:shadow")) {
String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), "", Getfile(n), Getline(n), "%feature(\"shadow\")");
String *pyaction = NewStringf("%s.%s", module, subfunc);
Replaceall(pycode, "$action", pyaction);
Delete(pyaction);
Printv(f_shadow_stubs, pycode, "\n", NIL);
Delete(pycode);
} else {
String *parms = make_pyParmList(n, false, false, allow_kwargs);
String *callParms = make_pyParmList(n, false, true, allow_kwargs);
Printv(f_shadow_stubs, "\ndef ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
if (have_docstring(n))
Printv(f_shadow_stubs, tab4, docstring(n, AUTODOC_CTOR, tab4), "\n", NIL);
if (have_pythonprepend(n))
Printv(f_shadow_stubs, indent_pythoncode(pythonprepend(n), tab4, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
String *subfunc = NULL;
/*
if (builtin)
subfunc = Copy(Getattr(getCurrentClass(), "sym:name"));
else
*/
subfunc = Swig_name_construct(NSPACE_TODO, symname);
Printv(f_shadow_stubs, tab4, "val = ", funcCall(subfunc, callParms), "\n", NIL);
Printv(f_shadow_stubs, "\ndef ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
if (have_docstring(n))
Printv(f_shadow_stubs, tab4, docstring(n, AUTODOC_CTOR, tab4), "\n", NIL);
if (have_pythonprepend(n))
Printv(f_shadow_stubs, indent_pythoncode(pythonprepend(n), tab4, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
Printv(f_shadow_stubs, tab4, "val = ", funcCall(subfunc, callParms), "\n", NIL);
#ifdef USE_THISOWN
Printv(f_shadow_stubs, tab4, "val.thisown = 1\n", NIL);
Printv(f_shadow_stubs, tab4, "val.thisown = 1\n", NIL);
#endif
if (have_pythonappend(n))
Printv(f_shadow_stubs, indent_pythoncode(pythonappend(n), tab4, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL);
Printv(f_shadow_stubs, tab4, "return val\n", NIL);
Delete(subfunc);
if (have_pythonappend(n))
Printv(f_shadow_stubs, indent_pythoncode(pythonappend(n), tab4, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL);
Printv(f_shadow_stubs, tab4, "return val\n", NIL);
}
} else {
Printf(f_shadow_stubs, "%s = %s\n", symname, subfunc);
}
}
Delete(subfunc);
}
}
return SWIG_OK;