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:
parent
812663de62
commit
fa7189b480
27 changed files with 66 additions and 327 deletions
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 pip
|
||||||
pip install --upgrade vermin
|
pip install --upgrade vermin
|
||||||
- name: vermin (Spack's Core)
|
- 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)
|
- 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
|
# Run style checks on the files that have been changed
|
||||||
style:
|
style:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -193,39 +193,6 @@ jobs:
|
||||||
if: ${{ needs.changes.outputs.with_coverage == 'true' }}
|
if: ${{ needs.changes.outputs.with_coverage == 'true' }}
|
||||||
with:
|
with:
|
||||||
flags: shelltests,linux
|
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
|
# Test RHEL8 UBI with platform Python. This job is run
|
||||||
# only on PRs modifying core Spack
|
# only on PRs modifying core Spack
|
||||||
|
|
|
@ -33,11 +33,11 @@ import sys
|
||||||
|
|
||||||
min_python3 = (3, 5)
|
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
|
sys.version_info[:2] >= (3, 0) and sys.version_info[:2] < min_python3
|
||||||
):
|
):
|
||||||
v_info = sys.version_info[:3]
|
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
|
msg += "You are running spack with Python %d.%d.%d." % v_info
|
||||||
sys.exit(msg)
|
sys.exit(msg)
|
||||||
|
|
||||||
|
@ -54,8 +54,6 @@ spack_external_libs = os.path.join(spack_lib_path, "external")
|
||||||
|
|
||||||
if sys.version_info[:2] <= (2, 7):
|
if sys.version_info[:2] <= (2, 7):
|
||||||
sys.path.insert(0, os.path.join(spack_external_libs, "py2"))
|
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)
|
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.
|
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:
|
perform 3 types of tests:
|
||||||
|
|
||||||
.. _cmd-spack-unit-test:
|
.. _cmd-spack-unit-test:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
Name, Supported Versions, Notes, Requirement Reason
|
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
|
C/C++ Compilers, , , Building software
|
||||||
make, , , Build software
|
make, , , Build software
|
||||||
patch, , , 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
|
* 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
|
* Version: 1.4.0
|
||||||
* Note: This package has been slightly modified to improve
|
* Note: This package has been slightly modified to improve
|
||||||
error message formatting. See the following commit if the
|
error message formatting. See the following commit if the
|
||||||
|
@ -39,15 +39,6 @@
|
||||||
* Usage: Provides a more stable linux distribution detection.
|
* Usage: Provides a more stable linux distribution detection.
|
||||||
* Version: 1.0.4 (last version supporting Python 2.6)
|
* 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
|
jinja2
|
||||||
------
|
------
|
||||||
|
|
||||||
|
@ -73,14 +64,6 @@
|
||||||
* Usage: Implements a XML/HTML/XHTML Markup safe string for Python.
|
* Usage: Implements a XML/HTML/XHTML Markup safe string for Python.
|
||||||
* Version: 1.0
|
* 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
|
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
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
import collections
|
||||||
import inspect
|
import inspect
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
@ -21,9 +22,6 @@
|
||||||
from _pytest.outcomes import fail, TEST_OUTCOME
|
from _pytest.outcomes import fail, TEST_OUTCOME
|
||||||
|
|
||||||
|
|
||||||
from ordereddict_backport import OrderedDict
|
|
||||||
|
|
||||||
|
|
||||||
def pytest_sessionstart(session):
|
def pytest_sessionstart(session):
|
||||||
import _pytest.python
|
import _pytest.python
|
||||||
scopename2class.update({
|
scopename2class.update({
|
||||||
|
@ -165,7 +163,7 @@ def reorder_items(items):
|
||||||
for scopenum in range(0, scopenum_function):
|
for scopenum in range(0, scopenum_function):
|
||||||
argkeys_cache[scopenum] = d = {}
|
argkeys_cache[scopenum] = d = {}
|
||||||
for item in items:
|
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:
|
if keys:
|
||||||
d[item] = keys
|
d[item] = keys
|
||||||
return reorder_items_atscope(items, set(), argkeys_cache, 0)
|
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):
|
for i, item in enumerate(it):
|
||||||
argkeys = scoped_argkeys_cache.get(item)
|
argkeys = scoped_argkeys_cache.get(item)
|
||||||
if argkeys is not None:
|
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
|
if newargkeys: # found a slicing key
|
||||||
slicing_argkey, _ = newargkeys.popitem()
|
slicing_argkey, _ = newargkeys.popitem()
|
||||||
items_before = items[:i]
|
items_before = items[:i]
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
class Barrier:
|
class Barrier:
|
||||||
"""Simple reusable semaphore 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.
|
See http://greenteapress.com/semaphores/downey08semaphores.pdf, p. 41.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
import codecs
|
import codecs
|
||||||
|
import collections
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
@ -15,7 +16,6 @@
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
import ruamel.yaml as yaml
|
import ruamel.yaml as yaml
|
||||||
from ordereddict_backport import OrderedDict
|
|
||||||
from six.moves.urllib.error import HTTPError, URLError
|
from six.moves.urllib.error import HTTPError, URLError
|
||||||
|
|
||||||
import llnl.util.lang
|
import llnl.util.lang
|
||||||
|
@ -1278,8 +1278,8 @@ def relocate_package(spec, allow_root):
|
||||||
# Spurious replacements (e.g. sbang) will cause issues with binaries
|
# Spurious replacements (e.g. sbang) will cause issues with binaries
|
||||||
# For example, the new sbang can be longer than the old one.
|
# For example, the new sbang can be longer than the old one.
|
||||||
# Hence 2 dictionaries are maintained here.
|
# Hence 2 dictionaries are maintained here.
|
||||||
prefix_to_prefix_text = OrderedDict({})
|
prefix_to_prefix_text = collections.OrderedDict()
|
||||||
prefix_to_prefix_bin = OrderedDict({})
|
prefix_to_prefix_bin = collections.OrderedDict()
|
||||||
|
|
||||||
if old_sbang_install_path:
|
if old_sbang_install_path:
|
||||||
install_path = spack.hooks.sbang.sbang_install_path()
|
install_path = spack.hooks.sbang.sbang_install_path()
|
||||||
|
|
|
@ -12,15 +12,10 @@
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import sysconfig
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
try:
|
|
||||||
import sysconfig # novm
|
|
||||||
except ImportError:
|
|
||||||
# Not supported on Python 2.6
|
|
||||||
pass
|
|
||||||
|
|
||||||
import archspec.cpu
|
import archspec.cpu
|
||||||
|
|
||||||
import llnl.util.filesystem as fs
|
import llnl.util.filesystem as fs
|
||||||
|
|
|
@ -46,9 +46,8 @@
|
||||||
r'^lib/spack/docs/.*\.py$',
|
r'^lib/spack/docs/.*\.py$',
|
||||||
r'^lib/spack/docs/spack.yaml$',
|
r'^lib/spack/docs/spack.yaml$',
|
||||||
|
|
||||||
# 2 files in external
|
# 1 file in external
|
||||||
r'^lib/spack/external/__init__.py$',
|
r'^lib/spack/external/__init__.py$',
|
||||||
r'^lib/spack/external/ordereddict_backport.py$',
|
|
||||||
|
|
||||||
# shell scripts in share
|
# shell scripts in share
|
||||||
r'^share/spack/.*\.sh$',
|
r'^share/spack/.*\.sh$',
|
||||||
|
|
|
@ -16,14 +16,13 @@
|
||||||
"""
|
"""
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import functools
|
||||||
import os.path
|
import os.path
|
||||||
import platform
|
import platform
|
||||||
import tempfile
|
import tempfile
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
from functools_backport import reverse_order
|
|
||||||
|
|
||||||
import archspec.cpu
|
import archspec.cpu
|
||||||
|
|
||||||
import llnl.util.filesystem as fs
|
import llnl.util.filesystem as fs
|
||||||
|
@ -48,6 +47,23 @@
|
||||||
_abi = llnl.util.lang.Singleton(lambda: spack.abi.ABI())
|
_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):
|
class Concretizer(object):
|
||||||
"""You can subclass this class to override some of the default
|
"""You can subclass this class to override some of the default
|
||||||
concretization strategies, or you can override all of them.
|
concretization strategies, or you can override all of them.
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
from typing import List # novm
|
from typing import List # novm
|
||||||
|
|
||||||
import ruamel.yaml as yaml
|
import ruamel.yaml as yaml
|
||||||
from ordereddict_backport import OrderedDict
|
|
||||||
from ruamel.yaml.error import MarkedYAMLError
|
from ruamel.yaml.error import MarkedYAMLError
|
||||||
from six import iteritems
|
from six import iteritems
|
||||||
|
|
||||||
|
@ -401,7 +400,7 @@ def __init__(self, *scopes):
|
||||||
Configuration, ordered from lowest to highest precedence
|
Configuration, ordered from lowest to highest precedence
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.scopes = OrderedDict()
|
self.scopes = collections.OrderedDict()
|
||||||
for scope in scopes:
|
for scope in scopes:
|
||||||
self.push_scope(scope)
|
self.push_scope(scope)
|
||||||
self.format_updates = collections.defaultdict(list)
|
self.format_updates = collections.defaultdict(list)
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
|
|
||||||
import ruamel.yaml as yaml
|
import ruamel.yaml as yaml
|
||||||
import six
|
import six
|
||||||
from ordereddict_backport import OrderedDict
|
|
||||||
|
|
||||||
import llnl.util.filesystem as fs
|
import llnl.util.filesystem as fs
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
|
@ -318,7 +317,11 @@ def to_dict(self):
|
||||||
# projections guaranteed to be ordered dict if true-ish
|
# projections guaranteed to be ordered dict if true-ish
|
||||||
# for python2.6, may be syaml or ruamel.yaml implementation
|
# for python2.6, may be syaml or ruamel.yaml implementation
|
||||||
# so we have to check for both
|
# 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)
|
assert isinstance(self.projections, types)
|
||||||
ret['projections'] = self.projections
|
ret['projections'] = self.projections
|
||||||
if self.select:
|
if self.select:
|
||||||
|
@ -638,7 +641,7 @@ def _read_manifest(self, f, raw_yaml=None):
|
||||||
else:
|
else:
|
||||||
self.raw_yaml, self.yaml = _read_yaml(f)
|
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', []):
|
for item in config_dict(self.yaml).get('definitions', []):
|
||||||
entry = copy.deepcopy(item)
|
entry = copy.deepcopy(item)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"""Service functions and classes to implement the hooks
|
"""Service functions and classes to implement the hooks
|
||||||
for Spack's command extensions.
|
for Spack's command extensions.
|
||||||
"""
|
"""
|
||||||
|
import importlib
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
@ -98,9 +99,7 @@ def ensure_package_creation(name):
|
||||||
ensure_package_creation(extension)
|
ensure_package_creation(extension)
|
||||||
ensure_package_creation(extension + '.cmd')
|
ensure_package_creation(extension + '.cmd')
|
||||||
|
|
||||||
# TODO: Upon removal of support for Python 2.6 substitute the call
|
module = importlib.import_module(module_name)
|
||||||
# TODO: below with importlib.import_module(module_name)
|
|
||||||
module = llnl.util.lang.load_module_from_file(module_name, cmd_path)
|
|
||||||
sys.modules[module_name] = module
|
sys.modules[module_name] = module
|
||||||
|
|
||||||
return module
|
return module
|
||||||
|
|
|
@ -3,14 +3,13 @@
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
import collections
|
||||||
import functools as ft
|
import functools as ft
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from ordereddict_backport import OrderedDict
|
|
||||||
|
|
||||||
from llnl.util import tty
|
from llnl.util import tty
|
||||||
from llnl.util.filesystem import mkdirp, remove_dead_links, remove_empty_directories
|
from llnl.util.filesystem import mkdirp, remove_dead_links, remove_empty_directories
|
||||||
from llnl.util.lang import index_by, match_predicate
|
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)
|
orig_sbang = '#!/bin/bash {0}/bin/sbang'.format(spack.paths.spack_root)
|
||||||
new_sbang = sbang.sbang_shebang_line()
|
new_sbang = sbang.sbang_shebang_line()
|
||||||
|
|
||||||
prefix_to_projection = OrderedDict({
|
prefix_to_projection = collections.OrderedDict({
|
||||||
spec.prefix: view.get_projection_for_spec(spec)})
|
spec.prefix: view.get_projection_for_spec(spec)})
|
||||||
|
|
||||||
for dep in spec.traverse():
|
for dep in spec.traverse():
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
where spack is run is not connected to the internet, it allows spack
|
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).
|
to download packages directly from a mirror (e.g., on an intranet).
|
||||||
"""
|
"""
|
||||||
|
import collections
|
||||||
import operator
|
import operator
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
|
@ -19,7 +20,6 @@
|
||||||
|
|
||||||
import ruamel.yaml.error as yaml_error
|
import ruamel.yaml.error as yaml_error
|
||||||
import six
|
import six
|
||||||
from ordereddict_backport import OrderedDict
|
|
||||||
|
|
||||||
if sys.version_info >= (3, 5):
|
if sys.version_info >= (3, 5):
|
||||||
from collections.abc import Mapping # novm
|
from collections.abc import Mapping # novm
|
||||||
|
@ -230,7 +230,7 @@ class MirrorCollection(Mapping):
|
||||||
"""A mapping of mirror names to mirrors."""
|
"""A mapping of mirror names to mirrors."""
|
||||||
|
|
||||||
def __init__(self, mirrors=None, scope=None):
|
def __init__(self, mirrors=None, scope=None):
|
||||||
self._mirrors = OrderedDict(
|
self._mirrors = collections.OrderedDict(
|
||||||
(name, Mirror.from_dict(mirror, name))
|
(name, Mirror.from_dict(mirror, name))
|
||||||
for name, mirror in (
|
for name, mirror in (
|
||||||
mirrors.items() if mirrors is not None else
|
mirrors.items() if mirrors is not None else
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
from typing import Any, Callable, Dict, List, Optional # novm
|
from typing import Any, Callable, Dict, List, Optional # novm
|
||||||
|
|
||||||
import six
|
import six
|
||||||
from ordereddict_backport import OrderedDict
|
|
||||||
|
|
||||||
import llnl.util.filesystem as fsys
|
import llnl.util.filesystem as fsys
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
|
@ -902,7 +901,7 @@ def version_urls(self):
|
||||||
explicitly defined ``url`` argument. So, this list may be empty
|
explicitly defined ``url`` argument. So, this list may be empty
|
||||||
if a package only defines ``url`` at the top level.
|
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()):
|
for v, args in sorted(self.versions.items()):
|
||||||
if 'url' in args:
|
if 'url' in args:
|
||||||
version_urls[v] = args['url']
|
version_urls[v] = args['url']
|
||||||
|
|
|
@ -2,15 +2,14 @@
|
||||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
import collections
|
||||||
import multiprocessing.pool
|
import multiprocessing.pool
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
import macholib.mach_o
|
import macholib.mach_o
|
||||||
import macholib.MachO
|
import macholib.MachO
|
||||||
from ordereddict_backport import OrderedDict
|
|
||||||
|
|
||||||
import llnl.util.lang
|
import llnl.util.lang
|
||||||
import llnl.util.tty as tty
|
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)
|
# orig_sbang = '#!/bin/bash {0}/bin/sbang'.format(orig_spack)
|
||||||
# new_sbang = '#!/bin/bash {0}/bin/sbang'.format(new_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():
|
for orig_prefix, new_prefix in prefixes.items():
|
||||||
if orig_prefix != new_prefix:
|
if orig_prefix != new_prefix:
|
||||||
|
@ -845,7 +844,7 @@ def relocate_text_bin(binaries, prefixes, concurrency=32):
|
||||||
Raises:
|
Raises:
|
||||||
BinaryTextReplaceError: when the new path is longer than the old path
|
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():
|
for orig_prefix, new_prefix in prefixes.items():
|
||||||
if orig_prefix != new_prefix:
|
if orig_prefix != new_prefix:
|
||||||
|
@ -1032,7 +1031,7 @@ def fixup_macos_rpath(root, filename):
|
||||||
# Convert rpaths list to (name -> number of occurrences)
|
# Convert rpaths list to (name -> number of occurrences)
|
||||||
add_rpaths = set()
|
add_rpaths = set()
|
||||||
del_rpaths = set()
|
del_rpaths = set()
|
||||||
rpaths = defaultdict(int)
|
rpaths = collections.defaultdict(int)
|
||||||
for rpath in rpath_list:
|
for rpath in rpath_list:
|
||||||
rpaths[rpath] += 1
|
rpaths[rpath] += 1
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
|
||||||
import codecs
|
import codecs
|
||||||
|
import collections
|
||||||
import hashlib
|
import hashlib
|
||||||
import os.path
|
import os.path
|
||||||
import platform
|
import platform
|
||||||
|
@ -13,7 +12,6 @@
|
||||||
import time
|
import time
|
||||||
import xml.sax.saxutils
|
import xml.sax.saxutils
|
||||||
|
|
||||||
from ordereddict_backport import OrderedDict
|
|
||||||
from six import iteritems, text_type
|
from six import iteritems, text_type
|
||||||
from six.moves.urllib.parse import urlencode
|
from six.moves.urllib.parse import urlencode
|
||||||
from six.moves.urllib.request import HTTPHandler, Request, build_opener
|
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)
|
buildstamp_format = "%Y%m%d-%H%M-{0}".format(args.cdash_track)
|
||||||
self.buildstamp = time.strftime(buildstamp_format,
|
self.buildstamp = time.strftime(buildstamp_format,
|
||||||
time.localtime(self.endtime))
|
time.localtime(self.endtime))
|
||||||
self.buildIds = OrderedDict()
|
self.buildIds = collections.OrderedDict()
|
||||||
self.revision = ''
|
self.revision = ''
|
||||||
git = which('git')
|
git = which('git')
|
||||||
with working_dir(spack.paths.spack_root):
|
with working_dir(spack.paths.spack_root):
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
@ -69,14 +68,6 @@ def test_url_with_no_version_fails():
|
||||||
url('parse', 'http://www.netlib.org/voronoi/triangle.zip')
|
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):
|
def test_url_list(mock_packages):
|
||||||
out = url('list')
|
out = url('list')
|
||||||
total_urls = len(out.split('\n'))
|
total_urls = len(out.split('\n'))
|
||||||
|
@ -106,7 +97,6 @@ def test_url_list(mock_packages):
|
||||||
assert 0 < correct_version_urls < total_urls
|
assert 0 < correct_version_urls < total_urls
|
||||||
|
|
||||||
|
|
||||||
@skip_python_26
|
|
||||||
def test_url_summary(mock_packages):
|
def test_url_summary(mock_packages):
|
||||||
"""Test the URL summary command."""
|
"""Test the URL summary command."""
|
||||||
# test url_summary, the internal function that does the work
|
# 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
|
assert out_correct_versions == correct_versions
|
||||||
|
|
||||||
|
|
||||||
@skip_python_26
|
|
||||||
def test_url_stats(capfd, mock_packages):
|
def test_url_stats(capfd, mock_packages):
|
||||||
with capfd.disabled():
|
with capfd.disabled():
|
||||||
output = url('stats')
|
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, nullcontext),
|
||||||
(mock_shell_v_v_no_termios, no_termios),
|
(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(
|
def test_foreground_background_output(
|
||||||
test_fn, capfd, termios_on_or_off, tmpdir):
|
test_fn, capfd, termios_on_or_off, tmpdir):
|
||||||
"""Tests hitting 'v' toggles output, and that force_echo works."""
|
"""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.
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
import collections
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import ordereddict_backport
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import llnl.util.tty as tty
|
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
|
# 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
|
# fuzzy match, the result depends on the internal ordering of the given
|
||||||
# mapping
|
# mapping
|
||||||
headers = ordereddict_backport.OrderedDict()
|
headers = collections.OrderedDict()
|
||||||
headers['Content-type'] = 'text/plain'
|
headers['Content-type'] = 'text/plain'
|
||||||
headers['contentType'] = 'text/html'
|
headers['contentType'] = 'text/html'
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ def test_get_header():
|
||||||
assert(spack.util.web.get_header(headers, 'CONTENT_TYPE') == 'text/html')
|
assert(spack.util.web.get_header(headers, 'CONTENT_TYPE') == 'text/html')
|
||||||
|
|
||||||
# Same as above, but different ordering
|
# Same as above, but different ordering
|
||||||
headers = ordereddict_backport.OrderedDict()
|
headers = collections.OrderedDict()
|
||||||
headers['contentType'] = 'text/html'
|
headers['contentType'] = 'text/html'
|
||||||
headers['Content-type'] = 'text/plain'
|
headers['Content-type'] = 'text/plain'
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
"""Infrastructure used by tests for mocking packages and repos."""
|
"""Infrastructure used by tests for mocking packages and repos."""
|
||||||
|
import collections
|
||||||
import ordereddict_backport
|
|
||||||
|
|
||||||
import spack.provider_index
|
import spack.provider_index
|
||||||
import spack.util.naming
|
import spack.util.naming
|
||||||
|
@ -149,7 +147,7 @@ class MockPackage(MockPackageBase):
|
||||||
MockPackage._repo = self
|
MockPackage._repo = self
|
||||||
|
|
||||||
# set up dependencies
|
# set up dependencies
|
||||||
MockPackage.dependencies = ordereddict_backport.OrderedDict()
|
MockPackage.dependencies = collections.OrderedDict()
|
||||||
for dep, dtype in zip(dependencies, dependency_types):
|
for dep, dtype in zip(dependencies, dependency_types):
|
||||||
d = Dependency(MockPackage, Spec(dep.name), type=dtype)
|
d = Dependency(MockPackage, Spec(dep.name), type=dtype)
|
||||||
if not conditions or dep.name not in conditions:
|
if not conditions or dep.name not in conditions:
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
default unorderd dict.
|
default unorderd dict.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import collections
|
||||||
import ctypes
|
import ctypes
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from typing import List # novm
|
from typing import List # novm
|
||||||
|
|
||||||
import ruamel.yaml as yaml
|
import ruamel.yaml as yaml
|
||||||
from ordereddict_backport import OrderedDict
|
|
||||||
from ruamel.yaml import RoundTripDumper, RoundTripLoader
|
from ruamel.yaml import RoundTripDumper, RoundTripLoader
|
||||||
from six import StringIO, string_types
|
from six import StringIO, string_types
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
# Also, use OrderedDict instead of just dict.
|
# Also, use OrderedDict instead of just dict.
|
||||||
|
|
||||||
|
|
||||||
class syaml_dict(OrderedDict):
|
class syaml_dict(collections.OrderedDict):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
mappings = ('%r: %r' % (k, v) for k, v in self.items())
|
mappings = ('%r: %r' % (k, v) for k, v in self.items())
|
||||||
return '{%s}' % ', '.join(mappings)
|
return '{%s}' % ', '.join(mappings)
|
||||||
|
|
Loading…
Reference in a new issue