Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/icalendar/caselessdict.py: 72%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

68 statements  

1from __future__ import annotations 

2 

3from icalendar.parser_tools import to_unicode 

4 

5from collections import OrderedDict 

6 

7from typing import Any, Optional, Iterable, Mapping, TypeVar 

8 

9KT = TypeVar("KT") 

10VT = TypeVar("VT") 

11 

12def canonsort_keys(keys: Iterable[KT], canonical_order: Optional[Iterable[KT]] = None) -> list[KT]: 

13 """Sorts leading keys according to canonical_order. Keys not specified in 

14 canonical_order will appear alphabetically at the end. 

15 """ 

16 canonical_map = {k: i for i, k in enumerate(canonical_order or [])} 

17 head = [k for k in keys if k in canonical_map] 

18 tail = [k for k in keys if k not in canonical_map] 

19 return sorted(head, key=lambda k: canonical_map[k]) + sorted(tail) 

20 

21 

22def canonsort_items(dict1: Mapping[KT, VT], canonical_order: Optional[Iterable[KT]] = None) -> list[tuple[KT, VT]]: 

23 """Returns a list of items from dict1, sorted by canonical_order.""" 

24 return [(k, dict1[k]) for k in canonsort_keys(dict1.keys(), canonical_order)] 

25 

26 

27class CaselessDict(OrderedDict): 

28 """A dictionary that isn't case sensitive, and only uses strings as keys. 

29 Values retain their case. 

30 """ 

31 

32 def __init__(self, *args: Any, **kwargs: Any) -> None: 

33 """Set keys to upper for initial dict.""" 

34 super().__init__(*args, **kwargs) 

35 for key, value in self.items(): 

36 key_upper = to_unicode(key).upper() 

37 if key != key_upper: 

38 super().__delitem__(key) 

39 self[key_upper] = value 

40 

41 def __getitem__(self, key: Any) -> Any: 

42 key = to_unicode(key) 

43 return super().__getitem__(key.upper()) 

44 

45 def __setitem__(self, key: Any, value: Any) -> None: 

46 key = to_unicode(key) 

47 super().__setitem__(key.upper(), value) 

48 

49 def __delitem__(self, key: Any) -> None: 

50 key = to_unicode(key) 

51 super().__delitem__(key.upper()) 

52 

53 def __contains__(self, key: Any) -> bool: 

54 key = to_unicode(key) 

55 return super().__contains__(key.upper()) 

56 

57 def get(self, key: Any, default: Any = None) -> Any: 

58 key = to_unicode(key) 

59 return super().get(key.upper(), default) 

60 

61 def setdefault(self, key: Any, value: Any = None) -> Any: 

62 key = to_unicode(key) 

63 return super().setdefault(key.upper(), value) 

64 

65 def pop(self, key: Any, default: Any = None) -> Any: 

66 key = to_unicode(key) 

67 return super().pop(key.upper(), default) 

68 

69 def popitem(self) -> tuple[Any, Any]: 

70 return super().popitem() 

71 

72 def has_key(self, key: Any) -> bool: 

73 key = to_unicode(key) 

74 return super().__contains__(key.upper()) 

75 

76 def update(self, *args: Any, **kwargs: Any) -> None: 

77 # Multiple keys where key1.upper() == key2.upper() will be lost. 

78 mappings = list(args) + [kwargs] 

79 for mapping in mappings: 

80 if hasattr(mapping, "items"): 

81 mapping = iter(mapping.items()) 

82 for key, value in mapping: 

83 self[key] = value 

84 

85 def copy(self) -> Self: 

86 return type(self)(super().copy()) 

87 

88 def __repr__(self) -> str: 

89 return f"{type(self).__name__}({dict(self)})" 

90 

91 def __eq__(self, other: object) -> bool: 

92 return self is other or dict(self.items()) == dict(other.items()) 

93 

94 def __ne__(self, other: object) -> bool: 

95 return not self == other 

96 

97 # A list of keys that must appear first in sorted_keys and sorted_items; 

98 # must be uppercase. 

99 canonical_order = None 

100 

101 def sorted_keys(self) -> list[str]: 

102 """Sorts keys according to the canonical_order for the derived class. 

103 Keys not specified in canonical_order will appear at the end. 

104 """ 

105 return canonsort_keys(self.keys(), self.canonical_order) 

106 

107 def sorted_items(self) -> list[tuple[Any, Any]]: 

108 """Sorts items according to the canonical_order for the derived class. 

109 Items not specified in canonical_order will appear at the end. 

110 """ 

111 return canonsort_items(self, self.canonical_order) 

112 

113 

114__all__ = ["canonsort_keys", "canonsort_items", "CaselessDict"]