From 7ec49dc2fb0a9dbf522e79d87e2bc13d29a2556e Mon Sep 17 00:00:00 2001 From: Donald Stufft Date: Thu, 21 Nov 2013 21:59:31 -0500 Subject: [PATCH] Enable --[no-]compile which will compile or not compile pyc files * Enables compilation for Wheel files * Adds an easy command line for distutils/setuptools compilation options --- pip/commands/install.py | 16 ++++++++++ pip/req.py | 14 +++++++-- pip/wheel.py | 8 ++++- tests/functional/test_install.py | 41 ++++++++++++++++++++++++ tests/functional/test_install_wheel.py | 43 ++++++++++++++++++++++++++ 5 files changed, 119 insertions(+), 3 deletions(-) diff --git a/pip/commands/install.py b/pip/commands/install.py index bf5aefb19e6..8cc6c41db2c 100644 --- a/pip/commands/install.py +++ b/pip/commands/install.py @@ -136,6 +136,21 @@ def __init__(self, *args, **kw): default=None, help="Install everything relative to this alternate root directory.") + cmd_opts.add_option( + "--compile", + action="store_true", + dest="compile", + default=True, + help="Compile py files to pyc", + ) + + cmd_opts.add_option( + "--no-compile", + action="store_false", + dest="compile", + help="Do not compile py files to pyc", + ) + cmd_opts.add_option(cmdoptions.use_wheel.make()) cmd_opts.add_option(cmdoptions.no_use_wheel.make()) @@ -227,6 +242,7 @@ def run(self, options, args): use_user_site=options.use_user_site, target_dir=temp_target_dir, session=session, + pycompile=options.compile, ) for name in args: requirement_set.add_requirement( diff --git a/pip/req.py b/pip/req.py index 4e1e1d92e79..0bbbf6c9f9b 100644 --- a/pip/req.py +++ b/pip/req.py @@ -39,7 +39,7 @@ class InstallRequirement(object): def __init__(self, req, comes_from, source_dir=None, editable=False, url=None, as_egg=False, update=True, prereleases=None, - editable_options=None, from_bundle=False): + editable_options=None, from_bundle=False, pycompile=True): self.extras = () if isinstance(req, string_types): req = pkg_resources.Requirement.parse(req) @@ -74,6 +74,8 @@ def __init__(self, req, comes_from, source_dir=None, editable=False, self.target_dir = None self.from_bundle = from_bundle + self.pycompile = pycompile + # True if pre-releases are acceptable if prereleases: self.prereleases = True @@ -638,6 +640,11 @@ def install(self, install_options, global_options=(), root=None): if root is not None: install_args += ['--root', root] + if self.pycompile: + install_args += ["--compile"] + else: + install_args += ["--no-compile"] + if running_under_virtualenv(): ## FIXME: I'm not sure if this is a reasonable location; probably not ## but we can't put it in the default location, as that is a virtualenv symlink that isn't writable @@ -843,6 +850,7 @@ def move_wheel_files(self, wheeldir, root=None): user=self.use_user_site, home=self.target_dir, root=root, + pycompile=self.pycompile, ) @property @@ -884,7 +892,7 @@ class RequirementSet(object): def __init__(self, build_dir, src_dir, download_dir, download_cache=None, upgrade=False, ignore_installed=False, as_egg=False, target_dir=None, ignore_dependencies=False, force_reinstall=False, use_user_site=False, - session=None): + session=None, pycompile=True): self.build_dir = build_dir self.src_dir = src_dir self.download_dir = download_dir @@ -904,6 +912,7 @@ def __init__(self, build_dir, src_dir, download_dir, download_cache=None, self.use_user_site = use_user_site self.target_dir = target_dir #set from --target option self.session = session or PipSession() + self.pycompile = pycompile def __str__(self): reqs = [req for req in self.requirements.values() @@ -916,6 +925,7 @@ def add_requirement(self, install_req): install_req.as_egg = self.as_egg install_req.use_user_site = self.use_user_site install_req.target_dir = self.target_dir + install_req.pycompile = self.pycompile if not name: #url or path requirement w/o an egg fragment self.unnamed_requirements.append(install_req) diff --git a/pip/wheel.py b/pip/wheel.py index 1411254801d..fa3e2709694 100644 --- a/pip/wheel.py +++ b/pip/wheel.py @@ -3,6 +3,7 @@ """ from __future__ import with_statement +import compileall import csv import functools import hashlib @@ -134,7 +135,8 @@ def get_entrypoints(filename): return console, gui -def move_wheel_files(name, req, wheeldir, user=False, home=None, root=None): +def move_wheel_files(name, req, wheeldir, user=False, home=None, root=None, + pycompile=True): """Install a wheel""" scheme = distutils_scheme(name, user=user, home=home, root=root) @@ -156,6 +158,10 @@ def move_wheel_files(name, req, wheeldir, user=False, home=None, root=None): changed = set() generated = [] + # Compile all of the pyc files that we're going to be installing + if pycompile: + compileall.compile_dir(source, force=True, quiet=True) + def normpath(src, p): return make_path_relative(src, p).replace(os.path.sep, '/') diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py index 4527c96f53a..97744280945 100644 --- a/tests/functional/test_install.py +++ b/tests/functional/test_install.py @@ -1,6 +1,7 @@ import os import sys import textwrap +import glob from os.path import abspath, join, curdir, pardir @@ -456,3 +457,43 @@ def test_url_req_case_mismatch(script, data): assert egg_folder in result.files_created, str(result) egg_folder = script.site_packages / 'Upper-2.0-py%s.egg-info' % pyversion assert egg_folder not in result.files_created, str(result) + + +def test_compiles_pyc(script): + """ + Test installing with --compile on + """ + del script.environ["PYTHONDONTWRITEBYTECODE"] + script.pip("install", "--compile", "--no-use-wheel", "INITools==0.2") + + # There are many locations for the __init__.pyc file so attempt to find + # any of them + exists = [ + os.path.exists(script.site_packages_path/"initools/__init__.pyc"), + ] + + exists += glob.glob( + script.site_packages_path/"initools/__pycache__/__init__*.pyc" + ) + + assert any(exists) + + +def test_no_compiles_pyc(script, data): + """ + Test installing from wheel with --compile on + """ + del script.environ["PYTHONDONTWRITEBYTECODE"] + script.pip("install", "--no-compile", "--no-use-wheel", "INITools==0.2") + + # There are many locations for the __init__.pyc file so attempt to find + # any of them + exists = [ + os.path.exists(script.site_packages_path/"initools/__init__.pyc"), + ] + + exists += glob.glob( + script.site_packages_path/"initools/__pycache__/__init__*.pyc" + ) + + assert not any(exists) diff --git a/tests/functional/test_install_wheel.py b/tests/functional/test_install_wheel.py index d3ecee23062..0cfeff46dea 100644 --- a/tests/functional/test_install_wheel.py +++ b/tests/functional/test_install_wheel.py @@ -1,5 +1,7 @@ import os import pytest +import glob + from tests.lib.path import Path @@ -186,3 +188,44 @@ def test_install_from_wheel_gui_entrypoint(script, data): wrapper_file = script.bin / 't1' assert wrapper_file in result.files_created + +def test_wheel_compiles_pyc(script, data): + """ + Test installing from wheel with --compile on + """ + script.pip( + "install", "--compile", "simple.dist==0.1", "--no-index", + "--find-links=" + data.find_links + ) + # There are many locations for the __init__.pyc file so attempt to find + # any of them + exists = [ + os.path.exists(script.site_packages_path/"simpledist/__init__.pyc"), + ] + + exists += glob.glob( + script.site_packages_path/"simpledist/__pycache__/__init__*.pyc" + ) + + assert any(exists) + + +def test_wheel_no_compiles_pyc(script, data): + """ + Test installing from wheel with --compile on + """ + script.pip( + "install", "--no-compile", "simple.dist==0.1", "--no-index", + "--find-links=" + data.find_links + ) + # There are many locations for the __init__.pyc file so attempt to find + # any of them + exists = [ + os.path.exists(script.site_packages_path/"simpledist/__init__.pyc"), + ] + + exists += glob.glob( + script.site_packages_path/"simpledist/__pycache__/__init__*.pyc" + ) + + assert not any(exists)