codekingpro/portable-devtools
114k
1# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license2 3import collections.abc4from typing import Any, Callable5 6from dns._immutable_ctx import immutable7 8 9@immutable10class Dict(collections.abc.Mapping): # lgtm[py/missing-equals]11 def __init__(12 self,13 dictionary: Any,14 no_copy: bool = False,15 map_factory: Callable[[], collections.abc.MutableMapping] = dict,16 ):17 """Make an immutable dictionary from the specified dictionary.18 19 If *no_copy* is `True`, then *dictionary* will be wrapped instead20 of copied. Only set this if you are sure there will be no external21 references to the dictionary.22 """23 if no_copy and isinstance(dictionary, collections.abc.MutableMapping):24 self._odict = dictionary25 else:26 self._odict = map_factory()27 self._odict.update(dictionary)28 self._hash = None29 30 def __getitem__(self, key):31 return self._odict.__getitem__(key)32 33 def __hash__(self): # pylint: disable=invalid-hash-returned34 if self._hash is None:35 h = 036 for key in sorted(self._odict.keys()):37 h ^= hash(key)38 object.__setattr__(self, "_hash", h)39 # this does return an int, but pylint doesn't figure that out40 return self._hash41 42 def __len__(self):43 return len(self._odict)44 45 def __iter__(self):46 return iter(self._odict)47 48 49def constify(o: Any) -> Any:50 """51 Convert mutable types to immutable types.52 """53 if isinstance(o, bytearray):54 return bytes(o)55 if isinstance(o, tuple):56 try:57 hash(o)58 return o59 except Exception:60 return tuple(constify(elt) for elt in o)61 if isinstance(o, list):62 return tuple(constify(elt) for elt in o)63 if isinstance(o, dict):64 cdict = dict()65 for k, v in o.items():66 cdict[k] = constify(v)67 return Dict(cdict, True)68 return o69 