This is a pre-production deployment of Warehouse. Changes made here affect the production instance of PyPI (
Help us improve Python packaging - Donate today!
Project Description


  • Declarative configuration based
  • Configurable path for the virtualenvs and the symlinks
  • Support one or many virtualenvs
  • Idempotent


Consider the following example.yaml:

        venv_prefix: /tmp/example
        symlink_prefix: /tmp/example
        install: true
        symlink: ['ipython', 'iptest']
    yadoma: {}
        venv_command: python2
        venv_prefix: /tmp/example
        symlink_prefix: /tmp/example
        url: git+ssh://
        symlink: ['git-hub']

This will create two system virtualenvs .demo_sysvenv3 and .demo_sysvenv2. The first, is based on Python 3 (the default) and the second on legacy Python. Each system virtualenv contains a number of packages that will be installed and linked.

The special triforce section contains additional parameters that govern how the system virtualenv will be configured. For example in both cases above, the virtualenvs themselves and their symlinks will be installed into /tmp/example (to ensure the example doesn’t screw with your system). In the .demo_sysvenv2 case, the venv_command command has been set to python2 indicating that a virtualenv with legacy python should be installed. In case the command it uses under the hood (use the force, read the source) doesn’t work for you, you can also simply type a custom command string to create the virtualenv for you. This is provided as a fallback since there seem to be a myriad of ways of setting up a virtualenv and you never know what might work on a given system. Lastly setting install to true will ensure that the triforce itself is installed and symlinked into the virtual environment, meaning you can delete whatever you used to bootstrap it.

In addition to the names of the packages on PyPi, you need to specify which executables or scripts should be symlinked. This may seem redundant, but a) I don’t know how to easily introspect a Python package to obtain the scripts it installs and b) maybe you want to have control over this. Anyway, for the tool yadoma above there is no list of symlinks and so the tool will attempt to symlink a script of the same name as the package on PyPi. Yes, this could have been done for ipython too, but then we wouldn’t link the iptest script. Lastly, you can also specify a url which may contain the string that will be passed on to pip. In the example above we install git-spindle from github.

Lastly, I should also note that the tools pip and pybuilder will be installed by default into each created system virtualenv.

Here is what it looks like in action:

% triforce example.yaml
{'name': '.demo_sysvenv3', 'symlinks': ['ipython', 'iptest', 'yadoma'], 'symlink_prefix': '/tmp/example', 'venv_command': 'python3', 'urls': ['ipython', 'yadoma'], 'venv_prefix': '/tmp/example', 'path': '/tmp/example/.demo_sysvenv3'}
Creating venv at: '/tmp/example/.demo_sysvenv3'

'pip' command is: '/tmp/example/.demo_sysvenv3/bin/pip'
Installing/upgrading utilities: 'pip' and 'pybuilder'
Collecting pip
  Using cached pip-8.1.2-py2.py3-none-any.whl
Installing collected packages: pip
  Found existing installation: pip 8.1.1
    Uninstalling pip-8.1.1:
      Successfully uninstalled pip-8.1.1
Successfully installed pip-8.1.2

Collecting pybuilder
Requirement already up-to-date: pip>=7.0 in /tmp/example/.demo_sysvenv3/lib/python3.5/site-packages (from pybuilder)
Collecting wheel (from pybuilder)
  Using cached wheel-0.29.0-py2.py3-none-any.whl
Collecting tblib (from pybuilder)
  Using cached tblib-1.3.0-py2.py3-none-any.whl
Installing collected packages: wheel, tblib, pybuilder
Successfully installed pybuilder-0.11.9 tblib-1.3.0 wheel-0.29.0

Installing dependencies: '['ipython', 'yadoma']'
Collecting ipython
  Using cached ipython-5.1.0-py3-none-any.whl
Collecting yadoma
Collecting traitlets>=4.2 (from ipython)
  Using cached traitlets-4.3.0-py2.py3-none-any.whl
Collecting pygments (from ipython)
  Using cached Pygments-2.1.3-py2.py3-none-any.whl
Collecting prompt-toolkit<2.0.0,>=1.0.3 (from ipython)
  Using cached prompt_toolkit-1.0.7-py3-none-any.whl
Collecting decorator (from ipython)
  Using cached decorator-4.0.10-py2.py3-none-any.whl
Collecting simplegeneric>0.8 (from ipython)
Collecting pexpect; sys_platform != "win32" (from ipython)
  Using cached pexpect-4.2.1-py2.py3-none-any.whl
Requirement already satisfied (use --upgrade to upgrade): setuptools>=18.5 in /tmp/example/.demo_sysvenv3/lib/python3.5/site-packages (from ipython)
Collecting pickleshare (from ipython)
  Using cached pickleshare-0.7.4-py2.py3-none-any.whl
Collecting pyyaml (from yadoma)
Collecting docopt (from yadoma)
Collecting six (from traitlets>=4.2->ipython)
  Using cached six-1.10.0-py2.py3-none-any.whl
Collecting ipython-genutils (from traitlets>=4.2->ipython)
  Using cached ipython_genutils-0.1.0-py2.py3-none-any.whl
Collecting wcwidth (from prompt-toolkit<2.0.0,>=1.0.3->ipython)
  Using cached wcwidth-0.1.7-py2.py3-none-any.whl
Collecting ptyprocess>=0.5 (from pexpect; sys_platform != "win32"->ipython)
  Using cached ptyprocess-0.5.1-py2.py3-none-any.whl
Installing collected packages: six, decorator, ipython-genutils, traitlets, pygments, wcwidth, prompt-toolkit, simplegeneric, ptyprocess, pexpect, pickleshare, ipython, pyyaml, docopt, yadoma
Successfully installed decorator-4.0.10 docopt-0.6.2 ipython-5.1.0 ipython-genutils-0.1.0 pexpect-4.2.1 pickleshare-0.7.4 prompt-toolkit-1.0.7 ptyprocess-0.5.1 pygments-2.1.3 pyyaml-3.12 simplegeneric-0.8.1 six-1.10.0 traitlets-4.3.0 wcwidth-0.1.7 yadoma-41.3

Will symlink: '/tmp/example/.demo_sysvenv3/bin/ipython' --> '/tmp/example/ipython'
Will symlink: '/tmp/example/.demo_sysvenv3/bin/iptest' --> '/tmp/example/iptest'
Will symlink: '/tmp/example/.demo_sysvenv3/bin/yadoma' --> '/tmp/example/yadoma'
{'name': '.demo_sysvenv2', 'symlinks': ['git-hub'], 'symlink_prefix': '/tmp/example', 'venv_command': 'python2', 'urls': ['git+ssh://'], 'venv_prefix': '/tmp/example', 'path': '/tmp/example/.demo_sysvenv2'}
Creating venv at: '/tmp/example/.demo_sysvenv2'
Running virtualenv with interpreter /usr/bin/python2
New python executable in /tmp/example/.demo_sysvenv2/bin/python2
Also creating executable in /tmp/example/.demo_sysvenv2/bin/python
Installing setuptools, pkg_resources, pip, wheel...done.

'pip' command is: '/tmp/example/.demo_sysvenv2/bin/pip'
Installing/upgrading utilities: 'pip' and 'pybuilder'
Requirement already up-to-date: pip in /tmp/example/.demo_sysvenv2/lib/python2.7/site-packages

Collecting pybuilder
Requirement already up-to-date: pip>=7.0 in /tmp/example/.demo_sysvenv2/lib/python2.7/site-packages (from pybuilder)
Collecting tblib (from pybuilder)
  Using cached tblib-1.3.0-py2.py3-none-any.whl
Requirement already up-to-date: wheel in /tmp/example/.demo_sysvenv2/lib/python2.7/site-packages (from pybuilder)
Installing collected packages: tblib, pybuilder
Successfully installed pybuilder-0.11.9 tblib-1.3.0

Installing dependencies: '['git+ssh://']'
Collecting git+ssh://
  Cloning ssh:// to /tmp/pip-wqHeBB-build
Collecting>=0.9.0 (from git-spindle==3.3)
  Using cached
Collecting whelk>=2.6 (from git-spindle==3.3)
Collecting docopt>=0.5.0 (from git-spindle==3.3)
Collecting>=0.2.0 (from>=0.9.0->git-spindle==3.3)
Collecting requests>=2.0 (from>=0.9.0->git-spindle==3.3)
  Using cached requests-2.11.1-py2.py3-none-any.whl
Collecting uritemplate>=2.0 (from>=0.2.0->>=0.9.0->git-spindle==3.3)
  Downloading uritemplate-3.0.0-py2.py3-none-any.whl
Installing collected packages: uritemplate,, requests,, whelk, docopt, git-spindle
  Running install for git-spindle ... done
Successfully installed docopt-0.6.2 git-spindle-3.3 requests-2.11.1 uritemplate-3.0.0 whelk-2.6

Will symlink: '/tmp/example/.demo_sysvenv2/bin/git-hub' --> '/tmp/example/git-hub'

TODO and Ideas



Copyright 2016 Valentin Haenel <>

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Release History

Release History

This version
History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


History Node


Download Files

Download Files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

File Name & Checksum SHA256 Checksum Help Version File Type Upload Date
triforce-83.16.tar.gz (5.6 kB) Copy SHA256 Checksum SHA256 Source Dec 16, 2016

Supported By

WebFaction WebFaction Technical Writing Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Rackspace Rackspace Cloud Servers DreamHost DreamHost Log Hosting