# -*- coding: utf-8; -*- ################################################################################ # # Rattail -- Retail Software Framework # Copyright © 2010-2018 Lance Edgar # # This file is part of Rattail. # # Rattail is free software: you can redistribute it and/or modify it under the # terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # Rattail is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # Rattail. If not, see . # ################################################################################ """ Fabric Library for Python """ from __future__ import unicode_literals, absolute_import from contextlib import contextmanager import six from fabric.api import abort, sudo, run, prefix, cd, settings, env from fabric.contrib.files import exists, append from rattail_fabric import apt, mkdir def install_pip(use_apt=False): """ Install/upgrade the Pip installer for Python. """ if use_apt: apt.install('python-pip') else: apt.install('build-essential', 'python-dev', 'libssl-dev', 'libffi-dev') with settings(warn_only=True): result = sudo('which pip') if result.failed: apt.install('python-pkg-resources', 'python-setuptools') sudo('easy_install pip') sudo('apt-get --assume-yes purge python-setuptools') pip('setuptools') pip('pip', upgrade=True) pip('setuptools', 'wheel', 'ndg-httpsclient', upgrade=True, upgrade_strategy='eager') def pip(*packages, **kwargs): """ Install one or more packages via ``pip install``. """ upgrade = kwargs.pop('upgrade', False) upgrade = '--upgrade' if upgrade else '' upgrade_strategy = kwargs.pop('upgrade_strategy', None) if upgrade and upgrade_strategy: upgrade_strategy = '--upgrade-strategy {}'.format(upgrade_strategy) else: upgrade_strategy = '' if kwargs: abort("Unknown kwargs for pip(): {}".format(kwargs)) packages = ["'{}'".format(p) for p in packages] sudo('pip install {} {} {}'.format(upgrade, upgrade_strategy, ' '.join(packages))) def install_virtualenvwrapper(workon_home=None, user='root', use_apt=False): """ Install the `virtualenvwrapper`_ system, with the given ``workon`` home, owned by the given user. """ workon_home = workon_home or getattr(env, 'python_workon_home', '/srv/envs') mkdir(workon_home, owner=user) if use_apt: apt.install('virtualenvwrapper') else: pip('virtualenvwrapper', upgrade=True) configure_virtualenvwrapper('root', workon_home) if user != 'root': configure_virtualenvwrapper(user, workon_home) configure_virtualenvwrapper(env.user, workon_home) def configure_virtualenvwrapper(user, workon_home=None, wrapper='/usr/local/bin/virtualenvwrapper.sh'): """ Configure virtualenvwrapper for the given user account. """ workon_home = workon_home or getattr(env, 'python_workon_home', '/srv/envs') home = sudo('echo $HOME', user=user) home = home.rstrip('/') def update(script): script = '{}/{}'.format(home, script) if not exists(script): sudo('touch {}'.format(script)) sudo('chown {}: {}'.format(user, script)) append(script, 'export WORKON_HOME={}'.format(workon_home), use_sudo=True) append(script, 'source {}'.format(wrapper), use_sudo=True) update('.profile') update('.bashrc') def mkvirtualenv(name, python=None, user=None, workon_home=None, upgrade_pip=True, upgrade_six=True, upgrade_setuptools=True, upgrade_strategy=None): """ Make a new Python virtual environment. """ workon_home = workon_home or getattr(env, 'python_workon_home', '/srv/envs') sudo('mkvirtualenv {} {}'.format('--python={}'.format(python) if python else '', name)) if upgrade_pip: if isinstance(upgrade_pip, six.string_types): pip_req = upgrade_pip else: pip_req = 'pip' with workon(name): if upgrade_six: pip('six', upgrade=True) pip(pip_req, upgrade=True) if upgrade_setuptools: pip('setuptools', 'wheel', 'ndg-httpsclient', upgrade=True, upgrade_strategy=upgrade_strategy) if user: with cdvirtualenv(name, workon_home=workon_home): mkdir('app/log', owner='{0}:{0}'.format(user)) @contextmanager def workon(name): """ Context manager to prefix your command(s) with the ``workon`` command. """ with prefix('workon {0}'.format(name)): yield @contextmanager def cdvirtualenv(name, subdirs=[], workon_home=None): """ Context manager to prefix your command(s) with the ``cdvirtualenv`` command. """ workon_home = workon_home or getattr(env, 'python_workon_home', '/srv/envs') if isinstance(subdirs, six.string_types): subdirs = [subdirs] path = '{0}/{1}'.format(workon_home, name) if subdirs: path = '{0}/{1}'.format(path, '/'.join(subdirs)) with workon(name): with cd(path): yield