Ejemplo n.º 1
0
def upload(environ, key, source, dest=None, **kwargs):
    """Uploads the file from ``source`` to filetracker under ``environ[key]``
    name.

    ``source``
      Filename to upload.

    ``dest``
      A filename, directory name or ``None``. In the two latter cases,
      the file is named the same as in ``environ[key]``.

    ``**kwargs``
      Passed directly to :meth:`filetracker.client.Client.put_file`.

    See the note about ``environ['use_filetracker']`` in
    :func:`sio.workers.ft.download`.

    Returns the filetracker path to the saved file.
    """

    if dest is None or key in environ:
        dest = environ[key]
    elif dest.endswith(os.sep):
        dest = os.path.join(dest, os.path.split(source)[1])
    if not _use_filetracker(dest, environ):
        dest = os.path.join(_original_cwd, dest)
        if not os.path.exists(dest) or not os.path.samefile(source, dest):
            shutil.copy(source, dest)
    else:
        logger.debug("Uploading %s", dest)
        perf_timer = util.PerfTimer()
        dest = instance().put_file(dest, source, **kwargs)
        logger.debug(" completed in %.2fs", perf_timer.elapsed)
    environ[key] = dest
    return dest
Ejemplo n.º 2
0
def download(environ, key, dest=None, skip_if_exists=False, **kwargs):
    """Downloads the file from ``environ[key]`` and saves it to ``dest``.

    ``dest``
      A filename, directory name or ``None``. In the two latter cases,
      the file is named the same as in ``environ[key]``.

    ``skip_if_exists``
      If ``True`` and ``dest`` points to an existing file (not a directory
      or ``None``), then the file is not downloaded.

    ``**kwargs``
      Passed directly to :meth:`filetracker.client.Client.get_file`.

    The value under ``environ['use_filetracker']`` affects downloading
    in the followins way:

    * if ``True``, nothing special happens

    * if ``False``, the file is not downloaded from filetracker, but the
      passed path is assumed to be a regular filesystem path

    * if ``'auto'``, the file is assumed to be a local filename only if
      it is a relative path (this is usually the case when developers play).

    Returns the path to the saved file.
    """

    if dest and skip_if_exists and os.path.exists(util.tempcwd(dest)):
        return dest
    source = environ[key]
    if dest is None:
        dest = os.path.split(source)[1]
    elif dest.endswith(os.sep):
        dest = os.path.join(dest, os.path.split(source)[1])

    dest = util.tempcwd(dest)
    if not _use_filetracker(source, environ):
        source = os.path.join(_original_cwd, source)
        if not os.path.exists(dest) or not os.path.samefile(source, dest):
            shutil.copy(source, dest)
    else:
        kwargs.setdefault('add_to_cache', False)
        logger.debug("Downloading %s", source)
        perf_timer = util.PerfTimer()
        instance().get_file(source, dest, **kwargs)
        logger.debug(" completed in %.2fs", perf_timer.elapsed)
    return dest
Ejemplo n.º 3
0
def execute_command(command,
                    env=None,
                    split_lines=False,
                    stdin=None,
                    stdout=None,
                    stderr=None,
                    forward_stderr=False,
                    capture_output=False,
                    output_limit=None,
                    real_time_limit=None,
                    ignore_errors=False,
                    extra_ignore_errors=(),
                    **kwargs):
    """Utility function to run arbitrary command.
    ``stdin``
      Could be either file opened with ``open(fname, 'r')``
      or None (then it is inherited from current process).

    ``stdout``, ``stderr``
      Could be files opened with ``open(fname, 'w')``, sys.std*
      or None - then it's suppressed.

    ``forward_stderr``
      Forwards stderr to stdout.

    ``capture_output``
      Returns program output in renv key ``stdout``.

    ``output_limit``
      Limits returned output when ``capture_output=True`` (in bytes).

    Returns renv: dictionary containing:
    ``real_time_used``
      Wall clock time it took to execute the command (in ms).

    ``return_code``
      Status code that program returned.

    ``real_time_killed``
      Only when process was killed due to exceeding real time limit.

    ``stdout``
      Only when ``capture_output=True``: output of the command
    """
    # Using temporary file is way faster than using subproces.PIPE
    # and it prevents deadlocks.
    command = shellquote(command)

    logger.debug('Executing: %s', command)

    stdout = capture_output and tempfile.TemporaryFile() or stdout
    # redirect output to /dev/null if None given
    devnull = open(os.devnull, 'wb')
    stdout = stdout or devnull
    stderr = stderr or devnull

    ret_env = {}
    if env is not None:
        for key, value in six.iteritems(env):
            env[key] = str(value)

    perf_timer = util.PerfTimer()
    p = subprocess.Popen(
        command,
        stdin=stdin,
        stdout=stdout,
        stderr=forward_stderr and subprocess.STDOUT or stderr,
        shell=True,
        close_fds=True,
        universal_newlines=True,
        env=env,
        cwd=tempcwd(),
        preexec_fn=os.setpgrp,
    )

    kill_timer = None
    if real_time_limit:

        def oot_killer():
            ret_env['real_time_killed'] = True
            os.killpg(p.pid, signal.SIGKILL)

        kill_timer = Timer(ms2s(real_time_limit), oot_killer)
        kill_timer.start()

    rc = p.wait()
    ret_env['return_code'] = rc

    if kill_timer:
        kill_timer.cancel()

    ret_env['real_time_used'] = s2ms(perf_timer.elapsed)

    logger.debug(
        'Command "%s" exited with code %d, took %.2fs',
        str(command),
        rc,
        perf_timer.elapsed,
    )

    devnull.close()
    if capture_output:
        stdout.seek(0)
        ret_env['stdout'] = stdout.read(output_limit or -1)
        stdout.close()
        if split_lines:
            ret_env['stdout'] = ret_env['stdout'].split(b'\n')

    if rc and not ignore_errors and rc not in extra_ignore_errors:
        raise ExecError(
            'Failed to execute command: %s. Returned with code %s\n' %
            (command, rc))

    return ret_env