squirrels 0.5.0rc0__py3-none-any.whl → 0.5.1__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.

Potentially problematic release.


This version of squirrels might be problematic. Click here for more details.

Files changed (108) hide show
  1. dateutils/__init__.py +6 -0
  2. dateutils/_enums.py +25 -0
  3. squirrels/dateutils.py → dateutils/_implementation.py +58 -111
  4. dateutils/types.py +6 -0
  5. squirrels/__init__.py +10 -12
  6. squirrels/_api_routes/__init__.py +5 -0
  7. squirrels/_api_routes/auth.py +271 -0
  8. squirrels/_api_routes/base.py +171 -0
  9. squirrels/_api_routes/dashboards.py +158 -0
  10. squirrels/_api_routes/data_management.py +148 -0
  11. squirrels/_api_routes/datasets.py +265 -0
  12. squirrels/_api_routes/oauth2.py +298 -0
  13. squirrels/_api_routes/project.py +252 -0
  14. squirrels/_api_server.py +245 -781
  15. squirrels/_arguments/__init__.py +0 -0
  16. squirrels/{arguments → _arguments}/init_time_args.py +7 -2
  17. squirrels/{arguments → _arguments}/run_time_args.py +13 -35
  18. squirrels/_auth.py +720 -212
  19. squirrels/_command_line.py +81 -41
  20. squirrels/_compile_prompts.py +147 -0
  21. squirrels/_connection_set.py +16 -7
  22. squirrels/_constants.py +29 -9
  23. squirrels/{_dashboards_io.py → _dashboards.py} +87 -6
  24. squirrels/_data_sources.py +570 -0
  25. squirrels/{dataset_result.py → _dataset_types.py} +2 -4
  26. squirrels/_exceptions.py +9 -37
  27. squirrels/_initializer.py +83 -59
  28. squirrels/_logging.py +117 -0
  29. squirrels/_manifest.py +129 -62
  30. squirrels/_model_builder.py +10 -52
  31. squirrels/_model_configs.py +3 -3
  32. squirrels/_model_queries.py +1 -1
  33. squirrels/_models.py +249 -118
  34. squirrels/{package_data → _package_data}/base_project/.env +16 -4
  35. squirrels/{package_data → _package_data}/base_project/.env.example +15 -3
  36. squirrels/{package_data → _package_data}/base_project/connections.yml +4 -3
  37. squirrels/{package_data → _package_data}/base_project/dashboards/dashboard_example.py +4 -4
  38. squirrels/_package_data/base_project/dashboards/dashboard_example.yml +22 -0
  39. squirrels/{package_data → _package_data}/base_project/duckdb_init.sql +1 -0
  40. squirrels/_package_data/base_project/macros/macros_example.sql +17 -0
  41. squirrels/{package_data → _package_data}/base_project/models/builds/build_example.py +2 -2
  42. squirrels/{package_data → _package_data}/base_project/models/builds/build_example.sql +1 -1
  43. squirrels/{package_data → _package_data}/base_project/models/builds/build_example.yml +2 -0
  44. squirrels/_package_data/base_project/models/dbviews/dbview_example.sql +17 -0
  45. squirrels/_package_data/base_project/models/dbviews/dbview_example.yml +32 -0
  46. squirrels/_package_data/base_project/models/federates/federate_example.py +48 -0
  47. squirrels/_package_data/base_project/models/federates/federate_example.sql +21 -0
  48. squirrels/{package_data → _package_data}/base_project/models/federates/federate_example.yml +7 -7
  49. squirrels/{package_data → _package_data}/base_project/models/sources.yml +5 -6
  50. squirrels/{package_data → _package_data}/base_project/parameters.yml +32 -45
  51. squirrels/_package_data/base_project/pyconfigs/connections.py +18 -0
  52. squirrels/{package_data → _package_data}/base_project/pyconfigs/context.py +31 -22
  53. squirrels/_package_data/base_project/pyconfigs/parameters.py +141 -0
  54. squirrels/_package_data/base_project/pyconfigs/user.py +44 -0
  55. squirrels/{package_data → _package_data}/base_project/seeds/seed_categories.yml +1 -1
  56. squirrels/{package_data → _package_data}/base_project/seeds/seed_subcategories.yml +1 -1
  57. squirrels/_package_data/base_project/squirrels.yml.j2 +61 -0
  58. squirrels/_package_data/templates/dataset_results.html +112 -0
  59. squirrels/_package_data/templates/oauth_login.html +271 -0
  60. squirrels/_package_data/templates/squirrels_studio.html +20 -0
  61. squirrels/_parameter_configs.py +76 -55
  62. squirrels/_parameter_options.py +348 -0
  63. squirrels/_parameter_sets.py +53 -45
  64. squirrels/_parameters.py +1664 -0
  65. squirrels/_project.py +403 -242
  66. squirrels/_py_module.py +3 -2
  67. squirrels/_request_context.py +33 -0
  68. squirrels/_schemas/__init__.py +0 -0
  69. squirrels/_schemas/auth_models.py +167 -0
  70. squirrels/_schemas/query_param_models.py +75 -0
  71. squirrels/{_api_response_models.py → _schemas/response_models.py} +48 -18
  72. squirrels/_seeds.py +1 -1
  73. squirrels/_sources.py +23 -19
  74. squirrels/_utils.py +121 -39
  75. squirrels/_version.py +1 -1
  76. squirrels/arguments.py +7 -0
  77. squirrels/auth.py +4 -0
  78. squirrels/connections.py +3 -0
  79. squirrels/dashboards.py +2 -81
  80. squirrels/data_sources.py +14 -563
  81. squirrels/parameter_options.py +13 -348
  82. squirrels/parameters.py +14 -1266
  83. squirrels/types.py +16 -0
  84. {squirrels-0.5.0rc0.dist-info → squirrels-0.5.1.dist-info}/METADATA +42 -30
  85. squirrels-0.5.1.dist-info/RECORD +98 -0
  86. squirrels/package_data/base_project/dashboards/dashboard_example.yml +0 -22
  87. squirrels/package_data/base_project/macros/macros_example.sql +0 -15
  88. squirrels/package_data/base_project/models/dbviews/dbview_example.sql +0 -12
  89. squirrels/package_data/base_project/models/dbviews/dbview_example.yml +0 -26
  90. squirrels/package_data/base_project/models/federates/federate_example.py +0 -44
  91. squirrels/package_data/base_project/models/federates/federate_example.sql +0 -17
  92. squirrels/package_data/base_project/pyconfigs/connections.py +0 -14
  93. squirrels/package_data/base_project/pyconfigs/parameters.py +0 -93
  94. squirrels/package_data/base_project/pyconfigs/user.py +0 -23
  95. squirrels/package_data/base_project/squirrels.yml.j2 +0 -71
  96. squirrels-0.5.0rc0.dist-info/RECORD +0 -70
  97. /squirrels/{package_data → _package_data}/base_project/assets/expenses.db +0 -0
  98. /squirrels/{package_data → _package_data}/base_project/assets/weather.db +0 -0
  99. /squirrels/{package_data → _package_data}/base_project/docker/.dockerignore +0 -0
  100. /squirrels/{package_data → _package_data}/base_project/docker/Dockerfile +0 -0
  101. /squirrels/{package_data → _package_data}/base_project/docker/compose.yml +0 -0
  102. /squirrels/{package_data/base_project/.gitignore → _package_data/base_project/gitignore} +0 -0
  103. /squirrels/{package_data → _package_data}/base_project/seeds/seed_categories.csv +0 -0
  104. /squirrels/{package_data → _package_data}/base_project/seeds/seed_subcategories.csv +0 -0
  105. /squirrels/{package_data → _package_data}/base_project/tmp/.gitignore +0 -0
  106. {squirrels-0.5.0rc0.dist-info → squirrels-0.5.1.dist-info}/WHEEL +0 -0
  107. {squirrels-0.5.0rc0.dist-info → squirrels-0.5.1.dist-info}/entry_points.txt +0 -0
  108. {squirrels-0.5.0rc0.dist-info → squirrels-0.5.1.dist-info}/licenses/LICENSE +0 -0
@@ -9,13 +9,13 @@ from fastapi import Query
9
9
  from pydantic.fields import Field
10
10
  import polars as pl, re
11
11
 
12
- from . import parameter_options as _po, parameters as p, data_sources as d, _utils as u, _constants as c
12
+ from . import _data_sources as d, _parameter_options as po, _parameters as p, _utils as u, _constants as c
13
13
  from ._exceptions import InvalidInputError
14
- from ._auth import BaseUser
14
+ from ._schemas.auth_models import AbstractUser
15
15
  from ._connection_set import ConnectionSet
16
16
  from ._seeds import Seeds
17
17
 
18
- ParamOptionType = TypeVar("ParamOptionType", bound=_po.ParameterOption)
18
+ ParamOptionType = TypeVar("ParamOptionType", bound=po.ParameterOption)
19
19
 
20
20
 
21
21
  @dataclass
@@ -56,12 +56,20 @@ class ParameterConfigBase(metaclass=ABCMeta):
56
56
  user_attribute: str | None = field(default=None, kw_only=True)
57
57
  parent_name: str | None = field(default=None, kw_only=True)
58
58
 
59
- def _get_user_group(self, user: BaseUser | None) -> Any:
60
- if self.user_attribute is not None:
61
- if user is None:
62
- raise u.ConfigurationError(f"Public datasets (accessible without authentication) cannot use parameter " +
63
- f"'{self.name}' because 'user_attribute' is defined on this parameter.")
64
- return getattr(user, self.user_attribute)
59
+ def _get_user_group(self, user: AbstractUser) -> Any:
60
+ if self.user_attribute is None:
61
+ return None
62
+
63
+ final_object = user
64
+ attribute = self.user_attribute
65
+ try:
66
+ if "." in attribute:
67
+ parts = attribute.split(".", 1)
68
+ final_object = getattr(final_object, parts[0])
69
+ attribute = parts[1]
70
+ return getattr(final_object, attribute)
71
+ except AttributeError:
72
+ raise u.ConfigurationError(f"User attribute '{self.user_attribute}' is not valid")
65
73
 
66
74
  def copy(self):
67
75
  """
@@ -108,16 +116,16 @@ class ParameterConfig(Generic[ParamOptionType], ParameterConfigBase):
108
116
  pass
109
117
 
110
118
  def _invalid_input_error(self, selection: str, more_details: str = '') -> InvalidInputError:
111
- return InvalidInputError(200, f'Selected value "{selection}" is not valid for parameter "{self.name}". ' + more_details)
119
+ return InvalidInputError(400, "invalid_parameter_selection", f'Selected value "{selection}" is not valid for parameter "{self.name}". ' + more_details)
112
120
 
113
121
  @abstractmethod
114
122
  def with_selection(
115
- self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
123
+ self, selection: str | None, user: AbstractUser, parent_param: p._SelectionParameter | None
116
124
  ) -> p.Parameter:
117
125
  pass
118
126
 
119
127
  def _get_options_iterator(
120
- self, all_options: Sequence[ParamOptionType], user: BaseUser | None, parent_param: p._SelectionParameter | None
128
+ self, all_options: Sequence[ParamOptionType], user: AbstractUser, parent_param: p._SelectionParameter | None
121
129
  ) -> Iterator[ParamOptionType]:
122
130
  user_group = self._get_user_group(user)
123
131
  selected_parent_option_ids = frozenset(parent_param._get_selected_ids_as_list()) if parent_param else None
@@ -129,7 +137,7 @@ class ParameterConfig(Generic[ParamOptionType], ParameterConfigBase):
129
137
 
130
138
 
131
139
  @dataclass
132
- class SelectionParameterConfig(ParameterConfig[_po.SelectParameterOption]):
140
+ class SelectionParameterConfig(ParameterConfig[po.SelectParameterOption]):
133
141
  """
134
142
  Abstract class for select parameter classes (single-select, multi-select, etc)
135
143
  """
@@ -138,7 +146,7 @@ class SelectionParameterConfig(ParameterConfig[_po.SelectParameterOption]):
138
146
 
139
147
  @abstractmethod
140
148
  def __init__(
141
- self, name: str, label: str, all_options: Sequence[_po.SelectParameterOption | dict], *,
149
+ self, name: str, label: str, all_options: Sequence[po.SelectParameterOption | dict], *,
142
150
  description: str = "", user_attribute: str | None = None, parent_name: str | None = None
143
151
  ) -> None:
144
152
  super().__init__(name, label, all_options, description=description, user_attribute=user_attribute, parent_name=parent_name)
@@ -147,16 +155,16 @@ class SelectionParameterConfig(ParameterConfig[_po.SelectParameterOption]):
147
155
 
148
156
  @staticmethod
149
157
  def ParameterOption(*args, **kwargs):
150
- return _po.SelectParameterOption(*args, **kwargs)
158
+ return po.SelectParameterOption(*args, **kwargs)
151
159
 
152
160
  def _add_child_mutate(self, child: ParameterConfigBase):
153
161
  self.children[child.name] = child
154
162
  self.trigger_refresh = True
155
163
 
156
- def _get_options(self, user: BaseUser | None, parent_param: p._SelectionParameter | None) -> Sequence[_po.SelectParameterOption]:
164
+ def _get_options(self, user: AbstractUser, parent_param: p._SelectionParameter | None) -> Sequence[po.SelectParameterOption]:
157
165
  return tuple(self._get_options_iterator(self.all_options, user, parent_param))
158
166
 
159
- def _get_default_ids_iterator(self, options: Sequence[_po.SelectParameterOption]) -> Iterator[str]:
167
+ def _get_default_ids_iterator(self, options: Sequence[po.SelectParameterOption]) -> Iterator[str]:
160
168
  return (x._identifier for x in options if x._is_default)
161
169
 
162
170
  def copy(self) -> Self:
@@ -175,7 +183,7 @@ class SingleSelectParameterConfig(SelectionParameterConfig):
175
183
  """
176
184
 
177
185
  def __init__(
178
- self, name: str, label: str, all_options: Sequence[_po.SelectParameterOption | dict], *, description: str = "",
186
+ self, name: str, label: str, all_options: Sequence[po.SelectParameterOption | dict], *, description: str = "",
179
187
  user_attribute: str | None = None, parent_name: str | None = None
180
188
  ) -> None:
181
189
  super().__init__(name, label, all_options, description=description, user_attribute=user_attribute, parent_name=parent_name)
@@ -189,7 +197,7 @@ class SingleSelectParameterConfig(SelectionParameterConfig):
189
197
  return d.SelectDataSource(*args, **kwargs)
190
198
 
191
199
  def with_selection(
192
- self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
200
+ self, selection: str | None, user: AbstractUser, parent_param: p._SelectionParameter | None
193
201
  ) -> p.SingleSelectParameter:
194
202
  options = self._get_options(user, parent_param)
195
203
  if selection is None:
@@ -217,7 +225,7 @@ class MultiSelectParameterConfig(SelectionParameterConfig):
217
225
  none_is_all: bool = field(default=True, kw_only=True)
218
226
 
219
227
  def __init__(
220
- self, name: str, label: str, all_options: Sequence[_po.SelectParameterOption | dict], *, description: str = "",
228
+ self, name: str, label: str, all_options: Sequence[po.SelectParameterOption | dict], *, description: str = "",
221
229
  show_select_all: bool = True, order_matters: bool = False, none_is_all: bool = True,
222
230
  user_attribute: str | None = None, parent_name: str | None = None
223
231
  ) -> None:
@@ -237,7 +245,7 @@ class MultiSelectParameterConfig(SelectionParameterConfig):
237
245
  return d.SelectDataSource(*args, **kwargs)
238
246
 
239
247
  def with_selection(
240
- self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
248
+ self, selection: str | None, user: AbstractUser, parent_param: p._SelectionParameter | None
241
249
  ) -> p.MultiSelectParameter:
242
250
  options = self._get_options(user, parent_param)
243
251
  if selection is None:
@@ -268,14 +276,14 @@ class _DateTypeParameterConfig(ParameterConfig[ParamOptionType]):
268
276
 
269
277
 
270
278
  @dataclass
271
- class DateParameterConfig(_DateTypeParameterConfig[_po.DateParameterOption]):
279
+ class DateParameterConfig(_DateTypeParameterConfig[po.DateParameterOption]):
272
280
  """
273
281
  Class to define configurations for date parameter widgets.
274
282
  """
275
- _all_options: Sequence[_po.DateParameterOption] = field(repr=False)
283
+ _all_options: Sequence[po.DateParameterOption] = field(repr=False)
276
284
 
277
285
  def __init__(
278
- self, name: str, label: str, all_options: Sequence[_po.DateParameterOption | dict], *,
286
+ self, name: str, label: str, all_options: Sequence[po.DateParameterOption | dict], *,
279
287
  description: str = "", user_attribute: str | None = None, parent_name: str | None = None
280
288
  ) -> None:
281
289
  super().__init__(name, label, all_options, description=description, user_attribute=user_attribute, parent_name=parent_name)
@@ -286,16 +294,16 @@ class DateParameterConfig(_DateTypeParameterConfig[_po.DateParameterOption]):
286
294
 
287
295
  @staticmethod
288
296
  def ParameterOption(*args, **kwargs):
289
- return _po.DateParameterOption(*args, **kwargs)
297
+ return po.DateParameterOption(*args, **kwargs)
290
298
 
291
299
  @staticmethod
292
300
  def DataSource(*args, **kwargs):
293
301
  return d.DateDataSource(*args, **kwargs)
294
302
 
295
303
  def with_selection(
296
- self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
304
+ self, selection: str | None, user: AbstractUser, parent_param: p._SelectionParameter | None
297
305
  ) -> p.DateParameter:
298
- curr_option: _po.DateParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
306
+ curr_option: po.DateParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
299
307
  selected_date = curr_option._default_date if selection is None and curr_option is not None else selection
300
308
  return p.DateParameter(self, curr_option, selected_date)
301
309
 
@@ -307,14 +315,14 @@ class DateParameterConfig(_DateTypeParameterConfig[_po.DateParameterOption]):
307
315
 
308
316
 
309
317
  @dataclass
310
- class DateRangeParameterConfig(_DateTypeParameterConfig[_po.DateRangeParameterOption]):
318
+ class DateRangeParameterConfig(_DateTypeParameterConfig[po.DateRangeParameterOption]):
311
319
  """
312
320
  Class to define configurations for date range parameter widgets.
313
321
  """
314
- _all_options: Sequence[_po.DateRangeParameterOption] = field(repr=False)
322
+ _all_options: Sequence[po.DateRangeParameterOption] = field(repr=False)
315
323
 
316
324
  def __init__(
317
- self, name: str, label: str, all_options: Sequence[_po.DateRangeParameterOption | dict], *,
325
+ self, name: str, label: str, all_options: Sequence[po.DateRangeParameterOption | dict], *,
318
326
  description: str = "", user_attribute: str | None = None, parent_name: str | None = None
319
327
  ) -> None:
320
328
  super().__init__(name, label, all_options, description=description, user_attribute=user_attribute, parent_name=parent_name)
@@ -325,16 +333,16 @@ class DateRangeParameterConfig(_DateTypeParameterConfig[_po.DateRangeParameterOp
325
333
 
326
334
  @staticmethod
327
335
  def ParameterOption(*args, **kwargs):
328
- return _po.DateRangeParameterOption(*args, **kwargs)
336
+ return po.DateRangeParameterOption(*args, **kwargs)
329
337
 
330
338
  @staticmethod
331
339
  def DataSource(*args, **kwargs):
332
340
  return d.DateRangeDataSource(*args, **kwargs)
333
341
 
334
342
  def with_selection(
335
- self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
343
+ self, selection: str | None, user: AbstractUser, parent_param: p._SelectionParameter | None
336
344
  ) -> p.DateRangeParameter:
337
- curr_option: _po.DateRangeParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
345
+ curr_option: po.DateRangeParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
338
346
  if selection is None:
339
347
  if curr_option is not None:
340
348
  selected_start_date = curr_option._default_start_date
@@ -370,14 +378,14 @@ class _NumericParameterConfig(ParameterConfig[ParamOptionType]):
370
378
 
371
379
 
372
380
  @dataclass
373
- class NumberParameterConfig(_NumericParameterConfig[_po.NumberParameterOption]):
381
+ class NumberParameterConfig(_NumericParameterConfig[po.NumberParameterOption]):
374
382
  """
375
383
  Class to define configurations for number parameter widgets.
376
384
  """
377
- _all_options: Sequence[_po.NumberParameterOption] = field(repr=False)
385
+ _all_options: Sequence[po.NumberParameterOption] = field(repr=False)
378
386
 
379
387
  def __init__(
380
- self, name: str, label: str, all_options: Sequence[_po.NumberParameterOption | dict], *,
388
+ self, name: str, label: str, all_options: Sequence[po.NumberParameterOption | dict], *,
381
389
  description: str = "", user_attribute: str | None = None, parent_name: str | None = None
382
390
  ) -> None:
383
391
  super().__init__(name, label, all_options, description=description, user_attribute=user_attribute, parent_name=parent_name)
@@ -388,16 +396,16 @@ class NumberParameterConfig(_NumericParameterConfig[_po.NumberParameterOption]):
388
396
 
389
397
  @staticmethod
390
398
  def ParameterOption(*args, **kwargs):
391
- return _po.NumberParameterOption(*args, **kwargs)
399
+ return po.NumberParameterOption(*args, **kwargs)
392
400
 
393
401
  @staticmethod
394
402
  def DataSource(*args, **kwargs):
395
403
  return d.NumberDataSource(*args, **kwargs)
396
404
 
397
405
  def with_selection(
398
- self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
406
+ self, selection: str | None, user: AbstractUser, parent_param: p._SelectionParameter | None
399
407
  ) -> p.NumberParameter:
400
- curr_option: _po.NumberParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
408
+ curr_option: po.NumberParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
401
409
  selected_value = curr_option._default_value if selection is None and curr_option is not None else selection
402
410
  return p.NumberParameter(self, curr_option, selected_value)
403
411
 
@@ -409,14 +417,14 @@ class NumberParameterConfig(_NumericParameterConfig[_po.NumberParameterOption]):
409
417
 
410
418
 
411
419
  @dataclass
412
- class NumberRangeParameterConfig(_NumericParameterConfig[_po.NumberRangeParameterOption]):
420
+ class NumberRangeParameterConfig(_NumericParameterConfig[po.NumberRangeParameterOption]):
413
421
  """
414
422
  Class to define configurations for number range parameter widgets.
415
423
  """
416
- _all_options: Sequence[_po.NumberRangeParameterOption] = field(repr=False)
424
+ _all_options: Sequence[po.NumberRangeParameterOption] = field(repr=False)
417
425
 
418
426
  def __init__(
419
- self, name: str, label: str, all_options: Sequence[_po.NumberRangeParameterOption | dict], *,
427
+ self, name: str, label: str, all_options: Sequence[po.NumberRangeParameterOption | dict], *,
420
428
  description: str = "", user_attribute: str | None = None, parent_name: str | None = None
421
429
  ) -> None:
422
430
  super().__init__(name, label, all_options, description=description, user_attribute=user_attribute, parent_name=parent_name)
@@ -427,16 +435,16 @@ class NumberRangeParameterConfig(_NumericParameterConfig[_po.NumberRangeParamete
427
435
 
428
436
  @staticmethod
429
437
  def ParameterOption(*args, **kwargs):
430
- return _po.NumberRangeParameterOption(*args, **kwargs)
438
+ return po.NumberRangeParameterOption(*args, **kwargs)
431
439
 
432
440
  @staticmethod
433
441
  def DataSource(*args, **kwargs):
434
442
  return d.NumberRangeDataSource(*args, **kwargs)
435
443
 
436
444
  def with_selection(
437
- self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
445
+ self, selection: str | None, user: AbstractUser, parent_param: p._SelectionParameter | None
438
446
  ) -> p.NumberRangeParameter:
439
- curr_option: _po.NumberRangeParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
447
+ curr_option: po.NumberRangeParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
440
448
  if selection is None:
441
449
  if curr_option is not None:
442
450
  selected_lower_value = curr_option._default_lower_value
@@ -458,15 +466,15 @@ class NumberRangeParameterConfig(_NumericParameterConfig[_po.NumberRangeParamete
458
466
 
459
467
 
460
468
  @dataclass
461
- class TextParameterConfig(ParameterConfig[_po.TextParameterOption]):
469
+ class TextParameterConfig(ParameterConfig[po.TextParameterOption]):
462
470
  """
463
471
  Class to define configurations for text parameter widgets.
464
472
  """
465
- _all_options: Sequence[_po.TextParameterOption] = field(repr=False)
473
+ _all_options: Sequence[po.TextParameterOption] = field(repr=False)
466
474
  input_type: str
467
475
 
468
476
  def __init__(
469
- self, name: str, label: str, all_options: Sequence[_po.TextParameterOption | dict], *, description: str = "",
477
+ self, name: str, label: str, all_options: Sequence[po.TextParameterOption | dict], *, description: str = "",
470
478
  input_type: str = "text", user_attribute: str | None = None, parent_name: str | None = None
471
479
  ) -> None:
472
480
  super().__init__(name, label, all_options, description=description, user_attribute=user_attribute, parent_name=parent_name)
@@ -517,16 +525,16 @@ class TextParameterConfig(ParameterConfig[_po.TextParameterOption]):
517
525
 
518
526
  @staticmethod
519
527
  def ParameterOption(*args, **kwargs):
520
- return _po.TextParameterOption(*args, **kwargs)
528
+ return po.TextParameterOption(*args, **kwargs)
521
529
 
522
530
  @staticmethod
523
531
  def DataSource(*args, **kwargs):
524
532
  return d.TextDataSource(*args, **kwargs)
525
533
 
526
534
  def with_selection(
527
- self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
535
+ self, selection: str | None, user: AbstractUser, parent_param: p._SelectionParameter | None
528
536
  ) -> p.TextParameter:
529
- curr_option: _po.TextParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
537
+ curr_option: po.TextParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
530
538
  entered_text = curr_option._default_text if selection is None and curr_option is not None else selection
531
539
  return p.TextParameter(self, curr_option, entered_text)
532
540
 
@@ -550,6 +558,8 @@ class DataSourceParameterConfig(Generic[ParamConfigType], ParameterConfigBase):
550
558
  super().__init__(name, label, description=description, user_attribute=user_attribute, parent_name=parent_name)
551
559
  self.parameter_type = parameter_type
552
560
  if isinstance(data_source, dict):
561
+ if "source" in data_source:
562
+ data_source["source"] = d.SourceEnum(data_source["source"])
553
563
  data_source = parameter_type.DataSource(**data_source)
554
564
  self.data_source = data_source
555
565
  self.extra_args = extra_args
@@ -557,15 +567,26 @@ class DataSourceParameterConfig(Generic[ParamConfigType], ParameterConfigBase):
557
567
  def convert(self, df: pl.DataFrame) -> ParamConfigType:
558
568
  return self.data_source._convert(self, df)
559
569
 
560
- def get_dataframe(self, default_conn_name: str, conn_set: ConnectionSet, seeds: Seeds) -> pl.DataFrame:
570
+ def get_dataframe(self, default_conn_name: str, conn_set: ConnectionSet, seeds: Seeds, datalake_db_path: str = "") -> pl.DataFrame:
561
571
  datasource = self.data_source
562
572
  query = datasource._get_query()
563
- if datasource._is_from_seeds:
573
+ if datasource._source == d.SourceEnum.SEEDS:
564
574
  df = seeds.run_query(query)
565
- else:
575
+ elif datasource._source == d.SourceEnum.VDL:
576
+ vdl_conn = u.create_duckdb_connection(datalake_db_path)
577
+ try:
578
+ # Query the VDL database
579
+ df = vdl_conn.sql(query).pl()
580
+ except Exception as e:
581
+ raise u.ConfigurationError(f'Error executing query for datasource parameter "{self.name}" from VDL') from e
582
+ finally:
583
+ vdl_conn.close()
584
+ else: # source == "connection"
585
+ conn_name = None
566
586
  try:
567
587
  conn_name = datasource._get_connection_name(default_conn_name)
568
588
  df = conn_set.run_sql_query_from_conn_name(query, conn_name)
569
589
  except RuntimeError as e:
570
- raise u.ConfigurationError(f'Error executing query for datasource parameter "{self.name}"') from e
590
+ ending = f' "{conn_name}"' if conn_name is not None else ""
591
+ raise u.ConfigurationError(f'Error executing query for datasource parameter "{self.name}" from connection{ending}') from e
571
592
  return df