diff options
Diffstat (limited to 'build/lib.linux-x86_64-2.7/dogtail/procedural.py')
-rw-r--r-- | build/lib.linux-x86_64-2.7/dogtail/procedural.py | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/build/lib.linux-x86_64-2.7/dogtail/procedural.py b/build/lib.linux-x86_64-2.7/dogtail/procedural.py new file mode 100644 index 00000000000..c87ae86181c --- /dev/null +++ b/build/lib.linux-x86_64-2.7/dogtail/procedural.py @@ -0,0 +1,455 @@ +""" +Dogtail's procedural UI +All the classes here are intended to be single-instance, except for Action. +""" +__author__ = 'Zack Cerza <zcerza@redhat.com>' +# +# +# WARNING: Here There Be Dragons (TM) # +# +# If you don't understand how to use this API, you almost certainly don't # +# want to read the code first. We make use of some very non-intuitive # +# features of Python in order to make the API very simplistic. Therefore, # +# you should probably only read this code if you're already familiar with # +# some of Python's advanced features. You have been warned. ;) # +# +# + +import tree +import predicate +from config import config +from utils import Lock +import rawinput + +#FocusError = "FocusError: %s not found" + + +class FocusError(Exception): + pass + +import errors + + +def focusFailed(pred): + errors.warn('The requested widget could not be focused: %s' % + pred.debugName) + +ENOARGS = "At least one argument is needed" + + +class FocusBase(object): + + """ + The base for every class in the module. Does nothing special, really. + """ + node = None + + def __getattr__(self, name): + # Fold all the Node's AT-SPI properties into the Focus object. + try: + return getattr(self.node, name) + except AttributeError: + raise AttributeError(name) + + def __setattr__(self, name, value): + # Fold all the Node's AT-SPI properties into the Focus object. + if name == 'node': + setattr(self.__class__, name, value) + else: + try: + setattr(self.node, name, value) + except AttributeError: + raise AttributeError(name) + + +class FocusApplication (FocusBase): + + """ + Keeps track of which application is currently focused. + """ + desktop = tree.root + + def __call__(self, name): + """ + Search for an application that matches and refocus on the given name. + """ + try: + pred = predicate.IsAnApplicationNamed(name) + app = self.desktop.findChild( + pred, recursive=False, retry=False) + except tree.SearchError: + if config.fatalErrors: + raise FocusError(name) + else: + focusFailed(pred) + return False + if app: + FocusApplication.node = app + FocusDialog.node = None + FocusWindow.node = None + FocusWidget.node = None + return True + + +class FocusDesktop (FocusBase): + + """ + This isn't used yet, and may never be used. + """ + pass + + +class FocusWindow (FocusBase): + + """ + Keeps track of which window is currently focused. + """ + + def __call__(self, name): + """ + Search for a dialog that matches the given name and refocus on it. + """ + result = None + pred = predicate.IsAWindowNamed(name) + try: + result = FocusApplication.node.findChild( + pred, requireResult=False, recursive=False) + except AttributeError: + pass + if result: + FocusWindow.node = result + FocusDialog.node = None + FocusWidget.node = None + else: + if config.fatalErrors: + raise FocusError(pred.debugName) + else: + focusFailed(pred) + return False + return True + + +class FocusDialog (FocusBase): + + """ + Keeps track of which dialog is currently focused. + """ + + def __call__(self, name): + """ + Search for a dialog that matches the given name and refocus on it. + """ + result = None + pred = predicate.IsADialogNamed(name) + try: + result = FocusApplication.node.findChild( + pred, requireResult=False, recursive=False) + except AttributeError: + pass + if result: + FocusDialog.node = result + FocusWidget.node = None + else: + if config.fatalErrors: + raise FocusError(pred.debugName) + else: + focusFailed(pred) + return False + return True + + +class FocusWidget (FocusBase): + + """ + Keeps track of which widget is currently focused. + """ + + def findByPredicate(self, pred): + result = None + try: + result = FocusWidget.node.findChild( + pred, requireResult=False, retry=False) + except AttributeError: + pass + if result: + FocusWidget.node = result + else: + try: + result = FocusDialog.node.findChild( + pred, requireResult=False, retry=False) + except AttributeError: + pass + if result: + FocusWidget.node = result + else: + try: + result = FocusWindow.node.findChild( + pred, requireResult=False, retry=False) + except AttributeError: + pass + if result: + FocusWidget.node = result + else: + try: + result = FocusApplication.node.findChild( + pred, requireResult=False, retry=False) + if result: + FocusWidget.node = result + except AttributeError: + if config.fatalErrors: + raise FocusError(pred) + else: + focusFailed(pred) + return False + + if result is None: + FocusWidget.node = result + if config.fatalErrors: + raise FocusError(pred.debugName) + else: + focusFailed(pred) + return False + return True + + def __call__(self, name='', roleName='', description=''): + """ + If name, roleName or description are specified, search for a widget that matches and refocus on it. + """ + if not name and not roleName and not description: + raise TypeError(ENOARGS) + + # search for a widget. + pred = predicate.GenericPredicate(name=name, + roleName=roleName, description=description) + return self.findByPredicate(pred) + + +class Focus (FocusBase): + + """ + The container class for the focused application, dialog and widget. + """ + + def __getattr__(self, name): + raise AttributeError(name) + + def __setattr__(self, name, value): + if name in ('application', 'dialog', 'widget', 'window'): + self.__dict__[name] = value + else: + raise AttributeError(name) + + desktop = tree.root + application = FocusApplication() + app = application # shortcut :) + dialog = FocusDialog() + window = FocusWindow() + frame = window + widget = FocusWidget() + + def button(self, name): + """ + A shortcut to self.widget.findByPredicate(predicate.IsAButtonNamed(name)) + """ + return self.widget.findByPredicate(predicate.IsAButtonNamed(name)) + + def icon(self, name): + """ + A shortcut to self.widget(name, roleName = 'icon') + """ + return self.widget(name=name, roleName='icon') + + def menu(self, name): + """ + A shortcut to self.widget.findByPredicate(predicate.IsAMenuNamed(name)) + """ + return self.widget.findByPredicate(predicate.IsAMenuNamed(name)) + + def menuItem(self, name): + """ + A shortcut to self.widget.findByPredicate(predicate.IsAMenuItemNamed(name)) + """ + return self.widget.findByPredicate(predicate.IsAMenuItemNamed(name)) + + def table(self, name=''): + """ + A shortcut to self.widget(name, roleName 'table') + """ + return self.widget(name=name, roleName='table') + + def tableCell(self, name=''): + """ + A shortcut to self.widget(name, roleName 'table cell') + """ + return self.widget(name=name, roleName='table cell') + + def text(self, name=''): + """ + A shortcut to self.widget.findByPredicate(IsATextEntryNamed(name)) + """ + return self.widget.findByPredicate(predicate.IsATextEntryNamed(name)) + + +class Action (FocusWidget): + + """ + Aids in executing AT-SPI actions, refocusing the widget if necessary. + """ + + def __init__(self, action): + """ + action is a string with the same name as the AT-SPI action you wish to execute using this class. + """ + self.action = action + + def __call__(self, name='', roleName='', description='', delay=config.actionDelay): + """ + If name, roleName or description are specified, first search for a widget that matches and refocus on it. + Then execute the action. + """ + if name or roleName or description: + FocusWidget.__call__( + self, name=name, roleName=roleName, description=description) + self.node.doActionNamed(self.action) + + def __getattr__(self, attr): + return getattr(FocusWidget.node, attr) + + def __setattr__(self, attr, value): + if attr == 'action': + self.__dict__[attr] = value + else: + setattr(FocusWidget, attr, value) + + def button(self, name): + """ + A shortcut to self(name, roleName = 'push button') + """ + self.__call__(name=name, roleName='push button') + + def menu(self, name): + """ + A shortcut to self(name, roleName = 'menu') + """ + self.__call__(name=name, roleName='menu') + + def menuItem(self, name): + """ + A shortcut to self(name, roleName = 'menu item') + """ + self.__call__(name=name, roleName='menu item') + + def table(self, name=''): + """ + A shortcut to self(name, roleName 'table') + """ + self.__call__(name=name, roleName='table') + + def tableCell(self, name=''): + """ + A shortcut to self(name, roleName 'table cell') + """ + self.__call__(name=name, roleName='table cell') + + def text(self, name=''): + """ + A shortcut to self(name, roleName = 'text') + """ + self.__call__(name=name, roleName='text') + + +class Click (Action): + + """ + A special case of Action, Click will eventually handle raw mouse events. + """ + primary = 1 + middle = 2 + secondary = 3 + + def __init__(self): + Action.__init__(self, 'click') + + def __call__(self, name='', roleName='', description='', raw=True, button=primary, delay=config.actionDelay): + """ + By default, execute a raw mouse event. + If raw is False or if button evaluates to False, just pass the rest of + the arguments to Action. + """ + if name or roleName or description: + FocusWidget.__call__( + self, name=name, roleName=roleName, description=description) + if raw and button: + # We're doing a raw mouse click + Click.node.click(button) + else: + Action.__call__( + self, name=name, roleName=roleName, description=description, delay=delay) + + +class Select (Action): + + """ + Aids in selecting and deselecting widgets, i.e. page tabs + """ + select = 'select' + deselect = 'deselect' + + def __init__(self, action): + """ + action must be 'select' or 'deselect'. + """ + if action not in (self.select, self.deselect): + raise ValueError(action) + Action.__init__(self, action) + + def __call__(self, name='', roleName='', description='', delay=config.actionDelay): + """ + If name, roleName or description are specified, first search for a widget that matches and refocus on it. + Then execute the action. + """ + if name or roleName or description: + FocusWidget.__call__( + self, name=name, roleName=roleName, description=description) + func = getattr(self.node, self.action) + func() + + +def type(text): + if focus.widget.node: + focus.widget.node.typeText(text) + else: + rawinput.typeText(text) + + +def keyCombo(combo): + if focus.widget.node: + focus.widget.node.keyCombo(combo) + else: + rawinput.keyCombo(combo) + + +def run(application, arguments='', appName=''): + from utils import run as utilsRun + pid = utilsRun(application + ' ' + arguments, appName=appName) + focus.application(application) + return pid + +import os +# tell sniff not to use auto-refresh while script using this module is running +# may have already been locked by dogtail.tree +if not os.path.exists('/tmp/sniff_refresh.lock'): # pragma: no cover + sniff_lock = Lock(lockname='sniff_refresh.lock', randomize=False) + try: + sniff_lock.lock() + except OSError: + pass # lock was already present from other script instance or leftover from killed instance + # lock should unlock automatically on script exit. + +focus = Focus() +click = Click() +activate = Action('activate') +openItem = Action('open') +menu = Action('menu') +select = Select(Select.select) +deselect = Select(Select.deselect) |