Python 3.10 support: collections.abc (#20441)

This commit is contained in:
Adam J. Stewart 2021-02-01 11:30:25 -06:00 committed by GitHub
parent f781403615
commit 40a40e0265
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 140 additions and 42 deletions

View file

@ -5,9 +5,12 @@
import _pytest._code import _pytest._code
import py import py
try: try:
from collections import Sequence from collections.abc import Sequence
except ImportError: except ImportError:
Sequence = list try:
from collections import Sequence
except ImportError:
Sequence = list
u = py.builtin._totext u = py.builtin._totext

View file

@ -10,9 +10,12 @@
import _pytest._code import _pytest._code
import py import py
try: try:
from collections import MutableMapping as MappingMixin from collections.abc import MutableMapping as MappingMixin
except ImportError: except ImportError:
from UserDict import DictMixin as MappingMixin try:
from collections import MutableMapping as MappingMixin
except ImportError:
from UserDict import DictMixin as MappingMixin
from _pytest.config import directory_arg, UsageError, hookimpl from _pytest.config import directory_arg, UsageError, hookimpl
from _pytest.outcomes import exit from _pytest.outcomes import exit

View file

@ -398,7 +398,10 @@ def approx(expected, rel=None, abs=None, nan_ok=False):
__ https://docs.python.org/3/reference/datamodel.html#object.__ge__ __ https://docs.python.org/3/reference/datamodel.html#object.__ge__
""" """
from collections import Mapping, Sequence if sys.version_info >= (3, 3):
from collections.abc import Mapping, Sequence
else:
from collections import Mapping, Sequence
from _pytest.compat import STRING_TYPES as String from _pytest.compat import STRING_TYPES as String
# Delegate the comparison to a class that knows how to deal with the type # Delegate the comparison to a class that knows how to deal with the type

View file

@ -315,10 +315,14 @@ def __repr__(self):
# register the context as mapping if possible # register the context as mapping if possible
try: try:
from collections import Mapping from collections.abc import Mapping
Mapping.register(Context) Mapping.register(Context)
except ImportError: except ImportError:
pass try:
from collections import Mapping
Mapping.register(Context)
except ImportError:
pass
class BlockReference(object): class BlockReference(object):

View file

@ -14,7 +14,7 @@
""" """
import types import types
import operator import operator
from collections import Mapping import sys
from jinja2.environment import Environment from jinja2.environment import Environment
from jinja2.exceptions import SecurityError from jinja2.exceptions import SecurityError
from jinja2._compat import string_types, PY2 from jinja2._compat import string_types, PY2
@ -23,6 +23,11 @@
from markupsafe import EscapeFormatter from markupsafe import EscapeFormatter
from string import Formatter from string import Formatter
if sys.version_info >= (3, 3):
from collections.abc import Mapping
else:
from collections import Mapping
#: maximum number of items a range may produce #: maximum number of items a range may produce
MAX_RANGE = 100000 MAX_RANGE = 100000
@ -79,7 +84,10 @@
pass pass
#: register Python 2.6 abstract base classes #: register Python 2.6 abstract base classes
from collections import MutableSet, MutableMapping, MutableSequence if sys.version_info >= (3, 3):
from collections.abc import MutableSet, MutableMapping, MutableSequence
else:
from collections import MutableSet, MutableMapping, MutableSequence
_mutable_set_types += (MutableSet,) _mutable_set_types += (MutableSet,)
_mutable_mapping_types += (MutableMapping,) _mutable_mapping_types += (MutableMapping,)
_mutable_sequence_types += (MutableSequence,) _mutable_sequence_types += (MutableSequence,)

View file

@ -10,11 +10,16 @@
""" """
import operator import operator
import re import re
from collections import Mapping import sys
from jinja2.runtime import Undefined from jinja2.runtime import Undefined
from jinja2._compat import text_type, string_types, integer_types from jinja2._compat import text_type, string_types, integer_types
import decimal import decimal
if sys.version_info >= (3, 3):
from collections.abc import Mapping
else:
from collections import Mapping
number_re = re.compile(r'^-?\d+(\.\d+)?$') number_re = re.compile(r'^-?\d+(\.\d+)?$')
regex_type = type(number_re) regex_type = type(number_re)

View file

@ -482,10 +482,14 @@ def __reversed__(self):
# register the LRU cache as mutable mapping if possible # register the LRU cache as mutable mapping if possible
try: try:
from collections import MutableMapping from collections.abc import MutableMapping
MutableMapping.register(LRUCache) MutableMapping.register(LRUCache)
except ImportError: except ImportError:
pass try:
from collections import MutableMapping
MutableMapping.register(LRUCache)
except ImportError:
pass
def select_autoescape(enabled_extensions=('html', 'htm', 'xml'), def select_autoescape(enabled_extensions=('html', 'htm', 'xml'),

View file

@ -10,10 +10,15 @@
""" """
import re import re
import string import string
from collections import Mapping import sys
from markupsafe._compat import text_type, string_types, int_types, \ from markupsafe._compat import text_type, string_types, int_types, \
unichr, iteritems, PY2 unichr, iteritems, PY2
if sys.version_info >= (3, 3):
from collections.abc import Mapping
else:
from collections import Mapping
__version__ = "1.0" __version__ = "1.0"
__all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent'] __all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent']

View file

@ -9,7 +9,12 @@
a separate base a separate base
""" """
from collections import MutableSet import sys
if sys.version_info >= (3, 3):
from collections.abc import MutableSet
else:
from collections import MutableSet
__all__ = ["CommentedSeq", "CommentedMap", "CommentedOrderedMap", __all__ = ["CommentedSeq", "CommentedMap", "CommentedOrderedMap",
"CommentedSet", 'comment_attrib', 'merge_attrib'] "CommentedSet", 'comment_attrib', 'merge_attrib']

View file

@ -12,9 +12,12 @@
from ruamel.ordereddict import ordereddict from ruamel.ordereddict import ordereddict
except: except:
try: try:
from collections import OrderedDict from collections.abc import OrderedDict
except ImportError: except ImportError:
from ordereddict import OrderedDict try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict
# to get the right name import ... as ordereddict doesn't do that # to get the right name import ... as ordereddict doesn't do that
class ordereddict(OrderedDict): class ordereddict(OrderedDict):

View file

@ -3,7 +3,6 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import print_function from __future__ import print_function
import collections
import datetime import datetime
import base64 import base64
import binascii import binascii
@ -26,6 +25,12 @@
from ruamel.yaml.scalarstring import * # NOQA from ruamel.yaml.scalarstring import * # NOQA
if sys.version_info >= (3, 3):
from collections.abc import Hashable
else:
from collections import Hashable
__all__ = ['BaseConstructor', 'SafeConstructor', 'Constructor', __all__ = ['BaseConstructor', 'SafeConstructor', 'Constructor',
'ConstructorError', 'RoundTripConstructor'] 'ConstructorError', 'RoundTripConstructor']
@ -163,7 +168,7 @@ def construct_mapping(self, node, deep=False):
# keys can be list -> deep # keys can be list -> deep
key = self.construct_object(key_node, deep=True) key = self.construct_object(key_node, deep=True)
# lists are not hashable, but tuples are # lists are not hashable, but tuples are
if not isinstance(key, collections.Hashable): if not isinstance(key, Hashable):
if isinstance(key, list): if isinstance(key, list):
key = tuple(key) key = tuple(key)
if PY2: if PY2:
@ -175,7 +180,7 @@ def construct_mapping(self, node, deep=False):
"found unacceptable key (%s)" % "found unacceptable key (%s)" %
exc, key_node.start_mark) exc, key_node.start_mark)
else: else:
if not isinstance(key, collections.Hashable): if not isinstance(key, Hashable):
raise ConstructorError( raise ConstructorError(
"while constructing a mapping", node.start_mark, "while constructing a mapping", node.start_mark,
"found unhashable key", key_node.start_mark) "found unhashable key", key_node.start_mark)
@ -959,7 +964,7 @@ def construct_mapping(self, node, maptyp, deep=False):
# keys can be list -> deep # keys can be list -> deep
key = self.construct_object(key_node, deep=True) key = self.construct_object(key_node, deep=True)
# lists are not hashable, but tuples are # lists are not hashable, but tuples are
if not isinstance(key, collections.Hashable): if not isinstance(key, Hashable):
if isinstance(key, list): if isinstance(key, list):
key = tuple(key) key = tuple(key)
if PY2: if PY2:
@ -971,7 +976,7 @@ def construct_mapping(self, node, maptyp, deep=False):
"found unacceptable key (%s)" % "found unacceptable key (%s)" %
exc, key_node.start_mark) exc, key_node.start_mark)
else: else:
if not isinstance(key, collections.Hashable): if not isinstance(key, Hashable):
raise ConstructorError( raise ConstructorError(
"while constructing a mapping", node.start_mark, "while constructing a mapping", node.start_mark,
"found unhashable key", key_node.start_mark) "found unhashable key", key_node.start_mark)
@ -1003,7 +1008,7 @@ def construct_setting(self, node, typ, deep=False):
# keys can be list -> deep # keys can be list -> deep
key = self.construct_object(key_node, deep=True) key = self.construct_object(key_node, deep=True)
# lists are not hashable, but tuples are # lists are not hashable, but tuples are
if not isinstance(key, collections.Hashable): if not isinstance(key, Hashable):
if isinstance(key, list): if isinstance(key, list):
key = tuple(key) key = tuple(key)
if PY2: if PY2:
@ -1015,7 +1020,7 @@ def construct_setting(self, node, typ, deep=False):
"found unacceptable key (%s)" % "found unacceptable key (%s)" %
exc, key_node.start_mark) exc, key_node.start_mark)
else: else:
if not isinstance(key, collections.Hashable): if not isinstance(key, Hashable):
raise ConstructorError( raise ConstructorError(
"while constructing a mapping", node.start_mark, "while constructing a mapping", node.start_mark,
"found unhashable key", key_node.start_mark) "found unhashable key", key_node.start_mark)

View file

@ -23,6 +23,12 @@
from llnl.util.lang import dedupe, memoized from llnl.util.lang import dedupe, memoized
from spack.util.executable import Executable from spack.util.executable import Executable
if sys.version_info >= (3, 3):
from collections.abc import Sequence # novm
else:
from collections import Sequence
__all__ = [ __all__ = [
'FileFilter', 'FileFilter',
'FileList', 'FileList',
@ -1106,7 +1112,7 @@ def find(root, files, recursive=True):
Parameters: Parameters:
root (str): The root directory to start searching from root (str): The root directory to start searching from
files (str or collections.Sequence): Library name(s) to search for files (str or Sequence): Library name(s) to search for
recurse (bool, optional): if False search only root folder, recurse (bool, optional): if False search only root folder,
if True descends top-down from the root. Defaults to True. if True descends top-down from the root. Defaults to True.
@ -1169,7 +1175,7 @@ def _find_non_recursive(root, search_files):
# Utilities for libraries and headers # Utilities for libraries and headers
class FileList(collections.Sequence): class FileList(Sequence):
"""Sequence of absolute paths to files. """Sequence of absolute paths to files.
Provides a few convenience methods to manipulate file paths. Provides a few convenience methods to manipulate file paths.
@ -1412,7 +1418,7 @@ def find_headers(headers, root, recursive=False):
""" """
if isinstance(headers, six.string_types): if isinstance(headers, six.string_types):
headers = [headers] headers = [headers]
elif not isinstance(headers, collections.Sequence): elif not isinstance(headers, Sequence):
message = '{0} expects a string or sequence of strings as the ' message = '{0} expects a string or sequence of strings as the '
message += 'first argument [got {1} instead]' message += 'first argument [got {1} instead]'
message = message.format(find_headers.__name__, type(headers)) message = message.format(find_headers.__name__, type(headers))
@ -1567,7 +1573,7 @@ def find_system_libraries(libraries, shared=True):
""" """
if isinstance(libraries, six.string_types): if isinstance(libraries, six.string_types):
libraries = [libraries] libraries = [libraries]
elif not isinstance(libraries, collections.Sequence): elif not isinstance(libraries, Sequence):
message = '{0} expects a string or sequence of strings as the ' message = '{0} expects a string or sequence of strings as the '
message += 'first argument [got {1} instead]' message += 'first argument [got {1} instead]'
message = message.format(find_system_libraries.__name__, message = message.format(find_system_libraries.__name__,
@ -1621,7 +1627,7 @@ def find_libraries(libraries, root, shared=True, recursive=False):
""" """
if isinstance(libraries, six.string_types): if isinstance(libraries, six.string_types):
libraries = [libraries] libraries = [libraries]
elif not isinstance(libraries, collections.Sequence): elif not isinstance(libraries, Sequence):
message = '{0} expects a string or sequence of strings as the ' message = '{0} expects a string or sequence of strings as the '
message += 'first argument [got {1} instead]' message += 'first argument [got {1} instead]'
message = message.format(find_libraries.__name__, type(libraries)) message = message.format(find_libraries.__name__, type(libraries))

View file

@ -9,13 +9,18 @@
import os import os
import re import re
import functools import functools
import collections
import inspect import inspect
from datetime import datetime, timedelta from datetime import datetime, timedelta
from six import string_types from six import string_types
import sys import sys
if sys.version_info >= (3, 3):
from collections.abc import Hashable, MutableMapping # novm
else:
from collections import Hashable, MutableMapping
# Ignore emacs backups when listing modules # Ignore emacs backups when listing modules
ignore_modules = [r'^\.#', '~$'] ignore_modules = [r'^\.#', '~$']
@ -189,7 +194,7 @@ def memoized(func):
@functools.wraps(func) @functools.wraps(func)
def _memoized_function(*args): def _memoized_function(*args):
if not isinstance(args, collections.Hashable): if not isinstance(args, Hashable):
# Not hashable, so just call the function. # Not hashable, so just call the function.
return func(*args) return func(*args)
@ -264,7 +269,7 @@ def setter(name, value):
@key_ordering @key_ordering
class HashableMap(collections.MutableMapping): class HashableMap(MutableMapping):
"""This is a hashable, comparable dictionary. Hash is performed on """This is a hashable, comparable dictionary. Hash is performed on
a tuple of the values in the dictionary.""" a tuple of the values in the dictionary."""

View file

@ -28,10 +28,11 @@ class OpenMpi(Package):
""" """
import collections
import functools import functools
import os.path import os.path
import re import re
import sys
from six import string_types from six import string_types
from typing import Set, List # novm from typing import Set, List # novm
@ -48,6 +49,13 @@ class OpenMpi(Package):
from spack.resource import Resource from spack.resource import Resource
from spack.version import Version, VersionChecksumError from spack.version import Version, VersionChecksumError
if sys.version_info >= (3, 3):
from collections.abc import Sequence # novm
else:
from collections import Sequence
__all__ = [] __all__ = []
#: These are variant names used by Spack internally; packages can't use them #: These are variant names used by Spack internally; packages can't use them
@ -203,7 +211,7 @@ class Foo(Package):
if isinstance(dicts, string_types): if isinstance(dicts, string_types):
dicts = (dicts, ) dicts = (dicts, )
if not isinstance(dicts, collections.Sequence): if not isinstance(dicts, Sequence):
message = "dicts arg must be list, tuple, or string. Found {0}" message = "dicts arg must be list, tuple, or string. Found {0}"
raise TypeError(message.format(type(dicts))) raise TypeError(message.format(type(dicts)))
# Add the dictionary names if not already there # Add the dictionary names if not already there
@ -244,7 +252,7 @@ def remove_directives(arg):
# ...so if it is not a sequence make it so # ...so if it is not a sequence make it so
values = result values = result
if not isinstance(values, collections.Sequence): if not isinstance(values, Sequence):
values = (values, ) values = (values, )
DirectiveMeta._directives_to_be_executed.extend(values) DirectiveMeta._directives_to_be_executed.extend(values)

View file

@ -40,6 +40,12 @@
import spack.version import spack.version
if sys.version_info >= (3, 3):
from collections.abc import Sequence # novm
else:
from collections import Sequence
class Timer(object): class Timer(object):
"""Simple timer for timing phases of a solve""" """Simple timer for timing phases of a solve"""
def __init__(self): def __init__(self):
@ -64,7 +70,7 @@ def write(self, out=sys.stdout):
def issequence(obj): def issequence(obj):
if isinstance(obj, string_types): if isinstance(obj, string_types):
return False return False
return isinstance(obj, (collections.Sequence, types.GeneratorType)) return isinstance(obj, (Sequence, types.GeneratorType))
def listify(args): def listify(args):

View file

@ -116,6 +116,13 @@
import spack.variant as vt import spack.variant as vt
import spack.version as vn import spack.version as vn
if sys.version_info >= (3, 3):
from collections.abc import Mapping # novm
else:
from collections import Mapping
__all__ = [ __all__ = [
'Spec', 'Spec',
'parse', 'parse',
@ -2120,7 +2127,7 @@ def validate_detection(self):
# which likely means the spec was created with Spec.from_detection # which likely means the spec was created with Spec.from_detection
msg = ('cannot validate "{0}" since it was not created ' msg = ('cannot validate "{0}" since it was not created '
'using Spec.from_detection'.format(self)) 'using Spec.from_detection'.format(self))
assert isinstance(self.extra_attributes, collections.Mapping), msg assert isinstance(self.extra_attributes, Mapping), msg
# Validate the spec calling a package specific method # Validate the spec calling a package specific method
validate_fn = getattr( validate_fn = getattr(

View file

@ -11,8 +11,7 @@
import ast import ast
import inspect import inspect
import os import os
import sys
from collections import Iterable, Mapping
import pytest import pytest
@ -29,6 +28,12 @@
from spack.util.mock_package import MockPackageMultiRepo from spack.util.mock_package import MockPackageMultiRepo
if sys.version_info >= (3, 3):
from collections.abc import Iterable, Mapping # novm
else:
from collections import Iterable, Mapping
def check_yaml_round_trip(spec): def check_yaml_round_trip(spec):
yaml_text = spec.to_yaml() yaml_text = spec.to_yaml()
spec_from_yaml = Spec.from_yaml(yaml_text) spec_from_yaml = Spec.from_yaml(yaml_text)

View file

@ -4,8 +4,14 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import inspect import inspect
import collections
import functools import functools
import sys
if sys.version_info >= (3, 3):
from collections.abc import MutableSequence # novm
else:
from collections import MutableSequence
class Delegate(object): class Delegate(object):
@ -52,7 +58,7 @@ def composite(interface=None, method_list=None, container=list):
# exception if it doesn't. The patched class returned by the decorator will # exception if it doesn't. The patched class returned by the decorator will
# inherit from the container class to expose the interface needed to manage # inherit from the container class to expose the interface needed to manage
# objects composition # objects composition
if not issubclass(container, collections.MutableSequence): if not issubclass(container, MutableSequence):
raise TypeError("Container must fulfill the MutableSequence contract") raise TypeError("Container must fulfill the MutableSequence contract")
# Check if at least one of the 'interface' or the 'method_list' arguments # Check if at least one of the 'interface' or the 'method_list' arguments

View file

@ -13,7 +13,7 @@
""" """
import ctypes import ctypes
import collections import sys
from typing import List # novm from typing import List # novm
from ordereddict_backport import OrderedDict from ordereddict_backport import OrderedDict
@ -26,6 +26,13 @@
import spack.error import spack.error
if sys.version_info >= (3, 3):
from collections.abc import Mapping # novm
else:
from collections import Mapping
# Only export load and dump # Only export load and dump
__all__ = ['load', 'dump', 'SpackYAMLError'] __all__ = ['load', 'dump', 'SpackYAMLError']
@ -344,7 +351,7 @@ def sorted_dict(dict_like):
""" """
result = syaml_dict(sorted(dict_like.items())) result = syaml_dict(sorted(dict_like.items()))
for key, value in result.items(): for key, value in result.items():
if isinstance(value, collections.Mapping): if isinstance(value, Mapping):
result[key] = sorted_dict(value) result[key] = sorted_dict(value)
return result return result