NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

__init__.py (17928B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\evegraphics\validation\__init__.py
      2 from __future__ import print_function
      3 import os
      4 import time
      5 import sys
      6 from evegraphics.validation.commonUtilities import BaseValidationRule
      7 from evegraphics.validation.errors import SingleObjectValidationError, ValidationError, MultipleValidationErrors
      8 import blue
      9 import trinity
     10 
     11 def GetObjectAttribute(obj, attribute):
     12     if attribute is not None:
     13         if hasattr(obj, attribute):
     14             return getattr(obj, attribute)
     15         else:
     16             print("object '%s' has no attribute '%s'" % (obj, attribute))
     17             return
     18     return obj
     19 
     20 
     21 def _FormatPath(stack):
     22     return '/'.join(((getattr(x, 'name') if getattr(x, 'name', '') else type(x).__name__) for x in stack))
     23 
     24 
     25 _jessicaSkipValidationObjects = {}
     26 
     27 def ValidationAttributeFilter(obj, attr):
     28     try:
     29         return _jessicaSkipValidationObjects[type(obj), attr]
     30     except KeyError:
     31         try:
     32             use = ':jessica-skip-validation:' not in obj.TypeInfo()[2][attr]['description']
     33         except Exception:
     34             use = True
     35 
     36         _jessicaSkipValidationObjects[type(obj), attr] = use
     37         return use
     38 
     39 
     40 class ObjectLink(object):
     41 
     42     def GetSourceObject(self):
     43         return None
     44 
     45     def GetBinding(self):
     46         return None
     47 
     48     def GetBoundObject(self):
     49         raise NotImplementedError()
     50 
     51     def GetBoundAttribute(self):
     52         raise NotImplementedError()
     53 
     54     def SetBoundAttribute(self, attr):
     55         raise NotImplementedError()
     56 
     57     def Patch(self, old, new):
     58         raise NotImplementedError()
     59 
     60     def IsDestination(self):
     61         raise NotImplementedError()
     62 
     63     def IsSource(self):
     64         raise NotImplementedError()
     65 
     66 
     67 class ControllerActionLink(ObjectLink):
     68 
     69     def __init__(self, action, parentController):
     70         self._action = action
     71         self._parentController = parentController
     72 
     73     def GetBoundObject(self):
     74         boundObject = self._action.GetDestination()
     75         if not boundObject and self._action.delayBinding:
     76             boundObject = trinity.ResolveObjectPath(self._action.path, {'Owner': self._parentController.GetOwner()})
     77         return boundObject
     78 
     79     def GetBoundAttribute(self):
     80         return self._action.attribute
     81 
     82     def SetBoundAttribute(self, attr):
     83         self._action.attribute = attr
     84 
     85     def IsDestination(self):
     86         return True
     87 
     88     def IsSource(self):
     89         return False
     90 
     91     def Patch(self, old, new):
     92         if self.GetBoundObject() == old:
     93             if self._action.path:
     94                 raise NotImplementedError()
     95             else:
     96                 self._action.destination = new
     97             return True
     98         return False
     99 
    100 
    101 class SourceBindingLink(ObjectLink):
    102 
    103     def __init__(self, binding):
    104         self._binding = binding
    105 
    106     def GetBinding(self):
    107         return self._binding
    108 
    109     def GetBoundObject(self):
    110         return self._binding.sourceObject
    111 
    112     def GetBoundAttribute(self):
    113         return self._binding.sourceAttribute
    114 
    115     def SetBoundAttribute(self, attr):
    116         self._binding.sourceAttribute = attr
    117 
    118     def Patch(self, old, new):
    119         if self.GetBoundObject() == old:
    120             self._binding.sourceObject = new
    121             return True
    122         return False
    123 
    124     def IsDestination(self):
    125         return False
    126 
    127     def IsSource(self):
    128         return True
    129 
    130 
    131 class SourceDynamicBindingLink(ObjectLink):
    132 
    133     def __init__(self, binding):
    134         self._binding = binding
    135 
    136     def GetBinding(self):
    137         return self._binding
    138 
    139     def GetBoundObject(self):
    140         return self._binding.source
    141 
    142     def GetBoundAttribute(self):
    143         return self._binding.sourceObjectAttribute
    144 
    145     def SetBoundAttribute(self, attr):
    146         self._binding.sourceObjectAttribute = attr
    147 
    148     def Patch(self, old, new):
    149         if self.GetBoundObject() == old:
    150             self._binding.source = new
    151             return True
    152         return False
    153 
    154     def IsDestination(self):
    155         return False
    156 
    157     def IsSource(self):
    158         return True
    159 
    160 
    161 class DestinationBindingLink(ObjectLink):
    162 
    163     def __init__(self, binding):
    164         self._binding = binding
    165 
    166     def GetBinding(self):
    167         return self._binding
    168 
    169     def GetSourceObject(self):
    170         return self._binding.sourceObject
    171 
    172     def GetBoundObject(self):
    173         return self._binding.destinationObject
    174 
    175     def GetBoundAttribute(self):
    176         return self._binding.destinationAttribute
    177 
    178     def SetBoundAttribute(self, attr):
    179         self._binding.destinationAttribute = attr
    180 
    181     def Patch(self, old, new):
    182         if self.GetBoundObject() == old:
    183             self._binding.destinationObject = new
    184             return True
    185         return False
    186 
    187     def IsDestination(self):
    188         return True
    189 
    190     def IsSource(self):
    191         return False
    192 
    193 
    194 class SmartLightMeshBindingLink(ObjectLink):
    195 
    196     def __init__(self, meshRenderer, area):
    197         self._meshRenderer = meshRenderer
    198         self._area = area
    199 
    200     def GetBinding(self):
    201         return self._meshRenderer
    202 
    203     def GetBoundObject(self):
    204         if self._area is not None:
    205             if self._area.effect is not None:
    206                 parameters = self._area.effect.parameters
    207                 param = parameters.FindByName(self.GetBoundAttribute())
    208                 return param
    209 
    210     def GetBoundAttribute(self):
    211         if self._meshRenderer:
    212             return self._meshRenderer.shaderParamColorName
    213         return ''
    214 
    215     def IsDestination(self):
    216         return True
    217 
    218     def IsSource(self):
    219         return False
    220 
    221 
    222 class ExternalParameterLink(ObjectLink):
    223 
    224     def __init__(self, binding):
    225         self._binding = binding
    226 
    227     def GetBinding(self):
    228         return self._binding
    229 
    230     def GetBoundObject(self):
    231         return self._binding.destinationObject
    232 
    233     def GetBoundAttribute(self):
    234         return self._binding.destinationAttribute
    235 
    236     def IsDestination(self):
    237         return True
    238 
    239     def IsSource(self):
    240         return True
    241 
    242 
    243 class ValidationContext(object):
    244 
    245     def __init__(self, rootObject, rules):
    246         self.errors = []
    247         self.root = rootObject
    248         self._rules = rules
    249         self._arguments = {}
    250         self._stack = []
    251         self._skipObjects = []
    252         self._stackStrs = ['root']
    253         self._destinationBindings = None
    254         self._sourceBindings = None
    255         self._allBindings = None
    256         self._currentRule = None
    257         self.cache = {}
    258         self._attributeFilter = ValidationAttributeFilter
    259 
    260     def GetStack(self):
    261         return self._stack
    262 
    263     def GetStackAsStr(self):
    264         return '.'.join(self._stackStrs)
    265 
    266     def GetTop(self):
    267         return self._stack[-1]
    268 
    269     def GetArgument(self, argumentType):
    270         return self._arguments[argumentType]
    271 
    272     def Walk(self, obj, callback, seen):
    273         try:
    274             hash(obj)
    275             key = obj
    276         except TypeError:
    277             key = id(obj)
    278 
    279         if key in seen:
    280             return
    281         seen.add(key)
    282         self._stack.append(obj)
    283         try:
    284             callback()
    285             if isinstance(obj, list) or getattr(obj, '__bluetype__', '') == 'blue.List':
    286                 for i, each in enumerate(obj):
    287                     if each in self._skipObjects:
    288                         continue
    289                     self._stackStrs.append(str(i))
    290                     self.Walk(each, callback, seen)
    291                     self._stackStrs.pop()
    292 
    293             else:
    294                 for each in dir(obj):
    295                     member = getattr(obj, each)
    296                     if each.startswith('_') or callable(member):
    297                         continue
    298                     if isinstance(member, (int,
    299                      float,
    300                      long,
    301                      str,
    302                      unicode)):
    303                         continue
    304                     if member in self._skipObjects:
    305                         continue
    306                     if isinstance(member, tuple) and all((isinstance(x, (int,
    307                      float,
    308                      long,
    309                      str,
    310                      unicode)) for x in member)):
    311                         continue
    312                     if self._attributeFilter and not self._attributeFilter(obj, each):
    313                         continue
    314                     self._stackStrs.append(each)
    315                     self.Walk(member, callback, seen)
    316                     self._stackStrs.pop()
    317 
    318         finally:
    319             self._stack.pop()
    320 
    321     def GetArguments(self):
    322         args = set()
    323         rulesWithArguments = [ x for x in map(lambda r: (r, r.GetArguments()), self._rules) if x[1] ]
    324         ruleMap = {}
    325 
    326         def inner():
    327             t = type(self._stack[-1])
    328             if t not in ruleMap:
    329                 ruleMap[t] = [ x for x in rulesWithArguments if x[0].CanApplyToTypeOf(self._stack[-1]) ]
    330             for each in ruleMap[t]:
    331                 if each[0].Applies(self):
    332                     args.update(each[1])
    333 
    334         self.Walk(self.root, inner, set())
    335         return args
    336 
    337     def Validate(self, arguments):
    338         self.errors = []
    339         self.cache = {}
    340         self._arguments = arguments
    341         self._destinationBindings = None
    342         self._sourceBindings = None
    343         self._allBindings = None
    344         self._currentRule = None
    345         self._ruleMap = {}
    346 
    347         def inner():
    348             validated = False
    349             t = type(self._stack[-1])
    350             if t not in self._ruleMap:
    351                 self._ruleMap[t] = [ x for x in self._rules if x.CanApplyToTypeOf(self._stack[-1]) ]
    352             for each in self._ruleMap[t]:
    353                 self._currentRule = each
    354                 try:
    355                     validated = each.Apply(self) or validated
    356                 except BaseException:
    357                     import traceback
    358                     self.Error(each, 'Exception in the rule:\n\n' + traceback.format_exc())
    359 
    360             time.sleep(0)
    361 
    362         self.Walk(self.root, inner, set())
    363         self._currentRule = None
    364 
    365     def SkipObject(self, obj):
    366         self._skipObjects.append(obj)
    367 
    368     def AddError(self, error):
    369         if error.rule is None:
    370             error.rule = self._currentRule
    371         self.errors.append(error)
    372 
    373     def Error(self, obj, message, actions = ()):
    374         self.AddError(SingleObjectValidationError(obj, message, actions))
    375 
    376     def Expect(self, obj, attribute, rule, message = None, actions = ()):
    377         try:
    378             objectToValidate = GetObjectAttribute(obj, attribute)
    379             if objectToValidate is None:
    380                 return
    381             rule(objectToValidate, message)
    382         except AssertionError as e:
    383             self.AddError(SingleObjectValidationError(obj, '%s %s' % (attribute, str(e)), actions))
    384         except MultipleValidationErrors as e:
    385             for error in e.errors:
    386                 self.AddError(error)
    387 
    388     def ExpectValue(self, obj, value, rule, message = None, actions = ()):
    389         try:
    390             rule(value, message)
    391         except AssertionError as e:
    392             self.AddError(SingleObjectValidationError(obj, '%s %s' % (value, str(e)), actions))
    393         except MultipleValidationErrors as e:
    394             for error in e.errors:
    395                 self.AddError(error)
    396 
    397     def ExpectAny(self, obj, attribute, rule, message):
    398         objectToValidate = GetObjectAttribute(obj, attribute)
    399         if objectToValidate is None:
    400             return
    401         for each in objectToValidate:
    402             try:
    403                 rule(each, message)
    404                 return
    405             except AssertionError:
    406                 pass
    407             except MultipleValidationErrors:
    408                 pass
    409 
    410         self.AddError(SingleObjectValidationError(obj, '%s %s' % (attribute, message)))
    411 
    412     def GetAllObjectBindings(self):
    413         bindings = blue.FindInterface(self.root, 'TriValueBinding')
    414         allBindings = [ SourceBindingLink(x) for x in bindings ]
    415         allBindings.extend((DestinationBindingLink(x) for x in bindings))
    416         allBindings.extend((SourceDynamicBindingLink(x) for x in blue.FindInterface(self.root, 'Tr2DynamicBinding')))
    417         allBindings.extend((ExternalParameterLink(x) for x in blue.FindInterface(self.root, 'Tr2ExternalParameter')))
    418         for slm in blue.FindInterface(self.root, 'EveSmartLightMesh'):
    419             if slm.mesh is not None:
    420                 for area in slm.mesh.GetAllAreas():
    421                     allBindings.append(SmartLightMeshBindingLink(slm, area))
    422 
    423         controllerActions = {}
    424         for controller in blue.FindInterface(self.root, 'Tr2Controller'):
    425             controllerActions[controller] = []
    426             for stateMachine in controller.stateMachines:
    427                 for state in stateMachine.states:
    428                     controllerActions[controller].extend(state.actions)
    429 
    430         actions = blue.FindInterface(self.root, 'Tr2ActionSetValue')
    431         actions.extend(blue.FindInterface(self.root, 'Tr2ActionAnimateValue'))
    432         for a in actions:
    433             for key, val in controllerActions.iteritems():
    434                 if a in val:
    435                     allBindings.append(ControllerActionLink(a, key))
    436                     break
    437 
    438         return allBindings
    439 
    440     def RemoveBinding(self, binding):
    441         toRemove = None
    442         if binding and self._allBindings:
    443             for each in self._allBindings:
    444                 if binding == each.GetBinding():
    445                     toRemove = each
    446                     break
    447 
    448         if toRemove:
    449             if self._destinationBindings:
    450                 cleanupKey = None
    451                 cleanupName = None
    452                 for key, each in self._destinationBindings.iteritems():
    453                     for name, val in each.iteritems():
    454                         if toRemove in val:
    455                             val.remove(toRemove)
    456                             cleanupKey = key
    457                             cleanupName = name
    458                             break
    459 
    460                 if cleanupKey and cleanupName:
    461                     if len(self._destinationBindings[cleanupKey][cleanupName]) == 0:
    462                         self._destinationBindings[cleanupKey].pop(cleanupName)
    463                     if len(self._destinationBindings[cleanupKey]) == 0:
    464                         self._destinationBindings.pop(cleanupKey)
    465             if self._sourceBindings:
    466                 cleanupKey = None
    467                 cleanupName = None
    468                 for key, each in self._sourceBindings.iteritems():
    469                     for name, val in each.iteritems():
    470                         if toRemove in val:
    471                             val.remove(toRemove)
    472                             cleanupKey = key
    473                             cleanupName = name
    474                             break
    475 
    476                 if cleanupKey and cleanupName:
    477                     if len(self._sourceBindings[cleanupKey][cleanupName]) == 0:
    478                         self._sourceBindings[cleanupKey].pop(cleanupName)
    479                     if len(self._sourceBindings[cleanupKey]) == 0:
    480                         self._sourceBindings.pop(cleanupKey)
    481             self._allBindings.remove(toRemove)
    482 
    483     def GetBindings(self):
    484         if self._allBindings is None:
    485             self._allBindings = self.GetAllObjectBindings()
    486         return self._allBindings
    487 
    488     def GetDestinationBindings(self):
    489         if self._destinationBindings is None:
    490             allBindings = self.GetBindings()
    491             self._destinationBindings = {}
    492             for binding in allBindings:
    493                 if binding.IsDestination():
    494                     self._destinationBindings.setdefault(binding.GetBoundObject(), {}).setdefault(binding.GetBoundAttribute(), []).append(binding)
    495 
    496         return self._destinationBindings
    497 
    498     def GetSourceBindings(self):
    499         if self._sourceBindings is None:
    500             allBindings = self.GetBindings()
    501             self._sourceBindings = {}
    502             for binding in allBindings:
    503                 if binding.IsSource():
    504                     self._sourceBindings.setdefault(binding.GetBoundObject(), {}).setdefault(binding.GetBoundAttribute(), []).append(binding)
    505 
    506         return self._sourceBindings
    507 
    508     def IsBoundAsDestination(self, obj, attribute = None):
    509         if obj.name == 'FresnelFactors':
    510             pass
    511         return self._IsBound(obj, attribute, self.GetDestinationBindings())
    512 
    513     def IsBoundAsSource(self, obj, attribute = None):
    514         return self._IsBound(obj, attribute, self.GetSourceBindings())
    515 
    516     def _IsBound(self, obj, attribute, bindings):
    517         if attribute is None:
    518             return obj in bindings
    519         else:
    520             boundAttributes = bindings.get(obj, {})
    521             attributeIsBound = attribute in boundAttributes
    522             if not attributeIsBound:
    523                 for boundAttribute in boundAttributes:
    524                     if boundAttribute.startswith(attribute + '.'):
    525                         return True
    526 
    527             return attributeIsBound
    528 
    529 
    530 def FindRules(path = None):
    531     if path is None:
    532         path = os.path.join(os.path.dirname(__file__), 'validators')
    533     rules = []
    534     for root, dirs, files in os.walk(path):
    535         if root.lower().endswith('test'):
    536             continue
    537         for each in files:
    538             rules.extend(FindRulesInFile(os.path.join(root, each)))
    539 
    540     return rules
    541 
    542 
    543 def FindRulesInFile(filePath):
    544     rules = []
    545     root = os.path.dirname(filePath)
    546     file = os.path.basename(filePath)
    547     if file.lower().endswith('.py'):
    548         sys.path.insert(0, root)
    549         try:
    550             module = __import__(os.path.splitext(file)[0])
    551             for name in dir(module):
    552                 member = getattr(module, name)
    553                 if isinstance(member, BaseValidationRule):
    554                     if member.name is None:
    555                         member.name = '%s.%s' % (os.path.splitext(file)[0], name)
    556                     rules.append(member)
    557 
    558         finally:
    559             del sys.path[0]
    560 
    561     return rules
    562 
    563 
    564 def InitializeArgumentsFromFilePath(argumentClasses, path, root):
    565     return {k:k.CreateFromPath(path, root) for k in argumentClasses}