The Python module import logic has changed to stop obfuscating real ImportError problems.

Only one import of the low-level C/C++ module from the pure Python module is
attempted now. Previously a second import of the low-level C/C++ module was attempted
after an ImportError occurred and was done to support 'split modules'. A 'split module' is
a configuration where the pure Python module is a module within a Python package and the
low-level C/C++ module is a global Python module. Now a 'split module' configuration is
no longer supported by default. This configuration can be supported with a simple
customization, such as:

  %module(package="mypackage", moduleimport="import $module") foo

or if using -builtin:

  %module(package="mypackage", moduleimport="from $module import *") foo

instead of

  %module(package="mypackage") foo

See the updated Python chapter titled "Location of modules" in the documentation.

Closes #848 #1343
This commit is contained in:
William S Fulton 2018-12-16 16:34:04 +00:00
commit 03323f5c8b
6 changed files with 275 additions and 126 deletions

View file

@ -697,35 +697,16 @@ public:
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, tab4, "mname = '.'.join((pkg, '", module, "')).lstrip('.')\n", NULL);
Printv(default_import_code, tab4, "return importlib.import_module(mname)\n", NULL);
Printv(default_import_code, module, " = swig_import_helper()\n", NULL);
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 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 *
*
* for attr in _foo.__all__:
* globals()[attr] = getattr(_foo, attr)
*
*/
Printf(default_import_code, "\n# Pull in all the attributes from %s\n", module);
Printv(default_import_code, "# Pull in all the attributes from the low-level C/C++ module\n", NULL);
Printv(default_import_code, "if __package__ or __name__.rpartition('.')[0]:\n", NULL);
Printv(default_import_code, tab4, "try:\n", NULL);
Printf(default_import_code, tab4 tab4 "from .%s import *\n", module);
Printv(default_import_code, tab4 "except ImportError:\n", NULL);
Printf(default_import_code, tab4 tab4 "from %s import *\n", module);
Printv(default_import_code, tab4, "from .", module, " import *\n", NULL);
Printv(default_import_code, "else:\n", NULL);
Printf(default_import_code, tab4 "from %s import *\n", module);
Printv(default_import_code, tab4, "from ", module, " import *\n", NULL);
}
/* Need builtins to qualify names like Exception that might also be