diff options
author | Eitan Isaacson <eitan@ascender.com> | 2009-08-31 11:53:09 -0700 |
---|---|---|
committer | Eitan Isaacson <eitan@ascender.com> | 2009-08-31 11:53:09 -0700 |
commit | 6e99dbe2d4b9e385b5347cc9d3106413603ca6b5 (patch) | |
tree | c3011200c7c6143968d3d8653d79fb8f584b8bed | |
parent | 18ec505eea6240f468778eaff0ce6a4b7e0637ad (diff) | |
parent | 128778a78635f2da62c0df1107b7b721a74ae569 (diff) |
Merge branch 'master' into lazy_loaderlazy_loader
-rw-r--r-- | ChangeLog | 42 | ||||
-rw-r--r-- | INSTALL | 291 | ||||
-rw-r--r-- | Makefile.am | 7 | ||||
-rw-r--r-- | NEWS | 0 | ||||
-rw-r--r-- | README | 0 | ||||
-rwxr-xr-x | autogen.sh | 5 | ||||
-rw-r--r-- | configure.in | 51 | ||||
-rwxr-xr-x | find-python-path.py | 17 | ||||
-rw-r--r-- | ldtp/Makefile.am | 21 | ||||
-rw-r--r-- | ldtp/__init__.py | 8 | ||||
-rw-r--r-- | ldtpd/Makefile.am | 34 | ||||
-rw-r--r-- | ldtpd/combo_box.py | 107 | ||||
-rw-r--r-- | ldtpd/core.py | 62 | ||||
-rw-r--r-- | ldtpd/generic.py | 12 | ||||
-rw-r--r-- | ldtpd/menu.py | 80 | ||||
-rw-r--r-- | ldtpd/page_tab_list.py | 25 | ||||
-rw-r--r-- | ldtpd/table.py | 44 | ||||
-rw-r--r-- | ldtpd/text.py | 36 | ||||
-rw-r--r-- | ldtpd/utils.py | 23 | ||||
-rw-r--r-- | ldtpd/value.py | 64 | ||||
-rw-r--r-- | ldtputils/Makefile.am | 17 | ||||
-rw-r--r-- | ooldtp/Makefile.am | 18 |
22 files changed, 817 insertions, 147 deletions
diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..588cbfc --- /dev/null +++ b/ChangeLog @@ -0,0 +1,42 @@ +2009-08-25 Nagappan Alagappan <nagappan@gmail.com> + + * ldtpd/value.py (Value.verifyslidervertical): Return 0 on + failure. + + * ldtpd/utils.py (Utils._match_name_to_acc): Added new condition, + which will check for the object name, by stripping all spaces. + (Utils._appmap_pairs): Increment object index to each specific + type and use that when the object doesn't have any associated + label. + (Utils._get_menu_hierarchy): Fix, fetching the child of a menu. + + * ldtpd/text.py (Text.gettextvalue): Added additional parameters + to reflect LDTPv1 arguments. + (Text.verifypartialmatch): Return 0 on failure. + + * ldtpd/table.py (Table.verifytablecell): Return 0 on failure. + + * ldtpd/page_tab_list.py (PageTabList.verifytabname): Return 0 on + failure, instead of raising exception. + + * ldtpd/menu.py (Menu.menuitemenabled, Menu.verifymenucheck): + (Menu.verifymenuuncheck): Added new method to reflect LDTPv1. + + * ldtpd/generic.py (Generic.imagecapture): Updated arguments to + reflect the latest LDTPv1. + + * ldtpd/core.py (Ldtpd.launchapp): Added arguments, same as + LDTPv1. + (Ldtpd.verifytoggled): Added try/except block, to avoid any + exception. This method has to either return 1 or 0. + (Ldtpd.getobjectinfo): Added new properties. + + * ldtpd/combo_box.py (ComboBox.verifydropdown): Added try/except + block, to avoid any exception. This method has to either return 1 + or 0. + + * configure.in: Added makefile and related files. + + * ldtp/__init__.py (imagecapture): Updated arguments to reflect + the latest LDTPv1. + @@ -0,0 +1,291 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007, 2008 Free Software Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 6. Often, you can also type `make uninstall' to remove the installed + files again. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `<wchar.h>' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *Note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..78bafe4 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,7 @@ +PYTHONDIR = ldtp ooldtp ldtpd ldtputils + +SUBDIRS = $(PYTHONDIR) + +DIST_SUBDIRS = $(PYTHONDIR) + +EXTRA_DIST = find-python-path.py diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..1729c80 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +aclocal +automake --add-missing; autoreconf -sfi -v +./configure $@ diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..faeecb7 --- /dev/null +++ b/configure.in @@ -0,0 +1,51 @@ +dnl ************************************************************* +dnl Process this file with autoconf to produce a configure script +dnl ************************************************************* +AC_INIT(ldtp2, 2.0, ldtp-dev@lists.freedesktop.org) +AC_CANONICAL_SYSTEM + +AM_INIT_AUTOMAKE + +AC_PREREQ(2.52) + +dnl checks for programs +AC_PROG_INSTALL + +AC_PATH_PROG(PYTHON_CMD, python, no) +if test "x$PYTHON_CMD" = "xno"; then + AC_MSG_ERROR([Your python installation doesn't expose python]) +fi + +dnl Check for the python site-packages install path +dnl Copied over from a11y-test-suite +AC_MSG_CHECKING([python site path]) +pythonsitedir="`./find-python-path.py`" +pythondir="${pythonsitedir}" +ldtpdir="${pythondir}/ldtp" +ldtpddir="${pythondir}/ldtpd" +ooldtpdir="${pythondir}/ooldtp" +ldtputilsdir="${pythondir}/ldtputils" +AC_MSG_RESULT([$ldtpdir]) +AC_MSG_RESULT([$ldtpddir]) +AC_MSG_RESULT([$ooldtpdir]) +AC_MSG_RESULT([$ldtputilsdir]) +AC_MSG_RESULT([$pythondir]) +AC_SUBST(ldtpdir) +AC_SUBST(ldtpddir) +AC_SUBST(ooldtpdir) +AC_SUBST(ldtputilsdir) +AC_SUBST(pythondir) + +AC_OUTPUT([ +ldtp/Makefile +ooldtp/Makefile +ldtpd/Makefile +ldtputils/Makefile +Makefile +]) + +echo "---" +echo "Configuration successful." +echo + +dnl configure.in ends here diff --git a/find-python-path.py b/find-python-path.py new file mode 100755 index 0000000..21a9d0b --- /dev/null +++ b/find-python-path.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +import sys +from os.path import split, basename + +def find_path (): + for path in sys.path: + (head, tail) = split (path) + # Forcing python path to be used as /usr/lib instead of /usr/local/lib + if (tail == 'site-packages' or tail == 'dist-packages') and \ + path.find ('local') == -1: + base = basename (head) + print path + #print base + '/' + tail + return + +find_path () diff --git a/ldtp/Makefile.am b/ldtp/Makefile.am new file mode 100644 index 0000000..3273f21 --- /dev/null +++ b/ldtp/Makefile.am @@ -0,0 +1,21 @@ +ldtp_DATA = \ + log.py \ + state.py \ + client_exception.py \ + client.py \ + __init__.py + +pyc_DATA = $(ldtp_DATA:.py=.pyc) +pycdir = $(ldtpdir) + +%.pyc: %.py + $(PYTHON_CMD) -c "import py_compile; py_compile.compile ('$<', '$@')" + +EXTRA_DIST = \ + $(ldtp_DATA) + +CLEANFILES = \ + $(pyc_DATA) + +MAINTAINERCLEANFILES = \ + Makefile.in diff --git a/ldtp/__init__.py b/ldtp/__init__.py index 4a72096..72d3bd2 100644 --- a/ldtp/__init__.py +++ b/ldtp/__init__.py @@ -45,12 +45,14 @@ def _populateNamespace(d): d[local_name] = getattr(client._client, method) d[local_name].__doc__ = client._client.system.methodHelp(method) -def imagecapture(winName = None, outFile = None, resolution1 = None, - resolution2 = None, x = 0, y = 0): +def imagecapture(winName = None, outFile = None, width = None, + height = None, x = 0, y = 0): if not outFile: outFile = tempfile.mktemp('.png', 'ldtp_') + else: + outFile = os.path.expanduser(outFile) - data = _remote_imagecapture(winName, resolution1, resolution2, x, y) + data = _remote_imagecapture(winName, width, height, x, y) f = open(outFile, 'w') f.write(b64decode(data)) f.close() diff --git a/ldtpd/Makefile.am b/ldtpd/Makefile.am new file mode 100644 index 0000000..7032350 --- /dev/null +++ b/ldtpd/Makefile.am @@ -0,0 +1,34 @@ +ldtpd_DATA = \ + server_exception.py \ + keypress_actions.py \ + generic.py \ + xmlrpc_daemon.py \ + waiters.py \ + mouse.py \ + value.py \ + text.py \ + constants.py \ + log.py \ + core.py \ + menu.py \ + sequence_step.py \ + utils.py \ + page_tab_list.py \ + table.py \ + combo_box.py \ + __init__.py + +pyc_DATA = $(ldtpd_DATA:.py=.pyc) +pycdir = $(ldtpddir) + +%.pyc: %.py + $(PYTHON_CMD) -c "import py_compile; py_compile.compile ('$<', '$@')" + +EXTRA_DIST = \ + $(ldtpd_DATA) + +CLEANFILES = \ + $(pyc_DATA) + +MAINTAINERCLEANFILES = \ + Makefile.in diff --git a/ldtpd/combo_box.py b/ldtpd/combo_box.py index 4596fcb..3de1313 100644 --- a/ldtpd/combo_box.py +++ b/ldtpd/combo_box.py @@ -234,20 +234,23 @@ class ComboBox(Utils): @return: 1 on success. @rtype: integer ''' - obj = self._get_object(window_name, object_name) - self._grab_focus(obj) + try: + obj = self._get_object(window_name, object_name) + self._grab_focus(obj) - child_obj = self._get_combo_child_object_type(obj) - if not child_obj: - raise LdtpServerException('Unable to get combo box children') + child_obj = self._get_combo_child_object_type(obj) + if not child_obj: + return 0 - if child_obj == pyatspi.ROLE_LIST and \ - self._check_state(obj, pyatspi.STATE_FOCUSABLE): - return 1 - elif child_obj == pyatspi.ROLE_MENU: - if self._check_state(obj, pyatspi.STATE_VISIBLE) and \ - self._check_state(obj, pyatspi.STATE_SHOWING): + if child_obj == pyatspi.ROLE_LIST and \ + self._check_state(obj, pyatspi.STATE_FOCUSABLE): return 1 + elif child_obj == pyatspi.ROLE_MENU: + if self._check_state(obj, pyatspi.STATE_VISIBLE) and \ + self._check_state(obj, pyatspi.STATE_SHOWING): + return 1 + except: + pass return 0 def verifyshowlist(self, window_name, object_name): @@ -280,20 +283,23 @@ class ComboBox(Utils): @return: 1 on success. @rtype: integer ''' - obj = self._get_object(window_name, object_name) - self._grab_focus(obj) + try: + obj = self._get_object(window_name, object_name) + self._grab_focus(obj) - child_obj = self._get_combo_child_object_type(obj) - if not child_obj: - raise LdtpServerException('Unable to get combo box children') + child_obj = self._get_combo_child_object_type(obj) + if not child_obj: + return 0 - if child_obj == pyatspi.ROLE_LIST and \ - not self._check_state(obj, pyatspi.STATE_FOCUSABLE): - return 1 - elif child_obj == pyatspi.ROLE_MENU: - if not self._check_state(obj, pyatspi.STATE_VISIBLE) and \ - not self._check_state(obj, pyatspi.STATE_SHOWING): + if child_obj == pyatspi.ROLE_LIST and \ + not self._check_state(obj, pyatspi.STATE_FOCUSABLE): return 1 + elif child_obj == pyatspi.ROLE_MENU: + if not self._check_state(obj, pyatspi.STATE_VISIBLE) and \ + not self._check_state(obj, pyatspi.STATE_SHOWING): + return 1 + except: + pass return 0 def verifyselect(self, window_name, object_name, item_name): @@ -312,32 +318,35 @@ class ComboBox(Utils): @return: 1 on success. @rtype: integer ''' - obj = self._get_object(window_name, object_name) - self._grab_focus(obj) - - child_obj = self._get_combo_child_object_type(obj) - if not child_obj: - raise LdtpServerException('Unable to get combo box children') - if child_obj.getRole() == pyatspi.ROLE_LIST: - for child in self._list_objects (child_obj): - if child == child_obj: - # As the _list_objects gives the current object as well - # ignore it - continue - try: - texti = child.queryText() - text = texti.getText(0, texti.characterCount) - except NotImplementedError: - text = child.name + try: + obj = self._get_object(window_name, object_name) + self._grab_focus(obj) + + child_obj = self._get_combo_child_object_type(obj) + if not child_obj: + return 0 + if child_obj.getRole() == pyatspi.ROLE_LIST: + for child in self._list_objects (child_obj): + if child == child_obj: + # As the _list_objects gives the current object as well + # ignore it + continue + try: + texti = child.queryText() + text = texti.getText(0, texti.characterCount) + except NotImplementedError: + text = child.name - if self._glob_match(item_name, text): - return 1 - elif child_obj.getRole() == pyatspi.ROLE_MENU: - for child in self._list_objects (child_obj): - if child == child_obj: - # As the _list_objects gives the current object as well - # ignore it - continue - if self._glob_match(item_name, child.name): - return 1 + if self._glob_match(item_name, text): + return 1 + elif child_obj.getRole() == pyatspi.ROLE_MENU: + for child in self._list_objects (child_obj): + if child == child_obj: + # As the _list_objects gives the current object as well + # ignore it + continue + if self._glob_match(item_name, child.name): + return 1 + except: + pass return 0 diff --git a/ldtpd/core.py b/ldtpd/core.py index 10a1bf5..0b4b357 100644 --- a/ldtpd/core.py +++ b/ldtpd/core.py @@ -30,6 +30,7 @@ from keypress_actions import TypeAction from server_exception import LdtpServerException import os import re +import time import pyatspi import traceback @@ -70,12 +71,18 @@ class Ldtpd(Utils, ComboBox, Table, Menu, PageTabList, self._states[state.__repr__()] = state return self._states - def launchapp(self, cmd, args=[]): + def launchapp(self, cmd, args=[], delay = 5, env = 1): ''' Launch application. @param cmdline: Command line string to execute. @type cmdline: string + @param args: Arguments to the application + @type args: list + @param delay: Delay after the application is launched + @type delay: int + @param env: GNOME accessibility environment to be set or not + @type env: int @return: PID of new process @rtype: integer @@ -84,8 +91,16 @@ class Ldtpd(Utils, ComboBox, Table, Menu, PageTabList, ''' os.environ['NO_GAIL'] = '0' os.environ['NO_AT_BRIDGE'] = '0' + if env: + os.environ['GTK_MODULES'] = 'gail:atk-bridge' + os.environ['GNOME_ACCESSIBILITY'] = '1' try: process = subprocess.Popen([cmd]+args) + # Let us wait so that the application launches + try: + time.sleep(int(delay)) + except ValueError: + time.sleep(5) except Exception, e: raise LdtpServerException(str(e)) os.environ['NO_GAIL'] = '1' @@ -234,14 +249,17 @@ class Ldtpd(Utils, ComboBox, Table, Menu, PageTabList, @return: 1 on success. @rtype: integer ''' - obj = self._get_object(window_name, object_name) + try: + obj = self._get_object(window_name, object_name) - _state = obj.getState() - _obj_state = _state.getStates() - state = 'STATE_%s' % state.upper() - if state in self._states and \ - self._states[state] in _obj_state: - return 1 + _state = obj.getState() + _obj_state = _state.getStates() + state = 'STATE_%s' % state.upper() + if state in self._states and \ + self._states[state] in _obj_state: + return 1 + except: + pass return 0 def click(self, window_name, object_name): @@ -360,9 +378,12 @@ class Ldtpd(Utils, ComboBox, Table, Menu, PageTabList, @return: 1 on success 0 on failure. @rtype: integer ''' - obj = self._get_object(window_name, object_name) + try: + obj = self._get_object(window_name, object_name) - return int(self._check_state(obj, pyatspi.STATE_CHECKED)) + return int(self._check_state(obj, pyatspi.STATE_CHECKED)) + except: + return 0 def verifyuncheck(self, window_name, object_name): ''' @@ -378,9 +399,12 @@ class Ldtpd(Utils, ComboBox, Table, Menu, PageTabList, @return: 1 on success 0 on failure. @rtype: integer ''' - obj = self._get_object(window_name, object_name) + try: + obj = self._get_object(window_name, object_name) - return int(not self._check_state(obj, pyatspi.STATE_CHECKED)) + return int(not self._check_state(obj, pyatspi.STATE_CHECKED)) + except: + return 0 def stateenabled(self, window_name, object_name): ''' @@ -396,9 +420,12 @@ class Ldtpd(Utils, ComboBox, Table, Menu, PageTabList, @return: 1 on success 0 on failure. @rtype: integer ''' - obj = self._get_object(window_name, object_name) + try: + obj = self._get_object(window_name, object_name) - return int(self._check_state(obj, pyatspi.STATE_ENABLED)) + return int(self._check_state(obj, pyatspi.STATE_ENABLED)) + except: + return 0 def getobjectlist(self, window_name): ''' @@ -437,9 +464,9 @@ class Ldtpd(Utils, ComboBox, Table, Menu, PageTabList, obj = self._get_object(window_name, object_name) props = \ - ['child_index', 'key', 'obj_index', 'parent', 'class', 'children'] + ['child_index', 'key', 'obj_index', 'parent', 'class', \ + 'children', 'label', 'label_by'] - # TODO: label and label_by, what else am I missing? return props def getobjectproperty(self, window_name, object_name, prop): @@ -464,6 +491,9 @@ class Ldtpd(Utils, ComboBox, Table, Menu, PageTabList, elif prop == 'key': obj = self._get_object(window_name, object_name) # A sanity check. return object_name # For now, we only match exact names anyway. + elif prop == 'label': + obj = self._get_object(window_name, object_name) # A sanity check. + return obj.name elif prop == 'obj_index': role_count = {} for gui in self._list_guis(): diff --git a/ldtpd/generic.py b/ldtpd/generic.py index 4af75b3..55df4a4 100644 --- a/ldtpd/generic.py +++ b/ldtpd/generic.py @@ -29,8 +29,8 @@ from utils import Utils from server_exception import LdtpServerException class Generic(Utils): - def imagecapture(self, winName = None, resolution1 = None, - resolution2 = None, x = 0, y = 0): + def imagecapture(self, winName = None, width = None, + height = None, x = 0, y = 0): if winName: acc = None for gui in self._list_guis(): @@ -47,12 +47,12 @@ class Generic(Utils): window = gtk.gdk.get_default_root_window () size = window.get_size () pb = gtk.gdk.Pixbuf (gtk.gdk.COLORSPACE_RGB, False, 8, - resolution1 or size [0], - resolution2 or size [1]) + width or size [0], + height or size [1]) pb = pb.get_from_drawable (window, window.get_colormap (), x, y, 0, 0, - resolution1 or size [0], - resolution2 or size [1]) + width or size [0], + height or size [1]) if pb: tmpFile = tempfile.mktemp('.png', 'ldtpd_') diff --git a/ldtpd/menu.py b/ldtpd/menu.py index 28e5a5c..6911e9d 100644 --- a/ldtpd/menu.py +++ b/ldtpd/menu.py @@ -149,6 +149,84 @@ class Menu(Utils): return 1 + def menuitemenabled(self, window_name, object_name): + ''' + Verify a menu item is enabled + + @param window_name: Window name to look for, either full name, + LDTP's name convention, or a Unix glob. + @type window_name: string + @param object_name: Object name to look for, either full name, + LDTP's name convention, or a Unix glob. Or menu heirarchy + @type object_name: string + + @return: 1 on success. + @rtype: integer + ''' + try: + if re.search(';', object_name): + obj = self._get_menu_hierarchy(window_name, object_name) + else: + obj = self._get_object(window_name, object_name) + + if self._check_state(obj, pyatspi.STATE_ENABLED): + return 1 + except: + pass + return 0 + + def verifymenucheck(self, window_name, object_name): + ''' + Verify a menu item is checked + + @param window_name: Window name to look for, either full name, + LDTP's name convention, or a Unix glob. + @type window_name: string + @param object_name: Object name to look for, either full name, + LDTP's name convention, or a Unix glob. Or menu heirarchy + @type object_name: string + + @return: 1 on success. + @rtype: integer + ''' + try: + if re.search(';', object_name): + obj = self._get_menu_hierarchy(window_name, object_name) + else: + obj = self._get_object(window_name, object_name) + + if self._check_state(obj, pyatspi.STATE_CHECKED): + return 1 + except: + pass + return 0 + + def verifymenuuncheck(self, window_name, object_name): + ''' + Verify a menu item is un-checked + + @param window_name: Window name to look for, either full name, + LDTP's name convention, or a Unix glob. + @type window_name: string + @param object_name: Object name to look for, either full name, + LDTP's name convention, or a Unix glob. Or menu heirarchy + @type object_name: string + + @return: 1 on success. + @rtype: integer + ''' + try: + if re.search(';', object_name): + obj = self._get_menu_hierarchy(window_name, object_name) + else: + obj = self._get_object(window_name, object_name) + + if not self._check_state(obj, pyatspi.STATE_CHECKED): + return 1 + except: + pass + return 0 + def invokemenu(self, window_name, object_name): ''' Invoke menu item. @@ -163,5 +241,5 @@ class Menu(Utils): @return: 1 on success. @rtype: integer ''' - return self.press (window_name, object_name) + return self.press(window_name, object_name) diff --git a/ldtpd/page_tab_list.py b/ldtpd/page_tab_list.py index 602464c..000a685 100644 --- a/ldtpd/page_tab_list.py +++ b/ldtpd/page_tab_list.py @@ -108,18 +108,21 @@ class PageTabList(Utils): @return: 1 on success 0 on failure @rtype: integer ''' - obj = self._get_object(window_name, object_name) - self._grab_focus(obj) - try: - for child in obj: - if not child: - continue - if self._match_name_to_acc(tab_name, child) and \ - self._check_state(child, pyatspi.STATE_SELECTED): - return 1 - except NotImplementedError: - raise LdtpServerException('Unable to select page tab object.') + obj = self._get_object(window_name, object_name) + self._grab_focus(obj) + + try: + for child in obj: + if not child: + continue + if self._match_name_to_acc(tab_name, child) and \ + self._check_state(child, pyatspi.STATE_SELECTED): + return 1 + except NotImplementedError: + pass + except: + pass return 0 diff --git a/ldtpd/table.py b/ldtpd/table.py index c3b8a14..369bd17 100644 --- a/ldtpd/table.py +++ b/ldtpd/table.py @@ -555,8 +555,11 @@ class Table(Utils): @return: 1 on success 0 on failure. @rtype: integer ''' - text = self.getcellvalue(window_name, object_name, row_index, column) - return int(self._glob_match(row_text, text)) + try: + text = self.getcellvalue(window_name, object_name, row_index, column) + return int(self._glob_match(row_text, text)) + except: + return 0 def doesrowexist(self, window_name, object_name, row_text): ''' @@ -573,20 +576,23 @@ class Table(Utils): @return: 1 on success 0 on failure. @rtype: integer - ''' - obj = self._get_object(window_name, object_name) + ''' + try: + obj = self._get_object(window_name, object_name) - def _searchString(acc): - try: - itext = acc.queryText() - except NotImplementedError: - return False - return row_text == itext.getText(0,-1) + def _searchString(acc): + try: + itext = acc.queryText() + except NotImplementedError: + return False + return row_text == itext.getText(0,-1) - results = pyatspi.findDescendant(obj, _searchString) - - return int(bool(results)) + results = pyatspi.findDescendant(obj, _searchString) + return int(bool(results)) + except: + return 0 + def verifypartialtablecell(self, window_name, object_name, row_index, column_index, row_text): ''' @@ -608,8 +614,10 @@ class Table(Utils): @return: 1 on success 0 on failure. @rtype: integer ''' - text = self.getcellvalue(window_name, object_name, row_index, column) - if re.search(row_text, text): - return 1 - else: - return 0 + try: + text = self.getcellvalue(window_name, object_name, row_index, column) + if re.search(row_text, text): + return 1 + except: + pass + return 0 diff --git a/ldtpd/text.py b/ldtpd/text.py index 533b2bb..57ca742 100644 --- a/ldtpd/text.py +++ b/ldtpd/text.py @@ -103,7 +103,8 @@ class Text(Utils): return int(texti.setTextContents(data.encode('utf-8'))) - def gettextvalue(self, window_name, object_name): + def gettextvalue(self, window_name, object_name, startPosition = None, + endPosition = None): ''' Get text value @@ -113,6 +114,10 @@ class Text(Utils): @param object_name: Object name to type in, either full name, LDTP's name convention, or a Unix glob. @type object_name: string + @param startPosition: Starting position of text to fetch + @type: startPosition: int + @param endPosition: Ending position of text to fetch + @type: endPosition: int @return: text on success. @rtype: string @@ -134,7 +139,16 @@ class Text(Utils): except NotImplementedError: raise LdtpServerException('Text cannot be entered into object.') - return texti.getText(0, texti.characterCount) + if startPosition and startPosition > 0: + start = startPosition + else: + start = 0 + if endPosition and endPosition > start: + end = endPosition + else: + end = texti.characterCount + + return texti.getText(start, end) def verifypartialmatch(self, window_name, object_name, partial_text): ''' @@ -152,9 +166,12 @@ class Text(Utils): @return: 1 on success. @rtype: integer ''' - return int(self._glob_match(partial_text, - self.gettextvalue(window_name, - object_name))) + try: + return int(self._glob_match(partial_text, + self.gettextvalue(window_name, + object_name))) + except: + return 0 def verifysettext(self, window_name, object_name, text): ''' @@ -242,9 +259,12 @@ class Text(Utils): @return: 1 on success 0 on failure. @rtype: integer ''' - obj = self._get_object(window_name, object_name) - self._grab_focus(obj) - return int(self._check_state(obj, pyatspi.STATE_EDITABLE)) + try: + obj = self._get_object(window_name, object_name) + self._grab_focus(obj) + return int(self._check_state(obj, pyatspi.STATE_EDITABLE)) + except: + return 0 def getcharcount(self, window_name, object_name): ''' diff --git a/ldtpd/utils.py b/ldtpd/utils.py index dca0438..ad15b5d 100644 --- a/ldtpd/utils.py +++ b/ldtpd/utils.py @@ -72,13 +72,15 @@ class Utils: if acc.name == name: return 1 _object_name = self._ldtpize_accessible(acc) - _object_name = '%s%s' % (_object_name[0],_object_name[1]) + _object_name = '%s%s' % (_object_name[0], _object_name[1]) if _object_name == name: return 1 if self._glob_match(name, acc.name): return 1 if self._glob_match(name, _object_name): return 1 + if self._glob_match(re.sub(' ', '', name), _object_name): + return 1 return 0 def _match_name_to_appmap(self, name, appmap_name): @@ -134,24 +136,33 @@ class Utils: def _appmap_pairs(self, gui): ldtpized_list = [] + ldtpized_obj_index = {} for obj in self._list_objects(gui): abbrev_role, abbrev_name = self._ldtpize_accessible(obj) + if abbrev_role in ldtpized_obj_index: + ldtpized_obj_index[abbrev_role] += 1 + else: + ldtpized_obj_index[abbrev_role] = 0 if abbrev_name == '': ldtpized_name_base = abbrev_role - ldtpized_name = '%s0' % ldtpized_name_base + ldtpized_name = '%s%d' % (ldtpized_name_base, + ldtpized_obj_index[abbrev_role]) else: - ldtpized_name_base = '%s%s' % (abbrev_role,abbrev_name) + ldtpized_name_base = '%s%s' % (abbrev_role, abbrev_name) ldtpized_name = ldtpized_name_base i = 1 while ldtpized_name in ldtpized_list: - ldtpized_name = '%s%d' % (ldtpized_name_base, i) + ldtpized_name = '%s%d' % (ldtpized_name_base, + i) i += 1 ldtpized_list.append(ldtpized_name) yield ldtpized_name, obj def _get_menu_hierarchy(self, window_name, object_name): _menu_hierarchy = re.split(';', object_name) - obj = self._get_object(window_name, _menu_hierarchy [0]) + # Get handle of menu + obj = self._get_object(window_name, _menu_hierarchy[0]) + # Navigate all sub-menu under a menu for _menu in _menu_hierarchy[1:]: _flag = False for _child in self._list_objects(obj): @@ -159,12 +170,12 @@ class Utils: # if the given object and child object matches continue if self._match_name_to_acc(_menu, _child): + obj = _child _flag = True break if not _flag: raise LdtpServerException ( "Menu item %s doesn't exist in hierarchy" % _menu) - obj = self._get_object(window_name, _menu) return obj def _click_object(self, obj, action = 'click'): diff --git a/ldtpd/value.py b/ldtpd/value.py index f3cdf27..46c9684 100644 --- a/ldtpd/value.py +++ b/ldtpd/value.py @@ -47,7 +47,7 @@ class Value(Utils): except NotImplementedError: raise LdtpServerException('Value cannot be entered into object.') - valuei.currentValue = float (data) + valuei.currentValue = float(data) return 1 def getvalue(self, window_name, object_name): @@ -105,17 +105,15 @@ class Value(Utils): @return: 1 on success 0 on failure. @rtype: 1 ''' - obj = self._get_object(window_name, object_name) - try: + obj = self._get_object(window_name, object_name) valuei = obj.queryValue() - except NotImplementedError: - raise LdtpServerException('Value cannot be entered into object.') - if valuei.currentValue == data: - return 1 - else: - return 0 + if valuei.currentValue == data: + return 1 + except: + pass + return 0 def getminvalue(self, window_name, object_name): ''' @@ -200,12 +198,14 @@ class Value(Utils): @return: 1 on success. @rtype: integer ''' - obj = self._get_object(window_name, object_name) + try: + obj = self._get_object(window_name, object_name) - if self._check_state(obj, pyatspi.STATE_VERTICAL): - return 1 - else: - return 0 + if self._check_state(obj, pyatspi.STATE_VERTICAL): + return 1 + except: + pass + return 0 def verifysliderhorizontal(self, window_name, object_name): ''' @@ -221,12 +221,14 @@ class Value(Utils): @return: 1 on success. @rtype: integer ''' - obj = self._get_object(window_name, object_name) + try: + obj = self._get_object(window_name, object_name) - if self._check_state(obj, pyatspi.STATE_HORIZONTAL): - return 1 - else: - return 0 + if self._check_state(obj, pyatspi.STATE_HORIZONTAL): + return 1 + except: + pass + return 0 def verifyscrollbarvertical(self, window_name, object_name): ''' @@ -242,12 +244,14 @@ class Value(Utils): @return: 1 on success. @rtype: integer ''' - obj = self._get_object(window_name, object_name) + try: + obj = self._get_object(window_name, object_name) - if self._check_state(obj, pyatspi.STATE_VERTICAL): - return 1 - else: - return 0 + if self._check_state(obj, pyatspi.STATE_VERTICAL): + return 1 + except: + pass + return 0 def verifyscrollbarhorizontal(self, window_name, object_name): ''' @@ -263,12 +267,14 @@ class Value(Utils): @return: 1 on success. @rtype: integer ''' - obj = self._get_object(window_name, object_name) + try: + obj = self._get_object(window_name, object_name) - if self._check_state(obj, pyatspi.STATE_HORIZONTAL): - return 1 - else: - return 0 + if self._check_state(obj, pyatspi.STATE_HORIZONTAL): + return 1 + except: + pass + return 0 def scrollup(self, window_name, object_name): ''' diff --git a/ldtputils/Makefile.am b/ldtputils/Makefile.am new file mode 100644 index 0000000..170bba6 --- /dev/null +++ b/ldtputils/Makefile.am @@ -0,0 +1,17 @@ +ldtputils_DATA = \ + __init__.py + +pyc_DATA = $(ldtputils_DATA:.py=.pyc) +pycdir = $(ldtputilsdir) + +%.pyc: %.py + $(PYTHON_CMD) -c "import py_compile; py_compile.compile ('$<', '$@')" + +EXTRA_DIST = \ + $(ldtputils_DATA) + +CLEANFILES = \ + $(pyc_DATA) + +MAINTAINERCLEANFILES = \ + Makefile.in diff --git a/ooldtp/Makefile.am b/ooldtp/Makefile.am new file mode 100644 index 0000000..f7ca285 --- /dev/null +++ b/ooldtp/Makefile.am @@ -0,0 +1,18 @@ +ooldtp_DATA = \ + _context.py \ + __init__.py + +pyc_DATA = $(ooldtp_DATA:.py=.pyc) +pycdir = $(ooldtpdir) + +%.pyc: %.py + $(PYTHON_CMD) -c "import py_compile; py_compile.compile ('$<', '$@')" + +EXTRA_DIST = \ + $(ooldtp_DATA) + +CLEANFILES = \ + $(pyc_DATA) + +MAINTAINERCLEANFILES = \ + Makefile.in |