Ejemplo n.º 1
0
    def format_string(self, template, *positional, **named):
        """Formats a ``template`` using the given ``positional`` and ``named`` arguments.

        The template can be either be a string or an absolute path to
        an existing file. In the latter case the file is read and its contents
        are used as the template. If the template file contains non-ASCII
        characters, it must be encoded using UTF-8.

        The template is formatted using Python's
        [https://docs.python.org/library/string.html#format-string-syntax|format
        string syntax]. Placeholders are marked using ``{}`` with possible
        field name and format specification inside. Literal curly braces
        can be inserted by doubling them like `{{` and `}}`.

        Examples:
        | ${to} = | Format String | To: {} <{}>                    | ${user}      | ${email} |
        | ${to} = | Format String | To: {name} <{email}>           | name=${name} | email=${email} |
        | ${to} = | Format String | To: {user.name} <{user.email}> | user=${user} |
        | ${xx} = | Format String | {:*^30}                        | centered     |
        | ${yy} = | Format String | {0:{width}{base}}              | ${42}        | base=X | width=10 |
        | ${zz} = | Format String | ${CURDIR}/template.txt         | positional   | named=value |

        New in Robot Framework 3.1.
        """
        if os.path.isabs(template) and os.path.isfile(template):
            template = template.replace('/', os.sep)
            logger.info('Reading template from file <a href="%s">%s</a>.' %
                        (template, template),
                        html=True)
            with Utf8Reader(template) as reader:
                template = reader.read()
        return template.format(*positional, **named)
Ejemplo n.º 2
0
    def split_to_lines(self, string, start=0, end=None):
        """Splits the given string to lines.

        It is possible to get only a selection of lines from ``start``
        to ``end`` so that ``start`` index is inclusive and ``end`` is
        exclusive. Line numbering starts from 0, and it is possible to
        use negative indices to refer to lines from the end.

        Lines are returned without the newlines. The number of
        returned lines is automatically logged.

        Examples:
        | @{lines} =        | Split To Lines | ${manylines} |    |    |
        | @{ignore first} = | Split To Lines | ${manylines} | 1  |    |
        | @{ignore last} =  | Split To Lines | ${manylines} |    | -1 |
        | @{5th to 10th} =  | Split To Lines | ${manylines} | 4  | 10 |
        | @{first two} =    | Split To Lines | ${manylines} |    | 1  |
        | @{last two} =     | Split To Lines | ${manylines} | -2 |    |

        Use `Get Line` if you only need to get a single line.
        """
        start = self._convert_to_index(start, 'start')
        end = self._convert_to_index(end, 'end')
        lines = string.splitlines()[start:end]
        logger.info('%d lines returned' % len(lines))
        return lines
Ejemplo n.º 3
0
    def split_to_lines(self, string, start=0, end=None):
        """Splits the given string to lines.

        It is possible to get only a selection of lines from ``start``
        to ``end`` so that ``start`` index is inclusive and ``end`` is
        exclusive. Line numbering starts from 0, and it is possible to
        use negative indices to refer to lines from the end.

        Lines are returned without the newlines. The number of
        returned lines is automatically logged.

        Examples:
        | @{lines} =        | Split To Lines | ${manylines} |    |    |
        | @{ignore first} = | Split To Lines | ${manylines} | 1  |    |
        | @{ignore last} =  | Split To Lines | ${manylines} |    | -1 |
        | @{5th to 10th} =  | Split To Lines | ${manylines} | 4  | 10 |
        | @{first two} =    | Split To Lines | ${manylines} |    | 1  |
        | @{last two} =     | Split To Lines | ${manylines} | -2 |    |

        Use `Get Line` if you only need to get a single line.
        """
        start = self._convert_to_index(start, 'start')
        end = self._convert_to_index(end, 'end')
        lines = string.splitlines()[start:end]
        logger.info('%d lines returned' % len(lines))
        return lines
Ejemplo n.º 4
0
    def format_string(self, template, *positional, **named):
        """Formats a ``template`` using the given ``positional`` and ``named`` arguments.

        The template can be either be a string or an absolute path to
        an existing file. In the latter case the file is read and its contents
        are used as the template. If the template file contains non-ASCII
        characters, it must be encoded using UTF-8.

        The template is formatted using Python's
        [https://docs.python.org/library/string.html#format-string-syntax|format
        string syntax]. Placeholders are marked using ``{}`` with possible
        field name and format specification inside. Literal curly braces
        can be inserted by doubling them like `{{` and `}}`.

        Examples:
        | ${to} = | Format String | To: {} <{}>                    | ${user}      | ${email} |
        | ${to} = | Format String | To: {name} <{email}>           | name=${name} | email=${email} |
        | ${to} = | Format String | To: {user.name} <{user.email}> | user=${user} |
        | ${xx} = | Format String | {:*^30}                        | centered     |
        | ${yy} = | Format String | {0:{width}{base}}              | ${42}        | base=X | width=10 |
        | ${zz} = | Format String | ${CURDIR}/template.txt         | positional   | named=value |

        New in Robot Framework 3.1.
        """
        if os.path.isabs(template) and os.path.isfile(template):
            template = template.replace('/', os.sep)
            logger.info('Reading template from file <a href="%s">%s</a>.'
                        % (template, template), html=True)
            with Utf8Reader(template) as reader:
                template = reader.read()
        return template.format(*positional, **named)
Ejemplo n.º 5
0
 def _kill(self, process):
     logger.info('Forcefully killing process.')
     if hasattr(os, 'killpg'):
         os.killpg(process.pid, signal_module.SIGKILL)
     else:
         process.kill()
     if not self._process_is_stopped(process, self.KILL_TIMEOUT):
         raise RuntimeError('Failed to kill process.')
Ejemplo n.º 6
0
 def _kill(self, process):
     logger.info('Forcefully killing process.')
     if hasattr(os, 'killpg'):
         os.killpg(process.pid, signal_module.SIGKILL)
     else:
         process.kill()
     if not self._process_is_stopped(process, self.KILL_TIMEOUT):
         raise RuntimeError('Failed to kill process.')
Ejemplo n.º 7
0
 def _manage_process_timeout(self, handle, on_timeout):
     if on_timeout == 'terminate':
         return self.terminate_process(handle)
     elif on_timeout == 'kill':
         return self.terminate_process(handle, kill=True)
     else:
         logger.info('Leaving process intact.')
         return None
Ejemplo n.º 8
0
 def _manage_process_timeout(self, handle, on_timeout):
     if on_timeout == 'terminate':
         return self.terminate_process(handle)
     elif on_timeout == 'kill':
         return self.terminate_process(handle, kill=True)
     else:
         logger.info('Leaving process intact.')
         return None
Ejemplo n.º 9
0
    def wait_for_process(self,
                         handle=None,
                         timeout=None,
                         on_timeout='continue'):
        """Waits for the process to complete or to reach the given timeout.

        The process to wait for must have been started earlier with
        `Start Process`. If ``handle`` is not given, uses the current
        `active process`.

        ``timeout`` defines the maximum time to wait for the process. It can be
        given in
        [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-format|
        various time formats] supported by Robot Framework, for example, ``42``,
        ``42 s``, or ``1 minute 30 seconds``.

        ``on_timeout`` defines what to do if the timeout occurs. Possible values
        and corresponding actions are explained in the table below. Notice
        that reaching the timeout never fails the test.

        | = Value = |               = Action =               |
        | continue  | The process is left running (default). |
        | terminate | The process is gracefully terminated.  |
        | kill      | The process is forcefully stopped.     |

        See `Terminate Process` keyword for more details how processes are
        terminated and killed.

        If the process ends before the timeout or it is terminated or killed,
        this keyword returns a `result object` containing information about
        the execution. If the process is left running, Python ``None`` is
        returned instead.

        Examples:
        | # Process ends cleanly      |                  |                  |
        | ${result} =                 | Wait For Process | example          |
        | Process Should Be Stopped   | example          |                  |
        | Should Be Equal As Integers | ${result.rc}     | 0                |
        | # Process does not end      |                  |                  |
        | ${result} =                 | Wait For Process | timeout=42 secs  |
        | Process Should Be Running   |                  |                  |
        | Should Be Equal             | ${result}        | ${NONE}          |
        | # Kill non-ending process   |                  |                  |
        | ${result} =                 | Wait For Process | timeout=1min 30s | on_timeout=kill |
        | Process Should Be Stopped   |                  |                  |
        | Should Be Equal As Integers | ${result.rc}     | -9               |

        ``timeout`` and ``on_timeout`` are new in Robot Framework 2.8.2.
        """
        process = self._processes[handle]
        logger.info('Waiting for process to complete.')
        if timeout:
            timeout = timestr_to_secs(timeout)
            if not self._process_is_stopped(process, timeout):
                logger.info('Process did not complete in %s.' %
                            secs_to_timestr(timeout))
                return self._manage_process_timeout(handle, on_timeout.lower())
        return self._wait(process)
Ejemplo n.º 10
0
def none_shall_pass(who):
    if who is not None:
        raise AssertionError('None shall pass!')
    logger.info('<object width="480" height="385">'
                '<param name="movie" value="http://www.youtube.com/v/dhRUe-gz690&hl=en_US&fs=1&rel=0&color1=0x234900&color2=0x4e9e00"></param>'
                '<param name="allowFullScreen" value="true"></param>'
                '<param name="allowscriptaccess" value="always"></param>'
                '<embed src="http://www.youtube.com/v/dhRUe-gz690&hl=en_US&fs=1&rel=0&color1=0x234900&color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed>'
                '</object>', html=True)
Ejemplo n.º 11
0
    def wait_for_process(self, handle=None, timeout=None, on_timeout='continue'):
        """Waits for the process to complete or to reach the given timeout.

        The process to wait for must have been started earlier with
        `Start Process`. If ``handle`` is not given, uses the current
        `active process`.

        ``timeout`` defines the maximum time to wait for the process. It can be
        given in
        [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-format|
        various time formats] supported by Robot Framework, for example, ``42``,
        ``42 s``, or ``1 minute 30 seconds``.

        ``on_timeout`` defines what to do if the timeout occurs. Possible values
        and corresponding actions are explained in the table below. Notice
        that reaching the timeout never fails the test.

        | = Value = |               = Action =               |
        | continue  | The process is left running (default). |
        | terminate | The process is gracefully terminated.  |
        | kill      | The process is forcefully stopped.     |

        See `Terminate Process` keyword for more details how processes are
        terminated and killed.

        If the process ends before the timeout or it is terminated or killed,
        this keyword returns a `result object` containing information about
        the execution. If the process is left running, Python ``None`` is
        returned instead.

        Examples:
        | # Process ends cleanly      |                  |                  |
        | ${result} =                 | Wait For Process | example          |
        | Process Should Be Stopped   | example          |                  |
        | Should Be Equal As Integers | ${result.rc}     | 0                |
        | # Process does not end      |                  |                  |
        | ${result} =                 | Wait For Process | timeout=42 secs  |
        | Process Should Be Running   |                  |                  |
        | Should Be Equal             | ${result}        | ${NONE}          |
        | # Kill non-ending process   |                  |                  |
        | ${result} =                 | Wait For Process | timeout=1min 30s | on_timeout=kill |
        | Process Should Be Stopped   |                  |                  |
        | Should Be Equal As Integers | ${result.rc}     | -9               |

        ``timeout`` and ``on_timeout`` are new in Robot Framework 2.8.2.
        """
        process = self._processes[handle]
        logger.info('Waiting for process to complete.')
        if timeout:
            timeout = timestr_to_secs(timeout)
            if not self._process_is_stopped(process, timeout):
                logger.info('Process did not complete in %s.'
                            % secs_to_timestr(timeout))
                return self._manage_process_timeout(handle, on_timeout.lower())
        return self._wait(process)
Ejemplo n.º 12
0
def none_shall_pass(who):
    if who is not None:
        raise AssertionError('None shall pass!')
    logger.info(
        '<iframe width="560" height="315" '
        'src="https://www.youtube-nocookie.com/embed/zKhEw7nD9C4?autoplay=1" '
        'frameborder="0" '
        'allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" '
        'allowfullscreen>'
        '</iframe>',
        html=True)
Ejemplo n.º 13
0
    def remove_duplicates(self, list_):
        """Returns a list without duplicates based on the given ``list``.

        Creates and returns a new list that contains all items in the given
        list so that one item can appear only once. Order of the items in
        the new list is the same as in the original except for missing
        duplicates. Number of the removed duplicates is logged.
        """
        self._validate_list(list_)
        ret = []
        for item in list_:
            if item not in ret:
                ret.append(item)
        removed = len(list_) - len(ret)
        logger.info('%d duplicate%s removed.' % (removed, plural_or_not(removed)))
        return ret
Ejemplo n.º 14
0
    def remove_from_dictionary(self, dictionary, *keys):
        """Removes the given ``keys`` from the ``dictionary``.

        If the given ``key`` cannot be found from the ``dictionary``, it
        is ignored.

        Example:
        | Remove From Dictionary | ${D3} | b | x | y |
        =>
        | ${D3} = {'a': 1, 'c': 3}
        """
        for key in keys:
            if key in dictionary:
                value = dictionary.pop(key)
                logger.info("Removed item with key '%s' and value '%s'." % (key, value))
            else:
                logger.info("Key '%s' not found." % key)
Ejemplo n.º 15
0
    def remove_duplicates(self, list_):
        """Returns a list without duplicates based on the given ``list``.

        Creates and returns a new list that contains all items in the given
        list so that one item can appear only once. Order of the items in
        the new list is the same as in the original except for missing
        duplicates. Number of the removed duplicates is logged.
        """
        self._validate_list(list_)
        ret = []
        for item in list_:
            if item not in ret:
                ret.append(item)
        removed = len(list_) - len(ret)
        logger.info('%d duplicate%s removed.' %
                    (removed, plural_or_not(removed)))
        return ret
Ejemplo n.º 16
0
    def remove_from_dictionary(self, dictionary, *keys):
        """Removes the given ``keys`` from the ``dictionary``.

        If the given ``key`` cannot be found from the ``dictionary``, it
        is ignored.

        Example:
        | Remove From Dictionary | ${D3} | b | x | y |
        =>
        | ${D3} = {'a': 1, 'c': 3}
        """
        for key in keys:
            if key in dictionary:
                value = dictionary.pop(key)
                logger.info("Removed item with key '%s' and value '%s'." %
                            (key, value))
            else:
                logger.info("Key '%s' not found." % key)
Ejemplo n.º 17
0
 def _terminate(self, process):
     logger.info('Gracefully terminating process.')
     # Sends signal to the whole process group both on POSIX and on Windows
     # if supported by the interpreter.
     if hasattr(os, 'killpg'):
         os.killpg(process.pid, signal_module.SIGTERM)
     elif hasattr(signal_module, 'CTRL_BREAK_EVENT'):
         if IRONPYTHON:
             # https://ironpython.codeplex.com/workitem/35020
             ctypes.windll.kernel32.GenerateConsoleCtrlEvent(
                 signal_module.CTRL_BREAK_EVENT, process.pid)
         else:
             process.send_signal(signal_module.CTRL_BREAK_EVENT)
     else:
         process.terminate()
     if not self._process_is_stopped(process, self.TERMINATE_TIMEOUT):
         logger.info('Graceful termination failed.')
         self._kill(process)
Ejemplo n.º 18
0
 def _terminate(self, process):
     logger.info('Gracefully terminating process.')
     # Sends signal to the whole process group both on POSIX and on Windows
     # if supported by the interpreter.
     if hasattr(os, 'killpg'):
         os.killpg(process.pid, signal_module.SIGTERM)
     elif hasattr(signal_module, 'CTRL_BREAK_EVENT'):
         if IRONPYTHON:
             # https://ironpython.codeplex.com/workitem/35020
             ctypes.windll.kernel32.GenerateConsoleCtrlEvent(
                 signal_module.CTRL_BREAK_EVENT, process.pid)
         else:
             process.send_signal(signal_module.CTRL_BREAK_EVENT)
     else:
         process.terminate()
     if not self._process_is_stopped(process, self.TERMINATE_TIMEOUT):
         logger.info('Graceful termination failed.')
         self._kill(process)
Ejemplo n.º 19
0
    def send_signal_to_process(self, signal, handle=None, group=False):
        """Sends the given ``signal`` to the specified process.

        If ``handle`` is not given, uses the current `active process`.

        Signal can be specified either as an integer as a signal name. In the
        latter case it is possible to give the name both with or without ``SIG``
        prefix, but names are case-sensitive. For example, all the examples
        below send signal ``INT (2)``:

        | Send Signal To Process | 2      |        | # Send to active process |
        | Send Signal To Process | INT    |        |                          |
        | Send Signal To Process | SIGINT | myproc | # Send to named process  |

        This keyword is only supported on Unix-like machines, not on Windows.
        What signals are supported depends on the system. For a list of
        existing signals on your system, see the Unix man pages related to
        signal handling (typically ``man signal`` or ``man 7 signal``).

        By default sends the signal only to the parent process, not to possible
        child processes started by it. Notice that when `running processes in
        shell`, the shell is the parent process and it depends on the system
        does the shell propagate the signal to the actual started process.

        To send the signal to the whole process group, ``group`` argument can
        be set to any true value (see `Boolean arguments`). This is not
        supported by Jython, however.

        New in Robot Framework 2.8.2. Support for ``group`` argument is new
        in Robot Framework 2.8.5.
        """
        if os.sep == '\\':
            raise RuntimeError('This keyword does not work on Windows.')
        process = self._processes[handle]
        signum = self._get_signal_number(signal)
        logger.info('Sending signal %s (%d).' % (signal, signum))
        if is_truthy(group) and hasattr(os, 'killpg'):
            os.killpg(process.pid, signum)
        elif hasattr(process, 'send_signal'):
            process.send_signal(signum)
        else:
            raise RuntimeError('Sending signals is not supported '
                               'by this Python version.')
Ejemplo n.º 20
0
    def send_signal_to_process(self, signal, handle=None, group=False):
        """Sends the given ``signal`` to the specified process.

        If ``handle`` is not given, uses the current `active process`.

        Signal can be specified either as an integer as a signal name. In the
        latter case it is possible to give the name both with or without ``SIG``
        prefix, but names are case-sensitive. For example, all the examples
        below send signal ``INT (2)``:

        | Send Signal To Process | 2      |        | # Send to active process |
        | Send Signal To Process | INT    |        |                          |
        | Send Signal To Process | SIGINT | myproc | # Send to named process  |

        This keyword is only supported on Unix-like machines, not on Windows.
        What signals are supported depends on the system. For a list of
        existing signals on your system, see the Unix man pages related to
        signal handling (typically ``man signal`` or ``man 7 signal``).

        By default sends the signal only to the parent process, not to possible
        child processes started by it. Notice that when `running processes in
        shell`, the shell is the parent process and it depends on the system
        does the shell propagate the signal to the actual started process.

        To send the signal to the whole process group, ``group`` argument can
        be set to any true value (see `Boolean arguments`). This is not
        supported by Jython, however.

        New in Robot Framework 2.8.2. Support for ``group`` argument is new
        in Robot Framework 2.8.5.
        """
        if os.sep == '\\':
            raise RuntimeError('This keyword does not work on Windows.')
        process = self._processes[handle]
        signum = self._get_signal_number(signal)
        logger.info('Sending signal %s (%d).' % (signal, signum))
        if is_truthy(group) and hasattr(os, 'killpg'):
            os.killpg(process.pid, signum)
        elif hasattr(process, 'send_signal'):
            process.send_signal(signum)
        else:
            raise RuntimeError('Sending signals is not supported '
                               'by this Python version.')
Ejemplo n.º 21
0
    def list_should_not_contain_duplicates(self, list_, msg=None):
        """Fails if any element in the ``list`` is found from it more than once.

        The default error message lists all the elements that were found
        from the ``list`` multiple times, but it can be overridden by giving
        a custom ``msg``. All multiple times found items and their counts are
        also logged.

        This keyword works with all iterables that can be converted to a list.
        The original iterable is never altered.
        """
        if not isinstance(list_, list):
            list_ = list(list_)
        dupes = []
        for item in list_:
            if item not in dupes:
                count = list_.count(item)
                if count > 1:
                    logger.info("'%s' found %d times." % (item, count))
                    dupes.append(item)
        if dupes:
            raise AssertionError(msg or
                                 '%s found multiple times.' % seq2str(dupes))
Ejemplo n.º 22
0
    def start_process(self, command, *arguments, **configuration):
        """Starts a new process on background.

        See `Specifying command and arguments` and `Process configuration`
        for more information about the arguments, and `Run Process` keyword
        for related examples.

        Makes the started process new `active process`. Returns an identifier
        that can be used as a handle to active the started process if needed.

        Starting from Robot Framework 2.8.5, processes are started so that
        they create a new process group. This allows sending signals to and
        terminating also possible child processes. This is not supported by
        Jython in general nor by Python versions prior to 2.7 on Windows.
        """
        config = ProcessConfig(**configuration)
        executable_command = self._cmd(command, arguments, config.shell)
        logger.info('Starting process:\n%s' % executable_command)
        logger.debug('Process configuration:\n%s' % config)
        process = subprocess.Popen(executable_command, **config.full_config)
        self._results[process] = ExecutionResult(process, config.stdout_stream,
                                                 config.stderr_stream)
        return self._processes.register(process, alias=config.alias)
Ejemplo n.º 23
0
    def list_should_not_contain_duplicates(self, list_, msg=None):
        """Fails if any element in the ``list`` is found from it more than once.

        The default error message lists all the elements that were found
        from the ``list`` multiple times, but it can be overridden by giving
        a custom ``msg``. All multiple times found items and their counts are
        also logged.

        This keyword works with all iterables that can be converted to a list.
        The original iterable is never altered.
        """
        if not isinstance(list_, list):
            list_ = list(list_)
        dupes = []
        for item in list_:
            if item not in dupes:
                count = list_.count(item)
                if count > 1:
                    logger.info("'%s' found %d times." % (item, count))
                    dupes.append(item)
        if dupes:
            raise AssertionError(
                msg or '%s found multiple times.' % seq2str(dupes))
Ejemplo n.º 24
0
    def start_process(self, command, *arguments, **configuration):
        """Starts a new process on background.

        See `Specifying command and arguments` and `Process configuration`
        for more information about the arguments, and `Run Process` keyword
        for related examples.

        Makes the started process new `active process`. Returns an identifier
        that can be used as a handle to active the started process if needed.

        Starting from Robot Framework 2.8.5, processes are started so that
        they create a new process group. This allows sending signals to and
        terminating also possible child processes. This is not supported by
        Jython in general nor by Python versions prior to 2.7 on Windows.
        """
        config = ProcessConfig(**configuration)
        executable_command = self._cmd(command, arguments, config.shell)
        logger.info('Starting process:\n%s' % executable_command)
        logger.debug('Process configuration:\n%s' % config)
        process = subprocess.Popen(executable_command, **config.full_config)
        self._results[process] = ExecutionResult(process,
                                                 config.stdout_stream,
                                                 config.stderr_stream)
        return self._processes.register(process, alias=config.alias)
Ejemplo n.º 25
0
 def _link_screenshot(self, path):
     link = utils.get_link_path(path, self._log_dir)
     logger.info("Screenshot saved to '<a href=\"%s\">%s</a>'." %
                 (link, path),
                 html=True)
Ejemplo n.º 26
0
 def _embed_screenshot(self, path, width):
     link = utils.get_link_path(path, self._log_dir)
     logger.info('<a href="%s"><img src="%s" width="%s"></a>' %
                 (link, link, width),
                 html=True)
Ejemplo n.º 27
0
 def _wait(self, process):
     result = self._results[process]
     result.rc = process.wait() or 0
     result.close_streams()
     logger.info('Process completed.')
     return result
Ejemplo n.º 28
0
 def _wait(self, process):
     result = self._results[process]
     result.rc = process.wait() or 0
     result.close_streams()
     logger.info('Process completed.')
     return result
Ejemplo n.º 29
0
 def _log_start(self, command, config):
     if is_list_like(command):
         command = self.join_command_line(command)
     logger.info(u'Starting process:\n%s' % system_decode(command))
     logger.debug(u'Process configuration:\n%s' % config)
Ejemplo n.º 30
0
 def get_line_count(self, string):
     """Returns and logs the number of lines in the given string."""
     count = len(string.splitlines())
     logger.info('%d lines' % count)
     return count
Ejemplo n.º 31
0
 def _get_matching_lines(self, string, matches):
     lines = string.splitlines()
     matching = [line for line in lines if matches(line)]
     logger.info('%d out of %d lines matched' % (len(matching), len(lines)))
     return '\n'.join(matching)
Ejemplo n.º 32
0
 def _get_matching_lines(self, string, matches):
     lines = string.splitlines()
     matching = [line for line in lines if matches(line)]
     logger.info('%d out of %d lines matched' % (len(matching), len(lines)))
     return '\n'.join(matching)
Ejemplo n.º 33
0
 def _embed_screenshot(self, path, width):
     link = utils.get_link_path(path, self._log_dir)
     logger.info('<a href="%s"><img src="%s" width="%s"></a>'
                 % (link, link, width), html=True)
Ejemplo n.º 34
0
 def get_line_count(self, string):
     """Returns and logs the number of lines in the given string."""
     count = len(string.splitlines())
     logger.info('%d lines' % count)
     return count
Ejemplo n.º 35
0
 def _link_screenshot(self, path):
     link = utils.get_link_path(path, self._log_dir)
     logger.info("Screenshot saved to '<a href=\"%s\">%s</a>'."
                 % (link, path), html=True)