squirrels 0.4.1__py3-none-any.whl → 0.5.0rc0__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 (80) hide show
  1. squirrels/__init__.py +10 -6
  2. squirrels/_api_response_models.py +93 -44
  3. squirrels/_api_server.py +571 -219
  4. squirrels/_auth.py +451 -0
  5. squirrels/_command_line.py +61 -20
  6. squirrels/_connection_set.py +38 -25
  7. squirrels/_constants.py +44 -34
  8. squirrels/_dashboards_io.py +34 -16
  9. squirrels/_exceptions.py +57 -0
  10. squirrels/_initializer.py +117 -44
  11. squirrels/_manifest.py +124 -62
  12. squirrels/_model_builder.py +111 -0
  13. squirrels/_model_configs.py +74 -0
  14. squirrels/_model_queries.py +52 -0
  15. squirrels/_models.py +860 -354
  16. squirrels/_package_loader.py +8 -4
  17. squirrels/_parameter_configs.py +45 -65
  18. squirrels/_parameter_sets.py +15 -13
  19. squirrels/_project.py +561 -0
  20. squirrels/_py_module.py +4 -3
  21. squirrels/_seeds.py +35 -16
  22. squirrels/_sources.py +106 -0
  23. squirrels/_utils.py +166 -63
  24. squirrels/_version.py +1 -1
  25. squirrels/arguments/init_time_args.py +78 -15
  26. squirrels/arguments/run_time_args.py +62 -101
  27. squirrels/dashboards.py +4 -4
  28. squirrels/data_sources.py +94 -162
  29. squirrels/dataset_result.py +86 -0
  30. squirrels/dateutils.py +4 -4
  31. squirrels/package_data/base_project/.env +30 -0
  32. squirrels/package_data/base_project/.env.example +30 -0
  33. squirrels/package_data/base_project/.gitignore +3 -2
  34. squirrels/package_data/base_project/assets/expenses.db +0 -0
  35. squirrels/package_data/base_project/connections.yml +11 -3
  36. squirrels/package_data/base_project/dashboards/dashboard_example.py +15 -13
  37. squirrels/package_data/base_project/dashboards/dashboard_example.yml +22 -0
  38. squirrels/package_data/base_project/docker/.dockerignore +5 -2
  39. squirrels/package_data/base_project/docker/Dockerfile +3 -3
  40. squirrels/package_data/base_project/docker/compose.yml +1 -1
  41. squirrels/package_data/base_project/duckdb_init.sql +9 -0
  42. squirrels/package_data/base_project/macros/macros_example.sql +15 -0
  43. squirrels/package_data/base_project/models/builds/build_example.py +26 -0
  44. squirrels/package_data/base_project/models/builds/build_example.sql +16 -0
  45. squirrels/package_data/base_project/models/builds/build_example.yml +55 -0
  46. squirrels/package_data/base_project/models/dbviews/dbview_example.sql +12 -22
  47. squirrels/package_data/base_project/models/dbviews/dbview_example.yml +26 -0
  48. squirrels/package_data/base_project/models/federates/federate_example.py +38 -15
  49. squirrels/package_data/base_project/models/federates/federate_example.sql +16 -2
  50. squirrels/package_data/base_project/models/federates/federate_example.yml +65 -0
  51. squirrels/package_data/base_project/models/sources.yml +39 -0
  52. squirrels/package_data/base_project/parameters.yml +36 -21
  53. squirrels/package_data/base_project/pyconfigs/connections.py +6 -11
  54. squirrels/package_data/base_project/pyconfigs/context.py +20 -33
  55. squirrels/package_data/base_project/pyconfigs/parameters.py +19 -21
  56. squirrels/package_data/base_project/pyconfigs/user.py +23 -0
  57. squirrels/package_data/base_project/seeds/seed_categories.yml +15 -0
  58. squirrels/package_data/base_project/seeds/seed_subcategories.csv +15 -15
  59. squirrels/package_data/base_project/seeds/seed_subcategories.yml +21 -0
  60. squirrels/package_data/base_project/squirrels.yml.j2 +17 -40
  61. squirrels/parameters.py +20 -20
  62. {squirrels-0.4.1.dist-info → squirrels-0.5.0rc0.dist-info}/METADATA +31 -32
  63. squirrels-0.5.0rc0.dist-info/RECORD +70 -0
  64. {squirrels-0.4.1.dist-info → squirrels-0.5.0rc0.dist-info}/WHEEL +1 -1
  65. squirrels-0.5.0rc0.dist-info/entry_points.txt +3 -0
  66. {squirrels-0.4.1.dist-info → squirrels-0.5.0rc0.dist-info/licenses}/LICENSE +1 -1
  67. squirrels/_authenticator.py +0 -85
  68. squirrels/_environcfg.py +0 -84
  69. squirrels/package_data/assets/favicon.ico +0 -0
  70. squirrels/package_data/assets/index.css +0 -1
  71. squirrels/package_data/assets/index.js +0 -58
  72. squirrels/package_data/base_project/dashboards.yml +0 -10
  73. squirrels/package_data/base_project/env.yml +0 -29
  74. squirrels/package_data/base_project/models/dbviews/dbview_example.py +0 -47
  75. squirrels/package_data/base_project/pyconfigs/auth.py +0 -45
  76. squirrels/package_data/templates/index.html +0 -18
  77. squirrels/project.py +0 -378
  78. squirrels/user_base.py +0 -55
  79. squirrels-0.4.1.dist-info/RECORD +0 -60
  80. squirrels-0.4.1.dist-info/entry_points.txt +0 -4
@@ -1,14 +1,18 @@
1
- import git, shutil, os, time
1
+ import shutil, os, time
2
2
 
3
- from . import _constants as c, _utils as _u
3
+ from . import _constants as c, _utils as u
4
4
  from ._manifest import ManifestConfig
5
5
 
6
6
 
7
7
  class PackageLoaderIO:
8
8
 
9
9
  @classmethod
10
- def load_packages(cls, logger: _u.Logger, manifest_cfg: ManifestConfig, *, reload: bool = False) -> None:
10
+ def load_packages(cls, logger: u.Logger, manifest_cfg: ManifestConfig, *, reload: bool = False) -> None:
11
11
  start = time.time()
12
+
13
+ # Importing git here avoids requirement of having git installed on system if not needed
14
+ import git
15
+
12
16
  # If reload, delete the modules directory (if it exists). It will be recreated later
13
17
  if reload and os.path.exists(c.PACKAGES_FOLDER):
14
18
  shutil.rmtree(c.PACKAGES_FOLDER)
@@ -20,6 +24,6 @@ class PackageLoaderIO:
20
24
  try:
21
25
  git.Repo.clone_from(repo.git, target_dir, branch=repo.revision, depth=1)
22
26
  except git.GitCommandError as e:
23
- raise _u.ConfigurationError(f"Git clone of package failed for this repository: {repo.git}") from e
27
+ raise u.ConfigurationError(f"Git clone of package failed for this repository: {repo.git}") from e
24
28
 
25
29
  logger.log_activity_time("loading packages", start)
@@ -1,5 +1,5 @@
1
1
  from __future__ import annotations
2
- from typing import Generic, TypeVar, Annotated, Type, Sequence, Iterator, Any
2
+ from typing import Generic, TypeVar, Annotated, Sequence, Iterator, Any
3
3
  from typing_extensions import Self
4
4
  from datetime import datetime
5
5
  from dataclasses import dataclass, field
@@ -7,10 +7,11 @@ from abc import ABCMeta, abstractmethod
7
7
  from copy import copy
8
8
  from fastapi import Query
9
9
  from pydantic.fields import Field
10
- import pandas as pd, re
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
13
- from .user_base import User
12
+ from . import parameter_options as _po, parameters as p, data_sources as d, _utils as u, _constants as c
13
+ from ._exceptions import InvalidInputError
14
+ from ._auth import BaseUser
14
15
  from ._connection_set import ConnectionSet
15
16
  from ._seeds import Seeds
16
17
 
@@ -27,16 +28,17 @@ class APIParamFieldInfo:
27
28
  pattern: str | None = None
28
29
  min_length: int | None = None
29
30
  max_length: int | None = None
31
+ default: Any = None
30
32
 
31
33
  def as_query_info(self):
32
34
  query_info = Query(
33
35
  title=self.title, description=self.description, examples=self.examples, pattern=self.pattern,
34
36
  min_length=self.min_length, max_length=self.max_length
35
37
  )
36
- return (self.name, Annotated[self.type, query_info], None)
38
+ return (self.name, Annotated[self.type, query_info], self.default)
37
39
 
38
40
  def as_body_info(self):
39
- field_info = Field(None,
41
+ field_info = Field(self.default,
40
42
  title=self.title, description=self.description, examples=self.examples, pattern=self.pattern,
41
43
  min_length=self.min_length, max_length=self.max_length
42
44
  )
@@ -50,26 +52,14 @@ class ParameterConfigBase(metaclass=ABCMeta):
50
52
  """
51
53
  name: str
52
54
  label: str
53
- description: str # = field(default="", kw_only=True)
54
- user_attribute: str | None # = field(default=None, kw_only=True)
55
- parent_name: str | None # = field(default=None, kw_only=True)
55
+ description: str = field(default="", kw_only=True)
56
+ user_attribute: str | None = field(default=None, kw_only=True)
57
+ parent_name: str | None = field(default=None, kw_only=True)
56
58
 
57
- @abstractmethod
58
- def __init__(
59
- self, widget_type: str, name: str, label: str, *, description: str = "", user_attribute: str | None = None,
60
- parent_name: str | None = None
61
- ) -> None:
62
- self.widget_type = widget_type
63
- self.name = name
64
- self.label = label
65
- self.description = description
66
- self.user_attribute = user_attribute
67
- self.parent_name = parent_name
68
-
69
- def _get_user_group(self, user: User | None) -> Any:
59
+ def _get_user_group(self, user: BaseUser | None) -> Any:
70
60
  if self.user_attribute is not None:
71
61
  if user is None:
72
- raise _u.ConfigurationError(f"Non-authenticated users (only allowed for public datasets) cannot use parameter " +
62
+ raise u.ConfigurationError(f"Public datasets (accessible without authentication) cannot use parameter " +
73
63
  f"'{self.name}' because 'user_attribute' is defined on this parameter.")
74
64
  return getattr(user, self.user_attribute)
75
65
 
@@ -92,7 +82,7 @@ class ParameterConfig(Generic[ParamOptionType], ParameterConfigBase):
92
82
  self, name: str, label: str, all_options: Sequence[ParamOptionType | dict], *, description: str = "",
93
83
  user_attribute: str | None = None, parent_name: str | None = None
94
84
  ) -> None:
95
- super().__init__(self.widget_type(), name, label, description=description, user_attribute=user_attribute, parent_name=parent_name)
85
+ super().__init__(name, label, description=description, user_attribute=user_attribute, parent_name=parent_name)
96
86
  self._all_options = tuple(self._to_param_option(x) for x in all_options)
97
87
 
98
88
  def _to_param_option(self, option: ParamOptionType | dict) -> ParamOptionType:
@@ -117,18 +107,17 @@ class ParameterConfig(Generic[ParamOptionType], ParameterConfigBase):
117
107
  def DataSource(*args, **kwargs) -> d.DataSource:
118
108
  pass
119
109
 
120
- def _invalid_input_error(self, selection: str, more_details: str = '') -> _u.InvalidInputError:
121
- return _u.InvalidInputError(f'Selected value "{selection}" is not valid for parameter "{self.name}". ' + more_details)
110
+ 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)
122
112
 
123
113
  @abstractmethod
124
114
  def with_selection(
125
- self, selection: str | None, user: User | None, parent_param: p._SelectionParameter | None,
126
- *, request_version: int | None = None
115
+ self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
127
116
  ) -> p.Parameter:
128
117
  pass
129
118
 
130
119
  def _get_options_iterator(
131
- self, all_options: Sequence[ParamOptionType], user: User | None, parent_param: p._SelectionParameter | None
120
+ self, all_options: Sequence[ParamOptionType], user: BaseUser | None, parent_param: p._SelectionParameter | None
132
121
  ) -> Iterator[ParamOptionType]:
133
122
  user_group = self._get_user_group(user)
134
123
  selected_parent_option_ids = frozenset(parent_param._get_selected_ids_as_list()) if parent_param else None
@@ -164,7 +153,7 @@ class SelectionParameterConfig(ParameterConfig[_po.SelectParameterOption]):
164
153
  self.children[child.name] = child
165
154
  self.trigger_refresh = True
166
155
 
167
- def _get_options(self, user: User | None, parent_param: p._SelectionParameter | None) -> Sequence[_po.SelectParameterOption]:
156
+ def _get_options(self, user: BaseUser | None, parent_param: p._SelectionParameter | None) -> Sequence[_po.SelectParameterOption]:
168
157
  return tuple(self._get_options_iterator(self.all_options, user, parent_param))
169
158
 
170
159
  def _get_default_ids_iterator(self, options: Sequence[_po.SelectParameterOption]) -> Iterator[str]:
@@ -200,8 +189,7 @@ class SingleSelectParameterConfig(SelectionParameterConfig):
200
189
  return d.SelectDataSource(*args, **kwargs)
201
190
 
202
191
  def with_selection(
203
- self, selection: str | None, user: User | None, parent_param: p._SelectionParameter | None,
204
- *, request_version: int | None = None
192
+ self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
205
193
  ) -> p.SingleSelectParameter:
206
194
  options = self._get_options(user, parent_param)
207
195
  if selection is None:
@@ -224,9 +212,9 @@ class MultiSelectParameterConfig(SelectionParameterConfig):
224
212
  """
225
213
  Class to define configurations for multi-select parameter widgets.
226
214
  """
227
- show_select_all: bool # = field(default=True, kw_only=True)
228
- order_matters: bool # = field(default=False, kw_only=True)
229
- none_is_all: bool # = field(default=True, kw_only=True)
215
+ show_select_all: bool = field(default=True, kw_only=True)
216
+ order_matters: bool = field(default=False, kw_only=True)
217
+ none_is_all: bool = field(default=True, kw_only=True)
230
218
 
231
219
  def __init__(
232
220
  self, name: str, label: str, all_options: Sequence[_po.SelectParameterOption | dict], *, description: str = "",
@@ -249,14 +237,13 @@ class MultiSelectParameterConfig(SelectionParameterConfig):
249
237
  return d.SelectDataSource(*args, **kwargs)
250
238
 
251
239
  def with_selection(
252
- self, selection: str | None, user: User | None, parent_param: p._SelectionParameter | None,
253
- *, request_version: int | None = None
240
+ self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
254
241
  ) -> p.MultiSelectParameter:
255
242
  options = self._get_options(user, parent_param)
256
243
  if selection is None:
257
244
  selected_ids = tuple(self._get_default_ids_iterator(options))
258
245
  else:
259
- selected_ids = _u.load_json_or_comma_delimited_str_as_list(selection)
246
+ selected_ids = u.load_json_or_comma_delimited_str_as_list(selection)
260
247
  return p.MultiSelectParameter(self, options, selected_ids)
261
248
 
262
249
  def get_api_field_info(self) -> APIParamFieldInfo:
@@ -306,8 +293,7 @@ class DateParameterConfig(_DateTypeParameterConfig[_po.DateParameterOption]):
306
293
  return d.DateDataSource(*args, **kwargs)
307
294
 
308
295
  def with_selection(
309
- self, selection: str | None, user: User | None, parent_param: p._SelectionParameter | None,
310
- *, request_version: int | None = None
296
+ self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
311
297
  ) -> p.DateParameter:
312
298
  curr_option: _po.DateParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
313
299
  selected_date = curr_option._default_date if selection is None and curr_option is not None else selection
@@ -316,7 +302,7 @@ class DateParameterConfig(_DateTypeParameterConfig[_po.DateParameterOption]):
316
302
  def get_api_field_info(self) -> APIParamFieldInfo:
317
303
  examples = [str(x._default_date) for x in self.all_options]
318
304
  return APIParamFieldInfo(
319
- self.name, str, title=self.label, description=self.description, examples=examples, pattern=c.date_regex
305
+ self.name, str, title=self.label, description=self.description, examples=examples, pattern=c.DATE_REGEX
320
306
  )
321
307
 
322
308
 
@@ -346,8 +332,7 @@ class DateRangeParameterConfig(_DateTypeParameterConfig[_po.DateRangeParameterOp
346
332
  return d.DateRangeDataSource(*args, **kwargs)
347
333
 
348
334
  def with_selection(
349
- self, selection: str | None, user: User | None, parent_param: p._SelectionParameter | None,
350
- *, request_version: int | None = None
335
+ self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
351
336
  ) -> p.DateRangeParameter:
352
337
  curr_option: _po.DateRangeParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
353
338
  if selection is None:
@@ -358,7 +343,7 @@ class DateRangeParameterConfig(_DateTypeParameterConfig[_po.DateRangeParameterOp
358
343
  selected_start_date, selected_end_date = None, None
359
344
  else:
360
345
  try:
361
- selected_start_date, selected_end_date = _u.load_json_or_comma_delimited_str_as_list(selection)
346
+ selected_start_date, selected_end_date = u.load_json_or_comma_delimited_str_as_list(selection)
362
347
  except ValueError:
363
348
  raise self._invalid_input_error(selection, "Date range parameter selection must be two dates.")
364
349
  return p.DateRangeParameter(self, curr_option, selected_start_date, selected_end_date)
@@ -410,8 +395,7 @@ class NumberParameterConfig(_NumericParameterConfig[_po.NumberParameterOption]):
410
395
  return d.NumberDataSource(*args, **kwargs)
411
396
 
412
397
  def with_selection(
413
- self, selection: str | None, user: User | None, parent_param: p._SelectionParameter | None,
414
- *, request_version: int | None = None
398
+ self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
415
399
  ) -> p.NumberParameter:
416
400
  curr_option: _po.NumberParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
417
401
  selected_value = curr_option._default_value if selection is None and curr_option is not None else selection
@@ -450,8 +434,7 @@ class NumberRangeParameterConfig(_NumericParameterConfig[_po.NumberRangeParamete
450
434
  return d.NumberRangeDataSource(*args, **kwargs)
451
435
 
452
436
  def with_selection(
453
- self, selection: str | None, user: User | None, parent_param: p._SelectionParameter | None,
454
- *, request_version: int | None = None
437
+ self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
455
438
  ) -> p.NumberRangeParameter:
456
439
  curr_option: _po.NumberRangeParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
457
440
  if selection is None:
@@ -462,7 +445,7 @@ class NumberRangeParameterConfig(_NumericParameterConfig[_po.NumberRangeParamete
462
445
  selected_lower_value, selected_upper_value = None, None
463
446
  else:
464
447
  try:
465
- selected_lower_value, selected_upper_value = _u.load_json_or_comma_delimited_str_as_list(selection)
448
+ selected_lower_value, selected_upper_value = u.load_json_or_comma_delimited_str_as_list(selection)
466
449
  except ValueError:
467
450
  raise self._invalid_input_error(selection, "Number range parameter selection must be two numbers.")
468
451
  return p.NumberRangeParameter(self, curr_option, selected_lower_value, selected_upper_value)
@@ -490,7 +473,7 @@ class TextParameterConfig(ParameterConfig[_po.TextParameterOption]):
490
473
 
491
474
  allowed_input_types = ["text", "textarea", "number", "date", "datetime-local", "month", "time", "color", "password"]
492
475
  if input_type not in allowed_input_types:
493
- raise _u.ConfigurationError(f"Invalid input type '{input_type}' for text parameter '{name}'. Must be one of {allowed_input_types}.")
476
+ raise u.ConfigurationError(f"Invalid input type '{input_type}' for text parameter '{name}'. Must be one of {allowed_input_types}.")
494
477
 
495
478
  self.input_type = input_type
496
479
  for option in self._all_options:
@@ -499,9 +482,9 @@ class TextParameterConfig(ParameterConfig[_po.TextParameterOption]):
499
482
  def validate_entered_text(self, entered_text: str) -> str:
500
483
  if self.input_type == "number":
501
484
  try:
502
- int(entered_text)
485
+ float(entered_text)
503
486
  except ValueError:
504
- raise self._invalid_input_error(entered_text, "Must be an integer (without decimals)")
487
+ raise self._invalid_input_error(entered_text, "Must be a number")
505
488
  elif self.input_type == "date":
506
489
  try:
507
490
  datetime.strptime(entered_text, "%Y-%m-%d")
@@ -523,7 +506,7 @@ class TextParameterConfig(ParameterConfig[_po.TextParameterOption]):
523
506
  except ValueError:
524
507
  raise self._invalid_input_error(entered_text, "Must be a time in hh:mm format.")
525
508
  elif self.input_type == "color":
526
- if not re.match(c.color_regex, entered_text):
509
+ if not re.match(c.COLOR_REGEX, entered_text):
527
510
  raise self._invalid_input_error(entered_text, "Must be a valid color hex code (e.g. #000000).")
528
511
 
529
512
  return entered_text
@@ -541,8 +524,7 @@ class TextParameterConfig(ParameterConfig[_po.TextParameterOption]):
541
524
  return d.TextDataSource(*args, **kwargs)
542
525
 
543
526
  def with_selection(
544
- self, selection: str | None, user: User | None, parent_param: p._SelectionParameter | None,
545
- *, request_version: int | None = None
527
+ self, selection: str | None, user: BaseUser | None, parent_param: p._SelectionParameter | None
546
528
  ) -> p.TextParameter:
547
529
  curr_option: _po.TextParameterOption | None = next(self._get_options_iterator(self.all_options, user, parent_param), None)
548
530
  entered_text = curr_option._default_text if selection is None and curr_option is not None else selection
@@ -555,29 +537,27 @@ class TextParameterConfig(ParameterConfig[_po.TextParameterOption]):
555
537
  )
556
538
 
557
539
 
558
- @dataclass
559
- class DataSourceParameterConfig(ParameterConfigBase):
540
+ ParamConfigType = TypeVar("ParamConfigType", bound=ParameterConfig)
541
+
542
+ class DataSourceParameterConfig(Generic[ParamConfigType], ParameterConfigBase):
560
543
  """
561
544
  Class to define configurations for parameter widgets whose options come from lookup tables
562
545
  """
563
- parameter_type: Type[ParameterConfig]
564
- data_source: d.DataSource
565
-
566
546
  def __init__(
567
- self, parameter_type: Type[ParameterConfig], name: str, label: str, data_source: d.DataSource | dict, *,
547
+ self, parameter_type: type[ParamConfigType], name: str, label: str, data_source: d.DataSource | dict, *,
568
548
  extra_args: dict = {}, description: str = "", user_attribute: str | None = None, parent_name: str | None = None
569
549
  ) -> None:
570
- super().__init__("data_source", name, label, description=description, user_attribute=user_attribute, parent_name=parent_name)
550
+ super().__init__(name, label, description=description, user_attribute=user_attribute, parent_name=parent_name)
571
551
  self.parameter_type = parameter_type
572
552
  if isinstance(data_source, dict):
573
553
  data_source = parameter_type.DataSource(**data_source)
574
554
  self.data_source = data_source
575
555
  self.extra_args = extra_args
576
556
 
577
- def convert(self, df: pd.DataFrame) -> ParameterConfig:
557
+ def convert(self, df: pl.DataFrame) -> ParamConfigType:
578
558
  return self.data_source._convert(self, df)
579
559
 
580
- def get_dataframe(self, default_conn_name: str, conn_set: ConnectionSet, seeds: Seeds) -> pd.DataFrame:
560
+ def get_dataframe(self, default_conn_name: str, conn_set: ConnectionSet, seeds: Seeds) -> pl.DataFrame:
581
561
  datasource = self.data_source
582
562
  query = datasource._get_query()
583
563
  if datasource._is_from_seeds:
@@ -587,5 +567,5 @@ class DataSourceParameterConfig(ParameterConfigBase):
587
567
  conn_name = datasource._get_connection_name(default_conn_name)
588
568
  df = conn_set.run_sql_query_from_conn_name(query, conn_name)
589
569
  except RuntimeError as e:
590
- raise _u.ConfigurationError(f'Error executing query for datasource parameter "{self.name}"') from e
570
+ raise u.ConfigurationError(f'Error executing query for datasource parameter "{self.name}"') from e
591
571
  return df
@@ -1,15 +1,15 @@
1
1
  from __future__ import annotations
2
- from typing import Optional, Sequence
2
+ from typing import Optional, Sequence, Any
3
3
  from dataclasses import dataclass, field
4
4
  from collections import OrderedDict
5
- import time, concurrent.futures, pandas as pd
5
+ import time, concurrent.futures, polars as pl
6
6
 
7
7
  from . import _utils as u, _constants as c, parameters as p, _parameter_configs as _pc, _py_module as pm, _api_response_models as arm
8
8
  from .arguments.init_time_args import ParametersArgs
9
9
  from ._manifest import ParametersConfig, ManifestConfig
10
10
  from ._connection_set import ConnectionSet, ConnectionsArgs
11
11
  from ._seeds import Seeds
12
- from .user_base import User
12
+ from ._auth import BaseUser
13
13
 
14
14
 
15
15
  @dataclass
@@ -51,7 +51,7 @@ class ParameterConfigsSet:
51
51
  def _get_all_ds_param_configs(self) -> Sequence[_pc.DataSourceParameterConfig]:
52
52
  return list(self._data_source_params.values())
53
53
 
54
- def __convert_datasource_params(self, df_dict: dict[str, pd.DataFrame]) -> None:
54
+ def __convert_datasource_params(self, df_dict: dict[str, pl.DataFrame]) -> None:
55
55
  done = set()
56
56
  for curr_name in self._data_source_params:
57
57
  stack = [curr_name] # Note: parents must be converted first before children
@@ -98,19 +98,21 @@ class ParameterConfigsSet:
98
98
 
99
99
  parent._add_child_mutate(param_config)
100
100
 
101
- def _post_process_params(self, df_dict: dict[str, pd.DataFrame]) -> None:
101
+ def _post_process_params(self, df_dict: dict[str, pl.DataFrame]) -> None:
102
102
  self.__convert_datasource_params(df_dict)
103
103
  self.__validate_param_relationships()
104
104
 
105
105
  def apply_selections(
106
- self, dataset_params: Optional[Sequence[str]], selections: dict[str, str], user: Optional[User],
107
- *, updates_only: bool = False, request_version: Optional[int] = None
106
+ self, dataset_params: Optional[Sequence[str]], selections: dict[str, Any], user: BaseUser | None, *, parent_param: str | None = None
108
107
  ) -> ParameterSet:
109
108
  if dataset_params is None:
110
- dataset_params = list(self._data.keys())
109
+ if user is None:
110
+ dataset_params = [k for k, v in self._data.items() if v.user_attribute is None]
111
+ else:
112
+ dataset_params = list(self._data.keys())
111
113
 
112
114
  parameters_by_name: dict[str, p.Parameter] = {}
113
- params_to_process = selections.keys() if selections and updates_only else dataset_params
115
+ params_to_process = [parent_param] if parent_param else dataset_params
114
116
  params_to_process_set = set(params_to_process)
115
117
  for some_name in params_to_process:
116
118
  stack = [some_name] # Note: process parent selections first (if applicable) before children
@@ -154,8 +156,8 @@ class ParameterConfigsSetIO:
154
156
  obj: ParameterConfigsSet # this is static (set in load_from_file) to simplify development experience for pyconfigs/parameters.py
155
157
 
156
158
  @classmethod
157
- def _get_df_dict_from_data_sources(cls, default_conn_name: str, seeds: Seeds, conn_set: ConnectionSet) -> dict[str, pd.DataFrame]:
158
- def get_dataframe(ds_param_config: _pc.DataSourceParameterConfig) -> tuple[str, pd.DataFrame]:
159
+ def _get_df_dict_from_data_sources(cls, default_conn_name: str, seeds: Seeds, conn_set: ConnectionSet) -> dict[str, pl.DataFrame]:
160
+ def get_dataframe(ds_param_config: _pc.DataSourceParameterConfig) -> tuple[str, pl.DataFrame]:
159
161
  return ds_param_config.name, ds_param_config.get_dataframe(default_conn_name, conn_set, seeds)
160
162
 
161
163
  ds_param_configs = cls.obj._get_all_ds_param_configs()
@@ -172,7 +174,7 @@ class ParameterConfigsSetIO:
172
174
 
173
175
  @classmethod
174
176
  def get_param_args(cls, conn_args: ConnectionsArgs) -> ParametersArgs:
175
- return ParametersArgs(conn_args.proj_vars, conn_args.env_vars)
177
+ return ParametersArgs(conn_args.project_path, conn_args.proj_vars, conn_args.env_vars)
176
178
 
177
179
  @classmethod
178
180
  def load_from_file(
@@ -186,7 +188,7 @@ class ParameterConfigsSetIO:
186
188
 
187
189
  pm.run_pyconfig_main(base_path, c.PARAMETERS_FILE, {"sqrl": param_args})
188
190
 
189
- default_conn_name = manifest_cfg.settings_obj.get_default_connection_name()
191
+ default_conn_name = manifest_cfg.env_vars.get(c.SQRL_CONNECTIONS_DEFAULT_NAME_USED, "default")
190
192
  df_dict = cls._get_df_dict_from_data_sources(default_conn_name, seeds, conn_set)
191
193
  cls.obj._post_process_params(df_dict)
192
194