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:
Massimiliano Culpo 2021-11-23 18:06:17 +01:00 committed by GitHub
parent 812663de62
commit fa7189b480
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 66 additions and 327 deletions

View file

@ -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

View file

@ -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)

View file

@ -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:

View file

@ -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

1 Name Supported Versions Notes Requirement Reason
2 Python 2.6/2.7/3.5-3.9 2.7/3.5-3.9 Interpreter for Spack
3 C/C++ Compilers Building software
4 make Build software
5 patch Build software

View file

@ -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
--

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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]

View file

@ -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.
"""

View file

@ -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()

View file

@ -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

View file

@ -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$',

View file

@ -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):

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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():

View file

@ -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

View file

@ -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']

View file

@ -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

View file

@ -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):

View file

@ -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')

View file

@ -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."""

View file

@ -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'

View file

@ -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:

View file

@ -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)