Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/dns/immutable.py: 28%

40 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-25 07:09 +0000

1# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 

2 

3import collections.abc 

4from typing import Any 

5 

6from dns._immutable_ctx import immutable 

7 

8 

9@immutable 

10class Dict(collections.abc.Mapping): # lgtm[py/missing-equals] 

11 def __init__(self, dictionary: Any, no_copy: bool = False): 

12 """Make an immutable dictionary from the specified dictionary. 

13 

14 If *no_copy* is `True`, then *dictionary* will be wrapped instead 

15 of copied. Only set this if you are sure there will be no external 

16 references to the dictionary. 

17 """ 

18 if no_copy and isinstance(dictionary, dict): 

19 self._odict = dictionary 

20 else: 

21 self._odict = dict(dictionary) 

22 self._hash = None 

23 

24 def __getitem__(self, key): 

25 return self._odict.__getitem__(key) 

26 

27 def __hash__(self): # pylint: disable=invalid-hash-returned 

28 if self._hash is None: 

29 h = 0 

30 for key in sorted(self._odict.keys()): 

31 h ^= hash(key) 

32 object.__setattr__(self, "_hash", h) 

33 # this does return an int, but pylint doesn't figure that out 

34 return self._hash 

35 

36 def __len__(self): 

37 return len(self._odict) 

38 

39 def __iter__(self): 

40 return iter(self._odict) 

41 

42 

43def constify(o: Any) -> Any: 

44 """ 

45 Convert mutable types to immutable types. 

46 """ 

47 if isinstance(o, bytearray): 

48 return bytes(o) 

49 if isinstance(o, tuple): 

50 try: 

51 hash(o) 

52 return o 

53 except Exception: 

54 return tuple(constify(elt) for elt in o) 

55 if isinstance(o, list): 

56 return tuple(constify(elt) for elt in o) 

57 if isinstance(o, dict): 

58 cdict = dict() 

59 for k, v in o.items(): 

60 cdict[k] = constify(v) 

61 return Dict(cdict, True) 

62 return o