Commit 29565304 authored by Thomas Leymonerie's avatar Thomas Leymonerie

Custom virtual environment

See merge request nexedi/slapos!1188
parents bddc5491 3aaa4189
Pipeline #22753 failed with stage
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
extends = extends =
../pygolang/buildout.cfg ../pygolang/buildout.cfg
parts =
[virtual-env-base] [virtual-env-base]
recipe = slapos.recipe.build recipe = slapos.recipe.build
name = ${:_buildout_section_name_} name = ${:_buildout_section_name_}
...@@ -10,64 +12,133 @@ init = ...@@ -10,64 +12,133 @@ init =
from zc.buildout.easy_install import working_set from zc.buildout.easy_install import working_set
import os import os
name = options['name'] name = options['name']
eggs = options['eggs'] eggs = options.get('eggs')
try: self.message = options.get('message')
scripts = "scripts = " + options['scripts'] self.chain = options.get('chain')
except KeyError: environment = options.get('environment')
scripts = "" scripts = options.get('scripts')
self.buildout.parse(""" eggs_template = """
[.%(name)s.install-eggs] [.%(name)s.install-eggs]
recipe = zc.recipe.egg recipe = zc.recipe.egg
eggs = %(eggs)s eggs =
%(eggs)s
%(scripts)s %(scripts)s
[.%(name)s.install-interpreter] [.%(name)s.install-interpreter]
<= python-interpreter <= python-interpreter
eggs += %(eggs)s eggs +=
""" % locals()) %(eggs)s
"""
instance_template = """
[.%(name)s.instance]
recipe = slapos.recipe.template
output = ${buildout:directory}/instance.cfg
depends = $%(cookbook)s
inline =
[buildout]
parts = publish
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
[publish]
recipe = slapos.cookbook:publish
activate-script = %(location)s
"""
if eggs:
self.buildout.parse(eggs_template % {
"eggs": "\n ".join(e.strip() for e in eggs.splitlines()),
"name": name,
"scripts": "scripts = " + scripts if scripts else "",
})
if is_true(options.get('default-instance')): if is_true(options.get('default-instance')):
cookbook = "{slapos-cookbook:recipe}" self.buildout.parse(instance_template % {
self.buildout.parse(""" "cookbook": "{slapos-cookbook:recipe}",
[.%(name)s.instance] "location": location,
recipe = slapos.recipe.template "name": name,
output = ${buildout:directory}/instance.cfg })
depends = $%(cookbook)s
inline = env = {
[buildout] "PATH": self.buildout['buildout']['bin-directory'] + ":\$PATH",
parts = publish "PS1": "\"(" + self.name + ") \$PS1\"",
}
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory} if environment:
for line in environment.splitlines():
[publish] key, value = line.split("=", 1)
recipe = slapos.cookbook:publish env[key.strip()] = value.strip()
activate-script = %(location)s
""" % locals()) self.env = env
install = install =
message = ""
if self.message:
message = "echo " + "\n echo ".join(
"%r" % line for line in self.message.splitlines())
message += "\n echo \'\'"
chain = ""
if self.chain:
chain = "source " + "\n source ".join(
"%r" % line for line in self.chain.splitlines())
with open(location, "w") as f: with open(location, "w") as f:
f.write(options['template'] % { f.write(options['template'] % {
"path" : self.buildout['buildout']['bin-directory'], "env": " ".join("%s %s" % (k, v) for k, v in self.env.items()),
"name" : self.name, "message": message,
"chain": chain,
}) })
# Template virtual env for bash shell in posix # Template virtual env for bash shell in posix
[virtual-env-base:posix] [virtual-env-base:posix]
template = template =
deactivate () { if type deactivate > /dev/null 2>&1
set PATH PS1 then
export _OLD_PARAM=( "$@")
set %(env)s
while [ "$1" ]; do while [ "$1" ]; do
eval "if [ \"\$_OLD_VENV_$1\" ]; then $1=\$_OLD_VENV_$1; else unset $1; fi; unset \$_OLD_VENV_$1" if ! ( echo $_LIST_OLD_VENV | grep $1 ) > /dev/null 2>&1
then
eval "export _OLD_VENV_$1=\$$1"
eval "export _LIST_OLD_VENV=\"$1 \$_LIST_OLD_VENV\""
fi
eval "export $1=\"$2\""
shift
shift shift
done done
unset -f deactivate if [[ -n "$_OLD_PARAM" ]]; then
} set "$${_OLD_PARAM[@]}"
fi
unset _OLD_PARAM
VENV_PATH=%(path)s %(chain)s
_OLD_VENV_PATH=$PATH %(message)s
_OLD_VENV_PS1=$PS1 else
PATH=$VENV_PATH:$PATH deactivate () {
PS1='(%(name)s) '$PS1 set $_LIST_OLD_VENV
while [ "$1" ]; do
eval "if [ \"\$_OLD_VENV_$1\" ]; then $1=\$_OLD_VENV_$1; else unset $1; fi; unset \$_OLD_VENV_$1"
shift
done
unset -f deactivate
unset _LIST_OLD_VENV
}
export _OLD_PARAM=( "$@" )
set %(env)s
while [ "$1" ]; do
eval "_OLD_VENV_$1=\$$1"
eval "export $1=\"$2\""
eval "export _LIST_OLD_VENV=\"$1 \$_LIST_OLD_VENV\""
shift
shift
done
if [[ -n "$_OLD_PARAM" ]]; then
set "$${_OLD_PARAM[@]}"
fi
unset _OLD_PARAM
%(chain)s
%(message)s
fi
Virtual environment
===================
Introduction
------------
The virtual environment macro allows you to quickly create a development environment.
Options
-------
Several options are available to customize your virtual environment :
name
~~~~
The ``name`` option is the name that will be displayed when the environment is activated. For example::
name = virtual-env
gives::
>> source activate
( virtual-env ) >>
**Note:** By default, ``name`` is the name of the Buildout section that uses the macro.
location
~~~~~~~~
The ``location`` option is where the script to be sourced will be stored. For example::
location = project/activate
gives::
>> source project/activate
( virtual-env ) >>
**Note:** Don't forget to add the name of the script in the path.
eggs
~~~~
This option should not be used to install eggs during instantiation (in an instance file).
It works the same way as ``zc.recipe.eggs``, you can add to the line several eggs to download for use in the virtual environment.
A custom Python with the chosen eggs will then be generated. For example::
eggs = numpy
gives::
( virtual-env ) >> python
python
>>> import numpy
scripts
~~~~~~~
This option should not be used to install scripts during instantiation (in an instance file).
It works in the same way as in ``zc.recipe.eggs``, you can add to the line several scripts to generate for use in the virtual environment.For example::
eggs = Django
scripts = django-admin
gives::
( virtual-env ) >> django-admin
**Note:** By default if the option is not used, all scripts will be installed.
default-instance
~~~~~~~~~~~~~~~~
The ``default-instance`` option takes the value ``true`` or ``false``.
If set to ``true``, it will create a minimal instance that will publish the path of the script to be sourced.
If it is set to ``false``, you will be able to create your own custom instance.
**Note:** If you want to use the macro in an ``instance`` file, you should set this option to ``false``.
environment
~~~~~~~~~~~
The ``environment`` option allows you to choose the value of the environment variables of the virtual environment.
They are to be written on the line in the form ``VAR = value``. For example::
environment =
VAR1 = value1
VAR2 = value2
gives::
( virtual-env ) >> echo $VAR1
value1
**Note:** If you want to keep the other values as well, like for PATH for example, you have to do::
PATH = new_val:$PATH
message
~~~~~~~
The ``message`` option allows to display a message when sourcing the virtual environment.
The message will be considered as a string. For example::
message =
You are in a virtual environment.
gives::
>> source activate
You are in a virtual environment.
( virtual-env) >>
chain
~~~~~
The ``chain`` option allows you to chain several scripts created by the macro as if it were one. This can be useful if one script is generated in a ``software`` file and another in an ``instance`` file.
When deactivating, the state of the environment will return to the initial state.
To use this option you just have to specify the script to source by running the script. For example::
chain = project/another_activate
Deactivate
----------
Once you want to exit the virtual environment, you just have to run the ``deactivate`` function. Like::
( virtual-env ) >> deactivate
>>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment