Coverage for src/plotly_gtk/utils/plotly_types.py: 66%

62 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-11-08 21:22 +0000

1"""Utilities to type plotly dicts.""" 

2 

3import importlib.resources 

4import json 

5import typing 

6 

7import numpy as np 

8 

9file = importlib.resources.files(anchor="plotly_gtk.utils.plotly_types").joinpath( 

10 "plot-schema.json" 

11) 

12 

13with open(file, encoding="utf-8") as f: 

14 schema = json.load(f) 

15 

16layout_attributes = schema["layout"]["layoutAttributes"] 

17data_attributes = schema["traces"] 

18 

19if typing.TYPE_CHECKING: 

20 SchemaType = dict[str, "SchemaType" | str] 

21 GenericType = dict[str, "GenericType" | float | str | bool] 

22 

23 

24def build_type(attribute: "GenericType") -> type: 

25 """ 

26 Build a type variable for part of the plotly schema. 

27 

28 Parameters 

29 ---------- 

30 attribute: GenericType 

31 A part of the plotly schema 

32 

33 Returns 

34 ------- 

35 type 

36 A type variable defining the type for this part of the schema. 

37 

38 """ 

39 

40 if "valType" in attribute: 

41 val_type = attribute["valType"] 

42 if val_type == "number": 

43 OUT_TYPE = float 

44 elif val_type == "integer": 

45 OUT_TYPE = int 

46 elif val_type == "boolean": 

47 OUT_TYPE = bool 

48 elif val_type == "data_array": 

49 OUT_TYPE = np.ndarray | list 

50 elif val_type == "angle": 

51 OUT_TYPE = float 

52 else: 

53 OUT_TYPE = str 

54 return OUT_TYPE 

55 OUT_TYPES = [] 

56 for v in attribute.values(): 

57 if isinstance(v, dict): 

58 OUT_TYPE = build_type(v) 

59 if OUT_TYPE is not None: 

60 OUT_TYPES.append(OUT_TYPE) 

61 if not OUT_TYPES: 

62 return None 

63 return dict[str, typing.Union[*OUT_TYPES]] 

64 

65 

66Layout = build_type(layout_attributes) 

67Data = typing.Union[ 

68 *[build_type(trace["attributes"]) for trace in data_attributes.values()] 

69] 

70 

71prebuilt_types = {"layout": Layout, "data": Data} 

72 

73 

74def get_schema(*args: list[str]) -> "SchemaType": 

75 """ 

76 Get part of the plotly schema. 

77 

78 Parameters 

79 ---------- 

80 args: list[str] 

81 A list of keys for indexing the plotly schema 

82 

83 Returns 

84 ------- 

85 SchemaType 

86 The relevant part of the ploty schema 

87 """ 

88 if args[0] == "layout": 

89 schema_dict = layout_attributes 

90 for key in args[1:]: 

91 schema_dict = schema_dict[key] 

92 elif args[0] == "data": 

93 schema_dict = data_attributes[args[1]]["attributes"] 

94 for key in args[2:]: 

95 schema_dict = schema_dict[key] 

96 return schema_dict 

97 

98 

99def get_type(*args: list[str]) -> type: 

100 """ 

101 Get a type variable for part of the plotly schema. 

102 

103 Parameters 

104 ---------- 

105 args: list[str] 

106 A list of keys for indexing the plotly schema 

107 

108 Returns 

109 ------- 

110 type 

111 A type defining part of the plotly schema 

112 

113 """ 

114 if "_".join(args) not in prebuilt_types: 

115 schema_dict = get_schema(*args) 

116 prebuilt_types["_".join(args)] = build_type(schema_dict) 

117 return prebuilt_types["_".join(args)] 

118 

119 

120def get_keys(*args: list[str]) -> type({}.keys()): 

121 """ 

122 Get the keys from the plotly schema. 

123 

124 Parameters 

125 ---------- 

126 args: list[str] 

127 A list of keys for indexing the plotly schema 

128 

129 Returns 

130 ------- 

131 dict_keys 

132 The keys available 

133 

134 Raises 

135 ------ 

136 ValueError 

137 If the path specified is a single value not a dictionary 

138 """ 

139 schema_dict = get_schema(*args) 

140 if "valType" in schema_dict: 

141 raise ValueError("This path is not a dictionary") 

142 return schema_dict.keys() 

143 

144 

145def get_description(*args: list[str]) -> str: 

146 """ 

147 Get a description from the plotly schema. 

148 

149 Parameters 

150 ---------- 

151 args: list[str] 

152 A list of keys for indexing the plotly schema 

153 

154 Returns 

155 ------- 

156 str 

157 The description of the relevant key. 

158 """ 

159 schema_dict = get_schema(*args) 

160 return schema_dict["description"]