squirrels 0.1.0__py3-none-any.whl → 0.6.0.post0__py3-none-any.whl

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.
Files changed (127) hide show
  1. dateutils/__init__.py +6 -0
  2. dateutils/_enums.py +25 -0
  3. squirrels/dateutils.py → dateutils/_implementation.py +409 -380
  4. dateutils/types.py +6 -0
  5. squirrels/__init__.py +21 -18
  6. squirrels/_api_routes/__init__.py +5 -0
  7. squirrels/_api_routes/auth.py +337 -0
  8. squirrels/_api_routes/base.py +196 -0
  9. squirrels/_api_routes/dashboards.py +156 -0
  10. squirrels/_api_routes/data_management.py +148 -0
  11. squirrels/_api_routes/datasets.py +220 -0
  12. squirrels/_api_routes/project.py +289 -0
  13. squirrels/_api_server.py +552 -134
  14. squirrels/_arguments/__init__.py +0 -0
  15. squirrels/_arguments/init_time_args.py +83 -0
  16. squirrels/_arguments/run_time_args.py +111 -0
  17. squirrels/_auth.py +777 -0
  18. squirrels/_command_line.py +239 -107
  19. squirrels/_compile_prompts.py +147 -0
  20. squirrels/_connection_set.py +94 -0
  21. squirrels/_constants.py +141 -64
  22. squirrels/_dashboards.py +179 -0
  23. squirrels/_data_sources.py +570 -0
  24. squirrels/_dataset_types.py +91 -0
  25. squirrels/_env_vars.py +209 -0
  26. squirrels/_exceptions.py +29 -0
  27. squirrels/_http_error_responses.py +52 -0
  28. squirrels/_initializer.py +319 -110
  29. squirrels/_logging.py +121 -0
  30. squirrels/_manifest.py +357 -187
  31. squirrels/_mcp_server.py +578 -0
  32. squirrels/_model_builder.py +69 -0
  33. squirrels/_model_configs.py +74 -0
  34. squirrels/_model_queries.py +52 -0
  35. squirrels/_models.py +1201 -0
  36. squirrels/_package_data/base_project/.env +7 -0
  37. squirrels/_package_data/base_project/.env.example +44 -0
  38. squirrels/_package_data/base_project/connections.yml +16 -0
  39. squirrels/_package_data/base_project/dashboards/dashboard_example.py +40 -0
  40. squirrels/_package_data/base_project/dashboards/dashboard_example.yml +22 -0
  41. squirrels/_package_data/base_project/docker/.dockerignore +16 -0
  42. squirrels/_package_data/base_project/docker/Dockerfile +16 -0
  43. squirrels/_package_data/base_project/docker/compose.yml +7 -0
  44. squirrels/_package_data/base_project/duckdb_init.sql +10 -0
  45. squirrels/_package_data/base_project/gitignore +13 -0
  46. squirrels/_package_data/base_project/macros/macros_example.sql +17 -0
  47. squirrels/_package_data/base_project/models/builds/build_example.py +26 -0
  48. squirrels/_package_data/base_project/models/builds/build_example.sql +16 -0
  49. squirrels/_package_data/base_project/models/builds/build_example.yml +57 -0
  50. squirrels/_package_data/base_project/models/dbviews/dbview_example.sql +17 -0
  51. squirrels/_package_data/base_project/models/dbviews/dbview_example.yml +32 -0
  52. squirrels/_package_data/base_project/models/federates/federate_example.py +51 -0
  53. squirrels/_package_data/base_project/models/federates/federate_example.sql +21 -0
  54. squirrels/_package_data/base_project/models/federates/federate_example.yml +65 -0
  55. squirrels/_package_data/base_project/models/sources.yml +38 -0
  56. squirrels/_package_data/base_project/parameters.yml +142 -0
  57. squirrels/_package_data/base_project/pyconfigs/connections.py +19 -0
  58. squirrels/_package_data/base_project/pyconfigs/context.py +96 -0
  59. squirrels/_package_data/base_project/pyconfigs/parameters.py +141 -0
  60. squirrels/_package_data/base_project/pyconfigs/user.py +56 -0
  61. squirrels/_package_data/base_project/resources/expenses.db +0 -0
  62. squirrels/_package_data/base_project/resources/public/.gitkeep +0 -0
  63. squirrels/_package_data/base_project/resources/weather.db +0 -0
  64. squirrels/_package_data/base_project/seeds/seed_categories.csv +6 -0
  65. squirrels/_package_data/base_project/seeds/seed_categories.yml +15 -0
  66. squirrels/_package_data/base_project/seeds/seed_subcategories.csv +15 -0
  67. squirrels/_package_data/base_project/seeds/seed_subcategories.yml +21 -0
  68. squirrels/_package_data/base_project/squirrels.yml.j2 +61 -0
  69. squirrels/_package_data/base_project/tmp/.gitignore +2 -0
  70. squirrels/_package_data/templates/login_successful.html +53 -0
  71. squirrels/_package_data/templates/squirrels_studio.html +22 -0
  72. squirrels/_package_loader.py +29 -0
  73. squirrels/_parameter_configs.py +592 -0
  74. squirrels/_parameter_options.py +348 -0
  75. squirrels/_parameter_sets.py +207 -0
  76. squirrels/_parameters.py +1703 -0
  77. squirrels/_project.py +796 -0
  78. squirrels/_py_module.py +122 -0
  79. squirrels/_request_context.py +33 -0
  80. squirrels/_schemas/__init__.py +0 -0
  81. squirrels/_schemas/auth_models.py +83 -0
  82. squirrels/_schemas/query_param_models.py +70 -0
  83. squirrels/_schemas/request_models.py +26 -0
  84. squirrels/_schemas/response_models.py +286 -0
  85. squirrels/_seeds.py +97 -0
  86. squirrels/_sources.py +112 -0
  87. squirrels/_utils.py +540 -149
  88. squirrels/_version.py +1 -3
  89. squirrels/arguments.py +7 -0
  90. squirrels/auth.py +4 -0
  91. squirrels/connections.py +3 -0
  92. squirrels/dashboards.py +3 -0
  93. squirrels/data_sources.py +14 -282
  94. squirrels/parameter_options.py +13 -189
  95. squirrels/parameters.py +14 -801
  96. squirrels/types.py +18 -0
  97. squirrels-0.6.0.post0.dist-info/METADATA +148 -0
  98. squirrels-0.6.0.post0.dist-info/RECORD +101 -0
  99. {squirrels-0.1.0.dist-info → squirrels-0.6.0.post0.dist-info}/WHEEL +1 -2
  100. {squirrels-0.1.0.dist-info → squirrels-0.6.0.post0.dist-info}/entry_points.txt +1 -0
  101. squirrels-0.6.0.post0.dist-info/licenses/LICENSE +201 -0
  102. squirrels/_credentials_manager.py +0 -87
  103. squirrels/_module_loader.py +0 -37
  104. squirrels/_parameter_set.py +0 -151
  105. squirrels/_renderer.py +0 -286
  106. squirrels/_timed_imports.py +0 -37
  107. squirrels/connection_set.py +0 -126
  108. squirrels/package_data/base_project/.gitignore +0 -4
  109. squirrels/package_data/base_project/connections.py +0 -21
  110. squirrels/package_data/base_project/database/sample_database.db +0 -0
  111. squirrels/package_data/base_project/database/seattle_weather.db +0 -0
  112. squirrels/package_data/base_project/datasets/sample_dataset/context.py +0 -8
  113. squirrels/package_data/base_project/datasets/sample_dataset/database_view1.py +0 -23
  114. squirrels/package_data/base_project/datasets/sample_dataset/database_view1.sql.j2 +0 -7
  115. squirrels/package_data/base_project/datasets/sample_dataset/final_view.py +0 -10
  116. squirrels/package_data/base_project/datasets/sample_dataset/final_view.sql.j2 +0 -2
  117. squirrels/package_data/base_project/datasets/sample_dataset/parameters.py +0 -30
  118. squirrels/package_data/base_project/datasets/sample_dataset/selections.cfg +0 -6
  119. squirrels/package_data/base_project/squirrels.yaml +0 -26
  120. squirrels/package_data/static/favicon.ico +0 -0
  121. squirrels/package_data/static/script.js +0 -234
  122. squirrels/package_data/static/style.css +0 -110
  123. squirrels/package_data/templates/index.html +0 -32
  124. squirrels-0.1.0.dist-info/LICENSE +0 -22
  125. squirrels-0.1.0.dist-info/METADATA +0 -67
  126. squirrels-0.1.0.dist-info/RECORD +0 -40
  127. squirrels-0.1.0.dist-info/top_level.txt +0 -1
squirrels/parameters.py CHANGED
@@ -1,801 +1,14 @@
1
- from __future__ import annotations
2
- from typing import Type, Sequence, Dict, List, Iterator, Optional, Union
3
- from dataclasses import dataclass
4
- from datetime import datetime
5
- from decimal import Decimal
6
- import copy
7
-
8
- from squirrels import parameter_options as po, _utils as u
9
- from squirrels.data_sources import DataSource
10
- from squirrels._parameter_set import ParameterSetBase
11
- from squirrels._timed_imports import pandas as pd
12
-
13
-
14
- @dataclass
15
- class Parameter:
16
- """
17
- Abstract class for all parameter classes. Useful for type hints.
18
- """
19
- widget_type: str
20
- name: str
21
- label: str
22
- all_options: Sequence[po.ParameterOption]
23
- is_hidden: bool
24
- parent: Optional[_SelectionParameter]
25
-
26
- def WithParent(all_options: Sequence[po.ParameterOption], parent: SingleSelectParameter, new_param: Parameter):
27
- """
28
- Helper class method to assign a SingleSelectParameter as the parent for another parameter
29
-
30
- Parameters:
31
- all_options: The list of options with one of "parent_option_id" or "parent_option_ids" attribute set.
32
- parent: The parent parameter. All option ids of the parent must exist at least once in "parent_option_ids" of all_options
33
- new_param: The child parameter to modify. Usually not a selection parameter
34
- """
35
- new_param._set_parent_and_options(parent, all_options)
36
- new_param.parent._add_child_mutate(new_param)
37
- return new_param.refresh(parent)
38
-
39
- def refresh(self, parent: Optional[_SelectionParameter] = None) -> Parameter:
40
- """
41
- Refreshes the selectable options (or change of default value) based on the selection of the parent parameter
42
-
43
- Parameters:
44
- parent: The parent parameter subscribed to for updates
45
-
46
- Returns:
47
- A copy of self for the new selectable options based on current selection of parent
48
- """
49
- param_copy = copy.copy(self)
50
- if parent is not None:
51
- param_copy.parent = parent
52
- param_copy._refresh_mutate()
53
- return param_copy
54
-
55
- def with_selection(self, _: str) -> Parameter:
56
- """
57
- Abstract method for applying the selection to the parameter
58
- """
59
- raise u.AbstractMethodCallError(self.__class__, "with_selection")
60
-
61
- def get_all_dependent_params(self) -> ParameterSetBase:
62
- """
63
- Gets the collection of descendent parameters with changes applied based on the selection of this parameter
64
-
65
- Returns:
66
- A collection of descendent parameters as a ParameterSetBase
67
- """
68
- dependent_params = ParameterSetBase()
69
- self._accum_all_dependent_params(dependent_params)
70
- return dependent_params
71
-
72
- def _set_default_as_selection_mutate(self) -> None:
73
- raise u.AbstractMethodCallError(self.__class__, "_set_default_as_selection_mutate")
74
-
75
- def _refresh_mutate(self) -> None:
76
- if self.parent is not None and hasattr(self, 'curr_option'):
77
- self.curr_option = next(self._get_valid_options_iterator())
78
- self._set_default_as_selection_mutate()
79
-
80
- def _get_valid_options_iterator(self) -> Iterator[po.ParameterOption]:
81
- selected_parent_option_ids = self.parent._get_selected_ids_as_list()
82
- return (x for x in self.all_options if x.is_valid(selected_parent_option_ids))
83
-
84
- def _raise_invalid_input_error(self, selection: str, more_details: str = '', e: Exception = None) -> None:
85
- raise u.InvalidInputError(f'Selected value "{selection}" is not valid for parameter "{self.name}". ' + more_details) from e
86
-
87
- def _verify_parent_is_single_select(self) -> None:
88
- if not isinstance(self.parent, SingleSelectParameter):
89
- raise u.ConfigurationError(f'For "{self.name}", it''s not a selection parameter, so its parent must be a SingleSelectParameter')
90
-
91
- def _verify_parent_options_have_one_child_each(self) -> None:
92
- accum_set = set()
93
- for option in self.all_options:
94
- if not accum_set.isdisjoint(option.parent_option_ids):
95
- raise u.ConfigurationError(f'For "{self.name}", it''s not a selection parameter, so no two options can share the same parent option')
96
- accum_set = accum_set.union(option.parent_option_ids)
97
- if len(accum_set) != len(self.parent.options):
98
- raise u.ConfigurationError(f'For "{self.name}", all parent option ids must exist across all options')
99
-
100
- def _set_parent_and_options(self, parent: SingleSelectParameter, all_options: Sequence[po.ParameterOption]) -> None:
101
- self.parent = parent
102
- self.all_options = all_options
103
- self._verify_parent_is_single_select()
104
- self._verify_parent_options_have_one_child_each()
105
-
106
- def _accum_all_dependent_params(self, param_set: ParameterSetBase) -> None:
107
- param_set.add_parameter(self)
108
-
109
- def _enquote(self, value: str) -> str:
110
- return "'" + value.replace("'", "''") + "'"
111
-
112
- def to_json_dict(self) -> Dict:
113
- """
114
- Helper method to convert the derived Parameter class into a JSON dictionary
115
- """
116
- return {
117
- 'widget_type': self.widget_type,
118
- 'name': self.name,
119
- 'label': self.label
120
- }
121
-
122
-
123
- @dataclass
124
- class _SelectionParameter(Parameter):
125
- def __post_init__(self) -> None:
126
- self.trigger_refresh: bool = False
127
- self.options: Sequence[po.SelectParameterOption] = tuple(self.all_options)
128
- self.children: List[_SelectionParameter] = list()
129
- if self.parent is not None:
130
- self.parent._add_child_mutate(self)
131
- self._refresh_mutate()
132
-
133
- def _add_child_mutate(self, child: Parameter) -> None:
134
- self.children.append(child)
135
- self.trigger_refresh = True
136
-
137
- def _refresh_mutate(self) -> None:
138
- if self.parent is not None:
139
- self.options = tuple(self._get_valid_options_iterator())
140
- self._set_default_as_selection_mutate()
141
- self.children = [child.refresh(self) for child in self.children]
142
-
143
- def _get_selected_ids_as_list(self) -> Sequence[str]:
144
- raise u.AbstractMethodCallError(self.__class__, "_get_selected_ids_as_list")
145
-
146
- def _get_default_iterator(self) -> Iterator[po.ParameterOption]:
147
- return (x.identifier for x in self.options if x.is_default)
148
-
149
- def _validate_selected_id_in_options(self, selected_id: str) -> str:
150
- if selected_id in (x.identifier for x in self.options):
151
- return selected_id
152
- else:
153
- self._raise_invalid_input_error(selected_id)
154
-
155
- def _accum_all_dependent_params(self, param_set: ParameterSetBase) -> None:
156
- super()._accum_all_dependent_params(param_set)
157
- for child in self.children:
158
- child._accum_all_dependent_params(param_set)
159
-
160
- def to_json_dict(self):
161
- """
162
- Helper method to convert the derived selection parameter class into a JSON object
163
- """
164
- output = super().to_json_dict()
165
- output['options'] = [x.to_dict() for x in self.options]
166
- output['trigger_refresh'] = self.trigger_refresh
167
- return output
168
-
169
-
170
- @dataclass
171
- class SingleSelectParameter(_SelectionParameter):
172
- """
173
- Class to define attributes for single-select parameter widgets.
174
- """
175
- selected_id: Optional[str]
176
-
177
- def __init__(self, name: str, label: str, all_options: Sequence[po.SelectParameterOption], *,
178
- is_hidden: bool = False, parent: Optional[_SelectionParameter] = None) -> None:
179
- """
180
- Constructor for SingleSelectParameter class
181
-
182
- Parameters:
183
- name: The name of the parameter
184
- label: The display label for the parameter
185
- all_options: A sequence of SelectParameterOption which defines the attribute for each dropdown option
186
- is_hidden: Whether the parameter is hidden in the parameters API response. Default is False.
187
- parent: The parent parameter that may cascade the options for this parameter. Default is no parent
188
- """
189
- super().__init__("SingleSelectParameter", name, label, all_options, is_hidden, parent)
190
-
191
- def with_selection(self, selection: str) -> SingleSelectParameter:
192
- """
193
- Applies the selected value to this widget parameter
194
-
195
- Parameters:
196
- selection: The selected value as an ID of one of the dropdown options
197
-
198
- Returns:
199
- A new copy of SingleSelectParameter with the selection applied
200
- """
201
- param_copy = copy.copy(self)
202
- param_copy.selected_id = self._validate_selected_id_in_options(selection)
203
- param_copy.children = [child.refresh(param_copy) for child in param_copy.children]
204
- return param_copy
205
-
206
- def get_selected(self) -> po.SelectParameterOption:
207
- """
208
- Gets the selected single-select option
209
-
210
- Returns:
211
- A SelectParameterOption class object
212
- """
213
- return next(x for x in self.options if x.identifier == self.selected_id)
214
-
215
- def get_selected_id(self) -> str:
216
- """
217
- Gets the ID of the selected option
218
-
219
- Returns:
220
- A string ID
221
- """
222
- return self.get_selected().identifier
223
-
224
- def get_selected_id_quoted(self) -> str:
225
- """
226
- Gets the ID of the selected option surrounded by single quotes
227
-
228
- Returns:
229
- A string
230
- """
231
- return self._enquote(self.get_selected_id())
232
-
233
- def get_selected_label(self) -> str:
234
- """
235
- Gets the label of the selected option
236
-
237
- Returns:
238
- A string
239
- """
240
- return self.get_selected().label
241
-
242
- def get_selected_label_quoted(self) -> str:
243
- """
244
- Gets the label of the selected option surrounded by single quotes
245
-
246
- Returns:
247
- A string
248
- """
249
- return self._enquote(self.get_selected_label())
250
-
251
- # Overriding for refresh method
252
- def _get_selected_ids_as_list(self) -> Sequence[str]:
253
- return (self.get_selected_id(),)
254
-
255
- def _get_default(self) -> str:
256
- default_id = next(self._get_default_iterator(), None)
257
- if default_id is None:
258
- default_id = self.options[0].identifier if len(self.options) > 0 else None
259
- return default_id
260
-
261
- def _set_default_as_selection_mutate(self) -> None:
262
- self.selected_id = self._get_default()
263
-
264
- def to_json_dict(self) -> Dict:
265
- """
266
- Converts this parameter as a JSON object for the parameters API response
267
-
268
- Returns:
269
- A dictionary for the JSON object
270
- """
271
- output = super().to_json_dict()
272
- output['selected_id'] = self.selected_id
273
- return output
274
-
275
-
276
- @dataclass
277
- class MultiSelectParameter(_SelectionParameter):
278
- """
279
- Class to define attributes for multi-select parameter widgets.
280
- """
281
- selected_ids: Sequence[str]
282
- include_all: bool
283
- order_matters: bool
284
-
285
- def __init__(self, name: str, label: str, all_options: Sequence[po.SelectParameterOption], *, is_hidden = False,
286
- parent: Optional[_SelectionParameter] = None, include_all: bool = True, order_matters: bool = False) -> None:
287
- """
288
- Constructor for MultiSelectParameter class
289
-
290
- Parameters:
291
- name: The name of the parameter
292
- label: The display label for the parameter
293
- all_options: A sequence of SelectParameterOption which defines the attribute for each dropdown option
294
- is_hidden: Whether the parameter is hidden in the parameters API response. Default is False.
295
- parent: The parent parameter that may cascade the options for this parameter. Default is no parent
296
- include_all: Whether applying no selection is equivalent to selecting all. Default is True
297
- order_matters: Whether the ordering of the selection matters. Default is False
298
- """
299
- super().__init__("MultiSelectParameter", name, label, all_options, is_hidden, parent)
300
- self.include_all = include_all
301
- self.order_matters = order_matters
302
-
303
- def with_selection(self, selection: str) -> MultiSelectParameter:
304
- """
305
- Applies the selected value(s) to this widget parameter
306
-
307
- Parameters:
308
- selection: A JSON string of list of strings representing IDs of selected values
309
-
310
- Returns:
311
- A new copy of MultiSelectParameter with the selection applied
312
- """
313
- param_copy = copy.copy(self)
314
- selection_split = u.load_json_or_comma_delimited_str_as_list(selection)
315
- param_copy.selected_ids = tuple(self._validate_selected_id_in_options(x) for x in selection_split)
316
- param_copy.children = [child.refresh(param_copy) for child in self.children]
317
- return param_copy
318
-
319
- def has_non_empty_selection(self) -> bool:
320
- """
321
- Returns True if more than zero options were selected. False otherwise.
322
-
323
- Note that even when this returns False, all "get_selected" functions would
324
- return the full list of options if "include_all" is set to True
325
-
326
- Returns:
327
- A boolean
328
- """
329
- return len(self.selected_ids) > 0
330
-
331
- def get_selected_list(self) -> Sequence[po.SelectParameterOption]:
332
- """
333
- Gets the sequence of the selected option(s)
334
-
335
- Returns:
336
- A sequence of SelectParameterOption class objects
337
- """
338
- if not self.has_non_empty_selection() and self.include_all:
339
- result = tuple(self.options)
340
- else:
341
- result = tuple(x for x in self.options if x.identifier in self.selected_ids)
342
- return result
343
-
344
- def get_selected_ids_as_list(self) -> Sequence[str]:
345
- """
346
- Gets the sequence of ID(s) of the selected option(s)
347
-
348
- Returns:
349
- A sequence of strings
350
- """
351
- return tuple(x.identifier for x in self.get_selected_list())
352
-
353
- def get_selected_ids_joined(self) -> str:
354
- """
355
- Gets the ID(s) of the selected option(s) joined by comma
356
-
357
- Returns:
358
- A string
359
- """
360
- return ', '.join(self.get_selected_ids_as_list())
361
-
362
- def get_selected_ids_quoted_as_list(self) -> Sequence[str]:
363
- """
364
- Gets the sequence of ID(s) of the selected option(s) surrounded by single quotes
365
-
366
- Returns:
367
- A sequence of strings
368
- """
369
- return tuple(self._enquote(x) for x in self.get_selected_ids_as_list())
370
-
371
- def get_selected_ids_quoted_joined(self) -> str:
372
- """
373
- Gets the ID(s) of the selected option(s) surrounded by single quotes and joined by comma
374
-
375
- Returns:
376
- A string
377
- """
378
- return ', '.join(self.get_selected_ids_quoted_as_list())
379
-
380
- def get_selected_labels_as_list(self) -> Sequence[str]:
381
- """
382
- Gets the sequence of label(s) of the selected option(s)
383
-
384
- Returns:
385
- A sequence of strings
386
- """
387
- return tuple(x.label for x in self.get_selected_list())
388
-
389
- def get_selected_labels_joined(self) -> str:
390
- """
391
- Gets the label(s) of the selected option(s) joined by comma
392
-
393
- Returns:
394
- A string
395
- """
396
- return ', '.join(self.get_selected_labels_as_list())
397
-
398
- def get_selected_labels_quoted_as_list(self) -> Sequence[str]:
399
- """
400
- Gets the sequence of label(s) of the selected option(s) surrounded by single quotes
401
-
402
- Returns:
403
- A sequence of strings
404
- """
405
- return tuple(self._enquote(x) for x in self.get_selected_labels_as_list())
406
-
407
- def get_selected_labels_quoted_joined(self) -> str:
408
- """
409
- Gets the label(s) of the selected option(s) surrounded by single quotes and joined by comma
410
-
411
- Returns:
412
- A string
413
- """
414
- return ', '.join(self.get_selected_labels_quoted_as_list())
415
-
416
- def _get_selected_ids_as_list(self) -> Sequence[str]:
417
- return self.get_selected_ids_as_list()
418
-
419
- def _get_default(self) -> Sequence[str]:
420
- return tuple(self._get_default_iterator())
421
-
422
- def _set_default_as_selection_mutate(self):
423
- self.selected_ids = self._get_default()
424
-
425
- def to_json_dict(self):
426
- """
427
- Converts this parameter as a JSON object for the parameters API response
428
-
429
- Returns:
430
- A dictionary for the JSON object
431
- """
432
- output = super().to_json_dict()
433
- output['selected_ids'] = list(self.selected_ids)
434
- output['include_all'] = self.include_all
435
- output['order_matters'] = self.order_matters
436
- return output
437
-
438
-
439
- @dataclass
440
- class DateParameter(Parameter):
441
- """
442
- Class to define attributes for date parameter widgets.
443
- """
444
- curr_option: po.DateParameterOption
445
- selected_date: datetime
446
-
447
- def __init__(self, name: str, label: str, default_date: Union[str, datetime], date_format: str = '%Y-%m-%d',
448
- *, is_hidden: bool = False) -> None:
449
- """
450
- Constructor for DateParameter class
451
-
452
- Parameters:
453
- name: The name of the parameter
454
- label: The display label for the parameter
455
- default_date: The default selected date
456
- date_format: The format of the default_date. Default is '%Y-%m-%d'
457
- is_hidden: Whether the parameter is hidden in the parameters API response. Default is False
458
- """
459
- self.curr_option = po.DateParameterOption(default_date, date_format)
460
- all_options = (self.curr_option,)
461
- super().__init__("DateParameter", name, label, all_options, is_hidden, None)
462
- self._set_default_as_selection_mutate()
463
-
464
- @staticmethod
465
- def WithParent(name: str, label: str, all_options: Sequence[po.DateParameterOption], parent: SingleSelectParameter, *,
466
- is_hidden: bool = False) -> DateParameter:
467
- """
468
- A factory method to construct a DateParameter with a parent parameter
469
-
470
- Parameters:
471
- name: The name of the parameter
472
- label: The display label for the parameter
473
- all_options: A sequence of DateParameterOption which contains various default dates linked to specific parent options
474
- parent: The parent parameter, which must be a SingleSelectParameter
475
- is_hidden: Whether the parameter is hidden in the parameters API response. Default is False
476
- """
477
- new_param = DateParameter(name, label, '2020-01-01', is_hidden=is_hidden) # dummy date in valid format
478
- return Parameter.WithParent(all_options, parent, new_param)
479
-
480
- def with_selection(self, selection: str):
481
- """
482
- Applies the selected date to this widget parameter
483
-
484
- Parameters:
485
- selection: The date string which must be in yyyy-mm-dd format (regardless of self.date_format value)
486
-
487
- Returns:
488
- A new copy of DateParameter with the selection applied
489
- """
490
- param_copy = copy.copy(self)
491
- try:
492
- param_copy.selected_date = datetime.strptime(selection, "%Y-%m-%d")
493
- except ValueError as e:
494
- self._raise_invalid_input_error(selection, 'Invalid selection for date.', e)
495
- return param_copy
496
-
497
- def get_selected_date(self, date_format: str = None) -> str:
498
- """
499
- Gets selected date as string
500
-
501
- Parameters:
502
- date_format: The date format (see Python's datetime formats). If not specified, self.date_format is used
503
-
504
- Returns:
505
- A string
506
- """
507
- date_format = self.curr_option.date_format if date_format is None else date_format
508
- return self.selected_date.strftime(date_format)
509
-
510
- def get_selected_date_quoted(self, date_format: str = None) -> str:
511
- """
512
- Gets selected date as string surrounded by single quotes
513
-
514
- Parameters:
515
- date_format: The date format (see Python's datetime formats). If not specified, self.date_format is used
516
-
517
- Returns:
518
- A string
519
- """
520
- return self._enquote(self.get_selected_date(date_format))
521
-
522
- def _set_default_as_selection_mutate(self) -> None:
523
- self.selected_date = self.curr_option.default_date
524
-
525
- def to_json_dict(self):
526
- """
527
- Converts this parameter as a JSON object for the parameters API response
528
-
529
- The "selected_date" field will always be in yyyy-mm-dd format
530
-
531
- Returns:
532
- A dictionary for the JSON object
533
- """
534
- output = super().to_json_dict()
535
- output['selected_date'] = self.get_selected_date("%Y-%m-%d")
536
- return output
537
-
538
-
539
- @dataclass
540
- class _NumericParameter(Parameter):
541
- curr_option: po.NumericParameterOption
542
-
543
- def to_json_dict(self):
544
- """
545
- Helper method to converts numeric parameters into JSON objects for the parameters API response
546
-
547
- Returns:
548
- A dictionary for the JSON object
549
- """
550
- output = super().to_json_dict()
551
- output['min_value'] = str(self.curr_option.min_value)
552
- output['max_value'] = str(self.curr_option.max_value)
553
- output['increment'] = str(self.curr_option.increment)
554
- return output
555
-
556
-
557
- @dataclass
558
- class NumberParameter(_NumericParameter):
559
- """
560
- Class to define attributes for number slider parameter widgets.
561
- """
562
- selected_value: Decimal
563
-
564
- def __init__(self, name: str, label: str, min_value: po.Number, max_value: po.Number, increment: po.Number = 1,
565
- default_value: po.Number = None, *, is_hidden: bool = False) -> None:
566
- """
567
- Constructor for NumberParameter class
568
-
569
- Parameters:
570
- name: The name of the parameter
571
- label: The display label for the parameter
572
- min_value: The minimum bound for selection. Can be of type Decimal, integer, or number parsable string
573
- max_value: The maxixmum bound for selection. Can be of type Decimal, integer, or number parsable string
574
- increment: The increment for allowable selections. Can be of type Decimal, integer, or number parsable string. Default is 1
575
- default_value: The default selection. Can be of type Decimal, integer, or number parsable string. Default is min_value
576
- is_hidden: Whether the parameter is hidden in the parameters API response. Default is False
577
- """
578
- default_value = default_value if default_value is not None else min_value
579
- curr_option = po.NumberParameterOption(min_value, max_value, increment, default_value)
580
- all_options = (curr_option,)
581
- super().__init__("NumberParameter", name, label, all_options, is_hidden, None, curr_option)
582
- self._set_default_as_selection_mutate()
583
-
584
- @staticmethod
585
- def WithParent(name: str, label: str, all_options: Sequence[po.NumberParameterOption], parent: SingleSelectParameter, *,
586
- is_hidden: bool = False) -> DateParameter:
587
- """
588
- A factory method to construct a NumberParameter with a parent parameter
589
-
590
- Parameters:
591
- name: The name of the parameter
592
- label: The display label for the parameter
593
- all_options: A sequence of NumberParameterOption which contains various bounds and default values linked to specific parent options
594
- parent: The parent parameter, which must be a SingleSelectParameter
595
- is_hidden: Whether the parameter is hidden in the parameters API response. Default is False
596
- """
597
- new_param = NumberParameter(name, label, 0, 1, is_hidden=is_hidden) # dummy values
598
- return Parameter.WithParent(all_options, parent, new_param)
599
-
600
- def with_selection(self, selection: str):
601
- """
602
- Applies the selected number to this widget parameter
603
-
604
- Parameters:
605
- selection: The selected number (must be a string parsable as a number)
606
-
607
- Returns:
608
- A new copy of NumberParameter with the selection applied
609
- """
610
- param_copy = copy.copy(self)
611
- try:
612
- param_copy.selected_value = param_copy.curr_option._validate_value(selection)
613
- except u.ConfigurationError as e:
614
- self._raise_invalid_input_error(selection, 'Invalid selection for number parameter.', e)
615
- return param_copy
616
-
617
- def get_selected_value(self) -> str:
618
- """
619
- Get the selected number
620
-
621
- Returns:
622
- A number parsable string of the selected number
623
- """
624
- return str(self.selected_value)
625
-
626
- def _set_default_as_selection_mutate(self) -> None:
627
- self.curr_option: po.NumberParameterOption
628
- self.selected_value = self.curr_option.default_value
629
-
630
- def to_json_dict(self):
631
- """
632
- Converts this parameter as a JSON object for the parameters API response
633
-
634
- Returns:
635
- A dictionary for the JSON object
636
- """
637
- output = super().to_json_dict()
638
- output['selected_value'] = self.get_selected_value()
639
- return output
640
-
641
-
642
- @dataclass
643
- class NumRangeParameter(_NumericParameter):
644
- """
645
- Class to define attributes for number range slider (double-ended) parameter widgets.
646
- """
647
- selected_lower_value: Decimal
648
- selected_upper_value: Decimal
649
-
650
- def __init__(self, name: str, label: str, min_value: po.Number, max_value: po.Number, increment: po.Number = 1,
651
- default_lower_value: po.Number = None, default_upper_value: po.Number = None, *, is_hidden: bool = False) -> None:
652
- """
653
- Constructor for NumberParameter class
654
-
655
- Parameters:
656
- name: The name of the parameter
657
- label: The display label for the parameter
658
- min_value: The minimum bound for selection. Can be of type Decimal, integer, or number parsable string
659
- max_value: The maxixmum bound for selection. Can be of type Decimal, integer, or number parsable string
660
- increment: The increment for allowable selections. Can be of type Decimal, integer, or number parsable string. Default is 1
661
- default_lower_value: The default lower selection. Can be of type Decimal, integer, or number parsable string. Default is min_value
662
- default_upper_value: The default upper selection. Can be of type Decimal, integer, or number parsable string. Default is max_value
663
- is_hidden: Whether the parameter is hidden in the parameters API response. Default is False
664
- """
665
- default_lower_value = default_lower_value if default_lower_value is not None else min_value
666
- default_upper_value = default_upper_value if default_upper_value is not None else max_value
667
- curr_option = po.NumRangeParameterOption(min_value, max_value, increment, default_lower_value, default_upper_value)
668
- all_options = (curr_option,)
669
- super().__init__("NumRangeParameter", name, label, all_options, is_hidden, None, curr_option)
670
- self._set_default_as_selection_mutate()
671
-
672
- @staticmethod
673
- def WithParent(name: str, label: str, all_options: Sequence[po.NumRangeParameterOption], parent: SingleSelectParameter, *,
674
- is_hidden: bool = False) -> DateParameter:
675
- """
676
- A factory method to construct a NumRangeParameter with a parent parameter
677
-
678
- Parameters:
679
- name: The name of the parameter
680
- label: The display label for the parameter
681
- all_options: A sequence of NumRangeParameterOption which contains various bounds and default values linked to specific parent options
682
- parent: The parent parameter, which must be a SingleSelectParameter
683
- is_hidden: Whether the parameter is hidden in the parameters API response. Default is False
684
- """
685
- new_param = NumRangeParameter(name, label, 0, 1, is_hidden=is_hidden) # dummy values
686
- return Parameter.WithParent(all_options, parent, new_param)
687
-
688
- def with_selection(self, selection: str):
689
- """
690
- Applies the selected numbers to this widget parameter
691
-
692
- Parameters:
693
- selection: The lower and upper selected numbers joined by comma (with no spaces)
694
-
695
- Returns:
696
- A new copy of NumRangeParameter with the selection applied
697
- """
698
- try:
699
- lower, upper = selection.split(',')
700
- except ValueError as e:
701
- self._raise_invalid_input_error(selection, "Range parameter selection must be two numbers joined by comma.", e)
702
-
703
- param_copy = copy.copy(self)
704
- try:
705
- param_copy.selected_lower_value = param_copy.curr_option._validate_value(lower)
706
- param_copy.selected_upper_value = param_copy.curr_option._validate_value(upper, param_copy.selected_lower_value)
707
- except u.ConfigurationError as e:
708
- self._raise_invalid_input_error(selection, 'Invalid selection for range parameter.', e)
709
- return param_copy
710
-
711
- def get_selected_lower_value(self) -> str:
712
- """
713
- Get the selected lower number
714
-
715
- Returns:
716
- A number parsable string of the selected number
717
- """
718
- return str(self.selected_lower_value)
719
-
720
- def get_selected_upper_value(self) -> str:
721
- """
722
- Get the selected upper number
723
-
724
- Returns:
725
- A number parsable string of the selected number
726
- """
727
- return str(self.selected_upper_value)
728
-
729
- def _set_default_as_selection_mutate(self) -> None:
730
- self.curr_option: po.NumRangeParameterOption
731
- self.selected_lower_value = self.curr_option.default_lower_value
732
- self.selected_upper_value = self.curr_option.default_upper_value
733
-
734
- def to_json_dict(self):
735
- """
736
- Converts this parameter as a JSON object for the parameters API response
737
-
738
- Returns:
739
- A dictionary for the JSON object
740
- """
741
- output = super().to_json_dict()
742
- output['selected_lower_value'] = self.get_selected_lower_value()
743
- output['selected_upper_value'] = self.get_selected_upper_value()
744
- return output
745
-
746
-
747
- @dataclass
748
- class DataSourceParameter(Parameter):
749
- """
750
- Class for parameters that can use a lookup table to convert itself into another parameter
751
- """
752
- parameter_class: Type[Parameter]
753
- data_source: DataSource
754
- parent: Optional[Parameter]
755
-
756
- def __init__(self, parameter_class: Type[Parameter], name: str, label: str, data_source: DataSource, *,
757
- is_hidden: bool = False, parent: Optional[Parameter] = None) -> None:
758
- """
759
- Constructor for DataSourceParameter, a Parameter that uses a DataSource to convert itself to another Parameter
760
-
761
- Parameters:
762
- parameter_class: The class of widget parameter to convert to
763
- name: The name of the parameter
764
- label: The display label for the parameter
765
- data_source: The lookup table to use for this parameter
766
- is_hidden: Whether the parameter is hidden in the parameters API response. Default is False
767
- parent: The parent parameter that may cascade the options for this parameter. Default is no parent
768
- """
769
- super().__init__("DataSourceParameter", name, label, None, is_hidden, None)
770
- self.parameter_class = parameter_class
771
- self.data_source = data_source
772
- self.parent = parent
773
-
774
- def convert(self, df: pd.DataFrame) -> Parameter:
775
- """
776
- Method to convert this DataSourceParameter into another parameter
777
-
778
- Parameters:
779
- df: The dataframe containing the parameter options data
780
-
781
- Returns:
782
- The converted parameter
783
- """
784
- return self.data_source.convert(self, df)
785
-
786
- def to_json_dict(self) -> Dict:
787
- """
788
- Converts this parameter as a JSON object for the parameters API response
789
-
790
- Returns:
791
- A dictionary for the JSON object
792
- """
793
- output = super().to_json_dict()
794
- output['widget_type'] = self.parameter_class.__name__
795
- output['data_source'] = self.data_source.__dict__
796
- return output
797
-
798
-
799
- # Types:
800
- SelectionParameter = Union[SingleSelectParameter, MultiSelectParameter]
801
- NumericParameter = Union[NumberParameter, NumRangeParameter]
1
+ from ._parameters import (
2
+ SingleSelectParameter,
3
+ MultiSelectParameter,
4
+ DateParameter,
5
+ DateRangeParameter,
6
+ NumberParameter,
7
+ NumberRangeParameter,
8
+ TextParameter
9
+ )
10
+
11
+ __all__ = [
12
+ "SingleSelectParameter", "MultiSelectParameter", "DateParameter", "DateRangeParameter",
13
+ "NumberParameter", "NumberRangeParameter", "TextParameter"
14
+ ]