Remove support for Python 2.6 (#27256)
Modifications: - [x] Removed `centos:6` unit test, adjusted vermin checks - [x] Removed backport of `collections.OrderedDict` - [x] Removed backport of `functools.total_ordering` - [x] Removed Python 2.6 specific skip markers in unit tests - [x] Fixed a few minor Python 2.6 related TODOs in code Updating the vendored dependencies will be done in separate PRs
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							812663de62
						
					
				
				
					commit
					fa7189b480
				
			
							
								
								
									
										37
									
								
								.github/workflows/unit_tests.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								.github/workflows/unit_tests.yaml
									
									
									
									
										vendored
									
									
								
							@@ -24,9 +24,9 @@ jobs:
 | 
			
		||||
        pip install --upgrade pip
 | 
			
		||||
        pip install --upgrade vermin
 | 
			
		||||
    - name: vermin (Spack's Core)
 | 
			
		||||
      run: vermin --backport argparse --violations --backport typing -t=2.6- -t=3.5- -vvv lib/spack/spack/ lib/spack/llnl/ bin/
 | 
			
		||||
      run: vermin --backport argparse --violations --backport typing -t=2.7- -t=3.5- -vvv lib/spack/spack/ lib/spack/llnl/ bin/
 | 
			
		||||
    - name: vermin (Repositories)
 | 
			
		||||
      run: vermin --backport argparse --violations --backport typing -t=2.6- -t=3.5- -vvv var/spack/repos
 | 
			
		||||
      run: vermin --backport argparse --violations --backport typing -t=2.7- -t=3.5- -vvv var/spack/repos
 | 
			
		||||
  # Run style checks on the files that have been changed
 | 
			
		||||
  style:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
@@ -193,39 +193,6 @@ jobs:
 | 
			
		||||
      if: ${{ needs.changes.outputs.with_coverage == 'true' }}
 | 
			
		||||
      with:
 | 
			
		||||
        flags: shelltests,linux
 | 
			
		||||
  # Test for Python2.6 run on Centos 6
 | 
			
		||||
  centos6:
 | 
			
		||||
    needs: [ validate, style, changes ]
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    container: spack/github-actions:centos6
 | 
			
		||||
    steps:
 | 
			
		||||
    - name: Run unit tests (full test-suite)
 | 
			
		||||
      # The CentOS 6 container doesn't run with coverage, but
 | 
			
		||||
      # under the same conditions it runs the full test suite
 | 
			
		||||
      if: ${{ needs.changes.outputs.with_coverage == 'true' }}
 | 
			
		||||
      env:
 | 
			
		||||
          HOME: /home/spack-test
 | 
			
		||||
          SPACK_TEST_SOLVER: original
 | 
			
		||||
      run: |
 | 
			
		||||
          whoami && echo $HOME && cd $HOME
 | 
			
		||||
          git clone "${{ github.server_url }}/${{ github.repository }}.git" && cd spack
 | 
			
		||||
          git fetch origin "${{ github.ref }}:test-branch"
 | 
			
		||||
          git checkout test-branch
 | 
			
		||||
          . .github/workflows/setup_git.sh
 | 
			
		||||
          bin/spack unit-test -x
 | 
			
		||||
    - name: Run unit tests (only package tests)
 | 
			
		||||
      if: ${{ needs.changes.outputs.with_coverage == 'false' }}
 | 
			
		||||
      env:
 | 
			
		||||
          HOME: /home/spack-test
 | 
			
		||||
          ONLY_PACKAGES: true
 | 
			
		||||
          SPACK_TEST_SOLVER: original
 | 
			
		||||
      run: |
 | 
			
		||||
          whoami && echo $HOME && cd $HOME
 | 
			
		||||
          git clone "${{ github.server_url }}/${{ github.repository }}.git" && cd spack
 | 
			
		||||
          git fetch origin "${{ github.ref }}:test-branch"
 | 
			
		||||
          git checkout test-branch
 | 
			
		||||
          . .github/workflows/setup_git.sh
 | 
			
		||||
          bin/spack unit-test -x -m "not maybeslow" -k "package_sanity"
 | 
			
		||||
 | 
			
		||||
  # Test RHEL8 UBI with platform Python. This job is run
 | 
			
		||||
  # only on PRs modifying core Spack
 | 
			
		||||
 
 | 
			
		||||
@@ -33,11 +33,11 @@ import sys
 | 
			
		||||
 | 
			
		||||
min_python3 = (3, 5)
 | 
			
		||||
 | 
			
		||||
if sys.version_info[:2] < (2, 6) or (
 | 
			
		||||
if sys.version_info[:2] < (2, 7) or (
 | 
			
		||||
    sys.version_info[:2] >= (3, 0) and sys.version_info[:2] < min_python3
 | 
			
		||||
):
 | 
			
		||||
    v_info = sys.version_info[:3]
 | 
			
		||||
    msg = "Spack requires Python 2.6, 2.7 or %d.%d or higher " % min_python3
 | 
			
		||||
    msg = "Spack requires Python 2.7 or %d.%d or higher " % min_python3
 | 
			
		||||
    msg += "You are running spack with Python %d.%d.%d." % v_info
 | 
			
		||||
    sys.exit(msg)
 | 
			
		||||
 | 
			
		||||
@@ -54,8 +54,6 @@ spack_external_libs = os.path.join(spack_lib_path, "external")
 | 
			
		||||
 | 
			
		||||
if sys.version_info[:2] <= (2, 7):
 | 
			
		||||
    sys.path.insert(0, os.path.join(spack_external_libs, "py2"))
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -71,7 +71,7 @@ locally to speed up the review process.
 | 
			
		||||
   new release that is causing problems. If this is the case, please file an issue.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
We currently test against Python 2.6, 2.7, and 3.5-3.7 on both macOS and Linux and
 | 
			
		||||
We currently test against Python 2.7 and 3.5-3.9 on both macOS and Linux and
 | 
			
		||||
perform 3 types of tests:
 | 
			
		||||
 | 
			
		||||
.. _cmd-spack-unit-test:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
Name, Supported Versions, Notes, Requirement Reason
 | 
			
		||||
Python, 2.6/2.7/3.5-3.9, , Interpreter for Spack
 | 
			
		||||
Python, 2.7/3.5-3.9, , Interpreter for Spack
 | 
			
		||||
C/C++ Compilers, , , Building software
 | 
			
		||||
make, , , Build software
 | 
			
		||||
patch, , , Build software
 | 
			
		||||
 
 | 
			
		||||
		
		
			
  | 
							
								
								
									
										19
									
								
								lib/spack/external/__init__.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								lib/spack/external/__init__.py
									
									
									
									
										vendored
									
									
								
							@@ -17,7 +17,7 @@
 | 
			
		||||
--------
 | 
			
		||||
 | 
			
		||||
* Homepage: https://pypi.python.org/pypi/argparse
 | 
			
		||||
* Usage: We include our own version to be Python 2.6 compatible.
 | 
			
		||||
* Usage: We include our own version to be Python 3.X compatible.
 | 
			
		||||
* Version: 1.4.0
 | 
			
		||||
* Note: This package has been slightly modified to improve
 | 
			
		||||
  error message formatting. See the following commit if the
 | 
			
		||||
@@ -39,15 +39,6 @@
 | 
			
		||||
* Usage: Provides a more stable linux distribution detection.
 | 
			
		||||
* Version: 1.0.4 (last version supporting Python 2.6)
 | 
			
		||||
 | 
			
		||||
functools
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
* Homepage: https://github.com/python/cpython/blob/2.7/Lib/functools.py
 | 
			
		||||
* Usage: Used for implementation of total_ordering.
 | 
			
		||||
* Version: Unversioned
 | 
			
		||||
* Note: This is the functools.total_ordering implementation
 | 
			
		||||
  from Python 2.7 backported so we can run on Python 2.6.
 | 
			
		||||
 | 
			
		||||
jinja2
 | 
			
		||||
------
 | 
			
		||||
 | 
			
		||||
@@ -73,14 +64,6 @@
 | 
			
		||||
* Usage: Implements a XML/HTML/XHTML Markup safe string for Python.
 | 
			
		||||
* Version: 1.0
 | 
			
		||||
 | 
			
		||||
orderddict
 | 
			
		||||
----------
 | 
			
		||||
 | 
			
		||||
* Homepage: https://pypi.org/project/ordereddict/
 | 
			
		||||
* Usage: A drop-in substitute for Py2.7's new collections.OrderedDict
 | 
			
		||||
  that works in Python 2.4-2.6.
 | 
			
		||||
* Version: 1.1
 | 
			
		||||
 | 
			
		||||
py
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										47
									
								
								lib/spack/external/functools_backport.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								lib/spack/external/functools_backport.py
									
									
									
									
										vendored
									
									
								
							@@ -1,47 +0,0 @@
 | 
			
		||||
#
 | 
			
		||||
# Backport of Python 2.7's total_ordering.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
def total_ordering(cls):
 | 
			
		||||
    """Class decorator that fills in missing ordering methods"""
 | 
			
		||||
    convert = {
 | 
			
		||||
        '__lt__': [('__gt__', lambda self, other: not (self < other or self == other)),
 | 
			
		||||
                   ('__le__', lambda self, other: self < other or self == other),
 | 
			
		||||
                   ('__ge__', lambda self, other: not self < other)],
 | 
			
		||||
        '__le__': [('__ge__', lambda self, other: not self <= other or self == other),
 | 
			
		||||
                   ('__lt__', lambda self, other: self <= other and not self == other),
 | 
			
		||||
                   ('__gt__', lambda self, other: not self <= other)],
 | 
			
		||||
        '__gt__': [('__lt__', lambda self, other: not (self > other or self == other)),
 | 
			
		||||
                   ('__ge__', lambda self, other: self > other or self == other),
 | 
			
		||||
                   ('__le__', lambda self, other: not self > other)],
 | 
			
		||||
        '__ge__': [('__le__', lambda self, other: (not self >= other) or self == other),
 | 
			
		||||
                   ('__gt__', lambda self, other: self >= other and not self == other),
 | 
			
		||||
                   ('__lt__', lambda self, other: not self >= other)]
 | 
			
		||||
    }
 | 
			
		||||
    roots = set(dir(cls)) & set(convert)
 | 
			
		||||
    if not roots:
 | 
			
		||||
        raise ValueError('must define at least one ordering operation: < > <= >=')
 | 
			
		||||
    root = max(roots)       # prefer __lt__ to __le__ to __gt__ to __ge__
 | 
			
		||||
    for opname, opfunc in convert[root]:
 | 
			
		||||
        if opname not in roots:
 | 
			
		||||
            opfunc.__name__ = opname
 | 
			
		||||
            opfunc.__doc__ = getattr(int, opname).__doc__
 | 
			
		||||
            setattr(cls, opname, opfunc)
 | 
			
		||||
    return cls
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@total_ordering
 | 
			
		||||
class reverse_order(object):
 | 
			
		||||
    """Helper for creating key functions.
 | 
			
		||||
 | 
			
		||||
       This is a wrapper that inverts the sense of the natural
 | 
			
		||||
       comparisons on the object.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, value):
 | 
			
		||||
        self.value = value
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other):
 | 
			
		||||
        return other.value == self.value
 | 
			
		||||
 | 
			
		||||
    def __lt__(self, other):
 | 
			
		||||
        return other.value < self.value
 | 
			
		||||
							
								
								
									
										22
									
								
								lib/spack/external/ordereddict_backport.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								lib/spack/external/ordereddict_backport.py
									
									
									
									
										vendored
									
									
								
							@@ -1,22 +0,0 @@
 | 
			
		||||
# Copyright 2013-2021 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)
 | 
			
		||||
 | 
			
		||||
"""This file dispatches to the correct implementation of OrderedDict."""
 | 
			
		||||
 | 
			
		||||
# TODO: this file, along with py26/ordereddict.py, can be removed when
 | 
			
		||||
# TODO: support for python 2.6 will be dropped
 | 
			
		||||
 | 
			
		||||
# Removing this import will make python 2.6
 | 
			
		||||
# fail on import of ordereddict
 | 
			
		||||
from __future__ import absolute_import
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
if sys.version_info[:2] == (2, 6):
 | 
			
		||||
    import ordereddict
 | 
			
		||||
    OrderedDict = ordereddict.OrderedDict
 | 
			
		||||
else:
 | 
			
		||||
    import collections
 | 
			
		||||
    OrderedDict = collections.OrderedDict
 | 
			
		||||
							
								
								
									
										127
									
								
								lib/spack/external/py26/ordereddict.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										127
									
								
								lib/spack/external/py26/ordereddict.py
									
									
									
									
										vendored
									
									
								
							@@ -1,127 +0,0 @@
 | 
			
		||||
# Copyright (c) 2009 Raymond Hettinger
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person
 | 
			
		||||
# obtaining a copy of this software and associated documentation files
 | 
			
		||||
# (the "Software"), to deal in the Software without restriction,
 | 
			
		||||
# including without limitation the rights to use, copy, modify, merge,
 | 
			
		||||
# publish, distribute, sublicense, and/or sell copies of the Software,
 | 
			
		||||
# and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
# subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
#     The above copyright notice and this permission notice shall be
 | 
			
		||||
#     included in all copies or substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
#     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
#     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 | 
			
		||||
#     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
#     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 | 
			
		||||
#     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | 
			
		||||
#     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
#     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | 
			
		||||
#     OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
from UserDict import DictMixin
 | 
			
		||||
 | 
			
		||||
class OrderedDict(dict, DictMixin):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwds):
 | 
			
		||||
        if len(args) > 1:
 | 
			
		||||
            raise TypeError('expected at most 1 arguments, got %d' % len(args))
 | 
			
		||||
        try:
 | 
			
		||||
            self.__end
 | 
			
		||||
        except AttributeError:
 | 
			
		||||
            self.clear()
 | 
			
		||||
        self.update(*args, **kwds)
 | 
			
		||||
 | 
			
		||||
    def clear(self):
 | 
			
		||||
        self.__end = end = []
 | 
			
		||||
        end += [None, end, end]         # sentinel node for doubly linked list
 | 
			
		||||
        self.__map = {}                 # key --> [key, prev, next]
 | 
			
		||||
        dict.clear(self)
 | 
			
		||||
 | 
			
		||||
    def __setitem__(self, key, value):
 | 
			
		||||
        if key not in self:
 | 
			
		||||
            end = self.__end
 | 
			
		||||
            curr = end[1]
 | 
			
		||||
            curr[2] = end[1] = self.__map[key] = [key, curr, end]
 | 
			
		||||
        dict.__setitem__(self, key, value)
 | 
			
		||||
 | 
			
		||||
    def __delitem__(self, key):
 | 
			
		||||
        dict.__delitem__(self, key)
 | 
			
		||||
        key, prev, next = self.__map.pop(key)
 | 
			
		||||
        prev[2] = next
 | 
			
		||||
        next[1] = prev
 | 
			
		||||
 | 
			
		||||
    def __iter__(self):
 | 
			
		||||
        end = self.__end
 | 
			
		||||
        curr = end[2]
 | 
			
		||||
        while curr is not end:
 | 
			
		||||
            yield curr[0]
 | 
			
		||||
            curr = curr[2]
 | 
			
		||||
 | 
			
		||||
    def __reversed__(self):
 | 
			
		||||
        end = self.__end
 | 
			
		||||
        curr = end[1]
 | 
			
		||||
        while curr is not end:
 | 
			
		||||
            yield curr[0]
 | 
			
		||||
            curr = curr[1]
 | 
			
		||||
 | 
			
		||||
    def popitem(self, last=True):
 | 
			
		||||
        if not self:
 | 
			
		||||
            raise KeyError('dictionary is empty')
 | 
			
		||||
        if last:
 | 
			
		||||
            key = reversed(self).next()
 | 
			
		||||
        else:
 | 
			
		||||
            key = iter(self).next()
 | 
			
		||||
        value = self.pop(key)
 | 
			
		||||
        return key, value
 | 
			
		||||
 | 
			
		||||
    def __reduce__(self):
 | 
			
		||||
        items = [[k, self[k]] for k in self]
 | 
			
		||||
        tmp = self.__map, self.__end
 | 
			
		||||
        del self.__map, self.__end
 | 
			
		||||
        inst_dict = vars(self).copy()
 | 
			
		||||
        self.__map, self.__end = tmp
 | 
			
		||||
        if inst_dict:
 | 
			
		||||
            return (self.__class__, (items,), inst_dict)
 | 
			
		||||
        return self.__class__, (items,)
 | 
			
		||||
 | 
			
		||||
    def keys(self):
 | 
			
		||||
        return list(self)
 | 
			
		||||
 | 
			
		||||
    setdefault = DictMixin.setdefault
 | 
			
		||||
    update = DictMixin.update
 | 
			
		||||
    pop = DictMixin.pop
 | 
			
		||||
    values = DictMixin.values
 | 
			
		||||
    items = DictMixin.items
 | 
			
		||||
    iterkeys = DictMixin.iterkeys
 | 
			
		||||
    itervalues = DictMixin.itervalues
 | 
			
		||||
    iteritems = DictMixin.iteritems
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        if not self:
 | 
			
		||||
            return '%s()' % (self.__class__.__name__,)
 | 
			
		||||
        return '%s(%r)' % (self.__class__.__name__, self.items())
 | 
			
		||||
 | 
			
		||||
    def copy(self):
 | 
			
		||||
        return self.__class__(self)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def fromkeys(cls, iterable, value=None):
 | 
			
		||||
        d = cls()
 | 
			
		||||
        for key in iterable:
 | 
			
		||||
            d[key] = value
 | 
			
		||||
        return d
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other):
 | 
			
		||||
        if isinstance(other, OrderedDict):
 | 
			
		||||
            if len(self) != len(other):
 | 
			
		||||
                return False
 | 
			
		||||
            for p, q in  zip(self.items(), other.items()):
 | 
			
		||||
                if p != q:
 | 
			
		||||
                    return False
 | 
			
		||||
            return True
 | 
			
		||||
        return dict.__eq__(self, other)
 | 
			
		||||
 | 
			
		||||
    def __ne__(self, other):
 | 
			
		||||
        return not self == other
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
from __future__ import absolute_import, division, print_function
 | 
			
		||||
 | 
			
		||||
import collections
 | 
			
		||||
import inspect
 | 
			
		||||
import sys
 | 
			
		||||
import warnings
 | 
			
		||||
@@ -21,9 +22,6 @@
 | 
			
		||||
from _pytest.outcomes import fail, TEST_OUTCOME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from ordereddict_backport import OrderedDict
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def pytest_sessionstart(session):
 | 
			
		||||
    import _pytest.python
 | 
			
		||||
    scopename2class.update({
 | 
			
		||||
@@ -165,7 +163,7 @@ def reorder_items(items):
 | 
			
		||||
    for scopenum in range(0, scopenum_function):
 | 
			
		||||
        argkeys_cache[scopenum] = d = {}
 | 
			
		||||
        for item in items:
 | 
			
		||||
            keys = OrderedDict.fromkeys(get_parametrized_fixture_keys(item, scopenum))
 | 
			
		||||
            keys = collections.OrderedDict.fromkeys(get_parametrized_fixture_keys(item, scopenum))
 | 
			
		||||
            if keys:
 | 
			
		||||
                d[item] = keys
 | 
			
		||||
    return reorder_items_atscope(items, set(), argkeys_cache, 0)
 | 
			
		||||
@@ -200,7 +198,7 @@ def slice_items(items, ignore, scoped_argkeys_cache):
 | 
			
		||||
        for i, item in enumerate(it):
 | 
			
		||||
            argkeys = scoped_argkeys_cache.get(item)
 | 
			
		||||
            if argkeys is not None:
 | 
			
		||||
                newargkeys = OrderedDict.fromkeys(k for k in argkeys if k not in ignore)
 | 
			
		||||
                newargkeys = collections.OrderedDict.fromkeys(k for k in argkeys if k not in ignore)
 | 
			
		||||
                if newargkeys:  # found a slicing key
 | 
			
		||||
                    slicing_argkey, _ = newargkeys.popitem()
 | 
			
		||||
                    items_before = items[:i]
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
class Barrier:
 | 
			
		||||
    """Simple reusable semaphore barrier.
 | 
			
		||||
 | 
			
		||||
    Python 2.6 doesn't have multiprocessing barriers so we implement this.
 | 
			
		||||
    Python 2 doesn't have multiprocessing barriers so we implement this.
 | 
			
		||||
 | 
			
		||||
    See http://greenteapress.com/semaphores/downey08semaphores.pdf, p. 41.
 | 
			
		||||
    """
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
 | 
			
		||||
 | 
			
		||||
import codecs
 | 
			
		||||
import collections
 | 
			
		||||
import hashlib
 | 
			
		||||
import json
 | 
			
		||||
import os
 | 
			
		||||
@@ -15,7 +16,6 @@
 | 
			
		||||
from contextlib import closing
 | 
			
		||||
 | 
			
		||||
import ruamel.yaml as yaml
 | 
			
		||||
from ordereddict_backport import OrderedDict
 | 
			
		||||
from six.moves.urllib.error import HTTPError, URLError
 | 
			
		||||
 | 
			
		||||
import llnl.util.lang
 | 
			
		||||
@@ -1278,8 +1278,8 @@ def relocate_package(spec, allow_root):
 | 
			
		||||
    # Spurious replacements (e.g. sbang) will cause issues with binaries
 | 
			
		||||
    # For example, the new sbang can be longer than the old one.
 | 
			
		||||
    # Hence 2 dictionaries are maintained here.
 | 
			
		||||
    prefix_to_prefix_text = OrderedDict({})
 | 
			
		||||
    prefix_to_prefix_bin = OrderedDict({})
 | 
			
		||||
    prefix_to_prefix_text = collections.OrderedDict()
 | 
			
		||||
    prefix_to_prefix_bin = collections.OrderedDict()
 | 
			
		||||
 | 
			
		||||
    if old_sbang_install_path:
 | 
			
		||||
        install_path = spack.hooks.sbang.sbang_install_path()
 | 
			
		||||
 
 | 
			
		||||
@@ -12,15 +12,10 @@
 | 
			
		||||
import os.path
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
import sysconfig
 | 
			
		||||
 | 
			
		||||
import six
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    import sysconfig  # novm
 | 
			
		||||
except ImportError:
 | 
			
		||||
    # Not supported on Python 2.6
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
import archspec.cpu
 | 
			
		||||
 | 
			
		||||
import llnl.util.filesystem as fs
 | 
			
		||||
 
 | 
			
		||||
@@ -46,9 +46,8 @@
 | 
			
		||||
    r'^lib/spack/docs/.*\.py$',
 | 
			
		||||
    r'^lib/spack/docs/spack.yaml$',
 | 
			
		||||
 | 
			
		||||
    # 2 files in external
 | 
			
		||||
    # 1 file in external
 | 
			
		||||
    r'^lib/spack/external/__init__.py$',
 | 
			
		||||
    r'^lib/spack/external/ordereddict_backport.py$',
 | 
			
		||||
 | 
			
		||||
    # shell scripts in share
 | 
			
		||||
    r'^share/spack/.*\.sh$',
 | 
			
		||||
 
 | 
			
		||||
@@ -16,14 +16,13 @@
 | 
			
		||||
"""
 | 
			
		||||
from __future__ import print_function
 | 
			
		||||
 | 
			
		||||
import functools
 | 
			
		||||
import os.path
 | 
			
		||||
import platform
 | 
			
		||||
import tempfile
 | 
			
		||||
from contextlib import contextmanager
 | 
			
		||||
from itertools import chain
 | 
			
		||||
 | 
			
		||||
from functools_backport import reverse_order
 | 
			
		||||
 | 
			
		||||
import archspec.cpu
 | 
			
		||||
 | 
			
		||||
import llnl.util.filesystem as fs
 | 
			
		||||
@@ -48,6 +47,23 @@
 | 
			
		||||
_abi = llnl.util.lang.Singleton(lambda: spack.abi.ABI())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@functools.total_ordering
 | 
			
		||||
class reverse_order(object):
 | 
			
		||||
    """Helper for creating key functions.
 | 
			
		||||
 | 
			
		||||
       This is a wrapper that inverts the sense of the natural
 | 
			
		||||
       comparisons on the object.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, value):
 | 
			
		||||
        self.value = value
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other):
 | 
			
		||||
        return other.value == self.value
 | 
			
		||||
 | 
			
		||||
    def __lt__(self, other):
 | 
			
		||||
        return other.value < self.value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Concretizer(object):
 | 
			
		||||
    """You can subclass this class to override some of the default
 | 
			
		||||
       concretization strategies, or you can override all of them.
 | 
			
		||||
@@ -130,11 +146,11 @@ def _valid_virtuals_and_externals(self, spec):
 | 
			
		||||
 | 
			
		||||
        # Use a sort key to order the results
 | 
			
		||||
        return sorted(usable, key=lambda spec: (
 | 
			
		||||
            not spec.external,                            # prefer externals
 | 
			
		||||
            pref_key(spec),                               # respect prefs
 | 
			
		||||
            spec.name,                                    # group by name
 | 
			
		||||
            reverse_order(spec.versions),                 # latest version
 | 
			
		||||
            spec                                          # natural order
 | 
			
		||||
            not spec.external,             # prefer externals
 | 
			
		||||
            pref_key(spec),                # respect prefs
 | 
			
		||||
            spec.name,                     # group by name
 | 
			
		||||
            reverse_order(spec.versions),  # latest version
 | 
			
		||||
            spec                           # natural order
 | 
			
		||||
        ))
 | 
			
		||||
 | 
			
		||||
    def choose_virtual_or_external(self, spec):
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,6 @@
 | 
			
		||||
from typing import List  # novm
 | 
			
		||||
 | 
			
		||||
import ruamel.yaml as yaml
 | 
			
		||||
from ordereddict_backport import OrderedDict
 | 
			
		||||
from ruamel.yaml.error import MarkedYAMLError
 | 
			
		||||
from six import iteritems
 | 
			
		||||
 | 
			
		||||
@@ -401,7 +400,7 @@ def __init__(self, *scopes):
 | 
			
		||||
                Configuration, ordered from lowest to highest precedence
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.scopes = OrderedDict()
 | 
			
		||||
        self.scopes = collections.OrderedDict()
 | 
			
		||||
        for scope in scopes:
 | 
			
		||||
            self.push_scope(scope)
 | 
			
		||||
        self.format_updates = collections.defaultdict(list)
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,6 @@
 | 
			
		||||
 | 
			
		||||
import ruamel.yaml as yaml
 | 
			
		||||
import six
 | 
			
		||||
from ordereddict_backport import OrderedDict
 | 
			
		||||
 | 
			
		||||
import llnl.util.filesystem as fs
 | 
			
		||||
import llnl.util.tty as tty
 | 
			
		||||
@@ -318,7 +317,11 @@ def to_dict(self):
 | 
			
		||||
            # projections guaranteed to be ordered dict if true-ish
 | 
			
		||||
            # for python2.6, may be syaml or ruamel.yaml implementation
 | 
			
		||||
            # so we have to check for both
 | 
			
		||||
            types = (OrderedDict, syaml.syaml_dict, yaml.comments.CommentedMap)
 | 
			
		||||
            types = (
 | 
			
		||||
                collections.OrderedDict,
 | 
			
		||||
                syaml.syaml_dict,
 | 
			
		||||
                yaml.comments.CommentedMap
 | 
			
		||||
            )
 | 
			
		||||
            assert isinstance(self.projections, types)
 | 
			
		||||
            ret['projections'] = self.projections
 | 
			
		||||
        if self.select:
 | 
			
		||||
@@ -638,7 +641,7 @@ def _read_manifest(self, f, raw_yaml=None):
 | 
			
		||||
        else:
 | 
			
		||||
            self.raw_yaml, self.yaml = _read_yaml(f)
 | 
			
		||||
 | 
			
		||||
        self.spec_lists = OrderedDict()
 | 
			
		||||
        self.spec_lists = collections.OrderedDict()
 | 
			
		||||
 | 
			
		||||
        for item in config_dict(self.yaml).get('definitions', []):
 | 
			
		||||
            entry = copy.deepcopy(item)
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
"""Service functions and classes to implement the hooks
 | 
			
		||||
for Spack's command extensions.
 | 
			
		||||
"""
 | 
			
		||||
import importlib
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
@@ -98,9 +99,7 @@ def ensure_package_creation(name):
 | 
			
		||||
    ensure_package_creation(extension)
 | 
			
		||||
    ensure_package_creation(extension + '.cmd')
 | 
			
		||||
 | 
			
		||||
    # TODO: Upon removal of support for Python 2.6 substitute the call
 | 
			
		||||
    # TODO: below with importlib.import_module(module_name)
 | 
			
		||||
    module = llnl.util.lang.load_module_from_file(module_name, cmd_path)
 | 
			
		||||
    module = importlib.import_module(module_name)
 | 
			
		||||
    sys.modules[module_name] = module
 | 
			
		||||
 | 
			
		||||
    return module
 | 
			
		||||
 
 | 
			
		||||
@@ -3,14 +3,13 @@
 | 
			
		||||
#
 | 
			
		||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
 | 
			
		||||
 | 
			
		||||
import collections
 | 
			
		||||
import functools as ft
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
import shutil
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
from ordereddict_backport import OrderedDict
 | 
			
		||||
 | 
			
		||||
from llnl.util import tty
 | 
			
		||||
from llnl.util.filesystem import mkdirp, remove_dead_links, remove_empty_directories
 | 
			
		||||
from llnl.util.lang import index_by, match_predicate
 | 
			
		||||
@@ -79,7 +78,7 @@ def view_copy(src, dst, view, spec=None):
 | 
			
		||||
        orig_sbang = '#!/bin/bash {0}/bin/sbang'.format(spack.paths.spack_root)
 | 
			
		||||
        new_sbang = sbang.sbang_shebang_line()
 | 
			
		||||
 | 
			
		||||
        prefix_to_projection = OrderedDict({
 | 
			
		||||
        prefix_to_projection = collections.OrderedDict({
 | 
			
		||||
            spec.prefix: view.get_projection_for_spec(spec)})
 | 
			
		||||
 | 
			
		||||
        for dep in spec.traverse():
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@
 | 
			
		||||
where spack is run is not connected to the internet, it allows spack
 | 
			
		||||
to download packages directly from a mirror (e.g., on an intranet).
 | 
			
		||||
"""
 | 
			
		||||
import collections
 | 
			
		||||
import operator
 | 
			
		||||
import os
 | 
			
		||||
import os.path
 | 
			
		||||
@@ -19,7 +20,6 @@
 | 
			
		||||
 | 
			
		||||
import ruamel.yaml.error as yaml_error
 | 
			
		||||
import six
 | 
			
		||||
from ordereddict_backport import OrderedDict
 | 
			
		||||
 | 
			
		||||
if sys.version_info >= (3, 5):
 | 
			
		||||
    from collections.abc import Mapping  # novm
 | 
			
		||||
@@ -230,7 +230,7 @@ class MirrorCollection(Mapping):
 | 
			
		||||
    """A mapping of mirror names to mirrors."""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, mirrors=None, scope=None):
 | 
			
		||||
        self._mirrors = OrderedDict(
 | 
			
		||||
        self._mirrors = collections.OrderedDict(
 | 
			
		||||
            (name, Mirror.from_dict(mirror, name))
 | 
			
		||||
            for name, mirror in (
 | 
			
		||||
                mirrors.items() if mirrors is not None else
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,6 @@
 | 
			
		||||
from typing import Any, Callable, Dict, List, Optional  # novm
 | 
			
		||||
 | 
			
		||||
import six
 | 
			
		||||
from ordereddict_backport import OrderedDict
 | 
			
		||||
 | 
			
		||||
import llnl.util.filesystem as fsys
 | 
			
		||||
import llnl.util.tty as tty
 | 
			
		||||
@@ -902,7 +901,7 @@ def version_urls(self):
 | 
			
		||||
        explicitly defined ``url`` argument. So, this list may be empty
 | 
			
		||||
        if a package only defines ``url`` at the top level.
 | 
			
		||||
        """
 | 
			
		||||
        version_urls = OrderedDict()
 | 
			
		||||
        version_urls = collections.OrderedDict()
 | 
			
		||||
        for v, args in sorted(self.versions.items()):
 | 
			
		||||
            if 'url' in args:
 | 
			
		||||
                version_urls[v] = args['url']
 | 
			
		||||
 
 | 
			
		||||
@@ -2,15 +2,14 @@
 | 
			
		||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
 | 
			
		||||
#
 | 
			
		||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
 | 
			
		||||
import collections
 | 
			
		||||
import multiprocessing.pool
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
import shutil
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
 | 
			
		||||
import macholib.mach_o
 | 
			
		||||
import macholib.MachO
 | 
			
		||||
from ordereddict_backport import OrderedDict
 | 
			
		||||
 | 
			
		||||
import llnl.util.lang
 | 
			
		||||
import llnl.util.tty as tty
 | 
			
		||||
@@ -807,7 +806,7 @@ def relocate_text(files, prefixes, concurrency=32):
 | 
			
		||||
    # orig_sbang = '#!/bin/bash {0}/bin/sbang'.format(orig_spack)
 | 
			
		||||
    # new_sbang = '#!/bin/bash {0}/bin/sbang'.format(new_spack)
 | 
			
		||||
 | 
			
		||||
    compiled_prefixes = OrderedDict({})
 | 
			
		||||
    compiled_prefixes = collections.OrderedDict({})
 | 
			
		||||
 | 
			
		||||
    for orig_prefix, new_prefix in prefixes.items():
 | 
			
		||||
        if orig_prefix != new_prefix:
 | 
			
		||||
@@ -845,7 +844,7 @@ def relocate_text_bin(binaries, prefixes, concurrency=32):
 | 
			
		||||
    Raises:
 | 
			
		||||
      BinaryTextReplaceError: when the new path is longer than the old path
 | 
			
		||||
    """
 | 
			
		||||
    byte_prefixes = OrderedDict({})
 | 
			
		||||
    byte_prefixes = collections.OrderedDict({})
 | 
			
		||||
 | 
			
		||||
    for orig_prefix, new_prefix in prefixes.items():
 | 
			
		||||
        if orig_prefix != new_prefix:
 | 
			
		||||
@@ -1032,7 +1031,7 @@ def fixup_macos_rpath(root, filename):
 | 
			
		||||
    # Convert rpaths list to (name -> number of occurrences)
 | 
			
		||||
    add_rpaths = set()
 | 
			
		||||
    del_rpaths = set()
 | 
			
		||||
    rpaths = defaultdict(int)
 | 
			
		||||
    rpaths = collections.defaultdict(int)
 | 
			
		||||
    for rpath in rpath_list:
 | 
			
		||||
        rpaths[rpath] += 1
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,9 +2,8 @@
 | 
			
		||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
 | 
			
		||||
#
 | 
			
		||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import codecs
 | 
			
		||||
import collections
 | 
			
		||||
import hashlib
 | 
			
		||||
import os.path
 | 
			
		||||
import platform
 | 
			
		||||
@@ -13,7 +12,6 @@
 | 
			
		||||
import time
 | 
			
		||||
import xml.sax.saxutils
 | 
			
		||||
 | 
			
		||||
from ordereddict_backport import OrderedDict
 | 
			
		||||
from six import iteritems, text_type
 | 
			
		||||
from six.moves.urllib.parse import urlencode
 | 
			
		||||
from six.moves.urllib.request import HTTPHandler, Request, build_opener
 | 
			
		||||
@@ -96,7 +94,7 @@ def __init__(self, args):
 | 
			
		||||
            buildstamp_format = "%Y%m%d-%H%M-{0}".format(args.cdash_track)
 | 
			
		||||
            self.buildstamp = time.strftime(buildstamp_format,
 | 
			
		||||
                                            time.localtime(self.endtime))
 | 
			
		||||
        self.buildIds = OrderedDict()
 | 
			
		||||
        self.buildIds = collections.OrderedDict()
 | 
			
		||||
        self.revision = ''
 | 
			
		||||
        git = which('git')
 | 
			
		||||
        with working_dir(spack.paths.spack_root):
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@
 | 
			
		||||
#
 | 
			
		||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
@@ -69,14 +68,6 @@ def test_url_with_no_version_fails():
 | 
			
		||||
        url('parse', 'http://www.netlib.org/voronoi/triangle.zip')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
skip_python_26 = pytest.mark.skipif(
 | 
			
		||||
    sys.version_info < (2, 7),
 | 
			
		||||
    reason="Python 2.6 tests are run in a container, where "
 | 
			
		||||
           "networking is super slow"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@skip_python_26
 | 
			
		||||
def test_url_list(mock_packages):
 | 
			
		||||
    out = url('list')
 | 
			
		||||
    total_urls = len(out.split('\n'))
 | 
			
		||||
@@ -106,7 +97,6 @@ def test_url_list(mock_packages):
 | 
			
		||||
    assert 0 < correct_version_urls < total_urls
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@skip_python_26
 | 
			
		||||
def test_url_summary(mock_packages):
 | 
			
		||||
    """Test the URL summary command."""
 | 
			
		||||
    # test url_summary, the internal function that does the work
 | 
			
		||||
@@ -133,7 +123,6 @@ def test_url_summary(mock_packages):
 | 
			
		||||
    assert out_correct_versions == correct_versions
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@skip_python_26
 | 
			
		||||
def test_url_stats(capfd, mock_packages):
 | 
			
		||||
    with capfd.disabled():
 | 
			
		||||
        output = url('stats')
 | 
			
		||||
 
 | 
			
		||||
@@ -429,10 +429,6 @@ def mock_shell_v_v_no_termios(proc, ctl, **kwargs):
 | 
			
		||||
    (mock_shell_v_v, nullcontext),
 | 
			
		||||
    (mock_shell_v_v_no_termios, no_termios),
 | 
			
		||||
])
 | 
			
		||||
@pytest.mark.skipif(
 | 
			
		||||
    sys.version_info < (2, 7),
 | 
			
		||||
    reason="Python 2.6 tests are run in a container, where this fails often"
 | 
			
		||||
)
 | 
			
		||||
def test_foreground_background_output(
 | 
			
		||||
        test_fn, capfd, termios_on_or_off, tmpdir):
 | 
			
		||||
    """Tests hitting 'v' toggles output, and that force_echo works."""
 | 
			
		||||
 
 | 
			
		||||
@@ -2,9 +2,9 @@
 | 
			
		||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
 | 
			
		||||
#
 | 
			
		||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
 | 
			
		||||
import collections
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
import ordereddict_backport
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
import llnl.util.tty as tty
 | 
			
		||||
@@ -152,7 +152,7 @@ def test_get_header():
 | 
			
		||||
    # If lookup has to fallback to fuzzy matching and there are more than one
 | 
			
		||||
    # fuzzy match, the result depends on the internal ordering of the given
 | 
			
		||||
    # mapping
 | 
			
		||||
    headers = ordereddict_backport.OrderedDict()
 | 
			
		||||
    headers = collections.OrderedDict()
 | 
			
		||||
    headers['Content-type'] = 'text/plain'
 | 
			
		||||
    headers['contentType'] = 'text/html'
 | 
			
		||||
 | 
			
		||||
@@ -161,7 +161,7 @@ def test_get_header():
 | 
			
		||||
    assert(spack.util.web.get_header(headers, 'CONTENT_TYPE') == 'text/html')
 | 
			
		||||
 | 
			
		||||
    # Same as above, but different ordering
 | 
			
		||||
    headers = ordereddict_backport.OrderedDict()
 | 
			
		||||
    headers = collections.OrderedDict()
 | 
			
		||||
    headers['contentType'] = 'text/html'
 | 
			
		||||
    headers['Content-type'] = 'text/plain'
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,10 +2,8 @@
 | 
			
		||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
 | 
			
		||||
#
 | 
			
		||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
 | 
			
		||||
 | 
			
		||||
"""Infrastructure used by tests for mocking packages and repos."""
 | 
			
		||||
 | 
			
		||||
import ordereddict_backport
 | 
			
		||||
import collections
 | 
			
		||||
 | 
			
		||||
import spack.provider_index
 | 
			
		||||
import spack.util.naming
 | 
			
		||||
@@ -149,7 +147,7 @@ class MockPackage(MockPackageBase):
 | 
			
		||||
        MockPackage._repo = self
 | 
			
		||||
 | 
			
		||||
        # set up dependencies
 | 
			
		||||
        MockPackage.dependencies = ordereddict_backport.OrderedDict()
 | 
			
		||||
        MockPackage.dependencies = collections.OrderedDict()
 | 
			
		||||
        for dep, dtype in zip(dependencies, dependency_types):
 | 
			
		||||
            d = Dependency(MockPackage, Spec(dep.name), type=dtype)
 | 
			
		||||
            if not conditions or dep.name not in conditions:
 | 
			
		||||
 
 | 
			
		||||
@@ -12,13 +12,13 @@
 | 
			
		||||
  default unorderd dict.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
import collections
 | 
			
		||||
import ctypes
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
from typing import List  # novm
 | 
			
		||||
 | 
			
		||||
import ruamel.yaml as yaml
 | 
			
		||||
from ordereddict_backport import OrderedDict
 | 
			
		||||
from ruamel.yaml import RoundTripDumper, RoundTripLoader
 | 
			
		||||
from six import StringIO, string_types
 | 
			
		||||
 | 
			
		||||
@@ -39,7 +39,7 @@
 | 
			
		||||
# Also, use OrderedDict instead of just dict.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class syaml_dict(OrderedDict):
 | 
			
		||||
class syaml_dict(collections.OrderedDict):
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        mappings = ('%r: %r' % (k, v) for k, v in self.items())
 | 
			
		||||
        return '{%s}' % ', '.join(mappings)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user