blob: bd9e17e8f0da4b0cf7da49a544ee23b1f063de5e [file] [log] [blame] [view] [edit]
# infra_virtualenv README
[TOC]
This repository provides a common Python virtualenv interface that
Chromium OS infrastructure code can depend on.
## Using virtualenv in another repository
A repository adding virtualenv should mimic this repository, which
itself uses virtualenv for running unit tests.
Key files:
* `bin/python_venv` starts an instance of Python that uses the
virtualenv.
* `bin/turtle` is an example script for running a Python module using
`bin/python_venv`
* `venv/requirements.txt` lists the packages to install inside the
virtualenv. Refer to Pip's
[documentation](https://pip.pypa.io/en/stable/) for the
`requirements.txt` format.
* `venv` is added to `PYTHONPATH`. For example, `venv/cros_venv` can
be imported inside the virtualenv using `import cros_venv`.
## Adding packages to be available for use
Packages to be installed inside a virtualenv must first be added to
`pip_packages`.
To add packages, run:
$ bin/python_venv -m pip wheel -w pip_packages <packages to install>
Refer to Pip's documentation for details on the arguments for `pip`.
Commit the added package and make a CL.
## Adding third party packages to a virtualenv
Add the packages to `requirements.txt`. If the packages are not in
`pip_packages` yet, add the packages to `pip_packages`.
## Adding first party modules to a virtualenv
"First party modules" refers to Chromium OS code (anything checked out
by `repo`).
NOTE: Do not use this for third party dependencies (stuff not owned by
Chromium OS)! This should only be used to set up imports for stuff we
own. For example, importing `python-MySQL` SHOULD NOT use this, but
importing `chromite` MAY use this.
There are two ways to do this:
1. Adding a relative symlink to `venv`.
2. Modifying `sys.path` in `__init__.py`.
Adding a symlink to `venv` is simple and should be self-explanatory.
However, keep in mind that `repo` checkouts may not always have the
same structure, and certain environments such as production servers
may check out repositories in completely different locations. This
method is not powerful enough to account for these environments.
Modifying `sys.path` is a lot more powerful. The way to do this is to
add a small bit of code to the `__init__.py` of the package that needs
the import.
Example (do not copy and paste blindly):
import os
import sys
# The path of the package
PKGDIR = __path__[0]
# Paths to check
_PATH1 = os.path.join(PKGDIR, '../foo')
_PATH2 = '/opt/foo'
if os.path.exists(_PATH1):
sys.path.append(_PATH1)
elif os.path.exists(_PATH2):
sys.path.append(_PATH2)
else:
raise ImportError('foo not found')
You must also add the contents of the other project's
`requirements.txt` to your project. We do not attempt to resolve
dependencies recursively as that is very difficult.
## Low level API
The `bin/create_venv` script prepares a virtualenv using a
`requirements.txt` file.
$ bin/create_venv requirements.txt
The script will print the path to the virtualenv to stdout. Note that
the output ends with a newline; Bash handles this, but Python does
not.
To run the virtualenv Python, call `bin/python` under the virtualenv
directory.
Together, this might look up:
$ venv=$(bin/create_venv requirements.txt)
$ ${venv}/bin/python
NOTE: It is not generally safe to run the other scripts in the
virtualenv's `bin` directory due to hard-coded paths. Instead of
running `bin/pip` for example, use `bin/python -m pip`.