示例#1
0
 def test_non_existing_paths(self):
     assert_equal(get_link_path('/nonex/target', '/nonex/base'), '../target')
     assert_equal(get_link_path('/nonex/t.ext', '/nonex/b.ext'), '../t.ext')
     buggy_jython = WINDOWS and JYTHON and PY_VERSION > (2, 7, 0)
     if not buggy_jython:
         assert_equal(get_link_path('/nonex', __file__),
                      os.path.relpath('/nonex', os.path.dirname(__file__)).replace(os.sep, '/'))
示例#2
0
 def test_non_existing_paths(self):
     assert_equal(get_link_path('/nonex/target', '/nonex/base'),
                  '../target')
     assert_equal(get_link_path('/nonex/t.ext', '/nonex/b.ext'), '../t.ext')
     assert_equal(
         get_link_path('/nonex', __file__),
         os.path.relpath('/nonex',
                         os.path.dirname(__file__)).replace(os.sep, '/'))
示例#3
0
 def _embed_to_log(self, path, width):
     # Image is shown on its own row and thus previous row is closed on
     # purpose. Depending on Robot's log structure is a bit risky.
     self.info(get_link_path(path, self.log_dir))
     self.info(
         '</td></tr><tr><td colspan="3">'
         '<a href="{src}"><img src="{src}" width="{width}px"></a>'.format(
             src=get_link_path(path, self.log_dir), width=width),
         html=True)
    def take_desktop_screenshot(self):
        """Takes a screenshot of the whole desktop and inserts screenshot link to log file.

        Returns path to the screenshot file.
        """
        filepath = self._get_screenshot_path("whitelib_screenshot_{index}.png")
        logger.info(get_link_path(filepath, self._log_directory), also_console=True)
        logger.info(
            '</td></tr><tr><td colspan="3">''<a href="{src}"><img src="{src}" width="800px"></a>'.format(
                src=get_link_path(filepath, self._log_directory)), html=True)
        bmp = Desktop.CaptureScreenshot()
        bmp.Save(filepath, ImageFormat.Png)
        return filepath
 def _embed_screenshot(cls, path, width=100):
     '''Support functions to edit the robot Logger to add screenshot from the Selenium-Python
     :param path:
     '''
     link = get_link_path(path, cls.outputdir)
     logger.info('<a href="%s"><img src="%s" width="%s"></a>'
                 % (link, link, width), html=True)
示例#6
0
 def take_screenshot_on_element(self, locator, filename):
     """
     param locator: element locator
     param filename: argument specifies the name of the file to write the
     screenshot into.
     return: screenshot path
     """
     if not self.drivers.current:
         self.info('Cannot capture screenshot because no browser is open.')
         return
     path = self._get_screenshot_path(filename)
     self._create_directory(path)
     if not self.driver.save_screenshot(path):
         raise RuntimeError("Failed to save screenshot '{}'.".format(path))
     item = self.find_element(locator)
     left = item.location['x']
     right = left + item.size['width']
     top = item.location['y']
     bottom = top + item.size['height']
     scop_to(path, left, top, right, bottom)
     self.info('</td></tr><tr><td colspan="3">'
               '<a href="{src}"><img src="{src}" width="800px"></a>'.format(
                   src=get_link_path(path, self.log_dir)),
               html=True)
     return path
示例#7
0
    def _link_wireshark_file(self, path):
        """
        功能描述:将抓包文件链接到log文件中

        参数: path:抓包文件全路径

        返回值:执行成功,返回(WIRESHARK_SUCCESS(0),成功信息)
                执行失败,返回(WIRESHARK_FAIL(-1),错误信息)
        """
        err_info = ""

        for i in [1]:
            err_info = u"开始链接报文文件到log文件中..."
            log.user_info(err_info)

            if not isinstance(path, unicode):
                path = path.decode('utf-8')
            default_log_path = self._get_default_log_dir()
            if not default_log_path:
                err_info = u"获取log文件路径失败!"
                break

            try:
                link = utils.get_link_path(path, default_log_path)
                logger.info("Capture file saved to '<a href=\"%s\">%s</a>'." %
                            (link, path),
                            html=True)

                err_info = u"链接报文文件到log文件中成功!"
                log.user_info(err_info)
                return

            except Exception, e:
                err_info = u"在log文件中链接抓包文件发生异常: %s" % e
 def _log_image_link(self, file_path: str) -> str:
     relative_path = get_link_path(file_path, self.library.outputdir)
     logger.info(
         f"Saved screenshot in <a href='{relative_path}'>{relative_path}</a>",
         html=True,
     )
     return file_path
示例#9
0
    def log_screenshot(self,
                       basename="screenshot",
                       directory=None,
                       log_file_directory=None,
                       width="100%"):
        """Takes a screenshot and logs it to Robot Framework's log file.

        Saves the files as defined in the keyword `Save Screenshot` and creates
        a picture to Robot Framework's log. `directory` defines the directory
        where the screenshots are saved. By default, its value is
        `default_directory`, which is set at the library import or with the
        keyword `Set Screenshot Directories`. `log_file_directory` is used to
        create relative paths to the pictures. This allows moving the log and
        pictures to different machines and having still working pictures. If
        `log_file_directory` is not given or set (in the same way as
        `default_directory` is set), the paths are absolute.

        The path where the screenshot is saved is returned.
        """
        path = self.save_screenshot(basename, directory)
        if log_file_directory is None:
            log_file_directory = self._log_file_dir
        if log_file_directory is not None:
            link = utils.get_link_path(path, log_file_directory)
        else:
            link = 'file:///' + path.replace('\\', '/')
        print '*HTML* <a href="%s"><img src="%s" width="%s" /></a>' \
              % (link, link, width)
        return path
示例#10
0
    def log_screenshot(self, basename="screenshot", directory=None,
                       log_file_directory=None, width="100%"):
        """Takes a screenshot and logs it to Robot Framework's log file.

        Saves the files as defined in the keyword `Save Screenshot` and creates
        a picture to Robot Framework's log. `directory` defines the directory
        where the screenshots are saved. By default, its value is
        `default_directory`, which is set at the library import or with the
        keyword `Set Screenshot Directories`. `log_file_directory` is used to
        create relative paths to the pictures. This allows moving the log and
        pictures to different machines and having still working pictures. If
        `log_file_directory` is not given or set (in the same way as
        `default_directory` is set), the paths are absolute.

        The path where the screenshot is saved is returned.
        """
        path = self.save_screenshot(basename, directory)
        if log_file_directory is None:
            log_file_directory = self._log_file_dir
        if log_file_directory is not None:
            link = utils.get_link_path(path, log_file_directory)
        else:
            link = 'file:///' + path.replace('\\', '/')
        print '*HTML* <a href="%s"><img src="%s" width="%s" /></a>' \
              % (link, link, width)
        return path
 def _link_screenshot(cls, path):
     '''Support functions to edit the robot Logger to add screenshot from the Selenium-Python
     :param path:
     '''
     link = get_link_path(path, cls.outputdir)
     logger.info("Screenshot saved to '<a href=\"%s\">%s</a>'."
                 % (link, path), html=True)
示例#12
0
 def _embed_screenshot(self, path, width, save_to_disk):
     link = get_link_path(path, self._log_dir)
     if save_to_disk:
         logger.info('<a href="%s"><img src="%s" width="%s"></a>' % (link, link, width), html=True)
     else:
         with open(path, "rb") as image_file:
             logger.info('<img src="data:image/png;base64, %s" width="%s">' % ((base64.b64encode(image_file.read())).decode("utf-8"), width), html=True)
         os.remove(path)
示例#13
0
 def _get_screenshot_paths(self, filename):
     filename = filename.format(index=self._get_screenshot_index(filename))
     filename = filename.replace('/', os.sep)
     screenshotdir = self._get_screenshot_directory()
     logdir = self._get_log_dir()
     path = os.path.join(screenshotdir, filename)
     link = get_link_path(path, logdir)
     return path, link
示例#14
0
 def _log_image_link(self, file_path: str) -> str:
     relative_path = get_link_path(file_path, self.outputdir)
     logger.info(
         '</td></tr><tr><td colspan="3">'
         f'<a href="{relative_path}"><img src="{relative_path}" width="800px"></a>',
         html=True,
     )
     return file_path
示例#15
0
 def _take_screenshot(self):
     logdir = self._get_log_dir()
     filepath = os.path.join(
         logdir,
         'remoteswinglibrary-screenshot%s.png' % int(time.time() * 1000))
     self._run_from_services('takeScreenshot', filepath)
     logger.info('<img src="%s"></img>' % get_link_path(filepath, logdir),
                 html=True)
    def _take_screenshot(self):
        logdir = self.get_log_dir()
        screenshotdir = logdir + "/" + "remote-screenshots"
        if not os.path.exists(screenshotdir):
            os.makedirs(screenshotdir)

        filepath = os.path.join(screenshotdir, 'remote-screenshot%s.png' % re.sub('[:. ]', '-', str(datetime.datetime.now())))
        self._run_from_services('takeScreenshot', filepath)
        logger.info('<img src="%s"></img>' % get_link_path(filepath, logdir), html=True)
示例#17
0
 def _get_screenshot_paths(self, filename):
     if not filename:
         filename = self._namegen.next()
     else:
         filename = filename.replace('/', os.sep)
     logdir = self._get_log_dir()
     path = os.path.join(logdir, filename)
     link = utils.get_link_path(path, logdir)
     return path, link
 def _get_screenshot_paths(self, filename):
     if not filename:
         filename = self._namegen.next()
     else:
         filename = filename.replace('/', os.sep)
     logdir = self._get_log_dir()
     path = os.path.join(logdir, filename)
     link = get_link_path(path, logdir)
     return path, link
    def _take_screenshot(self):
        logdir = self.get_log_dir()
        screenshotdir = logdir + "/" + "remote-screenshots"
        if not os.path.exists(screenshotdir):
            os.makedirs(screenshotdir)

        filepath = os.path.join(screenshotdir, 'remote-screenshot%s.png' % re.sub('[:. ]', '-', str(datetime.datetime.now())))
        self._run_from_services('takeScreenshot', filepath)
        logger.info('<img src="%s"></img>' % get_link_path(filepath, logdir), html=True)
示例#20
0
 def _get_screenshot_paths(self, filename):
     filename = filename.format(
         index=self._get_screenshot_index(filename))
     filename = filename.replace('/', os.sep)
     screenshotdir = self._get_screenshot_directory()
     logdir = self._get_log_dir()
     path = os.path.join(screenshotdir, filename)
     link = get_link_path(path, logdir)
     return path, link
示例#21
0
 def _get_loglink(self, inpath, target):
     """Finds matching log file and return link to it or None."""
     indir, infile = os.path.split(inpath)
     logname = os.path.splitext(infile.lower())[0]
     if logname.endswith('output'):
         logname = logname[:-6] + 'log'
     for item in os.listdir(indir):
         name, ext = os.path.splitext(item.lower())
         if name == logname and ext in ['.html', '.htm', '.xhtml']:
             logpath = os.path.join(indir, item)
             return utils.get_link_path(logpath, target)
     return None
示例#22
0
 def _embed_video(self, video: dict):
     if not video.get("video_path"):
         logger.debug("Video is not enabled.")
         return
     relative_path = get_link_path(video.get("video_path"), self.outputdir)
     video_size = self.context_cache.get(video["contextUuid"])
     video_width = video_size["width"]
     video_height = video_size["height"]
     video_type = relative_path.split(".")[1]
     logger.info(
         '</td></tr><tr><td colspan="3">'
         f'<video width="{video_width}" height="{video_height}" controls>'
         f'<source src="{relative_path}" type="video/{video_type}"></video>',
         html=True,
     )
示例#23
0
 def _embed_video(self, path, width, save_to_disk):
     link = get_link_path(path, self._log_dir)
     if save_to_disk:
         logger.info(
             '<a href="%s"><video width="%s" autoplay><source src="%s" type="video/webm"></video></a>'
             % (link, width, link),
             html=True)
     else:
         with open(path, "rb") as image_file:
             logger.info(
                 '<video width="%s" autoplay><source src="data:video/webm;base64, %s" type="video/webm"></video>'
                 % (width,
                    (base64.b64encode(image_file.read())).decode("utf-8")),
                 html=True)
         os.remove(path)
示例#24
0
    def capture_page_screenshot(self,
                                filename='selenium-screenshot-{index}.png'):
        """Takes screenshot of the current page and embeds it into log file.

        ``filename`` argument specifies the name of the file to write the
        screenshot into. The directory where screenshots are saved can be
        set when `importing` the library or by using the `Set Screenshot
        Directory` keyword. If the directory is not configured, screenshots
        are saved to the same directory where Robot Framework's log file is
        written.

        Starting from SeleniumLibrary 1.8, if ``filename`` contains marker
        ``{index}``, it will be automatically replaced with unique running
        index preventing files to be overwritten. Indices start from 1,
        and how they are represented can be customized using Python's
        [https://docs.python.org/2/library/string.html#formatstrings|
        format string syntax].

        An absolute path to the created screenshot file is returned.

        Examples:
        | `Capture Page Screenshot` |                                        |
        | `File Should Exist`       | ${OUTPUTDIR}/selenium-screenshot-1.png |
        | ${path} =                 | `Capture Page Screenshot`              |
        | `File Should Exist`       | ${OUTPUTDIR}/selenium-screenshot-2.png |
        | `File Should Exist`       | ${path}                                |
        | `Capture Page Screenshot` | custom_name.png                        |
        | `File Should Exist`       | ${OUTPUTDIR}/custom_name.png           |
        | `Capture Page Screenshot` | custom_with_index_{index}.png          |
        | `File Should Exist`       | ${OUTPUTDIR}/custom_with_index_1.png   |
        | `Capture Page Screenshot` | formatted_index_{index:03}.png         |
        | `File Should Exist`       | ${OUTPUTDIR}/formatted_index_001.png   |
        """
        if not self.drivers.current:
            self.info('Cannot capture screenshot because no browser is open.')
            return
        path = self._get_screenshot_path(filename)
        self._create_directory(path)
        if not self.driver.save_screenshot(path):
            raise RuntimeError("Failed to save screenshot '{}'.".format(path))
        # Image is shown on its own row and thus previous row is closed on
        # purpose. Depending on Robot's log structure is a bit risky.
        self.info('</td></tr><tr><td colspan="3">'
                  '<a href="{src}"><img src="{src}" width="800px"></a>'.format(
                      src=get_link_path(path, self.log_dir)),
                  html=True)
        return path
 def handle(self):
     data = self.rfile.readline()[:-1]
     fields = data.decode().split(':')
     if fields[0] == 'PORT':
         port = fields[1]
         name = ':'.join(fields[2:])
         address = ':'.join([self.client_address[0], port])
         logger.debug('Registered java remoteswinglibrary agent "%s" at %s' % \
                      (name, address))
         REMOTE_AGENTS_LIST.append(address, name)
     elif fields[0] == 'DIALOG':
         title = fields[1]
         path = ':'.join(fields[2:])
         logger.info('Security Warning "%s" was accepted automatically' % title)
         logger.info('<a href="%s"><img src="%s" width="%s"></a>'
                     % (path, get_link_path(path, RemoteSwingLibrary.get_log_dir()), 800), html=True)
     else:
         logger.debug('Unknown message "%s"' % fields[0])
 def handle(self):
     data = self.rfile.readline()[:-1]
     fields = data.decode().split(':')
     if fields[0] == 'PORT':
         port = fields[1]
         name = ':'.join(fields[2:])
         address = ':'.join([self.client_address[0], port])
         logger.debug('Registered java remoteswinglibrary agent "%s" at %s' % \
                      (name, address))
         REMOTE_AGENTS_LIST.append(address, name)
     elif fields[0] == 'DIALOG':
         title = fields[1]
         path = ':'.join(fields[2:])
         logger.info('Security Warning "%s" was accepted automatically' % title)
         logger.info('<a href="%s"><img src="%s" width="%s"></a>'
                     % (path, get_link_path(path, RemoteSwingLibrary.get_log_dir()), 800), html=True)
     else:
         logger.debug('Unknown message "%s"' % fields[0])
示例#27
0
    def _get_screenshot_paths(self, filename_template):
        screenshotdir = self._get_screenshot_directory()

        filename = filename_template.format(
            index=self._get_screenshot_index(filename_template))

        # try to match {index} but not {{index}} (plus handle
        # other variants like {index!r})
        if re.search(r'(?<!{){index(![rs])?(:.*?)?}(?!})', filename_template):
            # make sure the computed filename doesn't exist. We only
            # do this if the template had the {index} formatting
            # sequence (or one of it's variations)
            while os.path.exists(os.path.join(screenshotdir, filename)):
                filename = filename_template.format(
                    index=self._get_screenshot_index(filename_template))

        filename = filename.replace('/', os.sep)
        path = os.path.join(screenshotdir, filename)
        link = get_link_path(path, self.log_dir)
        return path, link
    def _get_screenshot_paths(self, filename_template):
        screenshotdir = self._get_screenshot_directory()

        filename = filename_template.format(
            index=self._get_screenshot_index(filename_template))

        # try to match {index} but not {{index}} (plus handle
        # other variants like {index!r})
        if re.search(r'(?<!{){index(![rs])?(:.*?)?}(?!})', filename_template):
            # make sure the computed filename doesn't exist. We only
            # do this if the template had the {index} formatting
            # sequence (or one of it's variations)
            while os.path.exists(os.path.join(screenshotdir, filename)):
                filename = filename_template.format(
                    index=self._get_screenshot_index(filename_template))

        filename = filename.replace('/', os.sep)
        path = os.path.join(screenshotdir, filename)
        link = get_link_path(path, self.log_dir)
        return path, link
示例#29
0
def log_screenshot_file(filepath):
    """Log screenshot file to robot framework log.

    Uses robot.utils.get_link_path to determine the relative path to the robot
    framework log file.

    Parameters
    ----------
    filepath : str
        Filepath to the screenshot file.
    """
    try:
        robot_output = BuiltIn().get_variable_value('${OUTPUT DIR}')
        if not config.get_config("OSScreenshots"):
            logger.info('Current url is: {}'.format(get_url()))
        link = get_link_path(filepath, robot_output)
        logger.info(
            '<a href="{0}"><img src="{0}" width="800px"></a>'.format(link),
            html=True)

    except RobotNotRunningError:
        return
示例#30
0
 def test_get_link_path_with_unicode(self):
     assert_equal(get_link_path(u'\xe4\xf6.txt', ''), '%C3%A4%C3%B6.txt')
示例#31
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)
示例#32
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)
 def test_get_link_path(self):
     inputs = self._posix_inputs if os.sep == '/' else self._windows_inputs
     for basedir, target, expected in inputs():
         assert_equal(get_link_path(target, basedir).replace('R:', 'r:'),
                      expected, '%s -> %s' % (target, basedir))
 def test_basics(self):
     for base, target, expected in self._get_basic_inputs():
         assert_equal(get_link_path(target, base).replace('R:', 'r:'),
                      expected, '%s -> %s' % (target, base))
示例#35
0
 def test_base_is_existing_file(self):
     assert_equal(get_link_path(__file__, __file__),
                  os.path.basename(__file__))
     assert_equal(get_link_path(os.path.dirname(__file__), __file__), '.')
示例#36
0
 def test_non_ascii_paths(self):
     assert_equal(get_link_path(u'\xe4\xf6.txt', ''), '%C3%A4%C3%B6.txt')
     assert_equal(get_link_path(u'\xe4/\xf6.txt', u'\xe4'), '%C3%B6.txt')
 def test_get_non_ascii_link_path(self):
     assert_equal(get_link_path(u"\xe4\xf6.txt", ""), "%C3%A4%C3%B6.txt")
示例#38
0
 def _get_relative_source(self, source):
     if not source or not self._output_path:
         return ''
     return get_link_path(source, os.path.dirname(self._output_path))
 def test_get_link_path(self):
     inputs = self._posix_inputs if os.sep == "/" else self._windows_inputs
     for basedir, target, expected in inputs():
         assert_equal(get_link_path(target, basedir).replace("R:", "r:"), expected, "%s -> %s" % (target, basedir))
 def test_get_link_path_to_non_existing_path(self):
     assert_equal(get_link_path("/non-ex/foo.txt", "/non-ex/nothing_here.txt"), "../foo.txt")
 def test_non_ascii_paths(self):
     assert_equal(get_link_path(u'\xe4\xf6.txt', ''), '%C3%A4%C3%B6.txt')
     assert_equal(get_link_path(u'\xe4/\xf6.txt', u'\xe4'), '%C3%B6.txt')
 def test_non_existing_paths(self):
     assert_equal(get_link_path('/nonex/target', '/nonex/base'), '../target')
     assert_equal(get_link_path('/nonex/t.ext', '/nonex/b.ext'), '../t.ext')
     assert_equal(get_link_path('/nonex', __file__),
                  os.path.relpath('/nonex', os.path.dirname(__file__)).replace(os.sep, '/'))
 def test_base_is_existing_file(self):
     assert_equal(get_link_path(os.path.dirname(__file__), __file__), '.')
     assert_equal(get_link_path(__file__, __file__),
                  self._expected_basename(__file__))
示例#44
0
 def _write_source(self, source):
     if source:
         if os.path.exists(source):
             ref = utils.get_link_path(source, self._writer.output.name)
             source = '<a href="%s">%s</a>' % (ref, source)
         self._write_metadata_row('Source', source, escape=False)
示例#45
0
 def _url_from_path(self, source, destination):
     if not destination:
         return None
     return utils.get_link_path(destination, os.path.dirname(source))
 def get_rel_log_path(self, path):
     if path and os.path.exists(path) and self._log_path != 'NONE':
         return utils.get_link_path(path, os.path.dirname(self._log_path))
     return ''
示例#47
0
 def _embed_video(self, path, width):
     link = get_link_path(path, self._log_dir)
     logger.info(
         '<a href="%s"><video width="%s" autoplay><source src="%s" type="video/webm"></video></a>'
         % (link, width, link),
         html=True)
 def _embed_to_log(self, path, width):
     # Image is shown on its own row and thus previous row is closed on
     # purpose. Depending on Robot's log structure is a bit risky.
     self.info('</td></tr><tr><td colspan="3">'
               '<a href="{src}"><img src="{src}" width="{width}px"></a>'
               .format(src=get_link_path(path, self.log_dir), width=width), html=True)
 def test_get_link_path_to_non_existing_path(self):
     assert_equal(get_link_path('/non-ex/foo.txt', '/non-ex/nothing_here.txt'),
                  '../foo.txt')
示例#50
0
 def __init__(self, output, logpath=None):
     self._writer = utils.HtmlWriter(output)
     self._loglink = logpath and \
             utils.get_link_path(logpath, output.name) or None
     self._suite_level = 0
示例#51
0
 def _get_relative_source(self, source):
     if not source or not self._output_path:
         return ''
     return utils.get_link_path(source, os.path.dirname(self._output_path))
 def relative_source(self, source):
     rel_source = get_link_path(source, self._log_dir) \
         if self._log_dir and source and os.path.exists(source) else ''
     return self.string(rel_source)
示例#53
0
 def test_get_link_path_to_non_existing_path(self):
     assert_equal(get_link_path('/non_existing/foo.txt', '/non_existing/does_not_exist_never.txt'), '../foo.txt')
 def relative_source(self, source):
     rel_source = get_link_path(source, self._log_dir) \
         if self._log_dir and source and exists(source) else ''
     return self.string(rel_source)
 def _take_screenshot(self):
     logdir = self._get_log_dir()
     filepath = os.path.join(logdir, 'remoteswinglibrary-screenshot%s.png' % long(time.time()*1000))
     self._run_from_services('takeScreenshot', filepath)
     logger.info('<img src="%s"></img>' % get_link_path(filepath, logdir), html=True)
示例#56
0
 def _embed_screenshot(self, path, width):
     link = get_link_path(path, self._log_dir)
     logger.info('<a href="%s"><img src="%s" width="%s"></a>' %
                 (link, link, width),
                 html=True)
示例#57
0
 def _embed_screenshot(self, path, width):
     link = utils.get_link_path(path, self._log_dir)
     print '*HTML* <a href="%s"><img src="%s" width="%s"></a>' \
           % (link, link, width)
示例#58
0
 def _link_screenshot(self, path):
     link = get_link_path(path, self._log_dir)
     logger.info("Screenshot saved to '<a href=\"%s\">%s</a>'." %
                 (link, path),
                 html=True)
示例#59
0
 def _link_screenshot(self, path):
     link = utils.get_link_path(path, self._log_dir)
     print "*HTML* Screenshot saved to '<a href=\"%s\">%s</a>'." % (link, path)