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
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-08 21:22 +0000
1"""Utilities to type plotly dicts."""
3import importlib.resources
4import json
5import typing
7import numpy as np
9file = importlib.resources.files(anchor="plotly_gtk.utils.plotly_types").joinpath(
10 "plot-schema.json"
11)
13with open(file, encoding="utf-8") as f:
14 schema = json.load(f)
16layout_attributes = schema["layout"]["layoutAttributes"]
17data_attributes = schema["traces"]
19if typing.TYPE_CHECKING:
20 SchemaType = dict[str, "SchemaType" | str]
21 GenericType = dict[str, "GenericType" | float | str | bool]
24def build_type(attribute: "GenericType") -> type:
25 """
26 Build a type variable for part of the plotly schema.
28 Parameters
29 ----------
30 attribute: GenericType
31 A part of the plotly schema
33 Returns
34 -------
35 type
36 A type variable defining the type for this part of the schema.
38 """
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]]
66Layout = build_type(layout_attributes)
67Data = typing.Union[
68 *[build_type(trace["attributes"]) for trace in data_attributes.values()]
69]
71prebuilt_types = {"layout": Layout, "data": Data}
74def get_schema(*args: list[str]) -> "SchemaType":
75 """
76 Get part of the plotly schema.
78 Parameters
79 ----------
80 args: list[str]
81 A list of keys for indexing the plotly schema
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
99def get_type(*args: list[str]) -> type:
100 """
101 Get a type variable for part of the plotly schema.
103 Parameters
104 ----------
105 args: list[str]
106 A list of keys for indexing the plotly schema
108 Returns
109 -------
110 type
111 A type defining part of the plotly schema
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)]
120def get_keys(*args: list[str]) -> type({}.keys()):
121 """
122 Get the keys from the plotly schema.
124 Parameters
125 ----------
126 args: list[str]
127 A list of keys for indexing the plotly schema
129 Returns
130 -------
131 dict_keys
132 The keys available
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()
145def get_description(*args: list[str]) -> str:
146 """
147 Get a description from the plotly schema.
149 Parameters
150 ----------
151 args: list[str]
152 A list of keys for indexing the plotly schema
154 Returns
155 -------
156 str
157 The description of the relevant key.
158 """
159 schema_dict = get_schema(*args)
160 return schema_dict["description"]