views: packages can customize how they're added to views (#7152)
Functional updates: - `python` now creates a copy of the `python` binaries when it is added to a view - Python extensions (packages which subclass `PythonPackage`) rewrite their shebang lines to refer to python in the view - Python packages in the same namespace will not generate conflicts if both have `...lib/site-packages/namespace-example/__init__.py` - These `__init__` files will also remain when removing any package in the namespace until the last package in the namespace is removed Generally (Updated 2/16): - Any package can define `add_files_to_view` to customize how it is added to a view (and at the moment custom definitions are included for `python` and `PythonPackage`) - Likewise any package can define `remove_files_from_view` to customize which files are removed (e.g. you don't always want to remove the namespace `__init__`) - Any package can define `view_file_conflicts` to customize what it considers a merge conflict - Global activations are handled like views (where the view root is the spec prefix of the extendee) - Benefit: filesystem-management aspects of activating extensions are now placed in views (e.g. now one can hardlink a global activation) - Benefit: overriding `Package.activate` is more straightforward (see `Python.activate`) - Complication: extension packages which have special-purpose logic *only* when activated outside of the extendee prefix must check for this in their `add_files_to_view` method (see `PythonPackage`) - `LinkTree` is refactored to have separate methods for copying a directory structure and for copying files (since it was found that generally packages may want to alter how files are copied but still wanted to copy directories in the same way) TODOs (updated 2/20): - [x] additional testing (there is some unit testing added at this point but more would be useful) - [x] refactor or reorganize `LinkTree` methods: currently there is a separate set of methods for replicating just the directory structure without the files, and a set for replicating everything - [x] Right now external views (i.e. those not used for global activations) call `view.add_extension`, but global activations do not to avoid some extra work that goes into maintaining external views. I'm not sure if addressing that needs to be done here but I'd like to clarify it in the comments (UPDATE: for now I have added a TODO and in my opinion this can be merged now and the refactor handled later) - [x] Several method descriptions (e.g. for `Package.activate`) are out of date and reference a distinction between global activations and views, they need to be updated - [x] Update aspell package activations
This commit is contained in:
@@ -950,11 +950,11 @@ directly when you run ``python``:
|
||||
ImportError: No module named numpy
|
||||
>>>
|
||||
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Extensions & Environment Modules
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^
|
||||
Using Extensions
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
There are two ways to get ``numpy`` working in Python. The first is
|
||||
There are three ways to get ``numpy`` working in Python. The first is
|
||||
to use :ref:`shell-support`. You can simply ``use`` or ``load`` the
|
||||
module for the extension, and it will be added to the ``PYTHONPATH``
|
||||
in your current shell.
|
||||
@@ -976,15 +976,26 @@ or, for dotkit:
|
||||
Now ``import numpy`` will succeed for as long as you keep your current
|
||||
session open.
|
||||
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
Activating Extensions
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Activating Extensions in a View
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It is often desirable to have certain packages *always* available as
|
||||
part of a Python installation. Spack offers a more permanent solution
|
||||
for this case. Instead of requiring users to load particular
|
||||
environment modules, you can *activate* the package within the Python
|
||||
installation:
|
||||
The second way to use extensions is to create a view, which merges the
|
||||
python installation along with the extensions into a single prefix.
|
||||
See :ref:`filesystem-views` for a more in-depth description of views and
|
||||
:ref:`cmd-spack-view` for usage of the ``spack view`` command.
|
||||
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Activating Extensions Globally
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
As an alternative to creating a merged prefix with Python and its extensions,
|
||||
and prior to support for views, Spack has provided a means to install the
|
||||
extension into the Spack installation prefix for the extendee. This has
|
||||
typically been useful since extendable packages typically search their own
|
||||
installation path for addons by default.
|
||||
|
||||
Global activations are performed with the ``spack activate`` command:
|
||||
|
||||
.. _cmd-spack-activate:
|
||||
|
||||
@@ -1044,11 +1055,11 @@ the ``py-numpy`` into the prefix of the ``python`` package. To the
|
||||
python interpreter, it looks like ``numpy`` is installed in the
|
||||
``site-packages`` directory.
|
||||
|
||||
The only limitation of activation is that you can only have a *single*
|
||||
The only limitation of global activation is that you can only have a *single*
|
||||
version of an extension activated at a time. This is because multiple
|
||||
versions of the same extension would conflict if symbolically linked
|
||||
into the same prefix. Users who want a different version of a package
|
||||
can still get it by using environment modules, but they will have to
|
||||
can still get it by using environment modules or views, but they will have to
|
||||
explicitly load their preferred version.
|
||||
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@@ -1854,18 +1854,38 @@ from being linked in at activation time.
|
||||
``depends_on('python')`` and ``extends(python)`` in the same
|
||||
package. ``extends`` implies ``depends_on``.
|
||||
|
||||
-----
|
||||
Views
|
||||
-----
|
||||
|
||||
As covered in :ref:`filesystem-views`, the ``spack view`` command can be
|
||||
used to symlink a number of packages into a merged prefix. The methods of
|
||||
``PackageViewMixin`` can be overridden to customize how packages are added
|
||||
to views. Generally this can be used to create copies of specific files rather
|
||||
than symlinking them when symlinking does not work. For example, ``Python``
|
||||
overrides ``add_files_to_view`` in order to create a copy of the ``python``
|
||||
binary since the real path of the Python executable is used to detect
|
||||
extensions; as a consequence python extension packages (those inheriting from
|
||||
``PythonPackage``) likewise override ``add_files_to_view`` in order to rewrite
|
||||
shebang lines which point to the Python interpreter.
|
||||
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Activation & deactivation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Adding an extension to a view is referred to as an activation. If the view is
|
||||
maintained in the Spack installation prefix of the extendee this is called a
|
||||
global activation. Activations may involve updating some centralized state
|
||||
that is maintained by the extendee package, so there can be additional work
|
||||
for adding extensions compared with non-extension packages.
|
||||
|
||||
Spack's ``Package`` class has default ``activate`` and ``deactivate``
|
||||
implementations that handle symbolically linking extensions' prefixes
|
||||
into the directory of the parent package. However, extendable
|
||||
packages can override these methods to add custom activate/deactivate
|
||||
logic of their own. For example, the ``activate`` and ``deactivate``
|
||||
methods in the Python class use the symbolic linking, but they also
|
||||
handle details surrounding Python's ``.pth`` files, and other aspects
|
||||
of Python packaging.
|
||||
into a specified view. Extendable packages can override these methods
|
||||
to add custom activate/deactivate logic of their own. For example,
|
||||
the ``activate`` and ``deactivate`` methods in the Python class handle
|
||||
symbolic linking of extensions, but they also handle details surrounding
|
||||
Python's ``.pth`` files, and other aspects of Python packaging.
|
||||
|
||||
Spack's extensions mechanism is designed to be extensible, so that
|
||||
other packages (like Ruby, R, Perl, etc.) can provide their own
|
||||
@@ -1880,7 +1900,7 @@ Let's look at Python's activate function:
|
||||
|
||||
This function is called on the *extendee* (Python). It first calls
|
||||
``activate`` in the superclass, which handles symlinking the
|
||||
extension package's prefix into this package's prefix. It then does
|
||||
extension package's prefix into the specified view. It then does
|
||||
some special handling of the ``easy-install.pth`` file, part of
|
||||
Python's setuptools.
|
||||
|
||||
|
@@ -402,31 +402,6 @@ Numpy, core Python, BLAS/LAPACK and anything else needed:
|
||||
|
||||
spack module loads --dependencies py-scipy
|
||||
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
Extension Packages
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:ref:`packaging_extensions` may be used as an alternative to loading
|
||||
Python (and similar systems) packages directly. If extensions are
|
||||
activated, then ``spack load python`` will also load all the
|
||||
extensions activated for the given ``python``. This reduces the need
|
||||
for users to load a large number of modules.
|
||||
|
||||
However, Spack extensions have two potential drawbacks:
|
||||
|
||||
#. Activated packages that involve compiled C extensions may still
|
||||
need their dependencies to be loaded manually. For example,
|
||||
``spack load openblas`` might be required to make ``py-numpy``
|
||||
work.
|
||||
|
||||
#. Extensions "break" a core feature of Spack, which is that multiple
|
||||
versions of a package can co-exist side-by-side. For example,
|
||||
suppose you wish to run a Python package in two different
|
||||
environments but the same basic Python --- one with
|
||||
``py-numpy@1.7`` and one with ``py-numpy@1.8``. Spack extensions
|
||||
will not support this potential debugging use case.
|
||||
|
||||
|
||||
^^^^^^^^^^^^^^
|
||||
Dummy Packages
|
||||
^^^^^^^^^^^^^^
|
||||
@@ -447,6 +422,8 @@ it. A disadvantage is the set of packages will be consistent; this
|
||||
means you cannot load up two applications this way if they are not
|
||||
consistent with each other.
|
||||
|
||||
.. _filesystem-views:
|
||||
|
||||
^^^^^^^^^^^^^^^^
|
||||
Filesystem Views
|
||||
^^^^^^^^^^^^^^^^
|
||||
@@ -587,6 +564,29 @@ symlinks. At any time one can delete ``/path/to/MYVIEW`` or use
|
||||
``spack view`` to manage it surgically. None of this will affect the
|
||||
real Spack install area.
|
||||
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
Global Activations
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:ref:`cmd-spack-activate` may be used as an alternative to loading
|
||||
Python (and similar systems) packages directly or creating a view.
|
||||
If extensions are globally activated, then ``spack load python`` will
|
||||
also load all the extensions activated for the given ``python``.
|
||||
This reduces the need for users to load a large number of modules.
|
||||
|
||||
However, Spack global activations have two potential drawbacks:
|
||||
|
||||
#. Activated packages that involve compiled C extensions may still
|
||||
need their dependencies to be loaded manually. For example,
|
||||
``spack load openblas`` might be required to make ``py-numpy``
|
||||
work.
|
||||
|
||||
#. Global activations "break" a core feature of Spack, which is that
|
||||
multiple versions of a package can co-exist side-by-side. For example,
|
||||
suppose you wish to run a Python package in two different
|
||||
environments but the same basic Python --- one with
|
||||
``py-numpy@1.7`` and one with ``py-numpy@1.8``. Spack extensions
|
||||
will not support this potential debugging use case.
|
||||
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Discussion: Running Binaries
|
||||
|
Reference in New Issue
Block a user