cave-utils 2.1.2__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cave_utils-2.1.2/cave_utils.egg-info → cave_utils-2.2.0}/PKG-INFO +8 -8
- {cave_utils-2.1.2 → cave_utils-2.2.0}/README.md +5 -5
- cave_utils-2.2.0/cave_utils/__init__.py +13 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api/__init__.py +4 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api/appBar.py +3 -3
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api/extraKwargs.py +1 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api/globalOutputs.py +1 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api/groupedOutputs.py +46 -17
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api/mapFeatures.py +34 -10
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api/maps.py +1 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api/pages.py +3 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api/panes.py +1 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api/settings.py +6 -0
- cave_utils-2.2.0/cave_utils/api_utils/__init__.py +22 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api_utils/general.py +57 -31
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api_utils/validator.py +3 -2
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/api_utils/validator_utils.py +94 -15
- cave_utils-2.2.0/cave_utils/builders/__init__.py +7 -0
- cave_utils-2.2.0/cave_utils/builders/groups.py +358 -0
- cave_utils-2.2.0/cave_utils/geo_utils.py +115 -0
- cave_utils-2.2.0/cave_utils/socket.py +11 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0/cave_utils.egg-info}/PKG-INFO +8 -8
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils.egg-info/SOURCES.txt +5 -0
- cave_utils-2.2.0/cave_utils.egg-info/requires.txt +2 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/pyproject.toml +2 -2
- {cave_utils-2.1.2 → cave_utils-2.2.0}/setup.cfg +1 -1
- cave_utils-2.2.0/test/test_builders_groups.py +168 -0
- cave_utils-2.2.0/test/test_geo_utils.py +17 -0
- cave_utils-2.1.2/cave_utils/__init__.py +0 -4
- cave_utils-2.1.2/cave_utils/api_utils/__init__.py +0 -3
- cave_utils-2.1.2/cave_utils/socket.py +0 -9
- cave_utils-2.1.2/cave_utils.egg-info/requires.txt +0 -2
- {cave_utils-2.1.2 → cave_utils-2.2.0}/LICENSE +0 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/NOTICE.md +0 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/arguments.py +0 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils/log.py +0 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils.egg-info/dependency_links.txt +0 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/cave_utils.egg-info/top_level.txt +0 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/test/test_arguments.py +0 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/test/test_import.py +0 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/test/test_log.py +0 -0
- {cave_utils-2.1.2 → cave_utils-2.2.0}/test/test_validator.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cave_utils
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Python wrapper for api use in the cave_app
|
|
5
5
|
Author-email: Connor Makowski <conmak@mit.edu>
|
|
6
6
|
Project-URL: Homepage, https://github.com/mit-cave/cave_utils
|
|
@@ -11,8 +11,8 @@ Requires-Python: >=3.9
|
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
13
|
License-File: NOTICE.md
|
|
14
|
-
Requires-Dist: pamda>=2.
|
|
15
|
-
Requires-Dist: type_enforced>=1.
|
|
14
|
+
Requires-Dist: pamda>=2.5.0
|
|
15
|
+
Requires-Dist: type_enforced>=1.4.0
|
|
16
16
|
|
|
17
17
|
Cave Utilities for the Cave App
|
|
18
18
|
==========
|
|
@@ -58,9 +58,9 @@ pip install cave_utils
|
|
|
58
58
|
|
|
59
59
|
# cave_utils development
|
|
60
60
|
|
|
61
|
-
## Using
|
|
61
|
+
## Using Local Hotloading
|
|
62
62
|
|
|
63
|
-
1. In your cave_app
|
|
63
|
+
1. In your `cave_app`, update the following file:
|
|
64
64
|
|
|
65
65
|
`utils/run_server.sh`
|
|
66
66
|
```
|
|
@@ -80,12 +80,12 @@ pip install cave_utils
|
|
|
80
80
|
|
|
81
81
|
2. Remove `cave_utils` from the root `requirements.txt` file
|
|
82
82
|
|
|
83
|
-
3. In your cave_app
|
|
83
|
+
3. In your `cave_app`, set `LIVE_API_VALIDATION_PRINT=True` in the `.env` file
|
|
84
84
|
- This will validate your data every time an API command is called for each session
|
|
85
85
|
|
|
86
|
-
4. Use the following command to run your cave_app
|
|
86
|
+
4. Use the following command to run your `cave_app`:
|
|
87
87
|
`cave run --docker-args "--volume {local_path_to_cave_utils}/cave_utils:/cave_utils"`
|
|
88
|
-
- As you edit cave_utils
|
|
88
|
+
- As you edit `cave_utils`, any changes will be hotloaded into your running `cave_app`
|
|
89
89
|
|
|
90
90
|
## Using interactive mode and running tests
|
|
91
91
|
|
|
@@ -42,9 +42,9 @@ pip install cave_utils
|
|
|
42
42
|
|
|
43
43
|
# cave_utils development
|
|
44
44
|
|
|
45
|
-
## Using
|
|
45
|
+
## Using Local Hotloading
|
|
46
46
|
|
|
47
|
-
1. In your cave_app
|
|
47
|
+
1. In your `cave_app`, update the following file:
|
|
48
48
|
|
|
49
49
|
`utils/run_server.sh`
|
|
50
50
|
```
|
|
@@ -64,12 +64,12 @@ pip install cave_utils
|
|
|
64
64
|
|
|
65
65
|
2. Remove `cave_utils` from the root `requirements.txt` file
|
|
66
66
|
|
|
67
|
-
3. In your cave_app
|
|
67
|
+
3. In your `cave_app`, set `LIVE_API_VALIDATION_PRINT=True` in the `.env` file
|
|
68
68
|
- This will validate your data every time an API command is called for each session
|
|
69
69
|
|
|
70
|
-
4. Use the following command to run your cave_app
|
|
70
|
+
4. Use the following command to run your `cave_app`:
|
|
71
71
|
`cave run --docker-args "--volume {local_path_to_cave_utils}/cave_utils:/cave_utils"`
|
|
72
|
-
- As you edit cave_utils
|
|
72
|
+
- As you edit `cave_utils`, any changes will be hotloaded into your running `cave_app`
|
|
73
73
|
|
|
74
74
|
## Using interactive mode and running tests
|
|
75
75
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The cave_utils package is a collection of utility classes and functions that are used in the CAVE project.
|
|
3
|
+
|
|
4
|
+
On the left hand side, you will find all available submodules, and their associated docs.
|
|
5
|
+
|
|
6
|
+
Click on a submodule to see the documentation for that submodule.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .log import LogObject, LogHelper
|
|
10
|
+
from .socket import Socket
|
|
11
|
+
from .api_utils.validator import Validator
|
|
12
|
+
from .arguments import Arguments
|
|
13
|
+
from .geo_utils import GeoUtils
|
|
@@ -11,6 +11,7 @@ Submodules (and their classes) are used to define the api at each level. You can
|
|
|
11
11
|
|
|
12
12
|
See the left hand side for all available submodules.
|
|
13
13
|
"""
|
|
14
|
+
|
|
14
15
|
from cave_utils.api_utils.validator_utils import *
|
|
15
16
|
from cave_utils.api.extraKwargs import extraKwargs
|
|
16
17
|
from cave_utils.api.settings import settings
|
|
@@ -95,6 +96,9 @@ class Root(ApiValidator):
|
|
|
95
96
|
root_data=self.data,
|
|
96
97
|
**kwargs,
|
|
97
98
|
)
|
|
99
|
+
# Special logic to add timeLength to kwargs
|
|
100
|
+
# This is used to validate timeValues across the app
|
|
101
|
+
kwargs["timeLength"] = pamda.path(["settings", "time", "timeLength"], self.data)
|
|
98
102
|
# Validate panes
|
|
99
103
|
panes_data = self.data.get("panes")
|
|
100
104
|
pane_validPaneIds = []
|
|
@@ -12,6 +12,7 @@ simultaneously.
|
|
|
12
12
|
[predefined]: #appBar_data_star.spec
|
|
13
13
|
[custom]: #appBar_data_star.spec
|
|
14
14
|
"""
|
|
15
|
+
|
|
15
16
|
from cave_utils.api_utils.validator_utils import ApiValidator, CustomKeyValidator
|
|
16
17
|
import type_enforced
|
|
17
18
|
|
|
@@ -52,9 +53,8 @@ class appBar_data_star(ApiValidator):
|
|
|
52
53
|
bar: str,
|
|
53
54
|
variant: [str, None] = None,
|
|
54
55
|
color: [str, None] = None,
|
|
55
|
-
order: [dict, None] = None,
|
|
56
56
|
apiCommand: [str, None] = None,
|
|
57
|
-
apiCommandKeys: [list, None] = None,
|
|
57
|
+
apiCommandKeys: [list[str], None] = None,
|
|
58
58
|
**kwargs,
|
|
59
59
|
):
|
|
60
60
|
"""
|
|
@@ -88,7 +88,7 @@ class appBar_data_star(ApiValidator):
|
|
|
88
88
|
* **Note**: It must be a valid RGBA string.
|
|
89
89
|
* **Example**: `"rgba(255, 255, 255, 1)"`.
|
|
90
90
|
* **`apiCommand`**: `[str]` = `None` → The name of the [API command][] to trigger.
|
|
91
|
-
* **`apiCommandKeys`**: `[list]` = `None` →
|
|
91
|
+
* **`apiCommandKeys`**: `[list[str]]` = `None` →
|
|
92
92
|
* The root API keys to pass to your `execute_command` function if an
|
|
93
93
|
`apiCommand` is provided. If omitted, all API keys are
|
|
94
94
|
passed to `execute_command`.
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
These outputs should be general to the entire application and they can be compared across sessions.
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
from cave_utils.api_utils.validator_utils import ApiValidator, CustomKeyValidator
|
|
6
7
|
from cave_utils.api_utils.general import props, values, layout
|
|
7
8
|
import type_enforced
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Create grouped outputs for building generalized charts and tables.
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from cave_utils.api_utils.validator_utils import ApiValidator, CustomKeyValidator
|
|
5
6
|
import type_enforced
|
|
6
7
|
from pamda import pamda
|
|
@@ -279,13 +280,13 @@ class groupedOutputs_groupings_star(ApiValidator):
|
|
|
279
280
|
levels_data = self.data.get("levels", {})
|
|
280
281
|
levels_data_keys = list(levels_data.keys())
|
|
281
282
|
data_data = self.data.get("data", {})
|
|
282
|
-
|
|
283
283
|
CustomKeyValidator(
|
|
284
284
|
data=levels_data,
|
|
285
285
|
log=self.log,
|
|
286
286
|
prepend_path=["levels"],
|
|
287
287
|
validator=groupedOutputs_groupings_star_levels_star,
|
|
288
288
|
acceptable_parents=levels_data_keys,
|
|
289
|
+
acceptable_data_levels=data_data,
|
|
289
290
|
**kwargs,
|
|
290
291
|
)
|
|
291
292
|
groupedOutputs_groupings_star_data(
|
|
@@ -348,7 +349,14 @@ class groupedOutputs_groupings_star_levels_star(ApiValidator):
|
|
|
348
349
|
"""
|
|
349
350
|
|
|
350
351
|
@staticmethod
|
|
351
|
-
def spec(
|
|
352
|
+
def spec(
|
|
353
|
+
name: str,
|
|
354
|
+
parent: [str, None] = None,
|
|
355
|
+
ordering: [list, None] = None,
|
|
356
|
+
orderWithParent: bool = True,
|
|
357
|
+
coloring: [dict, None] = None,
|
|
358
|
+
**kwargs,
|
|
359
|
+
):
|
|
352
360
|
"""
|
|
353
361
|
Arguments:
|
|
354
362
|
|
|
@@ -358,16 +366,22 @@ class groupedOutputs_groupings_star_levels_star(ApiValidator):
|
|
|
358
366
|
* **Notes**:
|
|
359
367
|
* The parent level key must be defined in `groupedOutputs.groupings.*.levels.*`
|
|
360
368
|
* If `None`, this will be considered to be the root of the hierarchy.
|
|
369
|
+
* **`ordering`**: `[list]` →
|
|
370
|
+
* The ordering of individual values for this level in charts and tables.
|
|
371
|
+
* **Note**: If none, the ordering will be alphabetical.
|
|
372
|
+
* **Note**: If a partial ordering is provided, the provided values will be placed first in order.
|
|
373
|
+
* **Note**: If a partial ordering is provided, the remaining values will be placed in alphabetical order.
|
|
374
|
+
* **Note**: All items in this list must be defined in `groupedOutputs.groupings.*.levels.*.values.*`
|
|
375
|
+
* **`orderWithParent`**: `[bool]`=True →
|
|
376
|
+
* Weather or not to order this level based on the parent level.
|
|
377
|
+
* If `True`, the ordering of this level will also be based on the parent level.
|
|
378
|
+
* If `False`, the ordering will be based on the ordering of this level only.
|
|
379
|
+
* **`coloring`**: `[dict]` →
|
|
380
|
+
* A dictionary of colors to be used for the level.
|
|
381
|
+
* Each key in this dictionary is a value in the level.
|
|
382
|
+
* Each value in this dictionary is an rgba string.
|
|
383
|
+
* **See**: `cave_utils.api.groupedOutputs.groupedOutputs_groupings_star_levels_star_coloring`
|
|
361
384
|
"""
|
|
362
|
-
# TODO: Figure out new way for ordering
|
|
363
|
-
# - `ordering`:
|
|
364
|
-
# - Type: list
|
|
365
|
-
# - What: The ordering of individual values for this level in charts and tables.
|
|
366
|
-
# - Note: If none, the ordering will be alphabetical.
|
|
367
|
-
# - Note: If a partial ordering is provided, the provided values will be placed first in order.
|
|
368
|
-
# - Note: If a partial ordering is provided, the remaining values will be placed in alphabetical order.
|
|
369
|
-
# - Note: All items in this list must be defined in `groupedOutputs.groupings.*.levels.*.values.*`
|
|
370
|
-
# """
|
|
371
385
|
return {"kwargs": kwargs, "accepted_values": {}}
|
|
372
386
|
|
|
373
387
|
def __extend_spec__(self, **kwargs):
|
|
@@ -378,9 +392,24 @@ class groupedOutputs_groupings_star_levels_star(ApiValidator):
|
|
|
378
392
|
valid_values=kwargs.get("acceptable_parents", []),
|
|
379
393
|
prepend_path=["parent"],
|
|
380
394
|
)
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
395
|
+
ordering = self.data.get("ordering")
|
|
396
|
+
if ordering is not None:
|
|
397
|
+
self.__check_subset_valid__(
|
|
398
|
+
subset=ordering,
|
|
399
|
+
valid_values=kwargs.get("acceptable_data_levels", {}).get(
|
|
400
|
+
kwargs.get("CustomKeyValidatorFieldId"), []
|
|
401
|
+
),
|
|
402
|
+
prepend_path=["ordering"],
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
coloring = self.data.get("coloring")
|
|
406
|
+
if coloring is not None:
|
|
407
|
+
self.__check_subset_valid__(
|
|
408
|
+
subset=list(coloring.keys()),
|
|
409
|
+
valid_values=kwargs.get("acceptable_data_levels", {}).get(
|
|
410
|
+
kwargs.get("CustomKeyValidatorFieldId"), []
|
|
411
|
+
),
|
|
412
|
+
prepend_path=["coloring"],
|
|
413
|
+
)
|
|
414
|
+
for key, value in coloring.items():
|
|
415
|
+
self.__check_rgba_string_valid__(rgba_string=value, prepend_path=["coloring", key])
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Create visualizations for your map, including `arc`s, `node`s, and `geo`s, and customize their appearance.
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from cave_utils.api_utils.validator_utils import ApiValidator, CustomKeyValidator
|
|
5
6
|
from cave_utils.api_utils.general import props, valueLists, layout
|
|
6
7
|
import type_enforced
|
|
@@ -155,8 +156,8 @@ class mapFeatures_data_star_data(ApiValidator):
|
|
|
155
156
|
**kwargs,
|
|
156
157
|
)
|
|
157
158
|
# Validate that all lengths are the same
|
|
158
|
-
lengths = [len(v) for k, v in location_data.items() if k not in ["
|
|
159
|
-
len(v) for k, v in valueLists_data.items() if k not in ["
|
|
159
|
+
lengths = [len(v) for k, v in location_data.items() if k not in ["timeValues", "order"]] + [
|
|
160
|
+
len(v) for k, v in valueLists_data.items() if k not in ["timeValues", "order"]
|
|
160
161
|
]
|
|
161
162
|
if len(set(lengths)) > 1:
|
|
162
163
|
self.__error__(msg=f"location and valueLists keys must have the same length.", path=[])
|
|
@@ -185,16 +186,35 @@ class mapFeatures_data_star_data_location(ApiValidator):
|
|
|
185
186
|
layer_type = kwargs.get("layer_type")
|
|
186
187
|
layer_geoJson = kwargs.get("layer_geoJson")
|
|
187
188
|
passed_keys = list(self.data.keys())
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if layer_type == "geo" or (layer_type == "arc" and layer_geoJson):
|
|
189
|
+
optional_keys = []
|
|
190
|
+
if layer_type == "geo":
|
|
191
191
|
required_keys = ["geoJsonValue"]
|
|
192
192
|
elif layer_type == "arc":
|
|
193
|
-
if
|
|
193
|
+
if layer_geoJson is not None:
|
|
194
|
+
required_keys = ["geoJsonValue"]
|
|
195
|
+
optional_keys += [
|
|
196
|
+
"path",
|
|
197
|
+
"startLatitude",
|
|
198
|
+
"startLongitude",
|
|
199
|
+
"endLatitude",
|
|
200
|
+
"endLongitude",
|
|
201
|
+
"startAltitude",
|
|
202
|
+
"endAltitude",
|
|
203
|
+
]
|
|
204
|
+
elif "path" in passed_keys:
|
|
194
205
|
required_keys = ["path"]
|
|
206
|
+
optional_keys += [
|
|
207
|
+
"startLatitude",
|
|
208
|
+
"startLongitude",
|
|
209
|
+
"endLatitude",
|
|
210
|
+
"endLongitude",
|
|
211
|
+
"geoJsonValue",
|
|
212
|
+
"startAltitude",
|
|
213
|
+
"endAltitude",
|
|
214
|
+
]
|
|
195
215
|
else:
|
|
196
216
|
required_keys = ["startLatitude", "startLongitude", "endLatitude", "endLongitude"]
|
|
197
|
-
optional_keys += ["startAltitude", "endAltitude"]
|
|
217
|
+
optional_keys += ["startAltitude", "endAltitude", "geoJsonValue", "path"]
|
|
198
218
|
else:
|
|
199
219
|
required_keys = ["latitude", "longitude"]
|
|
200
220
|
optional_keys += ["altitude"]
|
|
@@ -209,8 +229,12 @@ class mapFeatures_data_star_data_location(ApiValidator):
|
|
|
209
229
|
path=[],
|
|
210
230
|
)
|
|
211
231
|
continue
|
|
212
|
-
if key
|
|
213
|
-
|
|
232
|
+
if key == "geoJsonValue":
|
|
233
|
+
if len(value_list) != len(set(value_list)):
|
|
234
|
+
self.__warn__(
|
|
235
|
+
msg=f"`geoJsonValue` should be a list of unique values. Otherwise, the corresponding map feature may not render correctly.",
|
|
236
|
+
path=[key],
|
|
237
|
+
)
|
|
214
238
|
if not isinstance(value_list, list):
|
|
215
239
|
self.__error__(
|
|
216
240
|
msg=f"`{key}` must be a list but got {type(value_list)} instead.", path=[key]
|
|
@@ -240,7 +264,7 @@ class mapFeatures_data_star_data_location(ApiValidator):
|
|
|
240
264
|
altitudes = None
|
|
241
265
|
except:
|
|
242
266
|
self.__error__(
|
|
243
|
-
msg=f"`path` must be a list of lists of lists of length 2 or 3. EG: `[[[0,0],[1,1]],[[2,2],[3,3],[4,4],[5,5]]]`",
|
|
267
|
+
msg=f"`path` must be a list of lists of lists of length 2 [long,lat] or 3 [long,lat,alt]. EG: `[[[0,0],[1,1]],[[2,2],[3,3],[4,4],[5,5]]]`",
|
|
244
268
|
path=[key],
|
|
245
269
|
)
|
|
246
270
|
continue
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Configure your application's pages.
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from cave_utils.api_utils.validator_utils import ApiValidator, CustomKeyValidator
|
|
5
6
|
import type_enforced
|
|
6
7
|
|
|
@@ -82,6 +83,7 @@ class pages_data_star_pageLayout(ApiValidator):
|
|
|
82
83
|
statId: [str, list, None] = None,
|
|
83
84
|
showToolbar: bool = True,
|
|
84
85
|
maximized: bool = False,
|
|
86
|
+
defaultToZero: bool = False,
|
|
85
87
|
**kwargs,
|
|
86
88
|
):
|
|
87
89
|
"""
|
|
@@ -135,6 +137,7 @@ class pages_data_star_pageLayout(ApiValidator):
|
|
|
135
137
|
* **Note**: If left unspecified (i.e., `None`), it will default to `settings.showToolbar`.
|
|
136
138
|
* **`maximized`**: `[bool]` = `False` → Whether or not the layout should be maximized.
|
|
137
139
|
* **Note**: If more than one chart belonging to the same page layout is set to `True`, the first one found in the list will take precedence.
|
|
140
|
+
* **`defaultToZero`**: `[bool]` = `False` → Whether or not the chart should default missing values to zero.
|
|
138
141
|
|
|
139
142
|
[area chart]: https://en.wikipedia.org/wiki/Area_chart
|
|
140
143
|
[bar chart]: https://en.wikipedia.org/wiki/Bar_chart
|
|
@@ -3,6 +3,7 @@ Panes serve as main containers for UI controls such as toggles, text
|
|
|
3
3
|
and number fields, sliders, etc. They can also contain buttons that
|
|
4
4
|
facilitate interaction with actionable data.
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
from cave_utils.api_utils.validator_utils import ApiValidator, CustomKeyValidator
|
|
7
8
|
from cave_utils.api_utils.general import props, values, layout
|
|
8
9
|
import type_enforced
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Configure general settings for your application like the icons to use, how to sync data with the server, and more.
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from cave_utils.api_utils.validator_utils import *
|
|
5
6
|
import type_enforced
|
|
6
7
|
|
|
@@ -291,3 +292,8 @@ class settings_time(ApiValidator):
|
|
|
291
292
|
* **Example**: `"Decade"`.
|
|
292
293
|
"""
|
|
293
294
|
return {"kwargs": kwargs, "accepted_values": {}}
|
|
295
|
+
|
|
296
|
+
def __extend_spec__(self, **kwargs):
|
|
297
|
+
timeLength = self.data.get("timeLength")
|
|
298
|
+
if timeLength < 1:
|
|
299
|
+
self.__error__(f"Time length must be greater than 0.", path=["timeLength"])
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
## Validation
|
|
3
|
+
|
|
4
|
+
This code can be used directly for validation purposes:
|
|
5
|
+
|
|
6
|
+
```py
|
|
7
|
+
from cave_utils import Validator
|
|
8
|
+
|
|
9
|
+
session_data = {
|
|
10
|
+
"kwargs": {
|
|
11
|
+
"wipeExisting": True,
|
|
12
|
+
},
|
|
13
|
+
# All of your session data to validate here
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
x = Validator(
|
|
17
|
+
session_data=session_data,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
print(x.log.log)
|
|
21
|
+
```
|
|
22
|
+
"""
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
General API Spec items that are found in multiple places. This is not a key that should be passed as part of your `session_data`.
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from pamda import pamda
|
|
5
6
|
import type_enforced
|
|
6
7
|
from cave_utils.api_utils.validator_utils import ApiValidator, CustomKeyValidator
|
|
@@ -17,7 +18,7 @@ class props(ApiValidator):
|
|
|
17
18
|
display: [bool, None] = None,
|
|
18
19
|
enabled: [bool, None] = None,
|
|
19
20
|
apiCommand: [str, None] = None,
|
|
20
|
-
apiCommandKeys: [list, None] = None,
|
|
21
|
+
apiCommandKeys: [list[str], None] = None,
|
|
21
22
|
options: [dict, None] = None,
|
|
22
23
|
placeholder: [str, None] = None,
|
|
23
24
|
maxValue: [float, int, None] = None,
|
|
@@ -29,7 +30,7 @@ class props(ApiValidator):
|
|
|
29
30
|
precision: [int, None] = None,
|
|
30
31
|
notationDisplay: [str, None] = None,
|
|
31
32
|
unit: [str, None] = None,
|
|
32
|
-
views: [list, None] = None,
|
|
33
|
+
views: [list[str], None] = None,
|
|
33
34
|
legendNotation: [str, None] = None,
|
|
34
35
|
legendPrecision: [int, None] = None,
|
|
35
36
|
legendNotationDisplay: [str, None] = None,
|
|
@@ -99,7 +100,7 @@ class props(ApiValidator):
|
|
|
99
100
|
* **`apiCommand`**: `[str]` = `None` → The name of the API command to trigger.
|
|
100
101
|
* **Note**: If `None`, no `apiCommand` is triggered.
|
|
101
102
|
* **Note**: This attribute is applicable to all props except `"head"` props.
|
|
102
|
-
* **`apiCommandKeys`**: `[list]` = `None` →
|
|
103
|
+
* **`apiCommandKeys`**: `[list[str]]` = `None` →
|
|
103
104
|
* The root API keys to pass to your `execute_command` function if an `apiCommand` is provided.
|
|
104
105
|
* **Note**: If `None`, all API keys are passed to your `execute_command`.
|
|
105
106
|
* **Note**: This attribute is applicable to all props except `"head"` props.
|
|
@@ -126,15 +127,28 @@ class props(ApiValidator):
|
|
|
126
127
|
* **`rows`**: `[int]` = `None` →
|
|
127
128
|
* The fixed number of rows to show for a `"textarea"` variant.
|
|
128
129
|
* **Note**: This attribute is applicable exclusively to `"text"` props.
|
|
129
|
-
* **`views`**: `[list
|
|
130
|
+
* **`views`**: `[list[str]]` →
|
|
130
131
|
* The available time units for the represented date and/or time.
|
|
132
|
+
* **Default Value**:
|
|
133
|
+
* When **`variant`** == `"date"`: `["year", "day"]`
|
|
134
|
+
* When **`variant`** == `"time"`: `["hours", "minutes"]`
|
|
135
|
+
* When **`variant`** == `"datetime"`: `["year", "day", "hours", "minutes"]`
|
|
131
136
|
* **Accepted Values**:
|
|
132
|
-
* `"
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
* `"
|
|
137
|
-
|
|
137
|
+
* When **`variant`** == `"date"`:
|
|
138
|
+
* `"year"`: The year view
|
|
139
|
+
* `"month"`: The month view
|
|
140
|
+
* `"day"`: The day view
|
|
141
|
+
* When **`variant`** == `"time"`:
|
|
142
|
+
* `"hours"`: The hours view
|
|
143
|
+
* `"minutes"`: The minutes view
|
|
144
|
+
* `"seconds"`: The seconds view
|
|
145
|
+
* When **`variant`** == `"datetime"`:
|
|
146
|
+
* `"year"`: The year view
|
|
147
|
+
* `"month"`: The month view
|
|
148
|
+
* `"day"`: The day view
|
|
149
|
+
* `"hours"`: The hours view
|
|
150
|
+
* `"minutes"`: The minutes view
|
|
151
|
+
* `"seconds"`: The seconds view
|
|
138
152
|
* **Notes**:
|
|
139
153
|
* The views will be presented in the order specified in the `views` array.
|
|
140
154
|
* This attribute is applicable exclusively to `"date"` props.
|
|
@@ -173,7 +187,7 @@ class props(ApiValidator):
|
|
|
173
187
|
* **Notes**:
|
|
174
188
|
* If left unspecified (i.e., `None`), it will default to `settings.defaults.unitPlacement`.
|
|
175
189
|
* This attribute is applicable exclusively to `"num"` props.
|
|
176
|
-
* **`notation`**: `[
|
|
190
|
+
* **`notation`**: `[str]` = `"standard"` → The formatting style of a numeric value.
|
|
177
191
|
* **Accepted Values**:
|
|
178
192
|
* `"standard"`: Plain number formatting
|
|
179
193
|
* `"compact"`: Resembles the [metric prefix][] system
|
|
@@ -184,14 +198,18 @@ class props(ApiValidator):
|
|
|
184
198
|
* This attribute is applicable exclusively to `"num"` props.
|
|
185
199
|
* **`notationDisplay`**: `[str]` = `"e+"` | `"short"` → Further customize the formatting within the selected `notation`.
|
|
186
200
|
* **Accepted Values**:
|
|
187
|
-
*
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
* `"
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
201
|
+
* When **`notation`** == `"compact"`:
|
|
202
|
+
* `"short"`: Add symbols `K`, `M`, `B`, and `T` (in `"en-US"`) to denote thousands, millions, billions, and trillions, respectively.
|
|
203
|
+
* `"long"`: Present numeric values with the informal suffix words `thousand`, `million`, `billion`, and `trillion` (in `"en-US"`).
|
|
204
|
+
* When **`notation`** == `"scientific"` or `"engineering"`:
|
|
205
|
+
* `"e"`: Exponent symbol in lowercase as per the chosen `locale` identifier
|
|
206
|
+
* `"e+"`: Similar to `"e"`, but with a plus sign for positive exponents.
|
|
207
|
+
* `"E"`: Exponent symbol in uppercase as per the chosen `locale` identifier
|
|
208
|
+
* `"E+"`: Similar to `"E"`, but with a plus sign for positive exponents.
|
|
209
|
+
* `"x10^"`: Formal scientific notation representation
|
|
210
|
+
* `"x10^+"`: Similar to `"x10^"`, with a plus sign for positive exponents.
|
|
211
|
+
* When **`notation`** == `"standard"`:
|
|
212
|
+
* No `notationDisplay` option is allowed for a `"standard"` notation
|
|
195
213
|
* **Notes**:
|
|
196
214
|
* No `notationDisplay` option is provided for a `"standard"` notation
|
|
197
215
|
* The options `"short"` and `"long"` are only provided for the `"compact"` notation
|
|
@@ -304,20 +322,30 @@ class props(ApiValidator):
|
|
|
304
322
|
for k, v in passed_values.items():
|
|
305
323
|
if k not in required_fields + optional_fields:
|
|
306
324
|
kwargs[k] = v
|
|
325
|
+
notationDisplay_options_dict = {
|
|
326
|
+
"compact": ["short", "long"],
|
|
327
|
+
"scientific": ["e", "e+", "E", "E+", "x10^", "x10^+"],
|
|
328
|
+
"engineering": ["e", "e+", "E", "E+", "x10^", "x10^+"],
|
|
329
|
+
"standard": [],
|
|
330
|
+
}
|
|
331
|
+
notation = passed_values.get("notation", "standard")
|
|
332
|
+
legendNotation = passed_values.get("legendNotation", "standard")
|
|
333
|
+
view_options_dict = {
|
|
334
|
+
"date": ["year", "month", "day"],
|
|
335
|
+
"time": ["hours", "minutes", "seconds"],
|
|
336
|
+
"datetime": ["year", "month", "day", "hours", "minutes", "seconds"],
|
|
337
|
+
}
|
|
338
|
+
variant = passed_values.get("variant", None)
|
|
307
339
|
return {
|
|
308
340
|
"kwargs": kwargs,
|
|
309
341
|
"accepted_values": {
|
|
310
342
|
"type": ["head", "num", "toggle", "button", "text", "selector", "date", "media"],
|
|
311
|
-
"views":
|
|
343
|
+
"views": view_options_dict.get(variant, []),
|
|
312
344
|
"unitPlacement": ["after", "afterWithSpace", "before", "beforeWithSpace"],
|
|
313
|
-
# TODO: Validate
|
|
314
|
-
# compact: allowed notation displays -> "short", "long"
|
|
315
|
-
# scientific|engineering: allowed notation displays -> "e", "e+", "E", "E+", "x10^", "x10^+"
|
|
316
|
-
# standard: allowed notation displays -> None
|
|
317
345
|
"notation": ["compact", "precision", "scientific", "engineering"],
|
|
318
|
-
"notationDisplay":
|
|
346
|
+
"notationDisplay": notationDisplay_options_dict.get(notation, []),
|
|
319
347
|
"legendNotation": ["compact", "precision", "scientific", "engineering"],
|
|
320
|
-
"legendNotationDisplay":
|
|
348
|
+
"legendNotationDisplay": notationDisplay_options_dict.get(legendNotation, []),
|
|
321
349
|
"variant": {
|
|
322
350
|
"head": ["column", "row", "icon", "iconRow"],
|
|
323
351
|
"text": ["textarea"],
|
|
@@ -350,14 +378,15 @@ class props(ApiValidator):
|
|
|
350
378
|
)
|
|
351
379
|
|
|
352
380
|
|
|
381
|
+
@type_enforced.Enforcer
|
|
353
382
|
class props_options(ApiValidator):
|
|
354
383
|
@staticmethod
|
|
355
|
-
def spec(name: str, path: [list, None] = None, **kwargs):
|
|
384
|
+
def spec(name: str, path: [list[str], None] = None, **kwargs):
|
|
356
385
|
"""
|
|
357
386
|
Arguments:
|
|
358
387
|
|
|
359
388
|
* **`name`**: `[str]` → The name of the option.
|
|
360
|
-
* **`path`**: `[list]` = `None` → The path to an option.
|
|
389
|
+
* **`path`**: `[list[str]]` = `None` → The path to an option.
|
|
361
390
|
* **Notes**:
|
|
362
391
|
* If `None`, the option will not be selectable
|
|
363
392
|
* This attribute is applicable exclusively to `"nested"` props
|
|
@@ -379,9 +408,6 @@ class props_options(ApiValidator):
|
|
|
379
408
|
msg="`path` must be specified and a list of strings for nested options"
|
|
380
409
|
)
|
|
381
410
|
return
|
|
382
|
-
self.__check_type_list__(
|
|
383
|
-
data=self.data.get("path", []), types=(str,), prepend_path=["path"]
|
|
384
|
-
)
|
|
385
411
|
|
|
386
412
|
|
|
387
413
|
@type_enforced.Enforcer
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
This module contains the primary Validator class that is used to validate your session_data against the API spec.
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from cave_utils.api_utils.validator_utils import LogObject
|
|
5
6
|
from cave_utils.api import Root
|
|
6
7
|
import type_enforced
|
|
@@ -8,7 +9,7 @@ import type_enforced
|
|
|
8
9
|
|
|
9
10
|
@type_enforced.Enforcer
|
|
10
11
|
class Validator:
|
|
11
|
-
def __init__(self, session_data, ignore_keys: list = list(), **kwargs):
|
|
12
|
+
def __init__(self, session_data, ignore_keys: list[str] = list(), **kwargs):
|
|
12
13
|
"""
|
|
13
14
|
Util to validate your session_data against the API spec.
|
|
14
15
|
|
|
@@ -16,7 +17,7 @@ class Validator:
|
|
|
16
17
|
|
|
17
18
|
* **`session_data`**: `[dict]` → The data to validate.
|
|
18
19
|
* **Note**: This should be the data you are sending to the server.
|
|
19
|
-
* **`ignore_keys`**: `[list]` = `None` → Keys to ignore when validating.
|
|
20
|
+
* **`ignore_keys`**: `[list[str]]` = `None` → Keys to ignore when validating.
|
|
20
21
|
* **Note**: Any keys specified here will be not be validated if encountered in the data at any level.
|
|
21
22
|
"""
|
|
22
23
|
self.session_data = session_data
|