Skip to content

Commit

Permalink
Spack doesn't run site customization when started
Browse files Browse the repository at this point in the history
fixes spack#9206
fixes spack#9034

A possible solution to spack#9206 is to avoid running `import site` and all
the initialization procedures that this entails. This requires us to use
`python -S` as an interpreter, instead of plain `python`.

Of course things can't be that simple. In Linux (but not in BSD or
MacOS) the shebang pass a single string argument to the interpreter.
More details on the subject are here:

http://sambal.org/2014/02/passing-options-node-shebang-line/
https://github.com/smikes/node/blob/minus-x-switch/doc/Minus-X-Switch-Proposal.md#shebang-interpretation

but the bottom line is that this requires us to have a wrapper bash
script that invokes the interpreter with the correct option.

Finally, as now we are not picking up anything from the 'site', we need
to vendor `setuptools` (which was still missing).
  • Loading branch information
alalazo committed Oct 21, 2018
1 parent b4e9690 commit 5462d95
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 31 deletions.
32 changes: 2 additions & 30 deletions bin/spack
Original file line number Diff line number Diff line change
@@ -1,36 +1,8 @@
#!/usr/bin/env python
#!/usr/bin/env bash
#
# Copyright 2013-2018 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from __future__ import print_function

import os
import sys

if sys.version_info[:2] < (2, 6):
v_info = sys.version_info[:3]
sys.exit("Spack requires Python 2.6 or higher."
"This is Python %d.%d.%d." % v_info)

# Find spack's location and its prefix.
spack_file = os.path.realpath(os.path.expanduser(__file__))
spack_prefix = os.path.dirname(os.path.dirname(spack_file))

# Allow spack libs to be imported in our scripts
spack_lib_path = os.path.join(spack_prefix, "lib", "spack")
sys.path.insert(0, spack_lib_path)

# Add external libs
spack_external_libs = os.path.join(spack_lib_path, "external")

if sys.version_info[:2] == (2, 6):
sys.path.insert(0, os.path.join(spack_external_libs, 'py26'))

sys.path.insert(0, spack_external_libs)

# Once we've set up the system path, run the spack main method
import spack.main # noqa
sys.exit(spack.main.main())
exec /usr/bin/env python -S $0.py "$@"
65 changes: 65 additions & 0 deletions bin/spack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python
#
# Copyright 2013-2018 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

# Spack uses `python -S` as an interpreter to avoid the issue reported in:
#
# https://github.com/spack/spack/issues/9206
#
# Unfortunately not running `import site` by default causes all sort of
# inconsistencies as:
#
# - the system built-in modules that get linked into a virtual-env differ
# among python versions and might not include `__future__` or `inpect`
# (this means that `python -S` might prevent importing those modules)
#
# - the `site.py` used in Python 2.7 virtual environments is that of Python 2.6
# (https://github.com/pypa/virtualenv/issues/355)
#
# The hack below is needed to restore built-in modules from the system if
# they are missing. It assumes that the module `re` is always present as a
# built-in, and adds its real path to the end of `sys.path` to recover all
# the other system modules.
try:
import __future__ # noqa
import inspect # noqa
except ImportError:
# If `__future__` is not there, it's very likely we are within
# a Python 2.7 virtual environment. If `inspect` is not there
# it could be a Python 3.6 virtual environment.
import os.path
import re
import sys
re_realpath = os.path.realpath(re.__file__.replace('.pyc', '.py'))
sys.path.append(os.path.dirname(re_realpath))

import os
import sys

if sys.version_info[:2] < (2, 6):
v_info = sys.version_info[:3]
sys.exit("Spack requires Python 2.6 or higher."
"This is Python %d.%d.%d." % v_info)

# Find spack's location and its prefix.
spack_file = os.path.realpath(os.path.expanduser(__file__))
spack_prefix = os.path.dirname(os.path.dirname(spack_file))

# Allow spack libs to be imported in our scripts
spack_lib_path = os.path.join(spack_prefix, "lib", "spack")
sys.path.insert(0, spack_lib_path)

# Add external libs
spack_external_libs = os.path.join(spack_lib_path, "external")

if sys.version_info[:2] == (2, 6):
sys.path.insert(0, os.path.join(spack_external_libs, 'py26'))

sys.path.insert(0, spack_external_libs)

# Once we've set up the system path, run the spack main method
import spack.main # noqa
sys.exit(spack.main.main())
1 change: 1 addition & 0 deletions lib/spack/spack/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ def format_help(self, level='short'):
def make_argument_parser(**kwargs):
"""Create an basic argument parser without any subcommands added."""
parser = SpackArgumentParser(
prog='spack',
formatter_class=SpackHelpFormatter, add_help=False,
description=(
"A flexible package manager that supports multiple versions,\n"
Expand Down
2 changes: 1 addition & 1 deletion lib/spack/spack/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
bin_path = os.path.join(prefix, "bin")

#: The spack script itself
spack_script = os.path.join(bin_path, "spack")
spack_script = os.path.join(bin_path, "spack.py")

# spack directory hierarchy
lib_path = os.path.join(prefix, "lib", "spack")
Expand Down

0 comments on commit 5462d95

Please sign in to comment.