orca r4202 - in branches/phase2: . src/orca
- From: wwalker svn gnome org
- To: svn-commits-list gnome org
- Subject: orca r4202 - in branches/phase2: . src/orca
- Date: Sat, 13 Sep 2008 08:59:49 +0000 (UTC)
Author: wwalker
Date: Sat Sep 13 08:59:49 2008
New Revision: 4202
URL: http://svn.gnome.org/viewvc/orca?rev=4202&view=rev
Log:
Add some TODO's, do a little reorganizing.
Modified:
branches/phase2/pylintrc
branches/phase2/src/orca/braille.py
branches/phase2/src/orca/input_bindings.py
branches/phase2/src/orca/orca.in
branches/phase2/src/orca/orca.py
branches/phase2/src/orca/script.py
branches/phase2/src/orca/script_manager.py
branches/phase2/src/orca/settings.py
branches/phase2/src/orca/utils.py
Modified: branches/phase2/pylintrc
==============================================================================
--- branches/phase2/pylintrc (original)
+++ branches/phase2/pylintrc Sat Sep 13 08:59:49 2008
@@ -88,7 +88,7 @@
# R0915: Function or method has too many statements
#
#disable-msg=E0611,C0111,R0201,W0102,W0141,W0333,W0401,W0403,W0603,W0612,W0613,W0702,W0704,W0511,R0801,R0912,R0915,R0914,R0904,R0903,R0401,R0911,R0913,C0302,R0902
-disable-msg=W0403,W0612,W0613,W0702,W0704,R0201,R0903,R0912,R0913
+disable-msg=W0403,W0612,W0613,W0702,W0704,R0201,R0902,R0903,R0912,R0913
[REPORTS]
Modified: branches/phase2/src/orca/braille.py
==============================================================================
--- branches/phase2/src/orca/braille.py (original)
+++ branches/phase2/src/orca/braille.py Sat Sep 13 08:59:49 2008
@@ -15,6 +15,16 @@
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
+# Allow globals to be used in this module.
+#
+# pylint: disable-msg=W0603
+
+# TODO: make new module for braille regions. This module is now
+# just for I/O with the braille display.
+
+# TODO: find a way to output the attributes. Perhaps an extra line
+# under the VISIBLE line where we use - ~ and =.
+
"""Used to get input events from the braille display and to paint raw
strings to the braille display.
"""
@@ -119,10 +129,6 @@
#
_callback = None
-# Allow globals to be used in this module.
-#
-# pylint: disable-msg=W0603
-#
def writeText(text, attributeMask, cursorCell):
"""Writes the given text with the given attribute mask. Also
puts the cursor at the given 1-based cursorCell (0 means no cursor).
@@ -174,7 +180,7 @@
#
consumed = _callback(event)
except:
- log.exception('exception from braille callback')
+ log.exception("handled exception from braille callback:")
consumed = False
return consumed
@@ -212,7 +218,7 @@
keySet.append(brlapi.KEY_TYPE_CMD | key)
_brlAPI.acceptKeys(brlapi.rangeType_command, keySet)
except:
- log.exception('exception while setting up braille key ranges:')
+ log.exception("handled exception while setting up braille key ranges:")
def init(callback=None):
"""Initializes the braille module, connecting to the BrlTTY driver.
@@ -256,7 +262,7 @@
gobject.IO_IN,
_brlAPIKeyReader)
except:
- log.exception("exception while initializing brltty:")
+ log.exception("handled exception while initializing brltty:")
return False
_displaySize = _brlAPI.displaySize
Modified: branches/phase2/src/orca/input_bindings.py
==============================================================================
--- branches/phase2/src/orca/input_bindings.py (original)
+++ branches/phase2/src/orca/input_bindings.py Sat Sep 13 08:59:49 2008
@@ -199,12 +199,7 @@
- modifiers: any modifiers associated with the event
"""
log.debug("process %s for %s" % (inputEvent, script))
- try:
- consumed = self.function(script, inputEvent, modifiers)
- except:
- log.exception("while attempting to process input event")
- consumed = False
- return consumed
+ self.function(script, inputEvent, modifiers)
class Binding:
"""A single input event binding, consisting of a command, a keyboard
@@ -365,29 +360,24 @@
return None
- def _consumeInputEvent(self,
- script,
- inputEvent,
- commandCode,
- modifiers,
- process=True):
- """Attempts to consume the given input event.
+ def _processInputEvent(self,
+ script,
+ inputEvent,
+ commandCode,
+ modifiers,
+ process=True):
+ """Processes the given input event. Returns True if a handler
+ was found and the event was actually processed.
"""
- consumed = False
handler = self.getHandler(commandCode,
modifiers,
script.getClickCount())
if handler:
- consumed = True
- if process:
- try:
- handler.processInputEvent(script,
- inputEvent,
- modifiers)
- except:
- log.exception("while processing input event")
+ handler.processInputEvent(script,
+ inputEvent,
+ modifiers)
- return consumed
+ return handler != None
########################################################################
# #
@@ -437,13 +427,11 @@
def __init__(self):
Bindings.__init__(self)
- def consumeInputEvent(self, script, keyboardEvent, modifiers):
- """Attempts to consume the given keyboard event. If these
- keybindings have a handler for the given keyboardEvent, it is
- assumed the event will always be consumed (e.g., we want to
- consume key presses as well, but not really process them).
+ def processInputEvent(self, script, keyboardEvent, modifiers):
+ """Processes the given input event. Returns True if a handler
+ was found and the event was actually processed.
"""
- return Bindings._consumeInputEvent(
+ return Bindings._processInputEvent(
self,
script,
keyboardEvent,
@@ -491,10 +479,11 @@
def __init__(self):
Bindings.__init__(self)
- def consumeInputEvent(self, script, brailleEvent, modifiers):
- """Attempts to consume the given braille event.
+ def processInputEvent(self, script, brailleEvent, modifiers):
+ """Processes the given input event. Returns True if a handler
+ was found and the event was actually processed.
"""
- return Bindings._consumeInputEvent(
+ return Bindings._processInputEvent(
self,
script,
brailleEvent,
Modified: branches/phase2/src/orca/orca.in
==============================================================================
--- branches/phase2/src/orca/orca.in (original)
+++ branches/phase2/src/orca/orca.in Sat Sep 13 08:59:49 2008
@@ -113,41 +113,6 @@
cleanup
}
-main()
-{
- RUN=1
- while [ "$RUN" -gt 0 ]
- do
- runOrca &
- orca_pid=$!
- wait $orca_pid
-
- RUN=$? # quit on a normal exit status from Orca
-
- # We will stop re-running Orca on SEGV's (139 = SEGV + 128).
- # The reason for this is that there are cases where Python
- # will SEGV when Orca attempts to exit normally. This happens
- # because of something going on in pyorbit. This should be
- # fixed in pyorbit 2.14.1, but not everyone has that.
- # So...we'll check for it.
- #
- if [ "$RUN" -eq 139 ]
- then
- RUN=0
- fi
-
- # We will also stop re-running Orca on KILL's (137 = KILL + 128).
- # The reason for this is that if someone has done a "kill -KILL"
- # on the Python process, it was probably on purpose and they want
- # everything to die.
- #
- if [ "$RUN" -eq 137 ]
- then
- RUN=0
- fi
- done
-}
-
trap kill_orca QUIT TERM INT ABRT
trap hup_orca HUP
Modified: branches/phase2/src/orca/orca.py
==============================================================================
--- branches/phase2/src/orca/orca.py (original)
+++ branches/phase2/src/orca/orca.py Sat Sep 13 08:59:49 2008
@@ -15,6 +15,21 @@
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
+# TODO: key echo (perhaps move this to the script itself?)
+# TODO: speech stopping on mouse buttons (perhaps in script itself?)
+# TODO: learn mode (maybe in script manager?)
+# TODO: click count (maybe in script manager?)
+# TODO: capturing of keystrokes (maybe in script?)
+# TODO: setting Orca modifier (maybe in script manager?)
+# TODO: toggling of speech on/off (maybe per script?)
+# TODO: loading of user settings
+# TODO: main window GUI
+# TODO: preferences GUI
+# TODO: preferences console
+# TODO: help (gnome.help_display_with_doc_id)
+# TODO: quit GUI
+# TODO: find GUI
+
"""The main module for the Orca screen reader."""
__id__ = "$Id: orca.py 4148 2008-09-03 14:31:54Z wwalker $"
@@ -72,65 +87,6 @@
#
_commandLineSettings = settings.Settings(settings.globalSettings)
-def abort(exitCode=1):
- """Aborts orca because something went horribly wrong.
-
- Arguments:
- - exitCode: the exit code to send to the calling process.
- """
-
- # We know what we are doing here, so tell pylint not to flag
- # the _exit method call as a warning. The disable-msg is
- # localized to just this method.
- #
- # pylint: disable-msg=W0212
- #
- log.debug("aborting with exit code %d" % exitCode)
- os._exit(exitCode)
-
-def timeout(signum=None, frame=None):
- """Aborts when we get a timeout, indicating an operation has
- taken way too long.
- """
-
- log.debug("timeout with signum %d" % signum)
- abort(50)
-
-exitCount = 0
-def shutdownOnSignal(signum, frame):
- """Shuts down (gracefully if possible) when we get a given signal.
- """
- # We don't like globals, but we'll use it for this case.
- #
- # pylint: disable-msg=W0603
- #
- global exitCount
-
- log.debug("shutting down and exiting due to signal = %d" % signum)
-
- # Well...we'll try to exit nicely, but if we keep getting called,
- # something bad is happening, so just quit.
- #
- if exitCount:
- abort(signum)
- else:
- exitCount += 1
-
- try:
- shutdown()
- cleanExit = True
- except:
- cleanExit = False
-
- if not cleanExit:
- abort(signum)
-
-def abortOnSignal(signum, frame):
- """Aborts quickly when we get a given signal.
- """
- log.debug("aborting due to signal = %d" % signum)
- abort(signum)
-
def usage():
"""Prints out usage information.
"""
@@ -202,7 +158,7 @@
os.chdir(userPrefsDir)
_commandLineSettings["userPrefsDir"] = userPrefsDir
except:
- log.exception("exception processing user-prefs-dir:")
+ log.exception("handled exception with user-prefs-dir:")
if opt in ("-e", "--enable"):
feature = val.strip()
@@ -219,7 +175,7 @@
_commandLineSettings["showMainWindow"] = True
else:
usage()
- abort(2)
+ utils.abort(2)
if opt in ("-d", "--disable"):
feature = val.strip()
@@ -235,7 +191,7 @@
_commandLineSettings["showMainWindow"] = False
else:
usage()
- abort(2)
+ utils.abort(2)
if opt in ("-s", "--gui-setup", "--setup"):
_commandLineSettings["setupRequested"] = True
@@ -247,19 +203,19 @@
_commandLineSettings["bypassSetup"] = True
if opt in ("-?", "--help"):
usage()
- abort(0)
+ utils.abort(0)
if opt in ("-v", "--version"):
print "Orca %s" % platform.version
- abort(0)
+ utils.abort(0)
if opt in ("-l", "--list-apps"):
apps = utils.getKnownApplications()
for app in apps:
print app.name
- abort(0)
+ utils.abort(0)
except:
log.exception("exception processing command line arguments:")
usage()
- abort(2)
+ utils.abort(2)
def main():
"""The main entry point for Orca. The exit codes for Orca will
@@ -270,11 +226,12 @@
"""
# Various signal handlers we want to listen for.
#
- signal.signal(signal.SIGHUP, shutdownOnSignal)
- signal.signal(signal.SIGINT, shutdownOnSignal)
- signal.signal(signal.SIGTERM, shutdownOnSignal)
- signal.signal(signal.SIGQUIT, shutdownOnSignal)
- signal.signal(signal.SIGSEGV, abortOnSignal)
+ utils.shutdown = shutdown
+ signal.signal(signal.SIGHUP, utils.shutdownOnSignal)
+ signal.signal(signal.SIGINT, utils.shutdownOnSignal)
+ signal.signal(signal.SIGTERM, utils.shutdownOnSignal)
+ signal.signal(signal.SIGQUIT, utils.shutdownOnSignal)
+ signal.signal(signal.SIGSEGV, utils.abortOnSignal)
# See if the desktop is running. If it is, the import of gtk will
# succeed. If it isn't, the import will fail.
Modified: branches/phase2/src/orca/script.py
==============================================================================
--- branches/phase2/src/orca/script.py (original)
+++ branches/phase2/src/orca/script.py Sat Sep 13 08:59:49 2008
@@ -15,6 +15,21 @@
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
+# TODO: Add ability for script to find/load/save its own settings file.
+# TODO: Add bookmarks support
+# TODO: Add where am I support
+# TODO: Add braille generator support
+# TODO: Add speech generator support
+# TODO: Add tutorial support
+# TODO: Add structural navigation support
+# TODO: Add flat review support
+# TODO: Add click count
+# TODO: Add hook to override key bindings
+# TODO: Add hook to override braille bindings
+# TODO: Add hook to override pronunciations
+# TODO: Add locus of focus support
+# TODO: Add key bypass
+
"""Each script maintains a set of key bindings, braille bindings, and
AT-SPI event listeners. The key bindings are an instance of
KeyBindings. The braille bindings are also a dictionary where the
@@ -27,7 +42,8 @@
This Script class is not intended to be instantiated directly.
Instead, it is expected that subclasses of the Script class will be
-created in their own module. See default.py for an example."""
+created in their own module. See default.py for an example.
+"""
__id__ = "$Id: script.py 4103 2008-08-15 11:07:31Z wwalker $"
__version__ = "$Revision: 4103 $"
@@ -39,6 +55,8 @@
log = logging.getLogger('orca.script')
import braille
+import input_bindings
+import utils
class Script:
"""The specific focus tracking scripts for applications.
@@ -61,12 +79,16 @@
self._name += " (module=" + self.__module__ + ")"
self._isActive = False
-
self.presentIfInactive = False
- self.listeners = self._createListeners()
- self.keyBindings = self._createKeyBindings()
- self.brailleBindings = self._createBrailleBindings()
+
+ self._objectEventListeners = self._createObjectEventListeners()
+ self._inputEventHandlers = self._createInputEventHandlers()
+ self._keyBindings = self._createKeyBindings()
+ self._brailleBindings = self._createBrailleBindings()
+ self._focus = None
+ self._pointOfReference = {}
+
log.debug("NEW SCRIPT: %s" % self)
def __str__(self):
@@ -74,7 +96,7 @@
"""
return self._name
- def _createListeners(self):
+ def _createObjectEventListeners(self):
"""Sets up the AT-SPI event listeners for this script.
Returns a dictionary where the keys are AT-SPI event names
@@ -82,19 +104,28 @@
"""
return {}
+ def _createInputEventHandlers(self):
+ """Defines InputEventHandler fields for this script that can be
+ called by the key and braille bindings.
+
+ Returns a dictionary where the key is a handler name and the
+ values are instances if input_event.InputEventHandler.
+ """
+ return {}
+
def _createKeyBindings(self):
"""Defines the key bindings for this script.
Returns an instance of input_bindings.KeyBindings.
"""
- return []
+ return input_bindings.KeyBindings()
def _createBrailleBindings(self):
"""Defines the braille bindings for this script.
Returns an instance of input_bindings.BrailleBindings
"""
- return []
+ return input_bindings.BrailleBindings()
def _getPronunciations(self):
"""Defines the application specific pronunciations for this script.
@@ -114,12 +145,15 @@
Returns True if the event is of interest.
"""
+ # TODO: implement consumesKeyboardEvent
+ # TODO: add support for user-settings.py keyBindingsMap
return False
def processKeyboardEvent(self, keyboardEvent):
"""Called whenever a key is pressed on the Braille display
and we have an interest in it.
"""
+ # TODO: implement processKeyboardEvent
log.debug("processKeyboardEvent %s" % keyboardEvent)
def consumesBrailleEvent(self, brailleEvent):
@@ -132,6 +166,8 @@
Returns True if the event is of interest.
"""
+ # TODO: implement consumesBrailleEvent
+ # TODO: add support for user-settings.py keyBindingsMap
return False
def processBrailleEvent(self, brailleEvent):
@@ -141,6 +177,7 @@
Arguments:
- brailleEvent: an instance of input_event.BrailleEvent
"""
+ # TODO: implement processBrailleEvent
log.debug("processBrailleEvent %s" % brailleEvent)
def processObjectEvent(self, event):
@@ -171,25 +208,43 @@
# keys is *not* deterministic, and is not guaranteed to be related
# to the order in which they were added.
#
- for key in self.listeners.keys():
+ for key in self._objectEventListeners.keys():
if event.type.startswith(key):
- self.listeners[key](event)
+ self._objectEventListeners[key](event)
def activate(self):
- """Called when this script is activated."""
+ """Called when this script is activated.
+ """
+ if self._isActive:
+ return
+
log.debug("%s has been activated" % self)
- self._isActive = True
+ for eventType in self._objectEventListeners.keys():
+ utils.registerEventListener(eventType)
- # Tell BrlTTY which commands we care about.
- # [[[TODO: WDW - do this.]]]
+ # TODO: Tell BrlTTY which commands we care about by looking at
+ # self._brailleBindings
#
braille.setupKeyRanges([])
+ self._isActive = True
+
def deactivate(self):
- """Called when this script is deactivated."""
+ """Called when this script is deactivated.
+ """
+ if not self._isActive:
+ return
+
log.debug("%s has been deactivated" % self)
+ for eventType in self._objectEventListeners.keys():
+ utils.deregisterEventListener(eventType)
+
+ # Tell BrlTTY which commands we don't care about events any more.
+ #
+ braille.setupKeyRanges([])
+
self._isActive = False
if __name__ == "__main__":
Modified: branches/phase2/src/orca/script_manager.py
==============================================================================
--- branches/phase2/src/orca/script_manager.py (original)
+++ branches/phase2/src/orca/script_manager.py Sat Sep 13 08:59:49 2008
@@ -15,6 +15,9 @@
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
+# TODO: incorporate utils.startTimeout for handling events
+# TODO: add bandaid for tooltips from old focus_tracking_presenter?
+
"""Provides the script manager for Orca."""
__id__ = "$Id: focus_tracking_presenter.py 4088 2008-08-06 20:42:48Z wwalker $"
@@ -95,9 +98,10 @@
self._gidleId = 0
self._eventQueue = Queue.Queue(0)
- self._registerEventListener("window:activate")
- self._registerEventListener("window:deactivate")
- self._registerEventListener("object:children-changed:remove")
+ utils.setEventListenerCallback(self._enqueueEvent)
+ utils.registerEventListener("window:activate")
+ utils.registerEventListener("window:deactivate")
+ utils.registerEventListener("object:children-changed:remove")
# Cover all masks in 8 bits.
#
@@ -144,75 +148,6 @@
########################################################################
# #
- # METHODS FOR KEEPING TRACK OF LISTENERS REGISTERED WITH ATSPI #
- # #
- ########################################################################
-
- def _registerEventListener(self, eventType):
- """Tells this module to listen for the given event type.
-
- Arguments:
- - eventType: the event type.
- """
- if eventType in self._listenerCounts:
- self._listenerCounts[eventType] += 1
- else:
- pyatspi.Registry.registerEventListener(self._enqueueEvent,
- eventType)
- self._listenerCounts[eventType] = 1
-
- def _deregisterEventListener(self, eventType):
- """Tells this module to stop listening for the given event type.
-
- Arguments:
- - eventType: the event type.
- """
- self._listenerCounts[eventType] -= 1
- if self._listenerCounts[eventType] == 0:
- pyatspi.Registry.deregisterEventListener(self._enqueueEvent,
- eventType)
- del self._listenerCounts[eventType]
-
- def _registerAllEvents(self):
- """Register all top-level event types except for "mouse".
- """
- topLevelEvents = filter(lambda et: ':' not in et and 'mouse' not in et,
- pyatspi.EVENT_TREE)
- for event_type in topLevelEvents:
- pyatspi.Registry.registerEventListener(
- self._enqueueEvent, event_type)
-
- def _deregisterAllEvents(self):
- """Unregister for all the event types except for "mouse".
- """
- topLevelEvents = filter(lambda et: ':' not in et and 'mouse' not in et,
- pyatspi.EVENT_TREE)
- for event_type in topLevelEvents:
- pyatspi.Registry.deregisterEventListener(
- self._enqueueEvent, event_type)
-
- def _registerEventListeners(self, script):
- """Tells the ScriptManager to listen for all
- the event types of interest to the script.
-
- Arguments:
- - script: the script.
- """
- for eventType in script.listeners.keys():
- self._registerEventListener(eventType)
-
- def _deregisterEventListeners(self, script):
- """Tells the FocusTrackingPresenter to stop listening for all the
- event types of interest to the script.
-
- Arguments:
- - script: the script.
- """
- for eventType in script.listeners.keys():
- self._deregisterEventListener(eventType)
-
- ########################################################################
- # #
# METHODS FOR KEEPING TRACK OF KNOWN SCRIPTS. #
# #
########################################################################
@@ -279,7 +214,7 @@
except ImportError:
log.debug("...could not find %s.py" % name)
except:
- log.exception("while attempting to import %s" % name)
+ log.exception("handled exception importing %s:" % name)
if module:
try:
script = module.Script(app)
@@ -288,7 +223,7 @@
# we want to let the script developer know what went wrong,
# but we also want to move along without crashing Orca.
#
- log.exception("while attempting to create script")
+ log.exception("handled exception creating script:")
# If there is no custom script for an application, try seeing if
# there is a script for the toolkit of the application. If there
@@ -314,7 +249,7 @@
except ImportError:
log.debug("...could not find %s.py" % name)
except:
- log.exception("while attempting to import %s" % name)
+ log.exception("handled exception importing %s:" % name)
if not script:
script = default.Script(app)
@@ -338,13 +273,7 @@
for app in self._knownScripts.keys():
if app not in desktop:
script = self._knownScripts[app]
- self._deregisterEventListeners(script)
-
- # Provide a bunch of hints to the garbage collector
- # that we just don't care about this stuff any longer.
- # Note the "app.app = None" - that helps remove a
- # cycle of the application referring to itself.
- #
+ script.deactivate()
del self._knownScripts[app]
del app
del script
@@ -366,14 +295,12 @@
if not app:
if not self._defaultScript:
self._defaultScript = default.Script(None)
- self._registerEventListeners(self._defaultScript)
script = self._defaultScript
elif app in self._knownScripts:
script = self._knownScripts[app]
else:
script = self._createScript(app)
self._knownScripts[app] = script
- self._registerEventListeners(script)
return script
@@ -410,7 +337,7 @@
try:
self._activeScript.processKeyboardEvent(keyboardEvent)
except:
- log.exception("exception while processing keyboard event:")
+ log.exception("handled exception while processing keyboard event:")
def _dispatchBrailleEvent(self, brailleEvent):
"""Called whenever we get a braille input event.
@@ -421,7 +348,7 @@
try:
self._activeScript.processBrailleEvent(brailleEvent)
except:
- log.exception("exception while processing braille event:")
+ log.exception("handled exception while processing braille event:")
def _dispatchObjectEvent(self, event):
"""Handles all events destined for scripts.
@@ -487,7 +414,7 @@
log.debug("IGNORING DEFUNCT OBJECT")
return
except:
- log.exception("exception while checking object state for defunct:")
+ log.exception("handled exception while checking for defunct:")
return
try:
@@ -503,7 +430,7 @@
s = self._activeScript
except:
s = None
- log.exception("exception while trying to find script:")
+ log.exception("handled exception trying to find script:")
return
if not s:
@@ -580,7 +507,7 @@
log.warning(" SUCCEEDED AFTER %d TRIES" % retryCount)
break
except LookupError:
- log.exception("exception while processing %s" % event.type)
+ log.exception("handled exception processing %s:" % event.type)
retryCount += 1
if retryCount <= commFailureAttemptLimit:
log.warning(" TRYING AGAIN (%d)" % retryCount)
@@ -588,7 +515,7 @@
else:
log.warning(" GIVING UP AFTER %d TRIES" % (retryCount - 1))
except:
- log.exception("exception while processing %s" % event.type)
+ log.exception("handled exception processing %s:" % event.type)
break
def _enqueueEvent(self, e):
@@ -673,7 +600,7 @@
except Queue.Empty:
rerun = False
except:
- log.exception("while processing event")
+ log.exception("handled exception processing event:")
return rerun
Modified: branches/phase2/src/orca/settings.py
==============================================================================
--- branches/phase2/src/orca/settings.py (original)
+++ branches/phase2/src/orca/settings.py Sat Sep 13 08:59:49 2008
@@ -50,6 +50,11 @@
except TypeError:
raise KeyError(key)
+# Global settings that scripts can use when creating their own
+# Settings instances.
+#
+# TODO: fill these in with defaults from the old settings.py.
+#
globalSettings = Settings()
if __name__ == "__main__":
@@ -67,4 +72,4 @@
try:
print blah["o"]
except KeyError:
- log.exception("This exception is expected:")
+ log.exception("the following exception is expected:")
Modified: branches/phase2/src/orca/utils.py
==============================================================================
--- branches/phase2/src/orca/utils.py (original)
+++ branches/phase2/src/orca/utils.py Sat Sep 13 08:59:49 2008
@@ -15,6 +15,10 @@
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
+# Allow globals to be used in this module.
+#
+# pylint: disable-msg=W0603
+
"""Common utilities for the Orca screen reader."""
__id__ = "$Id: orca.py 4148 2008-09-03 14:31:54Z wwalker $"
@@ -26,7 +30,166 @@
import logging
log = logging.getLogger('orca.utils')
+import os
import pyatspi
+import signal
+import sys
+import traceback
+
+def logStack(logger):
+ """Logs a snapshot of the stack to the given logger without
+ including the stack trace for this specific method.
+ """
+ # We know what we are doing here, so tell pylint not to flag
+ # the _getframe method call as a warning. The disable-msg is
+ # localized to just this method.
+ #
+ # pylint: disable-msg=W0212
+ #
+ logger.debug('current stack:\n %s' \
+ % "".join(traceback.format_stack(sys._getframe(1), 100)).strip("\n")[1:])
+
+############################################################################
+# #
+# METHODS FOR DEALING WITH SIGNALS, EXITING, ABORTING, AND TIMEOUTS #
+# #
+############################################################################
+
+# The timeout value (in seconds) used to determine if Orca has hung or not.
+# A value of 0 means don't do hang checking.
+#
+timeoutTime = 10
+
+def abort(exitCode=1):
+ """Aborts orca because something went horribly wrong.
+
+ Arguments:
+ - exitCode: the exit code to send to the calling process.
+ """
+ # We know what we are doing here, so tell pylint not to flag
+ # the _exit method call as a warning. The disable-msg is
+ # localized to just this method.
+ #
+ # pylint: disable-msg=W0212
+ #
+ log.debug("aborting with exit code %d" % exitCode)
+ os._exit(exitCode)
+
+shutdown = None
+def shutdownOnSignal(signum, frame):
+ """Shuts down (gracefully if possible) when we get a given signal.
+ """
+ log.debug("shutting down and exiting due to signal = %d" % signum)
+
+ # We know shutdown may not be callable (i.e., it might be None),
+ # so we trap for it in a try/except clause.
+ #
+ # pylint: disable-msg=E1102
+ #
+ try:
+ shutdown()
+ except:
+ abort(signum)
+
+def abortOnSignal(signum, frame):
+ """Aborts quickly when we get a given signal.
+ """
+ log.debug("aborting due to signal = %d" % signum)
+ abort(signum)
+
+def timeout(signum=None, frame=None):
+ """Aborts when we get a timeout, indicating an operation has
+ taken way too long.
+ """
+ log.critical("timeout with signum %d:" % signum)
+ logStack(log)
+ abort(50)
+
+def startTimeout():
+ """Adds a timeout alarm. Must call stopTimeout to stop it."""
+ if timeoutTime > 0:
+ signal.signal(signal.SIGALRM, timeout)
+ signal.alarm(timeoutTime)
+
+def stopTimeout():
+ """Removes a timeout alarm set by startTimeout."""
+ if timeoutTime > 0:
+ signal.alarm(0)
+
+############################################################################
+# #
+# METHODS FOR LIMITING THE NUMBER OF REGISTERED EVENT LISTENERS TO 1 #
+# #
+############################################################################
+
+_eventListenerCounts = {}
+_eventListenerCallback = None
+
+def setEventListenerCallback(callback):
+ """Sets the event listener callback. This must be called before
+ any calls to registerEventListener or deregisterEventListener.
+ """
+ global _eventListenerCallback
+ if _eventListenerCallback:
+ log.critical("setEventListenerCallback called more than once!!!")
+ abort()
+ _eventListenerCallback = callback
+
+def registerEventListener(eventType):
+ """Listen for the given event type.
+
+ Arguments:
+ - eventType: the event type.
+ """
+ if not _eventListenerCallback:
+ log.critical("setEventListenerCallback not set!!!")
+ abort()
+
+ if eventType in _eventListenerCounts:
+ _eventListenerCounts[eventType] += 1
+ else:
+ pyatspi.Registry.registerEventListener(_eventListenerCallback,
+ eventType)
+ _eventListenerCounts[eventType] = 1
+
+def deregisterEventListener(eventType):
+ """Stop listening for the given event type.
+
+ Arguments:
+ - eventType: the event type.
+ """
+
+ if not _eventListenerCallback:
+ log.critical("setEventListenerCallback not set!!!")
+ abort()
+
+ _eventListenerCounts[eventType] -= 1
+ if _eventListenerCounts[eventType] == 0:
+ pyatspi.Registry.deregisterEventListener(_eventListenerCallback,
+ eventType)
+ del _eventListenerCounts[eventType]
+
+def registerAllEvents():
+ """Register all top-level event types except for "mouse".
+ """
+ topLevelEvents = filter(lambda et: ':' not in et and 'mouse' not in et,
+ pyatspi.EVENT_TREE)
+ for event_type in topLevelEvents:
+ registerEventListener(event_type)
+
+def deregisterAllEvents():
+ """Unregister for all the event types except for "mouse".
+ """
+ topLevelEvents = filter(lambda et: ':' not in et and 'mouse' not in et,
+ pyatspi.EVENT_TREE)
+ for event_type in topLevelEvents:
+ deregisterEventListener(event_type)
+
+############################################################################
+# #
+# METHODS FOR FINDING THE KNOWN ACCESSIBLE APPLICATIONS AND ACTIVE WINDOW #
+# #
+############################################################################
def getKnownApplications():
"""Retrieves the list of currently running apps for the desktop
@@ -60,12 +223,16 @@
window = child
break
except:
- log.exception("exception looking at accessible's state")
+ log.exception("handled exception looking at accessible state:")
log.debug("...findActiveWindow: %s" % window)
return window
+def _myCallback(event):
+ """Just for testing when run in standalone mode."""
+ print event
+
if __name__ == "__main__":
logging.basicConfig(format="%(name)s %(message)s")
log.setLevel(logging.DEBUG)
@@ -74,3 +241,20 @@
for application in getKnownApplications():
print " ", application
print "Active window: %s" % findActiveWindow()
+
+ print "Checking logStack method:"
+ logStack(log)
+
+ print "Checking timeout support (wait %d seconds):" % (timeoutTime - 3)
+ import time
+ startTimeout()
+ time.sleep(timeoutTime - 3)
+ stopTimeout()
+
+ print "Listening for window events. Press Ctrl+C to quit."
+ setEventListenerCallback(_myCallback)
+ registerEventListener("window")
+ registerEventListener("window")
+ deregisterEventListener("window")
+ pyatspi.Registry.start()
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]