You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					71 lines
				
				2.0 KiB
			
		
		
			
		
	
	
					71 lines
				
				2.0 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import collections.abc
							 | 
						||
| 
								 | 
							
								import sys
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# pylint: disable=unused-import
							 | 
						||
| 
								 | 
							
								if sys.version_info >= (3, 7):
							 | 
						||
| 
								 | 
							
								    odict = dict
							 | 
						||
| 
								 | 
							
								    from dns._immutable_ctx import immutable
							 | 
						||
| 
								 | 
							
								else:
							 | 
						||
| 
								 | 
							
								    # pragma: no cover
							 | 
						||
| 
								 | 
							
								    from collections import OrderedDict as odict
							 | 
						||
| 
								 | 
							
								    from dns._immutable_attr import immutable  # noqa
							 | 
						||
| 
								 | 
							
								# pylint: enable=unused-import
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@immutable
							 | 
						||
| 
								 | 
							
								class Dict(collections.abc.Mapping):
							 | 
						||
| 
								 | 
							
								    def __init__(self, dictionary, no_copy=False):
							 | 
						||
| 
								 | 
							
								        """Make an immutable dictionary from the specified dictionary.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        If *no_copy* is `True`, then *dictionary* will be wrapped instead
							 | 
						||
| 
								 | 
							
								        of copied.  Only set this if you are sure there will be no external
							 | 
						||
| 
								 | 
							
								        references to the dictionary.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        if no_copy and isinstance(dictionary, odict):
							 | 
						||
| 
								 | 
							
								            self._odict = dictionary
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            self._odict = odict(dictionary)
							 | 
						||
| 
								 | 
							
								        self._hash = None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __getitem__(self, key):
							 | 
						||
| 
								 | 
							
								        return self._odict.__getitem__(key)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __hash__(self):  # pylint: disable=invalid-hash-returned
							 | 
						||
| 
								 | 
							
								        if self._hash is None:
							 | 
						||
| 
								 | 
							
								            h = 0
							 | 
						||
| 
								 | 
							
								            for key in sorted(self._odict.keys()):
							 | 
						||
| 
								 | 
							
								                h ^= hash(key)
							 | 
						||
| 
								 | 
							
								            object.__setattr__(self, '_hash', h)
							 | 
						||
| 
								 | 
							
								        # this does return an int, but pylint doesn't figure that out
							 | 
						||
| 
								 | 
							
								        return self._hash
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __len__(self):
							 | 
						||
| 
								 | 
							
								        return len(self._odict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __iter__(self):
							 | 
						||
| 
								 | 
							
								        return iter(self._odict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def constify(o):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Convert mutable types to immutable types.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    if isinstance(o, bytearray):
							 | 
						||
| 
								 | 
							
								        return bytes(o)
							 | 
						||
| 
								 | 
							
								    if isinstance(o, tuple):
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            hash(o)
							 | 
						||
| 
								 | 
							
								            return o
							 | 
						||
| 
								 | 
							
								        except Exception:
							 | 
						||
| 
								 | 
							
								            return tuple(constify(elt) for elt in o)
							 | 
						||
| 
								 | 
							
								    if isinstance(o, list):
							 | 
						||
| 
								 | 
							
								        return tuple(constify(elt) for elt in o)
							 | 
						||
| 
								 | 
							
								    if isinstance(o, dict):
							 | 
						||
| 
								 | 
							
								        cdict = odict()
							 | 
						||
| 
								 | 
							
								        for k, v in o.items():
							 | 
						||
| 
								 | 
							
								            cdict[k] = constify(v)
							 | 
						||
| 
								 | 
							
								        return Dict(cdict, True)
							 | 
						||
| 
								 | 
							
								    return o
							 |