Skip to content

Commit

Permalink
Add clean wrapper for calling python in venv
Browse files Browse the repository at this point in the history
  • Loading branch information
aragilar committed Jun 12, 2017
1 parent 6774553 commit 044a978
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 13 deletions.
25 changes: 14 additions & 11 deletions venv_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
:copyright: (c) 2014 by James Tocknell.
:license: BSD, see LICENSE for more details.
"""
from logging import getLogger
import os
import os.path
import tempfile
Expand All @@ -18,7 +19,7 @@

from ._utils import (
pathprepend, get_default_venv_builder, is_venv, BIN_DIR, PYTHON_FILENAME,
abspath_python_exe,
abspath_python_exe, run_python_with_args
)

from ._version import get_versions
Expand All @@ -27,6 +28,7 @@


DEFAULT_INSTALL_COMMAND = "{python} -m pip install {package}"
log = getLogger(__name__)


class Venv(object):
Expand Down Expand Up @@ -77,13 +79,15 @@ def __enter__(self):
venv = self._venv_builder(**self._kwargs)
venv.create(self.env_dir)
pathprepend(os.path.join(self.env_dir, BIN_DIR), "PATH")
log.debug("PATH is now %s", os.environ["PATH"])
if self._python_home is not None:
os.environ.pop("PYTHONHOME")
os.environ["VIRTUAL_ENV"] = self.env_dir
return self

def __exit__(self, exc_type, exc_value, traceback):
os.environ["PATH"] = self._old_path
log.debug("PATH is now %s", os.environ["PATH"])
if self._python_home is not None:
os.environ["PYTHONHOME"] = self._python_home
os.environ.pop("VIRTUAL_ENV")
Expand Down Expand Up @@ -116,32 +120,31 @@ def install_command(self):
def install_command(self, new_cmd):
self._install_command = new_cmd

def call_python_file(self, filename):
def call_python_file(self, filename, *args, **kwargs):
"""
Call a python file with the python interpreter associated with this
virtualenv.
"""
return subprocess.check_output(
[self.python_exe, filename], stderr=subprocess.STDOUT
return run_python_with_args(
python_exe=self.python_exe, script=filename, args=args, **kwargs
)

def call_python_module(self, module_name, *args):
def call_python_module(self, module_name, *args, **kwargs):
"""
Call a python module with the python interpreter associated with this
virtualenv.
"""
return subprocess.check_output(
[self.python_exe, '-m', module_name].append(args),
stderr=subprocess.STDOUT
return run_python_with_args(
python_exe=self.python_exe, module=module_name, args=args, **kwargs
)

def call_python_code(self, code):
def call_python_code(self, code, *args, **kwargs):
"""
Call some python code with the python interpreter associated with this
virtualenv.
"""
return subprocess.check_output(
[self.python_exe, '-c', code], stderr=subprocess.STDOUT
return run_python_with_args(
python_exe=self.python_exe, code=code, args=args, **kwargs
)

def install_package(self, package):
Expand Down
40 changes: 38 additions & 2 deletions venv_tools/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,27 @@
:copyright: (c) 2014 by James Tocknell.
:license: BSD, see LICENSE for more details.
"""
from logging import getLogger
import os
import os.path as pth
import subprocess
import sys

from ._venv_builders import VirtualenvBuilder

BIN_DIR = "Scripts" if sys.platform == 'win32' else "bin"
PYTHON_FILENAME = "python.exe" if sys.platform == 'win32' else "python"
PYVENV_FILENAME = "pyvenv.cfg"
ACTIVATE_FILENAMES = [
ACTIVATE_FILENAMES = (
"activate",
"activate.csh",
"activate.fish",
"activate_this.py",
"activate.bat",
"activate.ps1",
]
)

log = getLogger(__name__)


def pathremove(dirname, path):
Expand Down Expand Up @@ -149,3 +153,35 @@ def abspath_path_executable(executable):
if is_executable(full_path):
return full_path
raise FileNotFoundError(executable + " is not on current path")


def run_python_with_args(
*, python_exe, args=None, module=None, code=None, script=None,
input=None, # pylint: disable=redefined-builtin
stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=None
):
"""
Wrapper around subprocess.run for calling python interpreter.
"""
if sum(1 for kw in (module, code, script) if kw is not None) != 1:
raise RuntimeError(
"One of module, code or script should be provided."
)

cmd_list = [python_exe]
if module is not None:
cmd_list.extend(['-m', module])
if code is not None:
cmd_list.extend(['-c', code])
if script is not None:
cmd_list.append(script)

if args is not None:
cmd_list.extend(args)

log.debug("Running command %s", cmd_list)

return subprocess.run(
cmd_list, input=input, stdin=stdin, stdout=stdout, stderr=stderr,
timeout=timeout, shell=False, universal_newlines=True, check=True
)

0 comments on commit 044a978

Please sign in to comment.