Script scriptHandler
[hide private]
[frames] | no frames]

Source Code for Script scriptHandler

  1  #scriptHandler.py 
  2  #A part of NonVisual Desktop Access (NVDA) 
  3  #Copyright (C) 2006-2008 NVDA Contributors <http://www.nvda-project.org/> 
  4  #This file is covered by the GNU General Public License. 
  5  #See the file COPYING for more details. 
  6   
  7  import time 
  8  import weakref 
  9  import inspect 
 10  import appModuleHandler 
 11  import api 
 12  import queueHandler 
 13  from logHandler import log 
 14  import inputCore 
 15  import globalPluginHandler 
 16  import braille 
 17   
 18  _numScriptsQueued=0 #Number of scripts that are queued to be executed 
 19  _lastScriptTime=0 #Time in MS of when the last script was executed 
 20  _lastScriptRef=None #Holds a weakref to the last script that was executed 
 21  _lastScriptCount=0 #The amount of times the last script was repeated 
 22  _isScriptRunning=False 
 23   
24 -def _makeKbEmulateScript(scriptName):
25 import keyboardHandler 26 keyName = scriptName[3:] 27 emuGesture = keyboardHandler.KeyboardInputGesture.fromName(keyName) 28 func = lambda gesture: inputCore.manager.emulateGesture(emuGesture) 29 if isinstance(scriptName, unicode): 30 # __name__ must be str; i.e. can't be unicode. 31 scriptName = scriptName.encode("mbcs") 32 func.__name__ = "script_%s" % scriptName 33 func.__doc__ = _("Emulates pressing %s on the system keyboard") % keyName 34 return func
35
36 -def _getObjScript(obj, gesture, globalMapScripts):
37 # Search the scripts from the global gesture maps. 38 for cls, scriptName in globalMapScripts: 39 if isinstance(obj, cls): 40 if scriptName is None: 41 # The global map specified that no script should execute for this gesture and object. 42 return None 43 if scriptName.startswith("kb:"): 44 # Emulate a key press. 45 return _makeKbEmulateScript(scriptName) 46 try: 47 return getattr(obj, "script_%s" % scriptName) 48 except AttributeError: 49 pass 50 51 # Search the object itself for in-built bindings. 52 return obj.getScript(gesture)
53
54 -def findScript(gesture):
55 focus = api.getFocusObject() 56 if not focus: 57 return None 58 59 # Import late to avoid circular import. 60 # We need to import this here because this might be the first import of this module 61 # and it might be needed by global maps. 62 import globalCommands 63 64 globalMapScripts = [] 65 globalMaps = [inputCore.manager.userGestureMap, inputCore.manager.localeGestureMap] 66 globalMap = braille.handler.display.gestureMap 67 if globalMap: 68 globalMaps.append(globalMap) 69 for globalMap in globalMaps: 70 for identifier in gesture.identifiers: 71 globalMapScripts.extend(globalMap.getScriptsForGesture(identifier)) 72 73 # Gesture specific scriptable object. 74 obj = gesture.scriptableObject 75 if obj: 76 func = _getObjScript(obj, gesture, globalMapScripts) 77 if func: 78 return func 79 80 # Global plugin level. 81 for plugin in globalPluginHandler.runningPlugins: 82 func = _getObjScript(plugin, gesture, globalMapScripts) 83 if func: 84 return func 85 86 # App module level. 87 app = focus.appModule 88 if app: 89 func = _getObjScript(app, gesture, globalMapScripts) 90 if func: 91 return func 92 93 # Tree interceptor level. 94 treeInterceptor = focus.treeInterceptor 95 if treeInterceptor and treeInterceptor.isReady: 96 func = _getObjScript(treeInterceptor, gesture, globalMapScripts) 97 if func and (not treeInterceptor.passThrough or getattr(func,"ignoreTreeInterceptorPassThrough",False)): 98 return func 99 100 # NVDAObject level. 101 func = _getObjScript(focus, gesture, globalMapScripts) 102 if func: 103 return func 104 for obj in reversed(api.getFocusAncestors()): 105 func = _getObjScript(obj, gesture, globalMapScripts) 106 if func and getattr(func, 'canPropagate', False): 107 return func 108 109 # Global commands. 110 func = _getObjScript(globalCommands.commands, gesture, globalMapScripts) 111 if func: 112 return func 113 114 return None
115
116 -def getScriptName(script):
117 return script.__name__[7:]
118
119 -def getScriptLocation(script):
120 try: 121 instance = script.__self__ 122 except AttributeError: 123 # Not an instance method, so this must be a fake script. 124 return None 125 name=script.__name__ 126 for cls in instance.__class__.__mro__: 127 if name in cls.__dict__: 128 return "%s.%s"%(cls.__module__,cls.__name__)
129
130 -def _queueScriptCallback(script,gesture):
131 global _numScriptsQueued 132 _numScriptsQueued-=1 133 executeScript(script,gesture)
134
135 -def queueScript(script,gesture):
136 global _numScriptsQueued 137 _numScriptsQueued+=1 138 queueHandler.queueFunction(queueHandler.eventQueue,_queueScriptCallback,script,gesture)
139
140 -def executeScript(script,gesture):
141 """Executes a given script (function) passing it the given gesture. 142 It also keeps track of the execution of duplicate scripts with in a certain amount of time, and counts how many times this happens. 143 Use L{getLastScriptRepeatCount} to find out this count value. 144 @param script: the function or method that should be executed. The function or method must take an argument of 'gesture'. 145 @type script: callable. 146 @param gesture: the input gesture that activated this script 147 @type gesture: L{inputCore.InputGesture} 148 """ 149 global _lastScriptTime, _lastScriptCount, _lastScriptRef, _isScriptRunning 150 lastScriptRef=_lastScriptRef() if _lastScriptRef else None 151 #We don't allow the same script to be executed from with in itself, but we still should pass the key through 152 scriptFunc=getattr(script,"__func__",script) 153 if _isScriptRunning and lastScriptRef==scriptFunc: 154 return gesture.send() 155 _isScriptRunning=True 156 try: 157 scriptTime=time.time() 158 scriptRef=weakref.ref(scriptFunc) 159 if (scriptTime-_lastScriptTime)<=0.5 and scriptFunc==lastScriptRef: 160 _lastScriptCount+=1 161 else: 162 _lastScriptCount=0 163 _lastScriptRef=scriptRef 164 _lastScriptTime=scriptTime 165 script(gesture) 166 except: 167 log.exception("error executing script: %s with gesture %r"%(script,gesture.displayName)) 168 finally: 169 _isScriptRunning=False
170
171 -def getLastScriptRepeatCount():
172 """The count of how many times the most recent script has been executed. 173 This should only be called from with in a script. 174 @returns: a value greater or equal to 0. If the script has not been repeated it is 0, if it has been repeated once its 1, and so forth. 175 @rtype: integer 176 """ 177 if (time.time()-_lastScriptTime)>0.5: 178 return 0 179 else: 180 return _lastScriptCount
181
182 -def isScriptWaiting():
183 return bool(_numScriptsQueued)
184
185 -def isCurrentScript(scriptFunc):
186 """Finds out if the given script is equal to the script that L{isCurrentScript} is being called from. 187 @param scriptFunc: the script retreaved from ScriptableObject.getScript(gesture) 188 @type scriptFunc: Instance method 189 @returns: True if they are equal, False otherwise 190 @rtype: boolean 191 """ 192 try: 193 givenFunc=getattr(scriptFunc.im_self.__class__,scriptFunc.__name__) 194 except AttributeError: 195 log.debugWarning("Could not get unbound method from given script",exc_info=True) 196 return False 197 parentFrame=inspect.currentframe().f_back 198 try: 199 realObj=parentFrame.f_locals['self'] 200 except KeyError: 201 log.debugWarning("Could not get self instance from parent frame instance method",exc_info=True) 202 return False 203 try: 204 realFunc=getattr(realObj.__class__,parentFrame.f_code.co_name) 205 except AttributeError: 206 log.debugWarning("Could not get unbound method from parent frame instance",exc_info=True) 207 return False 208 return givenFunc==realFunc
209