blob: f968b5d803c528279e3da715071580423955ba19 [file] [log] [blame]
# Copyright 2012 Google Inc. All Rights Reserved.
#
# 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.
"""A utility script to create a pristine new python virtual enviroment during
building."""
import datetime
import logging
import optparse
import os
import shutil
import subprocess
import sys
_SRC_DIR = os.path.abspath(os.path.join(__file__, '../../..'))
_VIRTUALENV_DIR = os.path.join(_SRC_DIR, 'third_party/virtualenv/files')
_LOGGER = logging.getLogger(__name__)
class VirtualEnvCreationError(RuntimeError):
"""Exception thrown on virtual enviroment creation error."""
pass
def _Subprocess(command, failure_msg):
_LOGGER.info('Executing command line %s.', command)
ret = subprocess.call(command)
if ret != 0:
_LOGGER.error(failure_msg)
raise VirtualEnvCreationError(failure_msg)
def _CreateVirtualEnv(base_dir):
"""Creates a new virtual python environment in base_dir, sets convenient
defaults for it, and installs the external modules we need.
Currently those modules are:
- numpy.
- matplotlib.
Raises a VirtualEnvCreationError on failure.
"""
# We want all paths to be absolute.
base_dir = os.path.abspath(base_dir)
if os.path.exists(base_dir):
command = ['cmd', '/c', 'rmdir', '/s', '/q', base_dir]
_Subprocess(command, 'Failed to delete existing directory')
# Start by creating the output directory and copying python26.dll, as well
# as pywintypes26.dll into it, as if the DLLs are not in path, the virtual
# environment won't work.
script_dir = os.path.join(base_dir, 'Scripts')
try:
os.makedirs(script_dir)
dll_path = os.path.join(os.path.dirname(sys.executable), 'python26.dll')
shutil.copy(dll_path, script_dir)
dll_path = os.path.join(os.path.dirname(sys.executable), 'pywintypes26.dll')
shutil.copy(dll_path, script_dir)
dll_path = os.path.join(os.path.dirname(sys.executable), 'pythoncom26.dll')
shutil.copy(dll_path, script_dir)
except Exception:
_LOGGER.exception('Unable to copy python DLL')
raise VirtualEnvCreationError('Unable to copy python DLL')
# Run virtualenv.py with our selfsame python interpreter.
command = [sys.executable,
os.path.join(_VIRTUALENV_DIR, 'virtualenv.py'),
'--verbose',
'--never-download',
base_dir]
_Subprocess(command, 'Virtualenv creation failed.')
# Set defaults for setuptools so that our built eggs get deposited
# to the release directory, and so that installing looks there.
opts = (
# Tag eggs with the SVN revision by default.
('egg_info', 'tag-svn-revision', 'True'),
# Drop created eggs in the base directory's parent dir (Debug or Release).
('bdist_egg', 'dist-dir', os.path.join(base_dir, '..')),
# Tell easy install to use the parent dir as the package index by default.
('easy_install', 'index-url', os.path.join(base_dir, '..')),
)
for (cmd, option, value) in opts:
command = [os.path.join(script_dir, 'python'),
'-c', 'from setuptools import setup; setup()',
'setopt',
'--global-config',
'--command', cmd,
'--option', option,
'--set-value', value]
_Subprocess(command, 'Failed to set option %s' % option)
# Hook numpy into the virtual environment by copying it in.
try:
numpy_dir = os.path.join(_SRC_DIR, 'third_party/numpy/files/numpy')
site_lib_dir = os.path.join(base_dir, 'Lib/site-packages')
shutil.copytree(numpy_dir, os.path.join(site_lib_dir, 'numpy'))
except Exception:
_LOGGER.exception('Unable to copy numpy.')
raise VirtualEnvCreationError('Unable to copy numpy.')
# Install matplotlib into the new environment. We use easy_install to do
# the needful, but provide it with an index URL that's the directory
# containing the matplotlib subdir.
matplotlib_dir = os.path.abspath(os.path.join(_SRC_DIR, 'third_party'))
command = [os.path.join(script_dir, 'easy_install'),
'--index-url', matplotlib_dir,
'matplotlib']
_Subprocess(command, 'Matplotlib installation failed.')
def _ParseArgs():
parser = optparse.OptionParser(usage='%prog [options]')
parser.add_option('-v', '--verbose', dest='verbose',
action='store_true', default=False,
help='Enable verbose logging.')
parser.add_option('', '--output-dir', dest='output_dir',
help='The base directory for the new virtual environment')
parser.add_option('', '--success-file', dest='success_file',
default=None,
help='Path to a file that will be touched on successful '
'virtual environment creation')
(opts, args) = parser.parse_args()
if args:
parser.error('This script takes no arguments.')
if not opts.output_dir:
parser.error('You must provide an output directory.')
if opts.verbose:
logging.basicConfig(level=logging.INFO)
else:
logging.basicConfig(level=logging.ERROR)
return (opts, args)
def Main():
"""Main function."""
opts, dummy_args = _ParseArgs()
_CreateVirtualEnv(opts.output_dir)
if opts.success_file:
with open(opts.success_file, 'w') as success_file:
success_file.write(str(datetime.datetime.now()))
return 0
if __name__ == '__main__':
sys.exit(Main())