Merge "Omaha #4120 Improve PythonOverriderInterface and PythonOverriderCore to handle incremental overrides for HS." into omaha_15.1.1
Former-commit-id: 27b51d7f74aa7e4c4116b51fc8ecefc0dc484fee
This commit is contained in:
commit
adf93766ab
2 changed files with 59 additions and 22 deletions
|
@ -33,6 +33,7 @@
|
|||
# 01/20/14 2712 bkowal Improve python class merging. Classes
|
||||
# will now truly override each other
|
||||
# instead of extending each other.
|
||||
# 02/09/15 4120 reblum Fixed bugs in the class merging.
|
||||
#
|
||||
#
|
||||
#
|
||||
|
@ -42,14 +43,16 @@ import ModuleUtil
|
|||
|
||||
def _internalOverride(files):
|
||||
"""
|
||||
Takes the files and overrides them
|
||||
Combines the different localization levels of the same class/module into a single
|
||||
class/module with the lower localization level methods taking precedence over the
|
||||
higher localization level methods.
|
||||
|
||||
Args:
|
||||
files : the files that are to be overridden
|
||||
|
||||
Returns:
|
||||
a new module that contains all the necessary elements
|
||||
"""
|
||||
"""
|
||||
themodule = imp.new_module('tmpmodule')
|
||||
# modules = list of all the modules
|
||||
for module in files :
|
||||
|
@ -126,12 +129,17 @@ def _mergeClasses(source, target, className):
|
|||
|
||||
attributeName = className + '.' + attr
|
||||
target = _mergeAttributes(source, target, attributeName)
|
||||
|
||||
|
||||
# Get the set of unimplemented abstractmethods from the sourceClass
|
||||
abstractMethods = set()
|
||||
if sourceClass.__dict__.has_key('__abstractmethods__'):
|
||||
for method in sourceClass.__abstractmethods__:
|
||||
abstractMethods.add(method)
|
||||
|
||||
# make new class "extend" the original class
|
||||
for attr in dir(targetClass):
|
||||
if attr != '__init__' \
|
||||
and isinstance(getattr(targetClass, attr), types.MethodType) \
|
||||
and not attr in dir(sourceClass):
|
||||
if isinstance(getattr(targetClass, attr), types.MethodType) \
|
||||
and not attr in sourceClass.__dict__:
|
||||
# complete the merge / override of methods for any method that
|
||||
# the new class does not implement
|
||||
|
||||
|
@ -141,7 +149,17 @@ def _mergeClasses(source, target, className):
|
|||
# copy the method implementation to the other class and give it
|
||||
# the same name as the original
|
||||
classMethodDirective = _buildReplaceClassMethodDirective(className, attr)
|
||||
exec(classMethodDirective)
|
||||
exec(classMethodDirective)
|
||||
# If the method we just merged was an abstractmethod remove it from
|
||||
# abstractMethods since it now has been implemented.
|
||||
if attr in abstractMethods:
|
||||
abstractMethods.remove(attr)
|
||||
|
||||
# Update __abstractmethods__ so that it correctly reflects if there are any
|
||||
# unimplemented abstactmethods for the merged class.
|
||||
if sourceClass.__dict__.has_key('__abstractmethods__'):
|
||||
directive = 'sourceClass.__abstractmethods__ = frozenset(abstractMethods)'
|
||||
exec(directive)
|
||||
|
||||
return _mergeAttributes(source, target, className)
|
||||
|
||||
|
@ -164,8 +182,13 @@ def _compareClasses(clazz1, clazz2):
|
|||
return False
|
||||
|
||||
# compare the attributes directly
|
||||
attr1 = getattr(clazz1, clazz1Attr[i])
|
||||
attr2 = getattr(clazz2, clazz2Attr[i])
|
||||
attr1 = None
|
||||
attr2 = None
|
||||
# see http://bugs.python.org/issue10006
|
||||
if clazz1Attr[i] != '__abstractmethods__':
|
||||
attr1 = getattr(clazz1, clazz1Attr[i])
|
||||
if clazz2Attr[i] != '__abstractmethods__':
|
||||
attr2 = getattr(clazz2, clazz2Attr[i])
|
||||
if (attr1 != attr2):
|
||||
return False
|
||||
|
||||
|
|
|
@ -23,25 +23,31 @@
|
|||
# Python RollbackMasterInterface. The objective of this class is
|
||||
# to prevent the MasterInterface from completing imports because the
|
||||
# MasterInterface will overwrite modules instead of merging them.
|
||||
#
|
||||
#
|
||||
# TODO: njensen thinks it may be safer and more stable to dynamically
|
||||
# create a new type with the appropriate inheritance tree and then
|
||||
# utilize normal object-oriented inheritance to provide the incremental/selective
|
||||
# overrides capability. Investigate as necessary.
|
||||
#
|
||||
# SOFTWARE HISTORY
|
||||
#
|
||||
# Date Ticket# Engineer Description
|
||||
# ------------ ---------- ----------- --------------------------
|
||||
# 01/14/2014 #2766 bkowal Initial Creation.
|
||||
# 02/09/2015 #4120 reblum Inherit straight from MasterInterface.
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
import os, sys, string, traceback
|
||||
import RollbackMasterInterface
|
||||
import MasterInterface
|
||||
import PythonOverrider
|
||||
|
||||
class PythonOverriderInterface(RollbackMasterInterface.RollbackMasterInterface):
|
||||
class PythonOverriderInterface(MasterInterface.MasterInterface):
|
||||
def __init__(self, scriptPath, localizationPath=None):
|
||||
super(PythonOverriderInterface, self).__init__(scriptPath)
|
||||
super(PythonOverriderInterface, self).__init__()
|
||||
self._localizationPath = localizationPath
|
||||
self._scriptPath = scriptPath
|
||||
|
||||
def importModules(self):
|
||||
modulesToImport = []
|
||||
|
@ -58,22 +64,23 @@ class PythonOverriderInterface(RollbackMasterInterface.RollbackMasterInterface):
|
|||
|
||||
for moduleName in modulesToImport:
|
||||
self._importModule(moduleName)
|
||||
|
||||
|
||||
def addModule(self, moduleName):
|
||||
if not moduleName in self.scripts:
|
||||
self.scripts.append(moduleName)
|
||||
self.reloadModules()
|
||||
|
||||
|
||||
def reloadModule(self, moduleName):
|
||||
if sys.modules.has_key(moduleName):
|
||||
self.clearModuleAttributes(moduleName)
|
||||
self._importModule(moduleName)
|
||||
|
||||
def reloadModules(self):
|
||||
for script in self.scripts:
|
||||
# first remove all references to the existing module
|
||||
if sys.modules.has_key(script):
|
||||
self.clearModuleAttributes(script)
|
||||
sys.modules.pop(script)
|
||||
|
||||
self.clearModuleAttributes(script)
|
||||
# now use PythonOverrider to re-import the module
|
||||
self._importModule(script)
|
||||
|
||||
|
||||
def _importModule(self, moduleName):
|
||||
scriptName = moduleName + '.py'
|
||||
if self._localizationPath:
|
||||
|
@ -86,4 +93,11 @@ class PythonOverriderInterface(RollbackMasterInterface.RollbackMasterInterface):
|
|||
return
|
||||
|
||||
if not moduleName in self.scripts:
|
||||
self.scripts.append(moduleName)
|
||||
self.scripts.append(moduleName)
|
||||
|
||||
def getStartupErrors(self):
|
||||
from java.util import ArrayList
|
||||
errorList = ArrayList()
|
||||
for err in self.getImportErrors():
|
||||
errorList.add(str(err))
|
||||
return errorList
|
Loading…
Add table
Reference in a new issue