Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleaning up Python module import infrastructure #3608

Merged
merged 18 commits into from
Jan 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -435,10 +435,8 @@ endif(DEFINED KRATOS_INSTALL_PREFIX)
# install core files for the KratosMultiphysics python module
# note that this does not install KratosLoader.py, as it is different for installation and packaging runs (see next code block)
install(FILES "${CMAKE_SOURCE_DIR}/kratos/python_interface/__init__.py" DESTINATION KratosMultiphysics )
install(FILES "${CMAKE_SOURCE_DIR}/kratos/python_interface/kratos_utilities.py" DESTINATION KratosMultiphysics )
install(FILES "${CMAKE_SOURCE_DIR}/kratos/python_interface/kratos_globals.py" DESTINATION KratosMultiphysics )
install(FILES "${CMAKE_SOURCE_DIR}/kratos/python_interface/application_importer.py" DESTINATION KratosMultiphysics )
install(FILES "${CMAKE_SOURCE_DIR}/kratos/python_interface/kratos_unittest.py" DESTINATION KratosMultiphysics RENAME KratosUnittest.py )

# Remove the tags in the event of multiple versions of boost being found
# in the same directory
Expand Down Expand Up @@ -466,7 +464,6 @@ kratos_applications=os.path.abspath(os.path.join(os.path.dirname(__file__),'../a
kratos_scripts=os.path.abspath(os.path.join(os.path.dirname(__file__),'../kratos/python_scripts'))
kratos_tests=os.path.abspath(os.path.join(os.path.dirname(__file__),'../kratos/tests'))
sys.path.append(kratos_libs)
sys.path.append(kratos_applications)
sys.path.append(kratos_scripts)
sys.path.append(kratos_tests)
")
Expand Down Expand Up @@ -495,7 +492,6 @@ kratos_applications=\"${CMAKE_SOURCE_DIR}/applications\"
kratos_scripts=\"${CMAKE_INSTALL_PREFIX}/kratos/python_scripts\"
kratos_tests=\"${CMAKE_INSTALL_PREFIX}/kratos/tests\"
sys.path.append(kratos_libs)
sys.path.append(kratos_applications)
sys.path.append(kratos_scripts)
sys.path.append(kratos_tests) ")
endif(${INSTALL_PYTHON_FILES} MATCHES ON)
9 changes: 3 additions & 6 deletions applications/MappingApplication/MappingApplication.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@
from __future__ import print_function, absolute_import, division

# Application dependent names and paths
import KratosMultiphysics as KM
from KratosMappingApplication import *
application = KratosMappingApplication()
application_name = "KratosMappingApplication"
application_folder = "MappingApplication"

# The following lines are common for all applications
from .. import application_importer
import inspect
caller = inspect.stack()[1] # Information about the file that imported this, to check for unexpected imports
application_importer.ImportApplication(application,application_name,application_folder,caller,__path__)
KM._ImportApplicationAsModule(application, application_name, application_folder, __path__)

'''
TODO:
Expand All @@ -27,4 +24,4 @@
- Delete copy and assignment-constructors?
- testing => do some logical tests with USE_TRANSPOSE
- MapperFlags: Check that they are used correctly and all of them are used in tests (USE_TRANSPOSE)
'''
'''
634 changes: 0 additions & 634 deletions applications/applications_interface.py

This file was deleted.

27 changes: 18 additions & 9 deletions kratos/python_interface/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
from __future__ import print_function, absolute_import, division #makes KratosMultiphysics backward compatible with python 2.6 and 2.7
import os.path
import sys
import inspect
from . import kratos_globals

from .kratos_utilities import *

# this adds the libs/ and applications/ folders to sys.path
from . import KratosLoader

Expand All @@ -19,6 +15,7 @@ def __ModuleInitDetail():
and the parallel DataCommunicator are initialized when the Kernel is built.
It is defined as a function to avoid polluting the Kratos namespace with local variables.
"""
import sys
if "--using-mpi" in sys.argv[1:]:
try:
import KratosMultiphysics.mpi
Expand All @@ -33,15 +30,27 @@ def __ModuleInitDetail():

__ModuleInitDetail()

KratosGlobals = kratos_globals.KratosGlobals(
Kernel(), inspect.stack()[1], KratosLoader.kratos_applications)

# Initialize Kernel so that core variables have an assigned Key even if we are not importing applications
KratosGlobals.Kernel.Initialize()
KratosGlobals = kratos_globals.KratosGlobalsImpl(
Kernel(), KratosLoader.kratos_applications)

# adding the scripts in "kratos/python_scripts" such that they are treated as a regular python-module
__path__.append(KratosLoader.kratos_scripts)

def _ImportApplicationAsModule(application, application_name, application_folder, mod_path):
Kernel = KratosGlobals.Kernel
applications_root = KratosGlobals.ApplicationsRoot

Logger.PrintInfo("", "Importing " + application_name)

# adding the scripts in "APP_NAME/python_scripts" such that they are treated as a regular python-module
application_path = os.path.join(applications_root, application_folder)
python_path = os.path.join(application_path, 'python_scripts')
mod_path.append(python_path)

# Add application to kernel
Kernel.ImportApplication(application)


def CheckForPreviousImport():
warn_msg = '"CheckForPreviousImport" is not needed any more and can be safely removed\n'
warn_msg += 'It does nothing any more'
Expand Down
47 changes: 16 additions & 31 deletions kratos/python_interface/application_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,22 @@
def ImportApplication(application, application_name, application_folder, caller, mod_path=None):
Globals = KratosMultiphysics.KratosGlobals
Kernel = Globals.Kernel
main_caller = Globals.AuthorizedCaller
applications_root = Globals.ApplicationsRoot
# caller and main_caller are generated from the output of inspect.stack().
# In particular position [1] is the name of the file containing the call.
# Note that position [0] (a frame instance) could also be used for the check,
# but can return false if both calls are made from the python interpreter
if main_caller[1] != caller[1]:
msg = "\n***\n* Python file " + str(caller[1]) + "\n* requires " + str(application_name) + "\n* Please import it from your main Python script, " +str(main_caller[1]+"\n* If your main Python script is already importing it, you may need to re-order the imports"+'\n***')
# print caller
# print main_caller
raise RuntimeError(msg)
elif application_name not in Globals.RequestedApplications: # This check is possibly redundant, as Python won't import the same module twice
Logger.PrintInfo("", "Importing " + application_name)
# Add application to dictionary of registered applications
Globals.RequestedApplications[application_name] = application
# Add python scrips folder to path
application_path = os.path.join(applications_root, application_folder)
python_path = os.path.join(application_path, 'python_scripts')
sys.path.append(python_path)
# Add constitutive laws python scrips folder to path
constitutive_laws_path = os.path.join(python_path, 'constitutive_laws')
sys.path.append(constitutive_laws_path)

# adding the scripts in "APP_NAME/python_scripts" such that they are treated as a regular python-module
if mod_path is not None: # optional for backwards compatibility
mod_path.append(python_path)
Logger.PrintInfo("", "Importing " + application_name)

# Add python scrips folder to path
application_path = os.path.join(applications_root, application_folder)
python_path = os.path.join(application_path, 'python_scripts')
sys.path.append(python_path)
# Add constitutive laws python scrips folder to path
constitutive_laws_path = os.path.join(python_path, 'constitutive_laws')
sys.path.append(constitutive_laws_path)

# adding the scripts in "APP_NAME/python_scripts" such that they are treated as a regular python-module
if mod_path is not None: # optional for backwards compatibility
mod_path.append(python_path)

# Add application to kernel
Kernel.ImportApplication(application)

# Add application to kernel
Kernel.ImportApplication(application)
# Dynamic renumbering of variables to ensure consistency
Kernel.Initialize()
for iterName, iterApplication in list(Globals.RequestedApplications.items()):
# print("Initializing",iterName)
Kernel.InitializeApplication(iterApplication)
11 changes: 2 additions & 9 deletions kratos/python_interface/kratos_globals.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
from __future__ import print_function, absolute_import, division #makes KratosMultiphysics backward compatible with python 2.6 and 2.7

class KratosGlobals:
class KratosGlobalsImpl(object):

def __init__(self, ThisKernel, ThisCaller, ApplicationsRoot):
def __init__(self, ThisKernel, ApplicationsRoot):
self.__dict__["Kernel"] = ThisKernel
self.__dict__["RequestedApplications"] = dict()
self.__dict__["AuthorizedCaller"] = ThisCaller
self.__dict__["ApplicationsRoot"] = ApplicationsRoot
self.__dict__["ApplicationsInterfaceIsDeprecated"] = False

def __setattr__(self, name, value):
if name in self.__dict__:
# self.__dict__[name] = value
print("Ignoring request to set KratosGlobals attribute", name)
else:
print("Ignoring request to set unknown KratosGlobals attribute:", name)

def echo(self):
print("Kernel:", self.Kernel)
print("RequestedApplications:", self.RequestedApplications)
print("Main Python script:", self.AuthorizedCaller)
print("Kratos Applications base folder:", self.ApplicationsRoot)
return

def GetFlag(self, FlagName):
""" This method returns the flag with the given name
Expand Down