Skip to content

Commit

Permalink
Initial attempt at documentation for ATOMac.
Browse files Browse the repository at this point in the history
  • Loading branch information
pekkle01 committed Mar 19, 2012
1 parent 97a1010 commit 52d5c8c
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 24 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ sdist
develop-eggs
MANIFEST
.installed.cfg
*.swp
doc/_build/

pip-log.txt

3 changes: 1 addition & 2 deletions doc/apireference.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
ATOMac API Reference
==================================

.. automodule:: atomac
:members:
.. module:: atomac

.. autoexception:: Error

Expand Down
13 changes: 8 additions & 5 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# This should locate the parent directory for atomac
sys.path.insert(0, os.path.join(os.path.abspath('..')))

import distutils.command.build
from distutils.dist import Distribution
Expand All @@ -25,17 +27,18 @@
b.initialize_options()
b.finalize_options()

# This should locate the parent directory for atomac
sys.path.insert(0, os.path.join(os.path.abspath('..'), b.build_platlib))

# -- General configuration -----------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc']
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.doctest',
'sphinx.ext.viewcode',
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
Expand All @@ -51,7 +54,7 @@

# General information about the project.
project = u'ATOMac'
copyright = u'2011, Jesse Mendonca, Ken Song, James Tatum, Andrew Wu'
copyright = u'2012, Jesse Mendonca, Ken Song, James Tatum, Andrew Wu'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
Expand Down
48 changes: 44 additions & 4 deletions doc/gettingstarted.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,51 @@
===============
Getting Started
===============

ATOMac requires a system running OS X and Xcode installed. It has been tested extensively on 10.6. 10.5 may work. If you experience issues with ATOMac on a particular version of OS X, please open a ticket in the issue tracker.
------------------
Basic Requirements
------------------

* *Host*

ATOMac requires an Intel-based system running OS X and Xcode installed.

Systemwide accessibility must be enabled. Check the checkbox: System Preferences > Universal Access > Enable access for assistive devices. Failure to enable this will result in ErrorAPIDisabled exceptions during some module usage.
Tested OS versions:

Installation should be as simple as running the following command line, which will download, build and install ATOMac::
* 10.6
* 10.7

$ sudo easy_install atomac
It may work on 10.5.
If you experience issues with ATOMac on a particular version of OS X,
please open a ticket in the issue tracker.

* *System Preferences*

System-wide accessibility must be enabled.

To enable access for assistive devices,
check the checkbox:

| *System Preferences >*
| *Universal Access >*
| *Enable access for assistive devices.*
Failure to enable this will result in ErrorAPIDisabled exceptions or invalid references.

To facilitate programmatic control via keyboard shortcuts,
select the radio button for *All Controls* under

| *System Preferences >*
| *Keyboard >*
| *Keyboard Shortcuts >*
| *Full Keyboard Access*
* *Installation*

Installation should be as simple as running the following command line,
which will download, build and install ATOMac::

$ sudo easy_install atomac

Alternatively, you can use `pip <http://pypi.python.org/pypi/pip>`_
for easier module management.
12 changes: 11 additions & 1 deletion doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@
Welcome to ATOMac's documentation!
==================================

Contents:
=====================================
ATOMac - Automated Testing on the Mac
=====================================

Welcome to ATOMac:
the first Python library to enable programmatic control
of GUI applications via the Mac OS X accessibility API.
It is fast and easy to use to write tests
or otherwise control your GUI application.

.. Contents:
.. toctree::
:maxdepth: 2
Expand Down
57 changes: 45 additions & 12 deletions doc/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,58 +5,86 @@ Usage
Working with Applications
-------------------------

Once the atomac module is installed, we should be able to use it to launch an application::
Once the atomac module is installed,
we should be able to use it to launch an application::

>>> import atomac
>>> atomac.launchAppByBundleId('com.apple.Automator')

This should launch Automator. Next, we can get a reference to the UI element for the application itself::
This should launch Automator.
Next, we can get a reference to the UI element
for the application itself::

>>> automator = atomac.getAppRefByBundleId('com.apple.Automator')
>>> automator
<pyatom.AXClasses.NativeUIElement AXApplication u'Automator'>
<atomac.AXClasses.NativeUIElement AXApplication u'Automator'>

Other means of obtaining references to a running application include::

>>> automator = atomac.getAppRefByLocalizedName('Automator')
>>> automator = atomac.getAppRefByPid(12345)

Finally, to terminate a running application, we can use the method ``terminateAppByBundleId``::
Finally, to terminate a running application,
we can use the method ``terminateAppByBundleId``::

>>> atomac.terminateAppByBundleId('com.apple.Automator')


Finding Objects in the Hierarchy
--------------------------------

Assuming we have an atomac reference to the running Automator application, we can find objects in the accessibility hierarchy::
Assuming we have an atomac reference
to the running Automator application,
we can find objects in the accessibility hierarchy::

>>> window = automator.windows()[0]
>>> window.AXTitle
u'Untitled'
>>> sheet = window.sheets()[0]

Note that we retrieved an accessibility attribute from the Window object - AXTitle. ATOMac supports reading and writing of most attributes. Using Xcode's included *Accessibility Inspector* utility can provide a quick way to find these attributes.
Note that we retrieved an accessibility attribute
from the Window object - AXTitle.
ATOMac supports reading and writing of most attributes.
Using Xcode's included *Accessibility Inspector* utility can provide
a quick way to find these attributes.

There is a shortcut for getting the sheet object which bypasses accessing it through the Window object - ATOMac can search all objects in the hierarchy by appending 'R' to the end of the method call::
There is a shortcut for getting the sheet object
which bypasses accessing it through the Window object.
ATOMac can search all objects in the hierarchy
by appending 'R' to the end of the method call::

>>> sheet = automator.sheetsR()[0]

There are search methods for most types of accessibility objects. Each search method, such as ``windows``, has a corresponding recursive search function, such as ``windowsR``. The recursive search finds items that aren't just direct children of the associated object, but children of its children. These search methods can be given terms to identify specific elements. Note that "*" and "?" can be used as wildcard match characters in all ATOMac search methods::
There are search methods for most types of accessibility objects.
Each search method, such as ``windows``,
has a corresponding recursive search function, such as ``windowsR``.
The recursive search finds items
that aren't just direct children of the associated object,
but children of its children.
These search methods can be given terms to identify specific elements.
Note that "*" and "?" can be used as wildcard match characters
in all ATOMac search methods::

>>> close = sheet.buttons('Close*')[0]

ATOMac has a method to search for UI elements that match any number of criteria. The criteria are accessibility attributes (as outlined in Accessibility Inspector)::
ATOMac has a method to search for UI elements
that match any number of criteria.
The criteria are accessibility attributes
(as outlined in Accessibility Inspector)::

>>> close = sheet.findFirst(AXRole='AXButton', AXTitle='Close')

``FindFirst`` and ``FindFirstR`` return the first item found to match the criteria or ``None``. ``FindAll`` and ``FindAllR`` return a list of all items that match the criteria or an empty list.
``FindFirst`` and ``FindFirstR`` return
the first item found to match the criteria or ``None``.
``FindAll`` and ``FindAllR`` return a list of all items
that match the criteria or an empty list.


Attributes and Actions
----------------------

Objects are fairly versatile. You can get a list of supported attributes and actions on an object::
Objects are fairly versatile.
You can get a list of supported attributes and actions on an object::

>>> close.getAttributes()
[u'AXRole', u'AXRoleDescription', u'AXHelp', u'AXEnabled', u'AXFocused',
Expand All @@ -71,5 +99,10 @@ Performing an action is as natural as::

>>> close.Press()

Note that in Accessibility Inspector the action name begins with "AX-". To distinguish actions more easily from attributes, atomac drops the initial "AX" for names of actions. As a result, "AXPress" in Accessibility Inspector becomes simply "Press" in atomac and can be invoked on the object as ``Press()``. Any appropriate action can be triggered this way.
Note that in Accessibility Inspector the action name begins with "AX-".
To distinguish actions more easily from attributes,
atomac drops the initial "AX" for names of actions.
As a result, "AXPress" in Accessibility Inspector simply becomes
"Press" in atomac and can be invoked on the object as ``Press()``.
Any appropriate action can be triggered this way.

0 comments on commit 52d5c8c

Please sign in to comment.