Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
tails
tails
Commits
a1e76036
Commit
a1e76036
authored
May 11, 2016
by
anonym
Browse files
Merge remote-tracking branch 'origin/devel' into test/9521-chutney
parents
77d16ece
a6aa7504
Changes
60
Hide whitespace changes
Inline
Side-by-side
Rakefile
View file @
a1e76036
...
...
@@ -18,14 +18,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
require
'open3'
require
'rbconfig'
require
'rubygems'
require
'vagrant'
require
'uri'
$:
.
unshift
File
.
expand_path
(
'../vagrant/lib'
,
__FILE__
)
require
'tails_build_settings'
require
'vagrant_version'
require_relative
'vagrant/lib/tails_build_settings'
# Path to the directory which holds our Vagrantfile
VAGRANT_PATH
=
File
.
expand_path
(
'../vagrant'
,
__FILE__
)
...
...
@@ -40,58 +37,61 @@ EXPORTED_VARIABLES = ['http_proxy', 'MKSQUASHFS_OPTIONS', 'TAILS_RAM_BUILD', 'TA
EXTERNAL_HTTP_PROXY
=
ENV
[
'http_proxy'
]
# In-VM proxy URL
INTERN
E
L_HTTP_PROXY
=
"http://
#{
VIRTUAL_MACHINE_HOSTNAME
}
:3142"
INTERN
A
L_HTTP_PROXY
=
"http://
#{
VIRTUAL_MACHINE_HOSTNAME
}
:3142"
def
primary_vm
env
=
Vagrant
::
Environment
.
new
(
:cwd
=>
VAGRANT_PATH
,
:ui_class
=>
Vagrant
::
UI
::
Basic
)
if
vagrant_old
return
env
.
primary_vm
else
name
=
env
.
primary_machine_name
return
env
.
machine
(
name
,
env
.
default_provider
)
end
end
def
primary_vm_state
if
vagrant_old
return
primary_vm
.
state
else
return
primary_vm
.
state
.
id
end
class
VagrantCommandError
<
StandardError
end
def
primary_vm_chan
if
vagrant_old
return
primary_vm
.
channel
else
return
primary_vm
.
communicate
# Runs the vagrant command, letting stdout/stderr through. Throws an
# exception unless the vagrant command succeeds.
def
run_vagrant
(
*
args
)
Process
.
wait
Kernel
.
spawn
(
'vagrant'
,
*
args
,
:chdir
=>
'./vagrant'
)
if
$?
.
exitstatus
!=
0
raise
(
VagrantCommandError
,
"'vagrant
#{
args
}
' command failed: "
+
"
#{
$?
.
exitstatus
}
"
)
end
end
def
vm_id
if
vagrant_old
primary_vm
.
uuid
else
primary_vm
.
id
# Runs the vagrant command, not letting stdout/stderr through, and
# returns [stdout, stderr, Preocess:Status].
def
capture_vagrant
(
*
args
)
stdout
,
stderr
,
proc_status
=
Open3
.
capture3
(
'vagrant'
,
*
args
,
:chdir
=>
'./vagrant'
)
if
proc_status
.
exitstatus
!=
0
raise
(
VagrantCommandError
,
"'vagrant
#{
args
}
' command failed: "
+
"
#{
proc_status
.
exitstatus
}
"
)
end
return
stdout
,
stderr
end
def
vm_driver
if
vagrant_old
primary_vm
.
driver
else
primary_vm
.
provider
.
driver
def
vagrant_ssh_config
(
key
)
# Cache results
if
$vagrant_ssh_config
.
nil?
$vagrant_ssh_config
=
capture_vagrant
(
'ssh-config'
).
first
.
split
(
"
\n
"
)
\
.
map
{
|
line
|
line
.
strip
.
split
(
/\s+/
,
2
)
}
.
to_h
# The path in the ssh-config output is quoted, which is not what
# is expected outside of a shell, so let's get rid of the quotes.
$vagrant_ssh_config
[
'IdentityFile'
].
gsub!
(
/^"|"$/
,
''
)
end
$vagrant_ssh_config
[
key
]
end
def
current_vm_cpus
info
=
vm_driver
.
execute
'showvminfo'
,
vm_id
,
'--machinereadable'
$1
.
to_i
if
info
=~
/^cpus=(\d+)/
capture_vagrant
(
'ssh'
,
'-c'
,
'grep -c "^processor\s*:" /proc/cpuinfo'
).
first
.
chomp
.
to_i
end
def
vm_running?
primary_vm_state
==
:running
def
vm_state
out
,
_
=
capture_vagrant
(
'status'
)
status_line
=
out
.
split
(
"
\n
"
)[
2
]
if
status_line
[
'not created'
]
return
:not_created
elsif
status_line
[
'shutoff'
]
return
:poweroff
elsif
status_line
[
'running'
]
return
:running
else
raise
"could not determine VM state"
end
end
def
enough_free_host_memory_for_ram_build?
...
...
@@ -106,9 +106,7 @@ def enough_free_host_memory_for_ram_build?
end
def
free_vm_memory
primary_vm_chan
.
execute
(
"free"
,
:error_check
=>
false
)
do
|
fd
,
data
|
return
data
.
split
[
16
].
to_i
end
capture_vagrant
(
'ssh'
,
'-c'
,
'free'
).
first
.
chomp
.
split
[
16
].
to_i
end
def
enough_free_vm_memory_for_ram_build?
...
...
@@ -116,7 +114,7 @@ def enough_free_vm_memory_for_ram_build?
end
def
enough_free_memory_for_ram_build?
if
vm_running
?
if
vm_
state
==
:
running
enough_free_vm_memory_for_ram_build?
else
enough_free_host_memory_for_ram_build?
...
...
@@ -172,7 +170,7 @@ task :parse_build_options do
abort
"No HTTP proxy set, but one is required by TAILS_BUILD_OPTIONS. Aborting."
unless
EXTERNAL_HTTP_PROXY
ENV
[
'http_proxy'
]
=
EXTERNAL_HTTP_PROXY
when
'vmproxy'
ENV
[
'http_proxy'
]
=
INTERN
E
L_HTTP_PROXY
ENV
[
'http_proxy'
]
=
INTERN
A
L_HTTP_PROXY
when
'noproxy'
ENV
[
'http_proxy'
]
=
nil
# SquashFS compression settings
...
...
@@ -221,6 +219,26 @@ task :ensure_clean_repository do
end
end
def
list_artifacts
user
=
vagrant_ssh_config
(
'User'
)
stdout
=
capture_vagrant
(
'ssh'
,
'-c'
,
"find '/home/
#{
user
}
/' -maxdepth 1 "
+
"-name 'tails-*.iso*'"
).
first
stdout
.
split
(
"
\n
"
)
rescue
VagrantCommandError
return
Array
.
new
end
def
remove_artifacts
list_artifacts
.
each
do
|
artifact
|
run_vagrant
(
'ssh'
,
'-c'
,
"sudo rm -f '
#{
artifact
}
'"
)
end
end
desc
"Make sure the vagrant user's home directory has no undesired artifacts"
task
:ensure_clean_home_directory
=>
[
'vm:up'
]
do
remove_artifacts
end
task
:validate_http_proxy
do
if
ENV
[
'http_proxy'
]
proxy_host
=
URI
.
parse
(
ENV
[
'http_proxy'
]).
host
...
...
@@ -242,7 +260,7 @@ task :validate_http_proxy do
end
desc
'Build Tails'
task
:build
=>
[
'parse_build_options'
,
'ensure_clean_repository'
,
'validate_http_proxy'
,
'vm:up'
]
do
task
:build
=>
[
'parse_build_options'
,
'ensure_clean_repository'
,
'ensure_clean_home_directory'
,
'validate_http_proxy'
,
'vm:up'
]
do
if
ENV
[
'TAILS_RAM_BUILD'
]
&&
not
(
enough_free_memory_for_ram_build?
)
$stderr
.
puts
<<-
END_OF_MESSAGE
.
gsub
(
/^ /
,
''
)
...
...
@@ -269,26 +287,41 @@ task :build => ['parse_build_options', 'ensure_clean_repository', 'validate_http
end
exported_env
=
EXPORTED_VARIABLES
.
select
{
|
k
|
ENV
[
k
]
}.
collect
{
|
k
|
"
#{
k
}
='
#{
ENV
[
k
]
}
'"
}.
join
(
' '
)
status
=
primary_vm_chan
.
execute
(
"
#{
exported_env
}
build-tails"
,
:error_check
=>
false
)
do
|
fd
,
data
|
(
fd
==
:stdout
?
$stdout
:
$stderr
).
write
data
collect
{
|
k
|
"
#{
k
}
='
#{
ENV
[
k
]
}
'"
}.
join
(
' '
)
run_vagrant
(
'ssh'
,
'-c'
,
"
#{
exported_env
}
build-tails"
)
artifacts
=
list_artifacts
raise
'No build artifacts was found!'
if
artifacts
.
empty?
user
=
vagrant_ssh_config
(
'User'
)
hostname
=
vagrant_ssh_config
(
'HostName'
)
key_file
=
vagrant_ssh_config
(
'IdentityFile'
)
$stderr
.
puts
"Retrieving artifacts from Vagrant build box."
artifacts
.
each
do
|
artifact
|
run_vagrant
(
'ssh'
,
'-c'
,
"sudo chown
#{
user
}
'
#{
artifact
}
'"
)
Process
.
wait
(
Kernel
.
spawn
(
'scp'
,
'-i'
,
key_file
,
# We need this since the user will not necessarily have a
# known_hosts entry. It is safe since an attacker must
# compromise libvirt's network config or the user running the
# command to modify the #{hostname} below.
'-o'
,
'StrictHostKeyChecking=no'
,
"
#{
user
}
@
#{
hostname
}
:
#{
artifact
}
"
,
'.'
)
)
raise
"Failed to fetch artifact '
#{
artifact
}
'"
unless
$?
.
success?
end
# Move build products to the current directory
FileUtils
.
mv
Dir
.
glob
(
"
#{
VAGRANT_PATH
}
/tails-*"
),
File
.
expand_path
(
'..'
,
__FILE__
),
:force
=>
true
exit
status
remove_artifacts
end
namespace
:vm
do
desc
'Start the build virtual machine'
task
:up
=>
[
'parse_build_options'
,
'validate_http_proxy'
]
do
case
primary_
vm_state
case
vm_state
when
:not_created
# Do not use non-existant in-VM proxy to download the basebox
if
ENV
[
'http_proxy'
]
==
INTERN
E
L_HTTP_PROXY
if
ENV
[
'http_proxy'
]
==
INTERN
A
L_HTTP_PROXY
ENV
[
'http_proxy'
]
=
nil
restore_internal_proxy
=
true
end
...
...
@@ -315,31 +348,56 @@ namespace :vm do
END_OF_MESSAGE
end
env
=
Vagrant
::
Environment
.
new
(
:cwd
=>
VAGRANT_PATH
,
:ui_class
=>
Vagrant
::
UI
::
Basic
)
result
=
env
.
cli
(
'up'
)
abort
"'vagrant up' failed"
unless
result
run_vagrant
(
'up'
)
ENV
[
'http_proxy'
]
=
INTERNAL_HTTP_PROXY
if
restore_internal_proxy
end
ENV
[
'http_proxy'
]
=
INTERNEL_HTTP_PROXY
if
restore_internal_proxy
desc
'SSH into the builder VM'
task
:ssh
do
run_vagrant
(
'ssh'
)
end
desc
'Stop the build virtual machine'
task
:halt
do
env
=
Vagrant
::
Environment
.
new
(
:cwd
=>
VAGRANT_PATH
,
:ui_class
=>
Vagrant
::
UI
::
Basic
)
result
=
env
.
cli
(
'halt'
)
abort
"'vagrant halt' failed"
unless
result
run_vagrant
(
'halt'
)
end
desc
'Re-run virtual machine setup'
task
:provision
=>
[
'parse_build_options'
,
'validate_http_proxy'
]
do
env
=
Vagrant
::
Environment
.
new
(
:cwd
=>
VAGRANT_PATH
,
:ui_class
=>
Vagrant
::
UI
::
Basic
)
result
=
env
.
cli
(
'provision'
)
abort
"'vagrant provision' failed"
unless
result
run_vagrant
(
'provision'
)
end
desc
'Destroy build virtual machine (clean up all files)'
task
:destroy
do
env
=
Vagrant
::
Environment
.
new
(
:cwd
=>
VAGRANT_PATH
,
:ui_class
=>
Vagrant
::
UI
::
Basic
)
result
=
env
.
cli
(
'destroy'
,
'--force'
)
abort
"'vagrant destroy' failed"
unless
result
run_vagrant
(
'destroy'
,
'--force'
)
end
end
namespace
:basebox
do
desc
'Generate a new base box'
task
:create
do
box_dir
=
VAGRANT_PATH
+
'/definitions/tails-builder'
Dir
.
chdir
(
box_dir
)
do
`./generate-tails-builder-box.sh`
raise
'Base box generation failed!'
unless
$?
.
success?
end
box
=
Dir
.
glob
(
"
#{
box_dir
}
/*.box"
).
sort_by
{
|
f
|
File
.
mtime
(
f
)
}
.
last
$stderr
.
puts
<<-
END_OF_MESSAGE
.
gsub
(
/^ /
,
''
)
You have successfully generated a new Vagrant base box:
#{
box
}
To install the new base box, please run:
$ vagrant box add
#{
box
}
To actually make Tails build using this base box, the `config.vm.box` key
in `vagrant/Vagrantfile` has to be updated. Please check the documentation
for details.
END_OF_MESSAGE
end
end
auto/build
View file @
a1e76036
...
...
@@ -180,20 +180,18 @@ set -o pipefail
time
eatmydata
lb
build
noauto
$
{
@
}
RET
=
$?
if
[
-
e
"${BUILD_FILENAME}.${BUILD_FILENAME_EXT}"
];
then
if
[
"$RET"
-
eq
0
];
then
[
-
z
"$JENKINS_URL"
]
||
date
--
utc
'+%s'
>
"$BUILD_END_FILENAME"
echo
"Image was successfully created"
if
[
"$LB_BINARY_IMAGES"
=
iso
];
then
ISO_FILE
=
"${BUILD_FILENAME}.${BUILD_FILENAME_EXT}"
print_iso_size
"$ISO_FILE"
echo
"Hybriding it..."
isohybrid
$
AMNESIA_ISOHYBRID_OPTS
"$ISO_FILE"
print_iso_size
"$ISO_FILE"
truncate
-
s
%
2048
"$ISO_FILE"
print_iso_size
"$ISO_FILE"
fi
else
echo
"Warning: image created, but lb build exited with code $RET"
echo
"Image was successfully created"
[
"$RET"
-
eq
0
]
||
\
echo
"Warning: lb build exited with code $RET"
[
-
z
"$JENKINS_URL"
]
||
date
--
utc
'+%s'
>
"$BUILD_END_FILENAME"
if
[
"$LB_BINARY_IMAGES"
=
iso
];
then
ISO_FILE
=
"${BUILD_FILENAME}.${BUILD_FILENAME_EXT}"
print_iso_size
"$ISO_FILE"
echo
"Hybriding it..."
isohybrid
$
AMNESIA_ISOHYBRID_OPTS
"$ISO_FILE"
print_iso_size
"$ISO_FILE"
truncate
-
s
%
2048
"$ISO_FILE"
print_iso_size
"$ISO_FILE"
fi
echo
"Renaming generated files..."
mv
-
i
"${BUILD_FILENAME}.${BUILD_FILENAME_EXT}"
"${BUILD_DEST_FILENAME}"
...
...
config/chroot_local-hooks/98-remove_unwanted_packages
View file @
a1e76036
...
...
@@ -29,7 +29,7 @@ apt-get --yes purge \
### since they have Priority: standard.
apt-get
--yes
purge
\
apt-listchanges at bsd-mailx dc debian-faq doc-debian dselect
\
'^exim4*'
ftp m4 mlocate mutt ncurses-term nfs-common portmap procmail
python-apt
\
'^exim4*'
ftp m4 mlocate mutt ncurses-term nfs-common portmap procmail
\
python-reportbug reportbug telnet texinfo
time
w3m wamerican
### Deinstall some other unwanted packages.
...
...
config/chroot_local-packageslists/tails-common.list
View file @
a1e76036
...
...
@@ -388,6 +388,7 @@ crda
wireless-regdb
### Automated test suite
python-dogtail
python3-serial
python3-systemd
xdotool
...
...
config/chroot_local-patches/python-dogtail_searchShowingOnly.diff
0 → 100644
View file @
a1e76036
Author: anonym <anonym@riseup.net>
Date: Mon Apr 4 18:04:52 2016 +0200
Add support for only searching among 'showing' nodes.
Here 'showing' refers to pyatspi.STATE_SHOWING, i.e. whether a node is
shown to the end-user or not. Quite often we are only interested in
such nodes, at least when dogtail is used to interact with an
application (e.g. clicking something that isn't there won't
work). Most importantly, this greatly simplifies situations where the
'shown' element we are looking for is hard to exactly pinpoint since
it lacks properties to distinguish it from some not 'shown' element.
Therefore we add a `showingOnly` boolean flag to all search methods
where it makes sense (e.g. it doesn't make sense for Application:s
since they seem to always be considered not 'showing'). The default
will be to not do this, for backwards-compatibility, but the default
is configurable via a new `searchShowingOnly` config option.
--- a/usr/share/pyshared/dogtail/config.py
+++ b/usr/share/pyshared/dogtail/config.py
@@ -58,6 +58,9 @@
class _Config(object):
searchCutoffCount (int):
Number of times to retry when a search fails.
+ searchShowingOnly (boolean):
+ Whether to only search among nodes that are currently being shown.
+
defaultDelay (float):
Default time in seconds to sleep when delaying.
@@ -134,6 +137,7 @@
class _Config(object):
'searchBackoffDuration': 0.5,
'searchWarningThreshold': 3,
'searchCutoffCount': 20,
+ 'searchShowingOnly': False,
'defaultDelay': 0.5,
'childrenLimit': 100,
--- a/usr/share/pyshared/dogtail/tree.py
+++ b/usr/share/pyshared/dogtail/tree.py
@@ -819,12 +819,18 @@
class Node(object):
else:
return False
- def _fastFindChild(self, pred, recursive=True):
+ def _fastFindChild(self, pred, recursive=True, showingOnly=None):
"""
Searches for an Accessible using methods from pyatspi.utils
"""
if isinstance(pred, predicate.Predicate):
pred = pred.satisfiedByNode
+ if showingOnly == None:
+ showingOnly = config.searchShowingOnly
+ if showingOnly:
+ orig_pred = pred
+ pred = lambda n: orig_pred(n) and \
+ n.getState().contains(pyatspi.STATE_SHOWING)
if not recursive:
cIter = iter(self)
while True:
@@ -839,7 +845,7 @@
class Node(object):
return pyatspi.utils.findDescendant(self, pred)
def findChild(self, pred, recursive=True, debugName=None,
- retry=True, requireResult=True):
+ retry=True, requireResult=True, showingOnly=None):
"""
Search for a node satisyfing the predicate, returning a Node.
@@ -871,7 +877,7 @@
class Node(object):
logger.log("searching for %s (attempt %i)" %
(describeSearch(self, pred, recursive, debugName), numAttempts))
- result = self._fastFindChild(pred.satisfiedByNode, recursive)
+ result = self._fastFindChild(pred.satisfiedByNode, recursive, showingOnly=showingOnly)
if result:
assert isinstance(result, Node)
if debugName:
@@ -891,12 +897,12 @@
class Node(object):
raise SearchError(describeSearch(self, pred, recursive, debugName))
# The canonical "search for multiple" method:
- def findChildren(self, pred, recursive=True, isLambda=False):
+ def findChildren(self, pred, recursive=True, isLambda=False, showingOnly=None):
"""
Find all children/descendents satisfying the predicate.
"""
if isLambda is True:
- nodes = self.findChildren(predicate.GenericPredicate(), recursive=recursive)
+ nodes = self.findChildren(predicate.GenericPredicate(), recursive=recursive, showingOnly=showingOnly)
result = []
for node in nodes:
try:
@@ -907,6 +913,12 @@
class Node(object):
return result
if isinstance(pred, predicate.Predicate):
pred = pred.satisfiedByNode
+ if showingOnly == None:
+ showingOnly = config.searchShowingOnly
+ if showingOnly:
+ orig_pred = pred
+ pred = lambda n: orig_pred(n) and \
+ n.getState().contains(pyatspi.STATE_SHOWING)
if not recursive:
cIter = iter(self)
result = []
@@ -929,7 +941,7 @@
class Node(object):
return descendants
# The canonical "search above this node" method:
- def findAncestor(self, pred):
+ def findAncestor(self, pred, showingOnly=None):
"""
Search up the ancestry of this node, returning the first Node
satisfying the predicate, or None.
@@ -945,7 +957,7 @@
class Node(object):
return None
# Various wrapper/helper search methods:
- def child(self, name='', roleName='', description='', label='', recursive=True, retry=True, debugName=None):
+ def child(self, name='', roleName='', description='', label='', recursive=True, retry=True, debugName=None, showingOnly=None):
"""
Finds a child satisying the given criteria.
@@ -953,9 +965,9 @@
class Node(object):
if no such child is found, and will eventually raise an exception. It
also logs the search.
"""
- return self.findChild(predicate.GenericPredicate(name=name, roleName=roleName, description=description, label=label), recursive=recursive, retry=retry, debugName=debugName)
+ return self.findChild(predicate.GenericPredicate(name=name, roleName=roleName, description=description, label=label), recursive=recursive, retry=retry, debugName=debugName, showingOnly=showingOnly)
- def isChild(self, name='', roleName='', description='', label='', recursive=True, retry=False, debugName=None):
+ def isChild(self, name='', roleName='', description='', label='', recursive=True, retry=False, debugName=None, showingOnly=None):
"""
Determines whether a child satisying the given criteria exists.
@@ -970,12 +982,12 @@
class Node(object):
self.findChild(
predicate.GenericPredicate(
name=name, roleName=roleName, description=description, label=label),
- recursive=recursive, retry=retry, debugName=debugName)
+ recursive=recursive, retry=retry, debugName=debugName, showingOnly=showingOnly)
except SearchError:
found = False
return found
- def menu(self, menuName, recursive=True):
+ def menu(self, menuName, recursive=True, showingOnly=None):
"""
Search below this node for a menu with the given name.
@@ -983,9 +995,9 @@
class Node(object):
if no such child is found, and will eventually raise an exception. It
also logs the search.
"""
- return self.findChild(predicate.IsAMenuNamed(menuName=menuName), recursive)
+ return self.findChild(predicate.IsAMenuNamed(menuName=menuName), recursive, showingOnly=showingOnly)
- def menuItem(self, menuItemName, recursive=True):
+ def menuItem(self, menuItemName, recursive=True, showingOnly=None):
"""
Search below this node for a menu item with the given name.
@@ -993,9 +1005,9 @@
class Node(object):
if no such child is found, and will eventually raise an exception. It
also logs the search.
"""
- return self.findChild(predicate.IsAMenuItemNamed(menuItemName=menuItemName), recursive)
+ return self.findChild(predicate.IsAMenuItemNamed(menuItemName=menuItemName), recursive, showingOnly=showingOnly)
- def textentry(self, textEntryName, recursive=True):
+ def textentry(self, textEntryName, recursive=True, showingOnly=None):
"""
Search below this node for a text entry with the given name.
@@ -1003,9 +1015,9 @@
class Node(object):
if no such child is found, and will eventually raise an exception. It
also logs the search.
"""
- return self.findChild(predicate.IsATextEntryNamed(textEntryName=textEntryName), recursive)
+ return self.findChild(predicate.IsATextEntryNamed(textEntryName=textEntryName), recursive, showingOnly=showingOnly)
- def button(self, buttonName, recursive=True):
+ def button(self, buttonName, recursive=True, showingOnly=None):
"""
Search below this node for a button with the given name.
@@ -1013,9 +1025,9 @@
class Node(object):
if no such child is found, and will eventually raise an exception. It
also logs the search.
"""
- return self.findChild(predicate.IsAButtonNamed(buttonName=buttonName), recursive)
+ return self.findChild(predicate.IsAButtonNamed(buttonName=buttonName), recursive, showingOnly=showingOnly)
- def childLabelled(self, labelText, recursive=True):
+ def childLabelled(self, labelText, recursive=True, showingOnly=None):
"""
Search below this node for a child labelled with the given text.
@@ -1023,9 +1035,9 @@
class Node(object):
if no such child is found, and will eventually raise an exception. It
also logs the search.
"""
- return self.findChild(predicate.IsLabelledAs(labelText), recursive)
+ return self.findChild(predicate.IsLabelledAs(labelText), recursive, showingOnly=showingOnly)
- def childNamed(self, childName, recursive=True):
+ def childNamed(self, childName, recursive=True, showingOnly=None):
"""
Search below this node for a child with the given name.
@@ -1033,9 +1045,9 @@
class Node(object):
if no such child is found, and will eventually raise an exception. It
also logs the search.
"""
- return self.findChild(predicate.IsNamed(childName), recursive)
+ return self.findChild(predicate.IsNamed(childName), recursive, showingOnly=showingOnly)
- def tab(self, tabName, recursive=True):
+ def tab(self, tabName, recursive=True, showingOnly=None):
"""
Search below this node for a tab with the given name.
@@ -1043,7 +1055,7 @@
class Node(object):
if no such child is found, and will eventually raise an exception. It
also logs the search.
"""
- return self.findChild(predicate.IsATabNamed(tabName=tabName), recursive)
+ return self.findChild(predicate.IsATabNamed(tabName=tabName), recursive, showingOnly=showingOnly)
def getUserVisibleStrings(self):
"""
@@ -1109,7 +1121,7 @@
class Root (Node):
Get all applications.
"""
return root.findChildren(predicate.GenericPredicate(
- roleName="application"), recursive=False)
+ roleName="application"), recursive=False, showingOnly=False)
def application(self, appName, retry=True):
"""
@@ -1120,12 +1132,12 @@
class Root (Node):
if no such child is found, and will eventually raise an exception. It
also logs the search.
"""
- return root.findChild(predicate.IsAnApplicationNamed(appName), recursive=False, retry=retry)
+ return root.findChild(predicate.IsAnApplicationNamed(appName), recursive=False, retry=retry, showingOnly=False)
class Application (Node):
- def dialog(self, dialogName, recursive=False):
+ def dialog(self, dialogName, recursive=False, showingOnly=None):
"""
Search below this node for a dialog with the given name,
returning a Window instance.
@@ -1136,9 +1148,9 @@
class Application (Node):
FIXME: should this method activate the dialog?
"""
- return self.findChild(predicate.IsADialogNamed(dialogName=dialogName), recursive)
+ return self.findChild(predicate.IsADialogNamed(dialogName=dialogName), recursive, showingOnly=showingOnly)
- def window(self, windowName, recursive=False):
+ def window(self, windowName, recursive=False, showingOnly=None):
"""