diff --git a/platypush/platyvenv/__init__.py b/platypush/platyvenv/__init__.py index 0e370f40c..723dc8c63 100755 --- a/platypush/platyvenv/__init__.py +++ b/platypush/platyvenv/__init__.py @@ -4,17 +4,19 @@ virtual environment for Platypush starting from a configuration file. """ import argparse +from contextlib import contextmanager import inspect import os import pathlib import re +import shutil import subprocess import sys -from typing import Sequence +import tempfile +from typing import Generator, Sequence import venv from platypush.config import Config -from platypush.utils import get_src_root from platypush.utils.manifest import ( Dependencies, InstallContext, @@ -58,6 +60,43 @@ class VenvBuilder: print(f'Installing system packages: {cmd}') subprocess.call(re.split(r'\s+', cmd.strip())) + @contextmanager + def _prepare_src_dir(self) -> Generator[str, None, None]: + """ + Prepare the source directory used to install the virtual enviornment. + + If platyvenv is launched from a local checkout of the Platypush source + code, then that checkout will be used. + + Otherwise, the source directory will be cloned from git into a + temporary folder. + """ + setup_py_path = os.path.join(os.getcwd(), 'setup.py') + if os.path.isfile(setup_py_path): + print('Using local checkout of the Platypush source code') + yield os.getcwd() + else: + checkout_dir = tempfile.mkdtemp(prefix='platypush-', suffix='.git') + print(f'Cloning Platypush source code from git into {checkout_dir}') + subprocess.call( + [ + 'git', + 'clone', + '--recursive', + 'https://github.com/BlackLight/platypush.git', + checkout_dir, + ] + ) + + pwd = os.getcwd() + os.chdir(checkout_dir) + subprocess.call(['git', 'checkout', self.gitref]) + yield checkout_dir + + os.chdir(pwd) + print(f'Cleaning up {checkout_dir}') + shutil.rmtree(checkout_dir, ignore_errors=True) + def _prepare_venv(self) -> None: """ Installs the virtual environment under the configured output_dir. @@ -75,14 +114,7 @@ class VenvBuilder: f'Installing base Python dependencies under {self.output_dir}...', ) - subprocess.call([*self._pip_cmd, 'pip']) - pwd = os.getcwd() - - try: - os.chdir(os.path.dirname(get_src_root())) - subprocess.call([*self._pip_cmd, '.']) - finally: - os.chdir(pwd) + subprocess.call([*self._pip_cmd, 'pip', '.']) def _install_extra_pip_packages(self, deps: Dependencies): """ @@ -111,8 +143,15 @@ class VenvBuilder: ) self._install_system_packages(deps) - self._prepare_venv() + + with self._prepare_src_dir(): + self._prepare_venv() + self._install_extra_pip_packages(deps) + print( + f'\nVirtual environment created at {self.output_dir}.\n' + f'Run source {os.path.join(self.output_dir, "bin", "activate")} to activate it.' + ) @classmethod def from_cmdline(cls, args: Sequence[str]) -> 'VenvBuilder':