Spaces:
Running
Running
# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license | |
import collections.abc | |
from typing import Any, Callable | |
from dns._immutable_ctx import immutable | |
class Dict(collections.abc.Mapping): # lgtm[py/missing-equals] | |
def __init__( | |
self, | |
dictionary: Any, | |
no_copy: bool = False, | |
map_factory: Callable[[], collections.abc.MutableMapping] = dict, | |
): | |
"""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, collections.abc.MutableMapping): | |
self._odict = dictionary | |
else: | |
self._odict = map_factory() | |
self._odict.update(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: Any) -> Any: | |
""" | |
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 = dict() | |
for k, v in o.items(): | |
cdict[k] = constify(v) | |
return Dict(cdict, True) | |
return o | |