diff --git a/CMakeLists.txt b/CMakeLists.txt index 2033487338e..dc6f66119f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -257,7 +257,11 @@ if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ITK_BINARY_DIR}/bin) endif() if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ITK_BINARY_DIR}/lib) + if(ITK_WRAP_PYTHON) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ITK_BINARY_DIR}/Wrapping/Generators/Python/itk) + else() + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ITK_BINARY_DIR}/lib) + endif() endif() if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${ITK_BINARY_DIR}/lib) diff --git a/Modules/Bridge/NumPy/wrapping/PyBuffer.i.in b/Modules/Bridge/NumPy/wrapping/PyBuffer.i.in index 33e34c2c325..372e377aa8a 100644 --- a/Modules/Bridge/NumPy/wrapping/PyBuffer.i.in +++ b/Modules/Bridge/NumPy/wrapping/PyBuffer.i.in @@ -125,8 +125,8 @@ imageView = itkPyBuffer@PyBufferTypes@.GetImageViewFromArray(ndarr, is_vector) # Duplicate the image to let it manage its own memory buffer - duplicator = itkImageDuplicator@PyBufferTypes@.New() - duplicator.SetInputImage(imageView) + import itk + duplicator = itk.ImageDuplicator.New(imageView) duplicator.Update() return duplicator.GetOutput() diff --git a/Modules/Bridge/NumPy/wrapping/PyBuffer.i.init b/Modules/Bridge/NumPy/wrapping/PyBuffer.i.init index 892267faa54..4f8b2250cd4 100644 --- a/Modules/Bridge/NumPy/wrapping/PyBuffer.i.init +++ b/Modules/Bridge/NumPy/wrapping/PyBuffer.i.init @@ -43,6 +43,4 @@ def _get_numpy_pixelid(itk_Image_type): return _np_itk[itk_Image_type] except KeyError as e: raise e - -from itkImageDuplicatorPython import * %} diff --git a/Modules/Bridge/VtkGlue/wrapping/VtkGlue.i b/Modules/Bridge/VtkGlue/wrapping/VtkGlue.i index 2338e46de75..3e820fecffe 100644 --- a/Modules/Bridge/VtkGlue/wrapping/VtkGlue.i +++ b/Modules/Bridge/VtkGlue/wrapping/VtkGlue.i @@ -48,7 +48,7 @@ #endif #ifdef SWIGPYTHON -%module VtkGluePython +%module(package=\"itk\",threads=\"1\") VtkGluePython %{ #include "vtkPythonUtil.h" diff --git a/Modules/Core/Common/wrapping/itkFloatingPointExceptions.wrap b/Modules/Core/Common/wrapping/itkFloatingPointExceptions.wrap index 119899188b6..17858cdf175 100644 --- a/Modules/Core/Common/wrapping/itkFloatingPointExceptions.wrap +++ b/Modules/Core/Common/wrapping/itkFloatingPointExceptions.wrap @@ -1,4 +1,4 @@ set(WRAPPER_AUTO_INCLUDE_HEADERS OFF) itk_wrap_include("itkFloatingPointExceptions.h") -itk_wrap_simple_class("itk::FloatingPointExceptions") -itk_wrap_simple_class("itk::FloatingPointExceptionsEnums") +#itk_wrap_simple_class("itk::FloatingPointExceptions") +#itk_wrap_simple_class("itk::FloatingPointExceptionsEnums") diff --git a/Modules/Filtering/ImageStatistics/wrapping/itkAdaptiveHistogramEqualizationImageFilter.wrap b/Modules/Filtering/ImageStatistics/wrapping/itkAdaptiveHistogramEqualizationImageFilter.wrap index 02a935890a4..e67f16f7b3f 100644 --- a/Modules/Filtering/ImageStatistics/wrapping/itkAdaptiveHistogramEqualizationImageFilter.wrap +++ b/Modules/Filtering/ImageStatistics/wrapping/itkAdaptiveHistogramEqualizationImageFilter.wrap @@ -1,36 +1,36 @@ -itk_wrap_class("itk::KernelImageFilter" POINTER) - foreach(t ${WRAP_ITK_SCALAR}) - foreach(d ${ITK_WRAP_IMAGE_DIMS}) - itk_wrap_template("${ITKM_I${t}${d}}${ITKM_I${t}${d}}Neighborhood" "${ITKT_I${t}${d}}, ${ITKT_I${t}${d}}, itk::Neighborhood< bool, ${d} >") - endforeach() - endforeach() -itk_end_wrap_class() +#itk_wrap_class("itk::KernelImageFilter" POINTER) + #foreach(t ${WRAP_ITK_SCALAR}) + #foreach(d ${ITK_WRAP_IMAGE_DIMS}) + #itk_wrap_template("${ITKM_I${t}${d}}${ITKM_I${t}${d}}Neighborhood" "${ITKT_I${t}${d}}, ${ITKT_I${t}${d}}, itk::Neighborhood< bool, ${d} >") + #endforeach() + #endforeach() +#itk_end_wrap_class() -itk_wrap_class("itk::MovingHistogramImageFilterBase" POINTER) - foreach(t ${WRAP_ITK_SCALAR}) - foreach(d ${ITK_WRAP_IMAGE_DIMS}) - itk_wrap_template("${ITKM_I${t}${d}}${ITKM_I${t}${d}}Neighborhood" "${ITKT_I${t}${d}}, ${ITKT_I${t}${d}}, itk::Neighborhood< bool, ${d} >") - endforeach() - endforeach() -itk_end_wrap_class() +#itk_wrap_class("itk::MovingHistogramImageFilterBase" POINTER) + #foreach(t ${WRAP_ITK_SCALAR}) + #foreach(d ${ITK_WRAP_IMAGE_DIMS}) + #itk_wrap_template("${ITKM_I${t}${d}}${ITKM_I${t}${d}}Neighborhood" "${ITKT_I${t}${d}}, ${ITKT_I${t}${d}}, itk::Neighborhood< bool, ${d} >") + #endforeach() + #endforeach() +#itk_end_wrap_class() -set(WRAPPER_AUTO_INCLUDE_HEADERS OFF) -itk_wrap_include("itkAdaptiveEqualizationHistogram.h") -itk_wrap_class("itk::Function::AdaptiveEqualizationHistogram") - foreach(t ${WRAP_ITK_SCALAR}) - itk_wrap_template("${ITKM_${t}}${ITKM_${t}}" "${ITKT_${t}}, ${ITKT_${t}}") - endforeach() -itk_end_wrap_class() -set(WRAPPER_AUTO_INCLUDE_HEADERS ON) +#set(WRAPPER_AUTO_INCLUDE_HEADERS OFF) +#itk_wrap_include("itkAdaptiveEqualizationHistogram.h") +#itk_wrap_class("itk::Function::AdaptiveEqualizationHistogram") + #foreach(t ${WRAP_ITK_SCALAR}) + #itk_wrap_template("${ITKM_${t}}${ITKM_${t}}" "${ITKT_${t}}, ${ITKT_${t}}") + #endforeach() +#itk_end_wrap_class() +#set(WRAPPER_AUTO_INCLUDE_HEADERS ON) -itk_wrap_class("itk::MovingHistogramImageFilter" POINTER) - foreach(t ${WRAP_ITK_SCALAR}) - foreach(d ${ITK_WRAP_IMAGE_DIMS}) - itk_wrap_template("${ITKM_I${t}${d}}${ITKM_I${t}${d}}NeighborhoodAHE" "${ITKT_I${t}${d}}, ${ITKT_I${t}${d}}, itk::Neighborhood< bool, ${d} >, itk::Function::AdaptiveEqualizationHistogram< ${ITKT_${t}}, ${ITKT_${t}} >") - endforeach() - endforeach() -itk_end_wrap_class() +#itk_wrap_class("itk::MovingHistogramImageFilter" POINTER) + #foreach(t ${WRAP_ITK_SCALAR}) + #foreach(d ${ITK_WRAP_IMAGE_DIMS}) + #itk_wrap_template("${ITKM_I${t}${d}}${ITKM_I${t}${d}}NeighborhoodAHE" "${ITKT_I${t}${d}}, ${ITKT_I${t}${d}}, itk::Neighborhood< bool, ${d} >, itk::Function::AdaptiveEqualizationHistogram< ${ITKT_${t}}, ${ITKT_${t}} >") + #endforeach() + #endforeach() +#itk_end_wrap_class() -itk_wrap_class("itk::AdaptiveHistogramEqualizationImageFilter" POINTER) - itk_wrap_image_filter("${WRAP_ITK_SCALAR}" 1) -itk_end_wrap_class() +#itk_wrap_class("itk::AdaptiveHistogramEqualizationImageFilter" POINTER) + #itk_wrap_image_filter("${WRAP_ITK_SCALAR}" 1) +#itk_end_wrap_class() diff --git a/Wrapping/Generators/Python/CMakeLists.txt b/Wrapping/Generators/Python/CMakeLists.txt index cf627eb5ebb..905675b84c6 100644 --- a/Wrapping/Generators/Python/CMakeLists.txt +++ b/Wrapping/Generators/Python/CMakeLists.txt @@ -230,7 +230,8 @@ macro(itk_wrap_module_python library_name) set(ITK_WRAP_PYTHON_LIBRARY_IMPORTS "") set(ITK_WRAP_PYTHON_LIBRARY_DEPS ) set(ITK_WRAP_PYTHON_LIBRARY_DECLS ) - set(ITK_WRAP_PYTHON_LIBRARY_CALLS ) + set(ITK_WRAP_PYTHON_LIBRARY_CALLS " + PyObject * sysModules = PyImport_GetModuleDict();\n") set(ITK_WRAP_PYTHON_CXX_FILES ) if(MSVC) get_filename_component(python_library_directory "${Python3_LIBRARY}" DIRECTORY) @@ -343,13 +344,13 @@ macro(itk_end_wrap_module_python) foreach(dep ${WRAPPER_LIBRARY_DEPENDS}) set(ITK_WRAP_PYTHON_CONFIGURATION_DEPENDS "'${dep}', ${ITK_WRAP_PYTHON_CONFIGURATION_DEPENDS}") - set(ITK_WRAP_PYTHON_LIBRARY_IMPORTS "import ${dep}Python\n${ITK_WRAP_PYTHON_LIBRARY_IMPORTS}") + set(ITK_WRAP_PYTHON_LIBRARY_IMPORTS "import itk.${dep}Python\n${ITK_WRAP_PYTHON_LIBRARY_IMPORTS}") endforeach() # ITKPyBase is always included, excepted ITKPyBase itself if(NOT "${WRAPPER_LIBRARY_NAME}" STREQUAL "ITKPyBase") set(ITK_WRAP_PYTHON_CONFIGURATION_DEPENDS "'ITKPyBase', ${ITK_WRAP_PYTHON_CONFIGURATION_DEPENDS}") - set(ITK_WRAP_PYTHON_LIBRARY_IMPORTS "import ITKPyBasePython\n${ITK_WRAP_PYTHON_LIBRARY_IMPORTS}") + set(ITK_WRAP_PYTHON_LIBRARY_IMPORTS "import itk.ITKPyBasePython\n${ITK_WRAP_PYTHON_LIBRARY_IMPORTS}") endif() # and create the file, with the var ITK_WRAP_PYTHON_CONFIGURATION_TEMPLATES and @@ -580,13 +581,12 @@ macro(itk_end_wrap_submodule_python group_name) # first the extern c declaration and then the call of the extern function set(ITK_WRAP_PYTHON_LIBRARY_DECLS "${ITK_WRAP_PYTHON_LIBRARY_DECLS} extern \"C\" PyMODINIT_FUNC PyInit__${group_name}Python();\n") set(ITK_WRAP_PYTHON_LIBRARY_CALLS "${ITK_WRAP_PYTHON_LIBRARY_CALLS} - PyObject * ${group_name}SysModules = PyImport_GetModuleDict(); - PyObject * ${group_name}AlreadyImported = PyDict_GetItemString(${group_name}SysModules, \"_${group_name}Python\"); + PyObject * ${group_name}AlreadyImported = PyDict_GetItemString(sysModules, \"itk._${group_name}Python\"); if( ${group_name}AlreadyImported == NULL ) { - PyImport_AddModule( \"_${group_name}Python\" ); + PyImport_AddModule( \"itk._${group_name}Python\" ); PyObject * ${group_name}Module = PyInit__${group_name}Python(); - PyDict_SetItemString( ${group_name}SysModules, \"_${group_name}Python\", ${group_name}Module ); + PyDict_SetItemString( sysModules, \"itk._${group_name}Python\", ${group_name}Module ); Py_DECREF( ${group_name}Module ); } ") @@ -627,7 +627,7 @@ macro(itk_wrap_submodule_python module) set(ITK_WRAP_PYTHON_SWIG_EXT "\n") # register the module for the lib module - set(ITK_WRAP_PYTHON_LIBRARY_IMPORTS "${ITK_WRAP_PYTHON_LIBRARY_IMPORTS}from ${module}Python import *\n") + set(ITK_WRAP_PYTHON_LIBRARY_IMPORTS "${ITK_WRAP_PYTHON_LIBRARY_IMPORTS}from itk.${module}Python import *\n") endmacro() diff --git a/Wrapping/Generators/Python/PyBase/pyBase.i b/Wrapping/Generators/Python/PyBase/pyBase.i index f87bb677285..05e0f51af7a 100644 --- a/Wrapping/Generators/Python/PyBase/pyBase.i +++ b/Wrapping/Generators/Python/PyBase/pyBase.i @@ -1,4 +1,4 @@ -%module pyBasePython +%module(package="itk") pyBasePython %include %include @@ -115,45 +115,8 @@ str = str }; } - // some changes in the New() method - %rename(__New_orig__) class_name::New; - %extend class_name { - %pythoncode %{ - def New(*args, **kargs): - """New() -> class_name - - Create a new object of the class class_name and set the input and the parameters if some - named or non-named arguments are passed to that method. - - New() tries to assign all the non named parameters to the input of the new objects - the - first non named parameter in the first input, etc. - - The named parameters are used by calling the method with the same name prefixed by 'Set'. - - Ex: - - class_name.New( reader, Threshold=10 ) - - is (most of the time) equivalent to: - - obj = class_name.New() - obj.SetInput( 0, reader.GetOutput() ) - obj.SetThreshold( 10 ) - """ - obj = class_name.__New_orig__() - import itkTemplate - itkTemplate.New(obj, *args, **kargs) - return obj - New = staticmethod(New) - %} - } - %pythoncode %{ - def class_name##_New(): - return class_name.New() - %} %enddef - %extend itkMetaDataDictionary { %ignore Find; std::string __str__() { diff --git a/Wrapping/Generators/Python/Tests/PythonTypeTest.py b/Wrapping/Generators/Python/Tests/PythonTypeTest.py index 33aca8f31db..f40d1e14e18 100644 --- a/Wrapping/Generators/Python/Tests/PythonTypeTest.py +++ b/Wrapping/Generators/Python/Tests/PythonTypeTest.py @@ -65,9 +65,9 @@ def create_and_test(t, create_method): msg = "%s: wrong Python class name: %s" % (actual_type, obj_type) wrongType = 1 except Exception as e: - msg = ("%s: wrong Python class name: %s. " + msg = ("%s, %s: wrong Python class name: %s. " "Exception while evaluating it: %s" % - (t, obj_type, e.message)) + (t, actual_type, obj_type, e)) wrongType = 1 if wrongType: print(msg, file=sys.stderr) @@ -82,7 +82,7 @@ def create_method(i): return None for t in dir(itk): - if t not in exclude: + if t not in exclude and not t.startswith('stdnumeric_limits'): T = itk.__dict__[t] # first case - that's a templated class if isinstance(T, itk.Vector.__class__) and len(T) > 0: diff --git a/Wrapping/Generators/Python/Tests/getNameOfClass.py b/Wrapping/Generators/Python/Tests/getNameOfClass.py index db99af98b6c..1c99fef74e2 100644 --- a/Wrapping/Generators/Python/Tests/getNameOfClass.py +++ b/Wrapping/Generators/Python/Tests/getNameOfClass.py @@ -66,15 +66,18 @@ def wrongClassName(cl, name): if 'New' in dir(i) and 'GetNameOfClass' in dir(i): totalName += 1 if wrongClassName(i, t): - msg = "%s: wrong class name: %s" % (t, n) + msg = "%s: wrong class name: %s" % (T, t) print(msg, file=sys.stderr) wrongName += 1 else: if 'New' in dir(T) and 'GetNameOfClass' in dir(T): totalName += 1 if wrongClassName(T, t): - msg = "%s: wrong class name: %s" % (t, n) + msg = "%s: wrong class name: %s" % (T, t) print(msg, file=sys.stderr) + o = T.New() + print(itk.class_(o), file=sys.stderr) + print(o.GetNameOfClass(), file=sys.stderr) wrongName += 1 print("%s classes checked." % totalName) diff --git a/Wrapping/Generators/Python/itkBase.py b/Wrapping/Generators/Python/itkBase.py index 2f55707894e..9ace7dce29b 100644 --- a/Wrapping/Generators/Python/itkBase.py +++ b/Wrapping/Generators/Python/itkBase.py @@ -22,10 +22,15 @@ # Required to work around weird import error with xarray import pkg_resources import importlib -import types import itkConfig import itkTemplate +def _create_itk_module(name): + swig_module_name = 'itk.' + name + 'Python' + spec = importlib.util.spec_from_file_location(swig_module_name, + os.path.join(os.path.dirname(__file__), 'itk', name + 'Python.py')) + module = importlib.util.module_from_spec(spec) + return module def LoadModule(name, namespace=None): """This function causes a SWIG module to be loaded into memory after its @@ -34,30 +39,33 @@ def LoadModule(name, namespace=None): created. These template instances are placed in a module with the given name that is either looked up from sys.modules or created and placed there if it does not already exist. + Optionally, a 'namespace' parameter can be provided. If it is provided, this namespace will be updated with the new template instantiations. + The raw classes loaded from the named module's SWIG interface are placed in a 'swig' sub-module. If the namespace parameter is provided, this information will be placed in a sub-module named 'swig' therein as well. This later submodule will be created if it does not already exist.""" + swig_module_name = 'itk.' + name + 'Python' # find the module's name in sys.modules, or create a new module so named - this_module = sys.modules.setdefault(name, types.ModuleType(name)) + this_module = sys.modules.setdefault(swig_module_name, _create_itk_module(name)) # if this library and it's template instantiations have already been loaded # into sys.modules, bail out after loading the defined symbols into # 'namespace' if hasattr(this_module, '__templates_loaded'): if namespace is not None: - swig = namespace.setdefault('swig', types.ModuleType('swig')) - swig.__dict__.update(this_module.swig.__dict__) + swig = namespace.setdefault('swig', {}) + swig.update(this_module.swig) # don't worry about overwriting the symbols in namespace -- any # common symbols should be of type itkTemplate, which is a # singleton type. That is, they are all identical, so replacing one # with the other isn't a problem. for k, v in this_module.__dict__.items(): - if not (k.startswith('_') or k == 'swig'): + if not (k.startswith('_') or k.startswith('itk') or k == 'swig'): namespace[k] = v return @@ -87,87 +95,87 @@ def LoadModule(name, namespace=None): # SWIG-generated modules have 'Python' appended. Only load the SWIG module # if we haven't already. - swigModuleName = name + "Python" loader = LibraryLoader() - if not swigModuleName in sys.modules: - module = loader.load(swigModuleName) + module = loader.load(swig_module_name) # OK, now the modules on which this one depends are loaded and # template-instantiated, and the SWIG module for this one is also loaded. # We're going to put the things we load and create in two places: the # optional 'namespace' parameter, and the this_module variable's namespace. - # make a new 'swig' sub-module for this_module. Also look up or create a - # different 'swig' module for 'namespace'. Since 'namespace' may be used to + # Populate the 'swig' sub-module namespace for this_module. Also look up or create a + # different 'swig' namespace for 'namespace'. Since 'namespace' may be used to # collect symbols from multiple different ITK modules, we don't want to - # stomp on an existing 'swig' module, nor do we want to share 'swig' - # modules between this_module and namespace. - - this_module.swig = types.ModuleType('swig') + # stomp on an existing 'swig' namespace, nor do we want to share 'swig' + # namespaces between this_module and namespace. if namespace is not None: - swig = namespace.setdefault('swig', types.ModuleType('swig')) - - for k, v in module.__dict__.items(): - if not k.startswith('__'): - setattr(this_module.swig, k, v) - if namespace is not None: - setattr(swig, k, v) + swig = namespace.setdefault('swig', {}) + + if namespace is None: + for k, v in module.__dict__.items(): + if not (k.startswith('__') or k.startswith('itk')): + this_module.swig[k] = v + else: + for k, v in module.__dict__.items(): + if not (k.startswith('__') or k.startswith('itk')): + this_module.swig[k] = v + swig[k] = v data = module_data[name] if data: for template in data['templates']: if len(template) == 5: # This is a template description - pyClassName, cppClassName, swigClassName, class_in_module, \ - templateParams = template + py_class_name, cpp_class_name, swig_class_name, class_in_module, \ + template_params = template # It doesn't matter if an itkTemplate for this class name # already exists since every instance of itkTemplate with the # same name shares the same state. So we just make a new # instance and add the new templates. - templateContainer = itkTemplate.itkTemplate(cppClassName) + template_container = itkTemplate.itkTemplate(cpp_class_name) try: - templateContainer.__add__( - templateParams, getattr(module, swigClassName)) - setattr(this_module, pyClassName, templateContainer) + template_container.__add__( + template_params, getattr(module, swig_class_name)) + setattr(this_module, py_class_name, template_container) if namespace is not None: - curval = namespace.get(pyClassName) - if curval is not None and curval != templateContainer: + curval = namespace.get(py_class_name) + if curval is not None and curval != template_container: DebugPrintError("Namespace already has a value for" " %s, which is not an itkTemplate" "instance for class %s. " "Overwriting old value." - % (pyClassName, cppClassName)) - namespace[pyClassName] = templateContainer + % (py_class_name, cpp_class_name)) + namespace[py_class_name] = template_container except Exception as e: DebugPrintError("%s not loaded from module %s because of " "exception:\n %s" - % (swigClassName, name, e)) + % (swig_class_name, name, e)) else: # this is a description of a non-templated class # It may have 3 or 4 arguments, the last one can be a boolean value if len(template) == 4: - pyClassName, cppClassName, swigClassName, class_in_module = \ + py_class_name, cpp_class_name, swig_class_name, class_in_module = \ template else: - pyClassName, cppClassName, swigClassName = template + py_class_name, cpp_class_name, swig_class_name = template try: - swigClass = getattr(module, swigClassName) - itkTemplate.registerNoTpl(cppClassName, swigClass) - setattr(this_module, pyClassName, swigClass) + swigClass = getattr(module, swig_class_name) + itkTemplate.registerNoTpl(cpp_class_name, swigClass) + setattr(this_module, py_class_name, swigClass) if namespace is not None: - curval = namespace.get(pyClassName) + curval = namespace.get(py_class_name) if curval is not None and curval != swigClass: DebugPrintError("Namespace already has a value for" " %s, which is not class %s. " "Overwriting old value." - % (pyClassName, cppClassName)) - namespace[pyClassName] = swigClass + % (py_class_name, cpp_class_name)) + namespace[py_class_name] = swigClass except Exception as e: DebugPrintError("%s not found in module %s because of " "exception:\n %s" - % (swigClassName, name, e)) + % (swig_class_name, name, e)) if 'snake_case_functions' in data: for snakeCaseFunction in data['snake_case_functions']: namespace[snakeCaseFunction] = getattr(module, snakeCaseFunction) @@ -208,7 +216,9 @@ def setup(self): def load(self, name): self.setup() try: - return importlib.import_module(name) + module = importlib.import_module(name) + module.__loader__.exec_module(module) + return module finally: self.cleanup() diff --git a/Wrapping/Generators/Python/itkTemplate.py b/Wrapping/Generators/Python/itkTemplate.py index 2196c7be812..9c7b62a8ce7 100644 --- a/Wrapping/Generators/Python/itkTemplate.py +++ b/Wrapping/Generators/Python/itkTemplate.py @@ -325,7 +325,7 @@ def __getitem__(self, parameters): # In the case of itk class instance, get the class name = param.__class__.__name__ isclass = inspect.isclass(param) - if not isclass and name[:3] == 'itk' and name != "itkCType": + if not isclass and name[:3] == 'itk' and name != 'itkCType': param = param.__class__ # append the parameter to the list. If it's not a supported type, @@ -360,7 +360,9 @@ def _LoadModules(self): modules = itkBase.lazy_attributes[name] for module in modules: # find the module's name in sys.modules, or create a new module so named - this_module = sys.modules.setdefault(module, types.ModuleType(module)) + swig_module_name = 'itk.' + module + 'Python' + this_module = sys.modules.setdefault(swig_module_name, + itkBase._create_itk_module(module)) namespace = {} if not hasattr(this_module, '__templates_loaded'): itkBase.LoadModule(module, namespace) diff --git a/Wrapping/Generators/Python/main_module_ext.i.in b/Wrapping/Generators/Python/main_module_ext.i.in index 7f474e6b5b5..61579cc0071 100644 --- a/Wrapping/Generators/Python/main_module_ext.i.in +++ b/Wrapping/Generators/Python/main_module_ext.i.in @@ -5,6 +5,7 @@ %} %pythoncode %{ +swig = {} @ITK_WRAP_PYTHON_LIBRARY_IMPORTS@ %} diff --git a/Wrapping/Generators/SwigInterface/CMakeLists.txt b/Wrapping/Generators/SwigInterface/CMakeLists.txt index 8f0a3ce2a62..87456fdf902 100644 --- a/Wrapping/Generators/SwigInterface/CMakeLists.txt +++ b/Wrapping/Generators/SwigInterface/CMakeLists.txt @@ -18,9 +18,9 @@ if(WIN32) set(ITK_SWIG_VERSION 4.0.1) set(swigwin_hash "2da147231164466c0dee91beca6a4f7b10e6f727062338ea6d70f44f4e4163ad6616b72c2de767539a69977ba96d3ee920ed3c182124c45569ca946750fd4495") else() - set(ITK_SWIG_VERSION 3.0.12) - set(swig_version_min 3.0.0) - set(swig_hash "85605bd98bf2b56f5bfca23ae23d76d764d76a174b05836c8686825e912d6326c370e9cf2134c0bf4f425560be103b16bf9c9d075077f52e713a69082616e906") + set(ITK_SWIG_VERSION 4.0.1) + set(swig_version_min 4.0.1) + set(swig_hash "595ef01cb83adfa960ceed9c325a9429192549e8d1e9aa3ab35a4301512a61d82e2e89a8c7939c2a5a0811254ea1832a443bd387e11459eb2b0bafc563ad1308") endif() if(WIN32) diff --git a/Wrapping/Generators/SwigInterface/igenerator.py b/Wrapping/Generators/SwigInterface/igenerator.py index cbe1344a24b..58544c143c1 100755 --- a/Wrapping/Generators/SwigInterface/igenerator.py +++ b/Wrapping/Generators/SwigInterface/igenerator.py @@ -139,6 +139,72 @@ class SwigInputGenerator(object): }; """} + new_override = ''' +// some changes in the New() method +%rename(__New_orig__) {class_name}::New; +%extend {class_name} {{ +%pythoncode %{{ + def New(*args, **kargs): + """New() -> {class_name} + + Create a new object of the class {class_name} and set the input and the parameters if some + named or non-named arguments are passed to that method. + + New() tries to assign all the non named parameters to the input of the new objects - the + first non named parameter in the first input, etc. + + The named parameters are used by calling the method with the same name prefixed by 'Set'. + + Ex: + + {class_name}.New(reader, threshold=10) + + is (most of the time) equivalent to: + + obj = {class_name}.New() + obj.SetInput(0, reader.GetOutput()) + obj.SetThreshold(10) + """ + obj = {class_name}.__New_orig__() + import itkTemplate + itkTemplate.New(obj, *args, **kargs) + return obj + New = staticmethod(New) + %}} +}} +%pythoncode %{{ + def {class_name}_New(): + return {class_name}.New() +%}} + + +''' + + new_override_pycommand = ''' +// some changes in the New() method +%rename(__New_orig__) {class_name}::New; +%extend {class_name} {{ +%pythoncode %{{ + def New(*args, **kargs): + """New() -> {class_name} + """ + obj = {class_name}.__New_orig__() + import itk + itk.set_inputs(obj, *args, **kargs) + return obj + New = staticmethod(New) +%}} +}} +%pythoncode %{{ + def {class_name}_New(): + return {class_name}.New() +%}} + + +''' + + + def __init__(self, moduleName, options): self.moduleName = moduleName self.options = options @@ -400,6 +466,15 @@ def generate_class(self, typedef, indent=0): decls = pygccxml.declarations if not typedef.name.startswith("stdcomplex"): + for member in getType(typedef).get_members(access=pygccxml.declarations.ACCESS_TYPES.PUBLIC): + if isinstance(member, decls.member_function_t) and member.name == 'New' and not typedef.name == 'itkLightObject': + if typedef.name == 'itkPyCommand': + self.outputFile.write(self.new_override_pycommand.format(class_name=typedef.name)) + else: + self.outputFile.write(self.new_override.format(class_name=typedef.name)) + self.outputFile.write("\n") + break + super_classes = [] for super_class in getType(typedef).bases: super_classes.append( @@ -475,7 +550,7 @@ def generate_class(self, typedef, indent=0): # finally, close the class self.outputFile.write(" " * indent) - self.outputFile.write("};\n\n\n") + self.outputFile.write("};\n\n") elif typedef.name == "stdcomplexD": self.outputFile.write(self.stdcomplex_headers["D"] + '\n') @@ -700,7 +775,7 @@ def generate_headerfile(self, idxFile, wrappersNamespace): headerFile.write("#ifdef SWIG%s\n" % lang) if lang == "PYTHON": # Also, release the GIL - headerFile.write("%%module(threads=\"1\") %s%s\n" % (self.moduleName, lang.title())) + headerFile.write("%%module(package=\"itk\",threads=\"1\") %s%s\n" % (self.moduleName, lang.title())) headerFile.write('%feature("nothreadallow");\n') else: headerFile.write("%%module %s%s\n" % (self.moduleName, lang.title())) diff --git a/Wrapping/Generators/SwigInterface/module.i.in b/Wrapping/Generators/SwigInterface/module.i.in index 9ec38564d88..55241d3a9f5 100644 --- a/Wrapping/Generators/SwigInterface/module.i.in +++ b/Wrapping/Generators/SwigInterface/module.i.in @@ -41,7 +41,7 @@ %module @WRAPPER_LIBRARY_NAME@Pike #endif #ifdef SWIGPYTHON -%module @WRAPPER_LIBRARY_NAME@Python +%module(package="itk") @WRAPPER_LIBRARY_NAME@Python #endif #ifdef SWIGR %module @WRAPPER_LIBRARY_NAME@R