awips2/edexOsgi/com.raytheon.uf.common.python/utility/common_static/base/python/MasterInterface.py

174 lines
6.8 KiB
Python
Raw Normal View History

##
# This software was developed and / or modified by Raytheon Company,
# pursuant to Contract DG133W-05-CQ-1067 with the US Government.
#
# U.S. EXPORT CONTROLLED TECHNICAL DATA
# This software product contains export-restricted data whose
# export/transfer/disclosure is restricted by U.S. law. Dissemination
# to non-U.S. persons whether in the United States or abroad requires
# an export license or other authorization.
#
# Contractor Name: Raytheon Company
# Contractor Address: 6825 Pine Street, Suite 340
# Mail Stop B8
# Omaha, NE 68106
# 402.291.0100
#
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information.
##
#
# Globally import and sets up instances of the scripts.
# Designed to be used as a master controller for inspecting and running
# python scripts from Java.
#
# This class should remain purely python. For Java interactions, extend this class.
#
#
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 10/20/08 njensen Initial Creation.
# 01/17/13 1486 dgilling Make a new-style class.
# 09/23/13 16614 njensen Fixed reload method
# 03/25/14 2963 randerso Added check to instantiate method to
# verify module contains desired class
# throw a useful error message if not
#
import os, string
import sys, inspect, traceback
class MasterInterface(object):
def __init__(self):
self.scripts = []
self.__importErrors = []
self.__instanceMap = {}
def importModules(self, scriptPath):
for s in scriptPath.split(os.path.pathsep):
if os.path.exists(s):
scriptfiles = os.listdir(s)
for filename in scriptfiles:
split = string.split(filename, ".")
if len(split) == 2 and len(split[0]) > 0 and split[1] == "py" and not filename.endswith("Interface.py"):
try:
MasterInterface.addModule(self, split[0])
except Exception, e:
msg = split[0] + "\n" + traceback.format_exc()
self.__importErrors.append(msg)
else:
os.makedirs(s)
def getMethodArgs(self, moduleName, className, methodName):
members = self.__getClassMethods(moduleName, className)
result = []
for x,y in members:
if x == methodName:
count = y.func_code.co_argcount
args = y.func_code.co_varnames
i = 0
for a in args:
if i < count:
result.append(a)
else:
break
i = i+1
return result
def getMethodInfo(self, moduleName, className, methodName):
members = self.__getClassMethods(moduleName, className)
result = None
for n, m in members:
if n == methodName:
result = m.__doc__
break
return result
def hasMethod(self, moduleName, className, methodName):
md = sys.modules[moduleName]
classObj = md.__dict__.get(className)
return classObj.__dict__.has_key(methodName)
def __getClassMethods(self, moduleName, className):
md = sys.modules[moduleName]
classObj = md.__dict__.get(className)
return inspect.getmembers(classObj, inspect.ismethod)
def isInstantiated(self, moduleName):
return self.__instanceMap.has_key(moduleName)
def instantiate(self, moduleName, className, **kwargs):
if sys.modules[moduleName].__dict__.has_key(className):
instance = sys.modules[moduleName].__dict__.get(className)(**kwargs)
self.__instanceMap[moduleName] = instance
else:
msg = "Module %s (in %s) has no class named %s" % (moduleName, sys.modules[moduleName].__file__, className)
raise Exception(msg)
def runMethod(self, moduleName, className, methodName, **kwargs):
instance = self.__instanceMap[moduleName]
methods = inspect.getmembers(instance, inspect.ismethod)
for name, methodObj in methods:
if name == methodName:
method = methodObj
break
result = methodObj(**kwargs)
return result
def removeModule(self, moduleName):
if self.isInstantiated(moduleName):
self.__instanceMap.__delitem__(moduleName)
if sys.modules.has_key(moduleName):
self.clearModuleAttributes(moduleName)
sys.modules.pop(moduleName)
if moduleName in self.scripts:
self.scripts.remove(moduleName)
def addModule(self, moduleName):
# we may be overriding something in self.scripts, so let's
# force an import here
if moduleName in self.scripts:
self.clearModuleAttributes(moduleName)
sys.modules.pop(moduleName)
__import__(moduleName)
if not moduleName in self.scripts:
self.scripts.append(moduleName)
def getImportErrors(self):
returnList = self.__importErrors
self.__importErrors = []
return returnList
def reloadModule(self, moduleName):
if sys.modules.has_key(moduleName):
# From the python documentation:
# "When a module is reloaded, its dictionary (containing the module's
# global variables) is retained. Redefinitions of names will override the
# old definitions, so this is generally not a problem. If the new version
# of a module does not define a name that was defined by the old
# version, the old definition remains."
#
#
# Because the user might have removed items
# from the module's dictionary, we cannot trust reload() to
# remove old items. We will manually remove everything
# but built-ins to ensure everything gets re-initialized when
# reload() is called.
self.clearModuleAttributes(moduleName)
reload(sys.modules[moduleName])
def clearModuleAttributes(self, moduleName):
if sys.modules.has_key(moduleName):
mod = sys.modules[moduleName]
modGlobalsToRemove = [k for k in mod.__dict__ if not k.startswith('_')]
for k in modGlobalsToRemove:
mod.__dict__.pop(k)