# Copyright 2013 The LUCI Authors. All rights reserved.
# Use of this source code is governed under the Apache License, Version 2.0
# that can be found in the LICENSE file.

"""Provides methods for running python scripts correctly.

This includes support for `vpython`, and knows how to specify parameters
correctly for bots (e.g. ensuring that python is working on Windows, passing the
unbuffered flag, etc.)
"""

import textwrap

from recipe_engine import config_types
from recipe_engine import recipe_api

class PythonApi(recipe_api.RecipeApi):
  def __call__(self, name, script, args=None, unbuffered=True, venv=None,
               **kwargs):
    """Return a step to run a python script with arguments.

    **TODO**: We should just use a single "args" list. Having "script"
    separate but required/first leads to weird things like:

        (... script='-m', args=['module'])

    Args:
      * name (str): The name of the step.
      * script (str or Path): The Path of the script to run, or the first
          command-line argument to pass to Python.
      * args (list or None): If not None, additional arguments to pass to the
          Python command.
      * unbuffered (bool): If True, run Python in unbuffered mode.
      * venv (None or False or True or Path): If True, run the script through
          "vpython". This will, by default, probe the target script for a
          configured VirtualEnv and, failing that, use an empty VirtualEnv. If a
          Path, this is a path to an explicit "vpython" VirtualEnv spec file to
          use. If False or None (default), the script will be run through the
          standard Python interpreter.
      * kwargs: Additional keyword arguments to forward to "step".

    **Returns (`step_data.StepData`)** - The StepData object as returned by
    api.step.
    """
    env = {}

    if venv:
      cmd = ['vpython']
      if isinstance(venv, config_types.Path):
        cmd += ['-vpython-spec', venv]
    else:
      cmd = ['python']

    if unbuffered:
      cmd.append('-u')
    else:
      env['PYTHONUNBUFFERED'] = None

    cmd.append(script)
    with self.m.context(env=env):
      return self.m.step(name, cmd + list(args or []), **kwargs)

  def inline(self, name, program, add_python_log=True, **kwargs):
    """Run an inline python program as a step.

    Program is output to a temp file and run when this step executes.

    Args:
      * name (str) - The name of the step
      * program (str) - The literal python program text. This will be dumped to
        a file and run like `python /path/to/file.py`
      * add_python_log (bool) - Whether to add a 'python.inline' link on this
        step on the build page. If true, the link will point to a log with
        a copy of `program`.

    **Returns (`step_data.StepData`)** - The StepData object as returned by
    api.step.
    """
    program = textwrap.dedent(program)
    compile(program, '<string>', 'exec', dont_inherit=1)

    try:
      self(name, self.m.raw_io.input(program, '.py'), **kwargs)
    finally:
      result = self.m.step.active_result
      if result and add_python_log:
        result.presentation.logs['python.inline'] = program.splitlines()

    return result

  def result_step(self, name, text, retcode, as_log=None, **kwargs):
    """Runs a no-op step that exits with a specified return code.

    The recipe engine will raise an exception when seeing a return code != 0.
    """
    try:
      return self.inline(
          name,
          'import sys; sys.exit(%d)' % (retcode,),
          add_python_log=False,
          step_test_data=lambda: self.m.raw_io.test_api.output(
              text, retcode=retcode),
          **kwargs)
    finally:
      if as_log:
        self.m.step.active_result.presentation.logs[as_log] = text
      else:
        self.m.step.active_result.presentation.step_text = text

  def succeeding_step(self, name, text, as_log=None):
    """Runs a succeeding step (exits 0)."""
    return self.result_step(name, text, 0, as_log=as_log)

  def failing_step(self, name, text, as_log=None):
    """Runs a failing step (exits 1)."""
    return self.result_step(name, text, 1, as_log=as_log)

  def infra_failing_step(self, name, text, as_log=None):
    """Runs an infra-failing step (exits 1)."""
    return self.result_step(name, text, 1, as_log=as_log, infra_step=True)
