This file is indexed.

/usr/lib/python3/dist-packages/autopilot/matchers/__init__.py is in python3-autopilot 1.5.1+16.04.20160412-0ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
#
# Autopilot Functional Test Tool
# Copyright (C) 2012-2013 Canonical
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#


"""Autopilot-specific testtools matchers."""

from functools import partial
from testtools.matchers import Matcher, Mismatch

from autopilot.utilities import sleep


class Eventually(Matcher):
    """Asserts that a value will eventually equal a given Matcher object.

    This matcher wraps another testtools matcher object. It makes that other
    matcher work with a timeout. This is necessary for several reasons:

    1. Since most actions in a GUI applicaton take some time to complete, the
       test may need to wait for the application to enter the expected state.

    2. Since the test is running in a separate process to the application under
       test, test authors cannot make any assumptions about when the
       application under test will recieve CPU time to update to the expected
       state.

    There are two main ways of using the Eventually matcher:

    **Attributes from the application**::

        self.assertThat(window.maximized, Eventually(Equals(True)))

    Here, ``window`` is an object generated by autopilot from the applications
    state. This pattern of usage will cover 90% (or more) of the assertions in
    an autopilot test. Note that any matcher can be used - either from
    testtools or any custom matcher that implements the matcher API::

        self.assertThat(window.height, Eventually(GreaterThan(200)))

    **Callable Objects**::

        self.assertThat(
            autopilot.platform.model, Eventually(Equals("Galaxy Nexus")))

    In this example we're using the :func:`autopilot.platform.model` function
    as a callable. In this form, Eventually matches against the return value
    of the callable.

    This can also be used to use a regular python property inside an Eventually
    matcher::

        self.assertThat(lambda: self.mouse.x, Eventually(LessThan(10)))

    .. note:: Using this form generally makes your tests less readable, and
        should be used with great care. It also relies the test author to have
        knowledge about the implementation of the object being matched against.
        In this example, if ``self.mouse.x`` were ever to change to be a
        regular python attribute, this test would likely break.

    **Timeout**

    By default timeout period is ten seconds. This can be altered by passing
    the timeout keyword::

        self.assertThat(foo.bar, Eventually(Equals(123), timeout=30))

    .. warning:: The Eventually matcher does not work with any other matcher
        that expects a callable argument (such as testtools' 'Raises' matcher)

    """

    def __init__(self, matcher, **kwargs):
        super(Eventually, self).__init__()
        self.timeout = kwargs.pop('timeout', 10)
        if kwargs:
            raise ValueError(
                "Unknown keyword arguments: %s" % ', '.join(kwargs.keys()))
        match_fun = getattr(matcher, 'match', None)
        if match_fun is None or not callable(match_fun):
            raise TypeError(
                "Eventually must be called with a testtools matcher argument.")
        self.matcher = matcher

    def match(self, value):
        if callable(value):
            wait_fun = partial(_callable_wait_for, value)
        else:
            wait_fun = getattr(value, 'wait_for', None)
            if wait_fun is None or not callable(wait_fun):
                raise TypeError(
                    "Eventually is only usable with attributes that have a "
                    "wait_for function or callable objects.")

        try:
            wait_fun(self.matcher, self.timeout)
        except AssertionError as e:
            return Mismatch(str(e))
        return None

    def __str__(self):
        return "Eventually " + str(self.matcher)


def _callable_wait_for(refresh_fn, matcher, timeout):
    """Like the patched :meth:`wait_for method`, but for callable objects
    instead of patched variables.

    """
    time_left = timeout
    while True:
        new_value = refresh_fn()
        mismatch = matcher.match(new_value)
        if mismatch:
            failure_msg = mismatch.describe()
        else:
            return

        if time_left >= 1:
            sleep(1)
            time_left -= 1
        else:
            sleep(time_left)
            break

    # can't give a very descriptive message here, especially as refresh_fn
    # is likely to be a lambda.
    raise AssertionError(
        "After %.1f seconds test failed: %s" % (timeout, failure_msg))