Skip to content

Commit

Permalink
Use a realpath for the temporary build directory.
Browse files Browse the repository at this point in the history
Some systems have /tmp symlinked which confuses custom builds, such as
numpy. This ensures that real path is passed and that such builds
resolve their paths correctly during build and install.

Added test for the change and also for the previous related fix:
#707
  • Loading branch information
zvezdan committed Feb 20, 2016
1 parent 92b1422 commit 9e97761
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGES.txt
Expand Up @@ -17,6 +17,9 @@
* Fix PipDeprecationWarning so that warnings can be turned off by
``-W`` / ``PYTHONWARNINGS`` (:pull:`3455`)

* Fix the build on systems with symlinked /tmp directory for custom
builds such as numpy.


**8.0.2 (2016-01-21)**

Expand Down
8 changes: 7 additions & 1 deletion pip/req/req_install.py
Expand Up @@ -312,7 +312,13 @@ def build_location(self, build_dir):
# package is not available yet so we create a temp directory
# Once run_egg_info will have run, we'll be able
# to fix it via _correct_build_location
self._temp_build_dir = tempfile.mkdtemp('-build', 'pip-')
#
# NOTE: Some systems have /tmp as a symlink which confuses
# custom builds (such as numpy). Thus, we have to
# ensure that the real path is returned.
self._temp_build_dir = os.path.realpath(
tempfile.mkdtemp('-build', 'pip-')
)
self._ideal_build_dir = build_dir
return self._temp_build_dir
if self.editable:
Expand Down
28 changes: 28 additions & 0 deletions tests/unit/test_req_install.py
@@ -0,0 +1,28 @@
import os
import tempfile

import pytest

from pip.req.req_install import InstallRequirement


class TestInstallRequirementBuildDirectory(object):
# no need to test symlinks on Windows
@pytest.mark.skipif("sys.platform == 'win32'")
def test_tmp_build_directory(self):
# when req is None, we can produce a temporary directory
# Make sure we're handling it correctly with real path.
requirement = InstallRequirement(None, None)
tmp_dir = tempfile.mkdtemp('-build', 'pip-')
tmp_build_dir = requirement.build_location(tmp_dir)
assert (
os.path.dirname(tmp_build_dir) ==
os.path.realpath(os.path.dirname(tmp_dir))
)
# are we on a system where /tmp is a symlink
if os.path.realpath(tmp_dir) != os.path.abspath(tmp_dir):
assert os.path.dirname(tmp_build_dir) != os.path.dirname(tmp_dir)
else:
assert os.path.dirname(tmp_build_dir) == os.path.dirname(tmp_dir)
os.rmdir(tmp_dir)
assert not os.path.exists(tmp_dir)
20 changes: 20 additions & 0 deletions tests/unit/test_utils.py
Expand Up @@ -15,6 +15,7 @@
from pip.exceptions import HashMismatch, HashMissing, InstallationError
from pip.utils import (egg_link_path, get_installed_distributions,
untar_file, unzip_file, rmtree, normalize_path)
from pip.utils.build import BuildDirectory
from pip.utils.hashes import Hashes, MissingHashes
from pip.operations.freeze import freeze_excludes
from pip._vendor.six import BytesIO
Expand Down Expand Up @@ -447,3 +448,22 @@ def test_non_zero(self):
assert Hashes({'sha256': 'dummy'})
assert not Hashes()
assert not Hashes({})


class TestBuildDirectory(object):
# No need to test symlinked directories on Windows
@pytest.mark.skipif("sys.platform == 'win32'")
def test_build_directory(self):
with BuildDirectory() as build_dir:
tmp_dir = tempfile.mkdtemp(prefix="pip-build-test")
assert (
os.path.dirname(build_dir) ==
os.path.dirname(os.path.realpath(tmp_dir))
)
# are we on a system where /tmp is a symlink
if os.path.realpath(tmp_dir) != os.path.abspath(tmp_dir):
assert os.path.dirname(build_dir) != os.path.dirname(tmp_dir)
else:
assert os.path.dirname(build_dir) == os.path.dirname(tmp_dir)
os.rmdir(tmp_dir)
assert not os.path.exists(tmp_dir)

0 comments on commit 9e97761

Please sign in to comment.