diff --git a/CHANGES.current b/CHANGES.current index c484ef6c0..c4cc251e6 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -61,6 +61,12 @@ Version 4.0.0 (in progress) Previously any SWIG generated modules in a package would fail with an ImportError when using 'python -m' for example 'python -m mypkg.mymodule'. + This fix also allows the SWIG generated module to be placed into a directory and + then renamed __init__.py to convert the module into a package again. This ability + stopped working in swig-3.0.9. However, only Python 2.7 or 3.3 and later work. If + Python 3.2 support is needed, use moduleimport in %module to customise the import + code. + 2018-11-13: wsfulton #1340 Remove -cppcast and -nocppcast command line options (this was an option available to the scripting language targets). diff --git a/Examples/python/import_packages/Makefile b/Examples/python/import_packages/Makefile index 2857866d4..c7f9a830b 100644 --- a/Examples/python/import_packages/Makefile +++ b/Examples/python/import_packages/Makefile @@ -8,6 +8,7 @@ import_packages_subdirs = \ from_init1 \ from_init2 \ from_init3 \ + module_is_init \ relativeimport1 \ relativeimport2 \ relativeimport3 \ diff --git a/Examples/python/import_packages/module_is_init/Makefile b/Examples/python/import_packages/module_is_init/Makefile new file mode 100644 index 000000000..43763aa4b --- /dev/null +++ b/Examples/python/import_packages/module_is_init/Makefile @@ -0,0 +1,15 @@ +TOP = ../../.. +LIBS = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' python_run + +build: + cd pkg1 && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' build + +static: + cd pkg1 && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' static + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' python_clean + cd pkg1 && $(MAKE) clean diff --git a/Examples/python/import_packages/module_is_init/README b/Examples/python/import_packages/module_is_init/README new file mode 100644 index 000000000..ee7391cda --- /dev/null +++ b/Examples/python/import_packages/module_is_init/README @@ -0,0 +1,18 @@ +This example tests renaming the generated SWIG pure Python module to __init__.py +to turn the module into a Python package. + +Use 'python runme.py' to run the test. + +Overview: +--------- + +SWIG generates a pure Python module foo.py from the input interface file foo.i. +The foo.py file is generated within the pkg1 directory and is then renamed __init__.py. +This results in everything in the SWIG generated module being available in the Python +pkg1 package. + +This approach of turning the SWIG generated module into a package worked in versions +of SWIG up to swig-3.0.8, but stopped working from swig-3.0.9 until it was +re-instated in swig-4.0.0. However, Python 2.7 or 3.3 and later are needed to +work out of the box. Python 3.2 does not work as this version of Python does +not set __package__ in __init__.py. diff --git a/Examples/python/import_packages/module_is_init/pkg1/Makefile b/Examples/python/import_packages/module_is_init/pkg1/Makefile new file mode 100644 index 000000000..d9d83ed0a --- /dev/null +++ b/Examples/python/import_packages/module_is_init/pkg1/Makefile @@ -0,0 +1,20 @@ +TOP = ../../../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +SWIGOPT = +LIBS = + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' TARGET='foo' INTERFACE='foo.i' python_cpp + mv foo.py __init__.py + +static: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' TARGET='foo' INTERFACE='foo.i' python_cpp_static + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='foo' python_clean + rm -f __init__.py diff --git a/Examples/python/import_packages/module_is_init/pkg1/foo.hpp b/Examples/python/import_packages/module_is_init/pkg1/foo.hpp new file mode 100644 index 000000000..01c462266 --- /dev/null +++ b/Examples/python/import_packages/module_is_init/pkg1/foo.hpp @@ -0,0 +1,10 @@ + +int foofunction(int i) { + return i *= 10; +} + +struct FooClass { + int foomethod(int i) { + return i += 5; + } +}; diff --git a/Examples/python/import_packages/module_is_init/pkg1/foo.i b/Examples/python/import_packages/module_is_init/pkg1/foo.i new file mode 100644 index 000000000..f8d71380c --- /dev/null +++ b/Examples/python/import_packages/module_is_init/pkg1/foo.i @@ -0,0 +1,5 @@ +%module foo +%{ +#include "./foo.hpp" +%} +%include "./foo.hpp" diff --git a/Examples/python/import_packages/module_is_init/runme.py b/Examples/python/import_packages/module_is_init/runme.py new file mode 100644 index 000000000..b5e646e85 --- /dev/null +++ b/Examples/python/import_packages/module_is_init/runme.py @@ -0,0 +1,26 @@ +import os.path +import sys + +# Test import of a SWIG generated module renamed as the package's __init__.py +testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) +print "Testing " + testname + " - module renamed as __init__.py" + +if sys.version_info >= (3, 0, 0) and sys.version_info < (3, 3, 0): + print " Not importing as Python version is >= 3.0 and < 3.3" + # Package detection does not work in these versions. + # Can be fixed by using this in the interface file: + # %module(moduleimport="from . import $module") foo # without -builtin + # %module(moduleimport="from .$module import *") foo # with -builtin + sys.exit(0) + +import pkg1 +print " Finished importing pkg1" + +if pkg1.foofunction(123) != 1230: + raise RuntimeError("foofunction failed") + +fc = pkg1.FooClass() +if fc.foomethod(1) != 6: + raise RuntimeError("foomethod failed") + +print " Finished testing pkg1"