def _loadState(self): ''' Loads the dialog state from configuration. ''' self._matchType = config.getInt(self._CONFIG_NAME, self._CONFIG_SECTION_OPTIONS, "match_type", self._PARTIAL_MATCH) self._caseSensitiveMatch = config.getBool(self._CONFIG_NAME, self._CONFIG_SECTION_OPTIONS, "case_sensitive", False) self._method = config.getInt(self._CONFIG_NAME, self._CONFIG_SECTION_OPTIONS, "method", self._DEEP_METHOD) if self._matchType == self._EXACT_MATCH: self.checkBoxExactMatch.setChecked(True) elif self._matchType == self._PARTIAL_MATCH: self.checkBoxExactMatch.setChecked(False) self.checkBoxCaseSensitive.setChecked(self._caseSensitiveMatch) if self._method == self._DEEP_METHOD: self.radioButtonDeep.setChecked(True) elif self._method == self._SIMPLE_METHOD: self.radioButtonSimple.setChecked(True) self._refreshCompleters() log.info("Search dialog state was loaded from configuration")
def getDevices(deviceArgs): ''' Converts command-line arguments representing devices. :param deviceArgs: Devices identifiers :type deviceArgs: list [string] :return: List of devices :rtype: list [tadek.connection.device.Device] ''' log.debug("Get devices from command-line arguments: %s" % deviceArgs) deviceList = [] if deviceArgs is None or deviceArgs == [None]: log.info("Using default device %s:%d" % (devices.DEFAULT_IP, devices.DEFAULT_PORT)) deviceList.append( Device('localhost', devices.DEFAULT_IP, devices.DEFAULT_PORT)) else: for arg in deviceArgs: device = devices.get(arg) if device is None: address = arg.split(':') if len(address) == 2: address, port = address port = int(port) elif len(address) == 1: address, port = address[0], devices.DEFAULT_PORT else: exitWithError("Invalid format of a device: %s" % arg) device = Device(address + ':' + str(port), address, port) log.info("Adding a device: %s=%s:%d" % (device.name, device.address[0], device.address[1])) deviceList.append(device) return deviceList
def _deviceDisconnected(self): ''' Emits the 'disconnected' device signal. ''' dev = self.sender() log.info("Device disconnected: %s" % dev) self.disconnected.emit(dev, self._errors.pop(dev, None) is not None)
def systemPut(processor, path, data): ''' Puts the given data in a system file of the specified path. :param processor: A processor object calling the function :type processor: Processor :param path: A path to the system file :type path: string :return: True if success, False otherwise :rtype: boolean ''' log.debug(str(locals())) # Reset the processor cache processor.cache = None fd = None try: dir = os.path.dirname(path) if not os.path.exists(dir): log.info("Create intermediate directories of file path: %s" % path) os.makedirs(dir) fd = open(path, 'w') fd.write(data) except: log.exception("Get system file failure: %s" % path) return False finally: if fd: fd.close() return True
def find(self, check, deep): ''' Initiates the searching process. ''' if not self._active: dialogs.runWarning("Device is disconnected") self.searchingStopped.emit() return log.info("Searching started for name: \"%s\", role: \"%s\", state: " "\"%s\", text: \"%s\", with deep option set to %s)" % (check.name, check.role, check.state, check.text, deep)) self._manualExpand = True self._manualSelect = True self._deep = deep self._check = check self._options = { "text": len(check.text) > 0, "states": len(check.state) > 0, } self._stopSearching = False self._nextIndex = 0 self._parentAccs = [] self._parentAcc = self.device.getAccessible( self.selectedItemPath(), 0) self._parentItem = self._pathItem(self._parentAcc.path) self._lastDisplayedItem = self._parentItem self._remainingItems = {} self._parentItem.takeChildren() if self._parentAcc.count: self._parentItem.setExpanded(True) self._responseFind()
def find(self, check, deep): ''' Initiates the searching process. ''' if not self._active: dialogs.runWarning("Device is disconnected") self.searchingStopped.emit() return log.info("Searching started for name: \"%s\", role: \"%s\", state: " "\"%s\", text: \"%s\", with deep option set to %s)" % (check.name, check.role, check.state, check.text, deep)) self._manualExpand = True self._manualSelect = True self._deep = deep self._check = check self._options = { "text": len(check.text) > 0, "states": len(check.state) > 0, } self._stopSearching = False self._nextIndex = 0 self._parentAccs = [] self._parentAcc = self.device.getAccessible(self.selectedItemPath(), 0) self._parentItem = self._pathItem(self._parentAcc.path) self._lastDisplayedItem = self._parentItem self._remainingItems = {} self._parentItem.takeChildren() if self._parentAcc.count: self._parentItem.setExpanded(True) self._responseFind()
def systemExec(processor, command, wait=True): ''' Executes the given system command. :param processor: A processor object calling the function :type processor: Processor :param command: A cammand to execute :type command: string :param wait: If True wait for termination of a command process :type wait: boolean :return: The command execution status, output and error :rtype: tuple ''' log.debug(str(locals())) # Reset the processor cache processor.cache = None stdout, stderr = '', '' try: cmd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) status = True if wait: code = cmd.wait() log.info("System command '%s' returned with code: %d" % (command, code)) status = (code == 0) stdout, stderr = cmd.communicate() stdout = stdout or '' stderr = stderr or '' except: log.exception("Execute system command failure: %s" % command) return False, stdout, stderr return status, stdout, stderr
def _editDevice(self): ''' Runs the 'Edit device' dialog for currently selected device. ''' items = self._deviceList.selectedItems() if not items: return dev = devices.get(items[0].text(0)) log.debug("Editing device: %s" % dev) dialog = DeviceConfigDialog(dev) if not dialog.run(): return connect = dialog.params.pop("connect", False) if dev.name != dialog.params["name"]: self._updateConnectionState(False, dev) devices.remove(dev.name) index = self._deviceList.indexOfTopLevelItem(items[0]) self._deviceList.takeTopLevelItem(index) dev = devices.add(type=Device, **dialog.params) self._addDeviceItem(dev) else: address = dialog.params["address"] port = dialog.params["port"] if dev.address != (address, port): self._updateConnectionState(False, dev) devices.update(**dialog.params) self._deviceItems[dev].updateDevice() log.info("Device edited: %s" % dev) if connect: self._updateConnectionState(True, dev)
def getDevices(deviceArgs): ''' Converts command-line arguments representing devices. :param deviceArgs: Devices identifiers :type deviceArgs: list [string] :return: List of devices :rtype: list [tadek.connection.device.Device] ''' log.debug("Get devices from command-line arguments: %s" % deviceArgs) deviceList = [] if deviceArgs is None or deviceArgs == [None]: log.info("Using default device %s:%d" % (devices.DEFAULT_IP, devices.DEFAULT_PORT) ) deviceList.append(Device('localhost', devices.DEFAULT_IP, devices.DEFAULT_PORT)) else: for arg in deviceArgs: device = devices.get(arg) if device is None: address = arg.split(':') if len(address) == 2: address, port = address port = int(port) elif len(address) == 1: address, port = address[0], devices.DEFAULT_PORT else: exitWithError("Invalid format of a device: %s" % arg) device = Device(address + ':' + str(port), address, port) log.info("Adding a device: %s=%s:%d" % (device.name, device.address[0], device.address[1])) deviceList.append(device) return deviceList
def accessibilityPutValue(processor, path, value): ''' Sets the given value in an accessible of the given path. :param processor: A processor object calling the function :type processor: Processor :param path: A path of the accessible :type path: tadek.core.accessible.Path :param value: New value of the accessible :type value: float :return: True if success, False otherwise :rtype: boolean ''' log.debug(str(locals())) try: # Get object from the processor cache or from the accessible provider if processor.cache and processor.cache[-1] == path: a11y, obj, path = processor.cache else: a11y, obj = providers.accessible(path) # Reset the processor cache processor.cache = None if obj is None: log.warning("Attempt of setting value for non-accessible") return False status = a11y.setValue(obj, value) except: log.exception("Set accessible value error: %s" % path) # Reset the processor cache before leaving processor.cache = None return False if not status: log.info("Set accessible value failure: %s" % path) return status
def _deviceConnected(self): ''' Emits the 'connected' device signal. ''' dev = self.sender() log.info("Device connected: %s" % dev) self.connected.emit(dev)
def printResult(result): ''' Prints the given test result. ''' log.debug("Print test result: %s" % result) summary = result.get(name=SUMMARY_CHANNEL)[0].getSummary() log.info("Print summary of test execution results: %s" % summary) report = "Ran %d of %d test cases in %s" % (summary[COUNTER_TESTS_RUN], summary[COUNTER_N_TESTS], summary[COUNTER_RUN_TIME]) print '\n', report printSeparator(len(report)) if summary[STATUS_PASSED]: print "Tests passed:\t\t%d" % summary[STATUS_PASSED] if summary[STATUS_FAILED]: print "Tests failed:\t\t%d" % summary[STATUS_FAILED] if summary[STATUS_NOT_COMPLETED]: print "Tests not completed:\t%d" % summary[STATUS_NOT_COMPLETED] if summary[COUNTER_CORE_DUMPS]: print "Core dumps:\t\t%d" % summary[COUNTER_CORE_DUMPS] if summary[STATUS_ERROR]: print "Tests error:\t\t%d" % summary[STATUS_ERROR] filechls = [chl for chl in result.get(cls=channels.TestResultFileChannel) if chl.isActive()] if filechls: print "Result file:" if len(filechls) == 1 else "Result files:" for channel in filechls: print "\t%s" % channel.filePath() printSeparator() status = (1 if (summary[STATUS_FAILED] + summary[STATUS_ERROR] + summary[STATUS_NOT_COMPLETED]) else 0) exitWithStatus("FAILURE" if status else "SUCCESS", status)
def accessibilityGet(processor, path, depth, name=False, description=False, role=False, count=False, position=False, size=False, text=False, value=False, actions=False, states=False, attributes=False, relations=False): ''' Gets an accessible of the given path and depth including specified accessible parameters. :param processor: A processor object calling the function :type processor: Processor :param path: A path of a demanded accessible :type path: tadek.core.accessible.Path :param depth: A depth of a demanded accessible tree :type depth: integer :param name: True if a demanded accessible should include name :type name: boolean :param description: True if a demanded accessible should include description :type description: boolean :param role: True if a demanded accessible should include role :type role: boolean :param count: True if a demanded accessible should include child count :type count: boolean :param position: True if a demanded accessible should include position :type position: boolean :param size: True if a demanded accessible should include size :type size: boolean :param text: True if a demanded accessible should include text :type text: boolean :param value: True if a demanded accessible should include value :type value: boolean :param actions: True if a demanded accessible should include actions :type actions: boolean :param states: True if a demanded accessible should include states :type states: boolean :param attributes: True if a demanded accessible should include attributes :type attributes: boolean :param relations: True if a demanded accessible should include relations :type relations: bool :return: A getting accessible status and an accessible of the given path :rtype: tuple ''' log.debug(str(locals())) # Reset the processor cache processor.cache = None try: a11y, obj = providers.accessible(path) if a11y is None and path.tuple: log.info("Get accessible of requested path failure: %s" % path) return False, Accessible(path) processor.cache = (a11y, obj, path) return True, dumpAccessible(a11y, obj, path, depth=depth, name=name, description=description, role=role, count=count, position=position, size=size, text=text, value=value, actions=actions, states=states, attributes=attributes, relations=relations) except: log.exception("Get accessible of requested path error: %s" % path) return False, Accessible(path)
def exitWithStatus(message=None, status=0): ''' Logs and prints the given message and exits with the specified status code. ''' if message: log.info(message) print message else: log.info("Exit with status: %d" % status) sys.exit(status)
def exitWithError(error): ''' Logs error, prints it and exits the program with 2 code. :param error: An error message :type error: string ''' log.info(error) print >> sys.stderr, error sys.exit(2)
def _saveState(self): ''' Saves the dialog state to configuration. ''' config.set(self._CONFIG_NAME, self._CONFIG_SECTION_OPTIONS, "match_type", self._matchType) config.set(self._CONFIG_NAME, self._CONFIG_SECTION_OPTIONS, "case_sensitive", self._caseSensitiveMatch) config.set(self._CONFIG_NAME, self._CONFIG_SECTION_OPTIONS, "method", self._method) log.info("Search dialog state was saved to configuration")
def runInformation(message, title="Information"): ''' Runs an information message box with the given title and message. :param message: Message to be displayed inside the dialog :type message: string :param title: Title of the dialog, if not provided, "Information" is set :type title: string ''' log.info(message) return QtGui.QMessageBox.information(utils.window(), title, message)
def findNext(self): ''' Runs the searching process again after a match was found. ''' if not self._active: dialogs.runWarning("Device is disconnected") self.searchingStopped.emit() return log.info("Searching for next match") self._manualExpand = True self._manualSelect = True self._responseFind()
def __init__(self, socket, client): ''' Initializes a handler and gets log. :param socket: Socket on which communication takes place. :type socket: socket :param client: Client address containing IP and port. :type client: tuple ''' log.info("Accepting connection from %s on %s" % (client, socket)) server.Handler.__init__(self, socket, client) log.info("Accepted connection from %s on %s" % (client, self)) self._processor = processor.Processor()
def _addDevice(self): ''' Runs the 'Add device' dialog. ''' log.debug("Adding new device") dialog = DeviceConfigDialog() if not dialog.run(): return connect = dialog.params.pop("connect", False) dev = devices.add(type=Device, **dialog.params) self._addDeviceItem(dev) log.info("New device added: %s" % dev) if connect: self._updateConnectionState(True, dev)
def runTestCases(tests, locations, devices): ''' A function responsible for running the given test cases. ''' log.debug("Run test cases from '%s' locations using '%s' devices: %s" % (", ".join(locations), ", ".join([str(d) for d in devices]), ", ".join(tests))) loader = TestLoader() amountToRun = 0 for path in locations: location.add(path) if not isinstance(tests, (list, tuple)): tests = [tests] suites, errors = loader.loadFromNames(*tests) ncases = 0 for test in suites: ncases += test.count() print (" LOADED %d TEST CASES " % ncases).center(80, '-') + '\n' if len(errors) > 0: print "There were errors during loading test cases:" for error in errors: print "%s\n%s" % (error.name, error.traceback) printSeparator() print if not ncases: #Nothing to do exitWithStatus(status=0) log.info("Start running tests: %s" % suites) channels.add("SummaryChannel", SUMMARY_CHANNEL) result = testresult.TestResult() runner = TestRunner(devices, suites, result) for device in devices: device.connect() try: runner.start() runner.join() except KeyboardInterrupt: runner.stop() finally: for device in devices: if device.isConnected(): device.disconnect() return result
def _removeDevice(self): ''' Removes the currently selected device. ''' items = self._deviceList.selectedItems() if not items: return dev = devices.get(items[0].text(0)) if not dialogs.runQuestion("Do you want to remove " "'%s' device permanently?" % dev.name): return log.debug("Removing device: %s" % dev) self._updateConnectionState(False, dev) devices.remove(dev.name) self._removeDeviceItem(dev) log.info("Device removed: %s" % dev)
def runQuestion(message, title="Question"): ''' Runs a question message box with the given title and message. :param message: Message to be displayed inside the dialog :type message: string :param title: Title of the dialog, if not provided, "Question" is set :type title: string :return: Answer to a question :rtype: boolean ''' btns = {QtGui.QMessageBox.Yes: True, QtGui.QMessageBox.No: False} b = reduce(QtGui.QMessageBox.StandardButton.__ror__, btns.keys()) ret = btns[QtGui.QMessageBox.question(utils.window(), title, message, b)] log.info("%s: %s" % (message, ret)) return ret
def _execute(self): ''' Executes keyboard event based on key code and modifiers. ''' log.info('Executing keyboard event') path = self._deviceTab.selectedItemPath() if path is None: dialogs.runWarning("No accessible item is selected. ", "Keyboard events unavailable") else: keycode = int(self._keycode.text()) items = self._modifiers.findItems('', QtCore.Qt.MatchContains) mods = [self._itemData(item)[1] for item in items if item.checkState() == QtCore.Qt.Checked] self._deviceTab.device.requestDevice("requestKeyboardEvent", path, keycode, mods)
def _execute(self): ''' Executes keyboard event based on key code and modifiers. ''' log.info('Executing mouse event') path = self._deviceTab.selectedItemPath() if path is None: dialogs.runWarning("No accessible item is selected." "Mouse events unavailable") else: x = int(self._x.value()) y = int(self._y.value()) button = self._buttons[self._button.checkedButton()] event = self._events[self._event.checkedButton()] self._deviceTab.device.requestDevice("requestMouseEvent", path, x, y, button, event)
def _execute(self): ''' Executes keyboard event based on key code and modifiers. ''' log.info('Executing keyboard event') path = self._deviceTab.selectedItemPath() if path is None: dialogs.runWarning("No accessible item is selected. ", "Keyboard events unavailable") else: keycode = int(self._keycode.text()) items = self._modifiers.findItems('', QtCore.Qt.MatchContains) mods = [ self._itemData(item)[1] for item in items if item.checkState() == QtCore.Qt.Checked ] self._deviceTab.device.requestDevice("requestKeyboardEvent", path, keycode, mods)
def printAccessibleTree(accessible): ''' Prints the given accessible tree recursively. ''' log.debug("Print accessible tree: %s" % accessible) lens = [len(attr[2 if len(attr) > 2 else 0]) for attr in _ATTRS_BASIC] _countColumnLens(accessible, lens) # Print column header row = [] for i, attr in enumerate(_ATTRS_BASIC): name = attr[2 if len(attr) > 2 else 0] row.append(name.upper().center(lens[i])) length = (sum(lens) + len(lens) - 1) printSeparator(length) print _COLUMN_SEPARATOR.join(row) printSeparator(length) # Print accessible tree log.info("Print accessible tree using column lengths: %s" % ", ".join([str(i) for i in lens])) _printAccessibleAligned(accessible, lens)
def accessibilityExecAction(processor, path, action): ''' Executes the specified action of an accessible given by the path. :param processor: A processor object calling the function :type processor: Processor :param path: A path of the accessible :type path: tadek.core.accessible.Path :param action: An accessible action to execute :type action: string :return: True if success, False otherwise :rtype: boolean ''' log.debug(str(locals())) try: # Get object from the processor cache or from the accessible provider if processor.cache and processor.cache[-1] == path: a11y, obj, path = processor.cache else: a11y, obj = providers.accessible(path) # Reset the processor cache processor.cache = None if obj is None: log.warning("Attempt of executing action of non-accessible") return False if action == A11Y_ACTION_FOCUS: status = a11y.grabFocus(obj) else: status = a11y.doAction(obj, getattr(a11y.actionset, action, action)) except: log.exception("Execute accessible action error: %s" % path) # Reset the processor cache before leaving processor.cache = None return False if not status: log.info("Execute accessible action failure: %s" % path) return status
def _startItemChanged(self): ''' Handles the event when the user changes the reference item ''' self._stopSearching() log.info("User selected new reference item to search")
def stopSearching(self): ''' Stops the searching process. ''' log.info("Searching was stopped") self._stopSearching = True
def onClose(self): ''' Function called when socket is closed. ''' log.info("Closing connection with %s on %s." % (str(self.client), self))
def accessibilitySearch(processor, path, method, name=None, description=None, role=None, index=None, count=None, action=None, relation=None, state=None, text=None, nth=0): ''' Searches an accessible using the given method according to specified accessible parameters. :param processor: A processor object calling the function :type processor: Processor :param path: A path of a demanded accessible :type path: tadek.core.accessible.Path :param method: A search method of accessible :type method: string :param name: A name of searched accessible or None :type name: string or NoneType :param description: A description of searched accessible or None :type description: string or NoneType :param role: A role of searched accessible or None :type role: string or NoneType :param index: An index of searched accessible or None :type index: integer or NoneType :param count: A child count of searched accessible or None :type count: string or NoneType :param action: An action of searched accessible or None :type action: string or NoneType :param relation: A relation of searched accessible or None :type relation: string or NoneType :param state: A state of searched accessible or None :type state: string or NoneType :param text: Text of searched accessible or None :type text: string or NoneType :param nth: A nth matched accessible :type nth: integer :return: A searching accessible status and an accessible of the given path :rtype: tuple ''' log.debug(str(locals())) def matchString(pattern, string): ''' Checks if the give string matches the regular expression pattern. ''' if string is None: return False match = pattern.match(string) return match is not None and match.span() == (0, len(string)) try: # Get object from the processor cache or from the accessible provider if processor.cache and processor.cache[-1] == path: a11y, obj, path = processor.cache else: a11y, obj = providers.accessible(path) # Reset the processor cache processor.cache = None if a11y is None and path.tuple: log.info("Accessible of requested path not found: %s" % path) return False, Accessible(path) if method == protocol.MHD_SEARCH_SIMPLE: provider = providers.Children elif method == protocol.MHD_SEARCH_BACKWARDS: provider = providers.ChildrenBackwards elif method == protocol.MHD_SEARCH_DEEP: provider = providers.Descendants else: log.error("Unknown search method: %s" % method) return False, Accessible(Path()) if name and name[0] == '&': name = re.compile(name[1:], re.DOTALL) cmpName = matchString else: cmpName = lambda pattern, string: pattern == string if description and description[0] == '&': description = re.compile(description[1:], re.DOTALL) cmpDesc = matchString else: cmpDesc = lambda pattern, string: pattern == string if text and text[0] == '&': text = re.compile(text[1:], re.DOTALL) cmpText = matchString else: cmpText = lambda pattern, string: pattern == string i = 0 for a11y, obj, path in provider(a11y, obj, path): if index is not None and index != path.index(): continue if obj is None: if name is not None and not cmpName(name, a11y.name): continue if count is not None and a11y.countChildren() != count: continue else: if name is not None and not cmpName(name, a11y.getName(obj)): continue if (description is not None and not cmpDesc(description, a11y.getDescription(obj))): continue if role is not None and a11y.getRoleName(obj) != role: continue if count is not None and a11y.countChildren(obj) != count: continue if action is not None: found = False for act in a11y.actionNames(obj): if action == act: found = True break if not found: continue if relation is not None: found = False for rel in a11y.relationNames(obj): if relation == rel: found = True break if not found: continue if (state is not None and not a11y.inState(obj, getattr(a11y.stateset, state, None))): continue if text is not None and not cmpText(text, a11y.getText(obj)): continue i += 1 if nth < i: processor.cache = (a11y, obj, path) return True, dumpAccessible(a11y, obj, path, depth=0, name=True, description=True, role=True, count=True, position=True, size=True, text=True, value=True, actions=True, states=True, attributes=True, relations=True) except: log.exception("Search an accessible of specified parmaters error") # Reset the processor cache before leaving processor.cache = None return False, Accessible(path) log.info("Search an accessible of specified parmaters failure") return False, Accessible(path)
def onClose(self): ''' Function called when socket is closed. ''' log.info("Daemon stopped running")
def run(self): ''' Starts asyncore.loop(). ''' log.info("Starting daemon at %s:%d" % self.address) run()
def accessibilitySearch(processor, path, method, name=None, description=None, role=None, index=None, count=None, action=None, relation=None, state=None, text=None, nth=0): ''' Searches an accessible using the given method according to specified accessible parameters. :param processor: A processor object calling the function :type processor: Processor :param path: A path of a demanded accessible :type path: tadek.core.accessible.Path :param method: A search method of accessible :type method: string :param name: A name of searched accessible or None :type name: string or NoneType :param description: A description of searched accessible or None :type description: string or NoneType :param role: A role of searched accessible or None :type role: string or NoneType :param index: An index of searched accessible or None :type index: integer or NoneType :param count: A child count of searched accessible or None :type count: string or NoneType :param action: An action of searched accessible or None :type action: string or NoneType :param relation: A relation of searched accessible or None :type relation: string or NoneType :param state: A state of searched accessible or None :type state: string or NoneType :param text: Text of searched accessible or None :type text: string or NoneType :param nth: A nth matched accessible :type nth: integer :return: A searching accessible status and an accessible of the given path :rtype: tuple ''' log.debug(str(locals())) def matchString(pattern, string): ''' Checks if the give string matches the regular expression pattern. ''' if string is None: return False match = pattern.match(string) return match is not None and match.span() == (0, len(string)) try: # Get object from the processor cache or from the accessible provider if processor.cache and processor.cache[-1] == path: a11y, obj, path = processor.cache else: a11y, obj = providers.accessible(path) # Reset the processor cache processor.cache = None if a11y is None and path.tuple: log.info("Accessible of requested path not found: %s" % path) return False, Accessible(path) if method == protocol.MHD_SEARCH_SIMPLE: provider = providers.Children elif method == protocol.MHD_SEARCH_BACKWARDS: provider = providers.ChildrenBackwards elif method == protocol.MHD_SEARCH_DEEP: provider = providers.Descendants else: log.error("Unknown search method: %s" % method) return False, Accessible(Path()) if name and name[0] == '&': name = re.compile(name[1:], re.DOTALL) cmpName = matchString else: cmpName = lambda pattern, string: pattern == string if description and description[0] == '&': description = re.compile(description[1:], re.DOTALL) cmpDesc = matchString else: cmpDesc = lambda pattern, string: pattern == string if text and text[0] == '&': text = re.compile(text[1:], re.DOTALL) cmpText = matchString else: cmpText = lambda pattern, string: pattern == string i = 0 for a11y, obj, path in provider(a11y, obj, path): if index is not None and index != path.index(): continue if obj is None: if name is not None and not cmpName(name, a11y.name): continue if count is not None and a11y.countChildren() != count: continue else: if name is not None and not cmpName(name, a11y.getName(obj)): continue if (description is not None and not cmpDesc(description, a11y.getDescription(obj))): continue if role is not None and a11y.getRoleName(obj) != role: continue if count is not None and a11y.countChildren(obj) != count: continue if action is not None: found = False for act in a11y.actionNames(obj): if action == act: found = True break if not found: continue if relation is not None: found = False for rel in a11y.relationNames(obj): if relation == rel: found = True break if not found: continue if (state is not None and not a11y.inState( obj, getattr(a11y.stateset, state, None))): continue if text is not None and not cmpText(text, a11y.getText(obj)): continue i += 1 if nth < i: processor.cache = (a11y, obj, path) return True, dumpAccessible(a11y, obj, path, depth=0, name=True, description=True, role=True, count=True, position=True, size=True, text=True, value=True, actions=True, states=True, attributes=True, relations=True) except: log.exception("Search an accessible of specified parmaters error") # Reset the processor cache before leaving processor.cache = None return False, Accessible(path) log.info("Search an accessible of specified parmaters failure") return False, Accessible(path)