Source code for provy.more.debian.package.virtualenv

#!/usr/bin/python
# -*- coding: utf-8 -*-

'''
Roles in this namespace are meant to provide virtual environments and run commands inside a `virtualenv <http://www.virtualenv.org/>`_, for Debian distributions.
'''

from contextlib import contextmanager
import os

from provy.core import Role


[docs]class VirtualenvRole(Role): ''' This role provides `virtualenv <http://www.virtualenv.org/>`_ management. It also provides `virtualenvwrapper <http://www.doughellmann.com/projects/virtualenvwrapper/>`_ provisioning, although it's not internally used in this role. When using the object as a context manager (that is, using a `with` block) it will make sure that the virtual environment is created and that the commands that run inside it run within this same virtual environment (which affects, for example, the `python` and `pip` commands). If the virtual environment already exists, it just bypasses the creation procedure. :param env_name: Name of the virtual environment to be created and to keep activated when running commands inside the context manager. :type env_name: :class:`str` :param system_site_packages: If :data:`True`, will include system-wide site-packages in the virtual environment. Defaults to :data:`False`. :type system_site_packages: :class:`bool` :ivar base_directory: (:class:`str`) Directory where the virtual environment subdirectory will be put at. For example, if you set it as "/home/johndoe/my_envs", and use venv("some_env"), it will create a virtual environment at "/home/johndoe/my_envs/some_env". Defaults to $HOME/.virtualenvs (or :attr:`venv.user` `/.virtualenvs`, if the user is explicitly set - see below -). :ivar user: (:class:`str`) The user with which the virtual environment should be created. Defaults to the context user. Example: :: from provy.core import Role from provy.more.debian import VirtualenvRole class MySampleRole(Role): def provision(self): # this example uses the defaults provided with self.using(PipRole) as pip, self.using(VirtualenvRole) as venv, venv('fancylib'): pip.ensure_package_installed('django') # this is when you want to set a different base virtualenv directory and user, and include the system-wide site-packages. with self.using(PipRole) as pip, self.using(VirtualenvRole) as venv: venv.base_directory = '/home/johndoe/Envs' venv.user = 'johndoe' with venv('fancylib2', system_site_packages=True): pip.ensure_package_installed('tornado') ''' def __init__(self, prov, context): super(VirtualenvRole, self).__init__(prov, context) self.user = context['user'] self.base_directory = None
[docs] def get_base_directory(self): ''' Gets the base directory that will be used to create the virtual environment. By default, it returns a subdir under the current venv user home and ".virtualenvs". If you wish to change the directory where it gets created, just set :attr:`role.base_directory <base_directory>` Example: :: from provy.core import Role from provy.more.debian import VirtualenvRole class MySampleRole(Role): def provision(self): with self.using(VirtualenvRole) as venv: venv.user = 'johndoe' venv.get_base_directory() # "/home/johndoe/.virtualenvs" venv.base_directory = '/home/johndoe/Envs' venv.get_base_directory() # "/home/johndoe/Envs" ''' return self.base_directory or os.path.join(self.__get_user_dir(), '.virtualenvs')
def __get_user_dir(self): if self.user == 'root': return '/root' else: return '/home/%s' % self.user
[docs] def env_dir(self, env_name): ''' Gets the virtual environment directory for a given environment name. Please note that this doesn't check if the env actually exists. :param env_name: Name of the virtual environment to be used to build a directory string. :type env_name: :class:`str` :return: The directory to be used. :rtype: :class:`str` Example: :: from provy.core import Role from provy.more.debian import VirtualenvRole class MySampleRole(Role): def provision(self): with self.using(VirtualenvRole) as venv, venv('fancylib'): venv.env_dir('fancylib') ''' return os.path.join(self.get_base_directory(), env_name)
@contextmanager def __call__(self, env_name, system_site_packages=False): from fabric.api import prefix if not self.env_exists(env_name): self.create_env(env_name, system_site_packages=system_site_packages) with prefix('source %s/bin/activate' % self.env_dir(env_name)): yield
[docs] def provision(self): ''' Installs virtualenv and virtualenvwrapper, and their dependencies. This method should be called upon if overriden in base classes, or virtualenv won't work properly in the remote server. Example: :: from provy.core import Role from provy.more.debian import VirtualenvRole class MySampleRole(Role): def provision(self): self.provision_role(VirtualenvRole) # does not need to be called if using with block. ''' from provy.more.debian import PipRole with self.using(PipRole) as pip: pip.ensure_package_installed('virtualenv') pip.ensure_package_installed('virtualenvwrapper')
[docs] def create_env(self, env_name, system_site_packages=False): ''' Creates a virtual environment. :param env_name: Name of the virtual environment to be created. :type env_name: :class:`str` :param system_site_packages: If :data:`True`, will include system-wide site-packages in the virtual environment. Defaults to :data:`False`. :type system_site_packages: :class:`bool` Examples: :: from provy.core import Role from provy.more.debian import VirtualenvRole class MySampleRole(Role): def provision(self): with self.using(VirtualenvRole) as venv: env_dir = venv.create_env('fancylib') # will return the directory where the virtual environment was created ''' env_dir = self.env_dir(env_name) site_packages_arg = '--system-site-packages ' if system_site_packages else '' self.execute('virtualenv %s%s' % (site_packages_arg, env_dir), user=self.user) return env_dir
[docs] def env_exists(self, env_name): ''' Checks if a virtual environment exists. :param env_name: Name of the virtual environment to be checked. :type env_name: :class:`str` :return: Whether the virtual environment exists. :rtype: :class:`bool` Example: :: from provy.core import Role from provy.more.debian import VirtualenvRole class MySampleRole(Role): def provision(self): with self.using(VirtualenvRole) as venv: venv.env_exists('fancylib') # True or False ''' return self.remote_exists_dir(self.env_dir(env_name))