squirrels 0.4.0__py3-none-any.whl → 0.5.0__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.
- dateutils/__init__.py +6 -0
- dateutils/_enums.py +25 -0
- squirrels/dateutils.py → dateutils/_implementation.py +58 -111
- dateutils/types.py +6 -0
- squirrels/__init__.py +13 -11
- squirrels/_api_routes/__init__.py +5 -0
- squirrels/_api_routes/auth.py +271 -0
- squirrels/_api_routes/base.py +165 -0
- squirrels/_api_routes/dashboards.py +150 -0
- squirrels/_api_routes/data_management.py +145 -0
- squirrels/_api_routes/datasets.py +257 -0
- squirrels/_api_routes/oauth2.py +298 -0
- squirrels/_api_routes/project.py +252 -0
- squirrels/_api_server.py +256 -450
- squirrels/_arguments/__init__.py +0 -0
- squirrels/_arguments/init_time_args.py +108 -0
- squirrels/_arguments/run_time_args.py +147 -0
- squirrels/_auth.py +960 -0
- squirrels/_command_line.py +126 -45
- squirrels/_compile_prompts.py +147 -0
- squirrels/_connection_set.py +48 -26
- squirrels/_constants.py +68 -38
- squirrels/_dashboards.py +160 -0
- squirrels/_data_sources.py +570 -0
- squirrels/_dataset_types.py +84 -0
- squirrels/_exceptions.py +29 -0
- squirrels/_initializer.py +177 -80
- squirrels/_logging.py +115 -0
- squirrels/_manifest.py +208 -79
- squirrels/_model_builder.py +69 -0
- squirrels/_model_configs.py +74 -0
- squirrels/_model_queries.py +52 -0
- squirrels/_models.py +926 -367
- squirrels/_package_data/base_project/.env +42 -0
- squirrels/_package_data/base_project/.env.example +42 -0
- squirrels/_package_data/base_project/assets/expenses.db +0 -0
- squirrels/_package_data/base_project/connections.yml +16 -0
- squirrels/_package_data/base_project/dashboards/dashboard_example.py +34 -0
- squirrels/_package_data/base_project/dashboards/dashboard_example.yml +22 -0
- squirrels/{package_data → _package_data}/base_project/docker/.dockerignore +5 -2
- squirrels/{package_data → _package_data}/base_project/docker/Dockerfile +3 -3
- squirrels/{package_data → _package_data}/base_project/docker/compose.yml +1 -1
- squirrels/_package_data/base_project/duckdb_init.sql +10 -0
- squirrels/{package_data/base_project/.gitignore → _package_data/base_project/gitignore} +3 -2
- squirrels/_package_data/base_project/macros/macros_example.sql +17 -0
- squirrels/_package_data/base_project/models/builds/build_example.py +26 -0
- squirrels/_package_data/base_project/models/builds/build_example.sql +16 -0
- squirrels/_package_data/base_project/models/builds/build_example.yml +57 -0
- squirrels/_package_data/base_project/models/dbviews/dbview_example.sql +12 -0
- squirrels/_package_data/base_project/models/dbviews/dbview_example.yml +26 -0
- squirrels/_package_data/base_project/models/federates/federate_example.py +37 -0
- squirrels/_package_data/base_project/models/federates/federate_example.sql +19 -0
- squirrels/_package_data/base_project/models/federates/federate_example.yml +65 -0
- squirrels/_package_data/base_project/models/sources.yml +38 -0
- squirrels/{package_data → _package_data}/base_project/parameters.yml +56 -40
- squirrels/_package_data/base_project/pyconfigs/connections.py +14 -0
- squirrels/{package_data → _package_data}/base_project/pyconfigs/context.py +21 -40
- squirrels/_package_data/base_project/pyconfigs/parameters.py +141 -0
- squirrels/_package_data/base_project/pyconfigs/user.py +44 -0
- squirrels/_package_data/base_project/seeds/seed_categories.yml +15 -0
- squirrels/_package_data/base_project/seeds/seed_subcategories.csv +15 -0
- squirrels/_package_data/base_project/seeds/seed_subcategories.yml +21 -0
- squirrels/_package_data/base_project/squirrels.yml.j2 +61 -0
- squirrels/_package_data/templates/dataset_results.html +112 -0
- squirrels/_package_data/templates/oauth_login.html +271 -0
- squirrels/_package_data/templates/squirrels_studio.html +20 -0
- squirrels/_package_loader.py +8 -4
- squirrels/_parameter_configs.py +104 -103
- squirrels/_parameter_options.py +348 -0
- squirrels/_parameter_sets.py +57 -47
- squirrels/_parameters.py +1664 -0
- squirrels/_project.py +721 -0
- squirrels/_py_module.py +7 -5
- squirrels/_schemas/__init__.py +0 -0
- squirrels/_schemas/auth_models.py +167 -0
- squirrels/_schemas/query_param_models.py +75 -0
- squirrels/{_api_response_models.py → _schemas/response_models.py} +126 -47
- squirrels/_seeds.py +35 -16
- squirrels/_sources.py +110 -0
- squirrels/_utils.py +248 -73
- squirrels/_version.py +1 -1
- squirrels/arguments.py +7 -0
- squirrels/auth.py +4 -0
- squirrels/connections.py +3 -0
- squirrels/dashboards.py +2 -81
- squirrels/data_sources.py +14 -631
- squirrels/parameter_options.py +13 -348
- squirrels/parameters.py +14 -1266
- squirrels/types.py +16 -0
- squirrels-0.5.0.dist-info/METADATA +113 -0
- squirrels-0.5.0.dist-info/RECORD +97 -0
- {squirrels-0.4.0.dist-info → squirrels-0.5.0.dist-info}/WHEEL +1 -1
- squirrels-0.5.0.dist-info/entry_points.txt +3 -0
- {squirrels-0.4.0.dist-info → squirrels-0.5.0.dist-info/licenses}/LICENSE +1 -1
- squirrels/_authenticator.py +0 -85
- squirrels/_dashboards_io.py +0 -61
- squirrels/_environcfg.py +0 -84
- squirrels/arguments/init_time_args.py +0 -40
- squirrels/arguments/run_time_args.py +0 -208
- squirrels/package_data/assets/favicon.ico +0 -0
- squirrels/package_data/assets/index.css +0 -1
- squirrels/package_data/assets/index.js +0 -58
- squirrels/package_data/base_project/assets/expenses.db +0 -0
- squirrels/package_data/base_project/connections.yml +0 -7
- squirrels/package_data/base_project/dashboards/dashboard_example.py +0 -32
- squirrels/package_data/base_project/dashboards.yml +0 -10
- squirrels/package_data/base_project/env.yml +0 -29
- squirrels/package_data/base_project/models/dbviews/dbview_example.py +0 -47
- squirrels/package_data/base_project/models/dbviews/dbview_example.sql +0 -22
- squirrels/package_data/base_project/models/federates/federate_example.py +0 -21
- squirrels/package_data/base_project/models/federates/federate_example.sql +0 -3
- squirrels/package_data/base_project/pyconfigs/auth.py +0 -45
- squirrels/package_data/base_project/pyconfigs/connections.py +0 -19
- squirrels/package_data/base_project/pyconfigs/parameters.py +0 -95
- squirrels/package_data/base_project/seeds/seed_subcategories.csv +0 -15
- squirrels/package_data/base_project/squirrels.yml.j2 +0 -94
- squirrels/package_data/templates/index.html +0 -18
- squirrels/project.py +0 -378
- squirrels/user_base.py +0 -55
- squirrels-0.4.0.dist-info/METADATA +0 -117
- squirrels-0.4.0.dist-info/RECORD +0 -60
- squirrels-0.4.0.dist-info/entry_points.txt +0 -4
- /squirrels/{package_data → _package_data}/base_project/assets/weather.db +0 -0
- /squirrels/{package_data → _package_data}/base_project/seeds/seed_categories.csv +0 -0
- /squirrels/{package_data → _package_data}/base_project/tmp/.gitignore +0 -0
|
@@ -4,36 +4,48 @@ parameters:
|
|
|
4
4
|
arguments: ## arguments to specify depend on values for 'type' and 'factory'
|
|
5
5
|
name: group_by
|
|
6
6
|
label: Group By
|
|
7
|
-
description: Dimension to aggregate by
|
|
7
|
+
description: Dimension(s) to aggregate by ## optional, default is empty string
|
|
8
|
+
user_attribute: access_level ## optional, default is null
|
|
8
9
|
all_options:
|
|
9
|
-
- id:
|
|
10
|
+
- id: trans
|
|
10
11
|
label: Transaction
|
|
11
|
-
columns: ["
|
|
12
|
-
aliases: ["
|
|
13
|
-
is_default: false ## optional, default
|
|
14
|
-
user_groups: []
|
|
15
|
-
parent_option_ids: [] ## optional, default
|
|
16
|
-
- id:
|
|
17
|
-
label:
|
|
12
|
+
columns: ["id", "date", "category", "subcategory", "description"] ## custom field
|
|
13
|
+
aliases: ["_id", "date", "category", "subcategory", "description"] ## custom field (any alias starting with "_" will not be selected - see context.py for implementation)
|
|
14
|
+
is_default: false ## optional, shown is default - exists for SingleSelect or MultiSelect options only
|
|
15
|
+
user_groups: ["admin"] ## optional, default is empty list
|
|
16
|
+
parent_option_ids: [] ## optional, shown is default - exists for all parameter options
|
|
17
|
+
- id: day
|
|
18
|
+
label: Day
|
|
18
19
|
columns: [date]
|
|
19
|
-
|
|
20
|
+
aliases: [day]
|
|
21
|
+
user_groups: ["admin", "member"]
|
|
22
|
+
- id: month
|
|
23
|
+
label: Month
|
|
24
|
+
columns: [month]
|
|
25
|
+
user_groups: ["admin", "member", "guest"]
|
|
26
|
+
- id: cat
|
|
20
27
|
label: Category
|
|
21
28
|
columns: [category]
|
|
22
|
-
|
|
29
|
+
user_groups: ["admin", "member", "guest"]
|
|
30
|
+
- id: subcat
|
|
23
31
|
label: Subcategory
|
|
24
32
|
columns: [category, subcategory]
|
|
25
|
-
|
|
26
|
-
parent_name: null ## optional, default
|
|
33
|
+
user_groups: ["admin", "member", "guest"]
|
|
34
|
+
parent_name: null ## optional, shown is default - exists for all parameter types
|
|
27
35
|
|
|
28
|
-
- type:
|
|
36
|
+
- type: NumberParameter
|
|
29
37
|
factory: CreateWithOptions
|
|
30
38
|
arguments:
|
|
31
|
-
name:
|
|
32
|
-
label:
|
|
33
|
-
description:
|
|
39
|
+
name: limit
|
|
40
|
+
label: Max Number of Rows
|
|
41
|
+
description: Maximum number of rows to return
|
|
34
42
|
parent_name: group_by
|
|
35
43
|
all_options:
|
|
36
|
-
-
|
|
44
|
+
- min_value: 0
|
|
45
|
+
max_value: 1000
|
|
46
|
+
increment: 10
|
|
47
|
+
default_value: 1000
|
|
48
|
+
parent_option_ids: trans
|
|
37
49
|
|
|
38
50
|
- type: DateParameter
|
|
39
51
|
factory: CreateFromSource
|
|
@@ -42,7 +54,7 @@ parameters:
|
|
|
42
54
|
label: Start Date
|
|
43
55
|
description: Start date to filter transactions by
|
|
44
56
|
data_source:
|
|
45
|
-
table_or_query: SELECT min(date) AS min_date, max(date) AS max_date FROM
|
|
57
|
+
table_or_query: SELECT min(date) AS min_date, max(date) AS max_date FROM expenses
|
|
46
58
|
default_date_col: min_date
|
|
47
59
|
min_date_col: min_date
|
|
48
60
|
max_date_col: max_date
|
|
@@ -54,7 +66,9 @@ parameters:
|
|
|
54
66
|
label: End Date
|
|
55
67
|
description: End date to filter transactions by
|
|
56
68
|
all_options:
|
|
57
|
-
- default_date:
|
|
69
|
+
- default_date: 2024-12-31
|
|
70
|
+
min_date: 2024-01-01
|
|
71
|
+
max_date: 2024-12-31
|
|
58
72
|
|
|
59
73
|
- type: DateRangeParameter
|
|
60
74
|
factory: CreateWithOptions
|
|
@@ -63,8 +77,10 @@ parameters:
|
|
|
63
77
|
label: Date Range
|
|
64
78
|
description: Date range to filter transactions by
|
|
65
79
|
all_options:
|
|
66
|
-
- default_start_date:
|
|
67
|
-
default_end_date:
|
|
80
|
+
- default_start_date: 2024-01-01
|
|
81
|
+
default_end_date: 2024-12-31
|
|
82
|
+
min_date: 2024-01-01
|
|
83
|
+
max_date: 2024-12-31
|
|
68
84
|
|
|
69
85
|
- type: MultiSelectParameter
|
|
70
86
|
factory: CreateFromSource
|
|
@@ -76,14 +92,14 @@ parameters:
|
|
|
76
92
|
table_or_query: seed_categories
|
|
77
93
|
id_col: category_id
|
|
78
94
|
options_col: category
|
|
79
|
-
|
|
80
|
-
order_by_col: null ## optional, default
|
|
81
|
-
is_default_col: null ## optional, default
|
|
82
|
-
custom_cols: {} ## optional, default
|
|
83
|
-
include_all: true ## optional, default
|
|
84
|
-
order_matters: false ## optional, default
|
|
85
|
-
user_group_col: null ## optional, default
|
|
86
|
-
connection_name: default ## optional, default
|
|
95
|
+
source: seeds ## optional, default is "connection" - must be one of "connection", "seeds", or "vdl" - exists for data_source of any parameters
|
|
96
|
+
order_by_col: null ## optional, shown is default - exists for data_source of SingleSelect and MultiSelect
|
|
97
|
+
is_default_col: null ## optional, shown is default - exists for data_source of SingleSelect and MultiSelect
|
|
98
|
+
custom_cols: {} ## optional, shown is default - exists for data_source of SingleSelect and MultiSelect
|
|
99
|
+
include_all: true ## optional, shown is default - exists for data_source of MultiSelect only
|
|
100
|
+
order_matters: false ## optional, shown is default - exists for data_source of MultiSelect only
|
|
101
|
+
user_group_col: null ## optional, shown is default - exists for data_source of any parameters
|
|
102
|
+
connection_name: default ## optional, shown is default - exists for data_source of any parameters
|
|
87
103
|
|
|
88
104
|
- type: MultiSelectParameter
|
|
89
105
|
factory: CreateFromSource
|
|
@@ -96,8 +112,8 @@ parameters:
|
|
|
96
112
|
table_or_query: seed_subcategories
|
|
97
113
|
id_col: subcategory_id
|
|
98
114
|
options_col: subcategory
|
|
99
|
-
|
|
100
|
-
parent_id_col: category_id ## optional, default is null
|
|
115
|
+
source: seeds
|
|
116
|
+
parent_id_col: category_id ## optional, default is null - exists for all parameter types
|
|
101
117
|
|
|
102
118
|
- type: NumberParameter
|
|
103
119
|
factory: CreateWithOptions
|
|
@@ -107,9 +123,9 @@ parameters:
|
|
|
107
123
|
description: Number to filter on transactions with an amount greater than this value
|
|
108
124
|
all_options:
|
|
109
125
|
- min_value: 0
|
|
110
|
-
max_value:
|
|
111
|
-
increment: 10 ## optional, default is 1
|
|
112
|
-
default_value: null ## optional, default
|
|
126
|
+
max_value: 300
|
|
127
|
+
increment: 10 ## optional, default is 1 - exists for Number and NumberRange options
|
|
128
|
+
default_value: null ## optional, shown is default - exists for Number options only
|
|
113
129
|
|
|
114
130
|
- type: NumberParameter
|
|
115
131
|
factory: CreateFromSource
|
|
@@ -118,12 +134,12 @@ parameters:
|
|
|
118
134
|
label: Amounts Less Than
|
|
119
135
|
description: Number to filter on transactions with an amount less than this value
|
|
120
136
|
data_source:
|
|
121
|
-
table_or_query: "SELECT 0 as min_value,
|
|
137
|
+
table_or_query: "SELECT 0 as min_value, 300 as max_value, 10 as increment"
|
|
122
138
|
min_value_col: min_value
|
|
123
139
|
max_value_col: max_value
|
|
124
140
|
increment_col: increment ## optional, default is null
|
|
125
141
|
default_value_col: max_value ## optional, default is null
|
|
126
|
-
id_col: null ## optional, default
|
|
142
|
+
id_col: null ## optional, shown is default - required for SingleSelect and MultiSelect, optional for others
|
|
127
143
|
|
|
128
144
|
- type: NumberRangeParameter
|
|
129
145
|
factory: CreateWithOptions
|
|
@@ -133,8 +149,8 @@ parameters:
|
|
|
133
149
|
description: Number range to filter on transactions with an amount within this range
|
|
134
150
|
all_options:
|
|
135
151
|
- min_value: 0
|
|
136
|
-
max_value:
|
|
137
|
-
default_lower_value:
|
|
138
|
-
default_upper_value:
|
|
152
|
+
max_value: 300
|
|
153
|
+
default_lower_value: 0 ## optional, default is null (or min_value) - exists for NumberRange options only
|
|
154
|
+
default_upper_value: 300 ## optional, default is null (or max_value) - exists for NumberRange options only
|
|
139
155
|
|
|
140
156
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
from squirrels import arguments as args, connections as cn
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def main(connections: dict[str, cn.ConnectionProperties | Any], sqrl: args.ConnectionsArgs) -> None:
|
|
6
|
+
"""
|
|
7
|
+
Define sqlalchemy engines by adding them to the "connections" dictionary
|
|
8
|
+
"""
|
|
9
|
+
## SQLAlchemy URL for a connection engine
|
|
10
|
+
conn_str: str = sqrl.env_vars["SQLITE_URI"].format(project_path=sqrl.project_path)
|
|
11
|
+
|
|
12
|
+
## Assigning names to connection engines
|
|
13
|
+
connections["default"] = cn.ConnectionProperties(label="SQLite Expenses Database", type=cn.ConnectionTypeEnum.SQLALCHEMY, uri=conn_str)
|
|
14
|
+
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
from typing import Any
|
|
2
|
-
from squirrels import
|
|
2
|
+
from squirrels import arguments as args, parameters as p
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
def main(ctx: dict[str, Any], sqrl: ContextArgs) -> None:
|
|
5
|
+
def main(ctx: dict[str, Any], sqrl: args.ContextArgs) -> None:
|
|
6
6
|
"""
|
|
7
7
|
Define context variables AFTER parameter selections are made by adding entries to the dictionary "ctx".
|
|
8
8
|
These context variables can then be used in the models.
|
|
9
9
|
|
|
10
10
|
Note that the code here is used by all datasets, regardless of the parameters they use. You can use
|
|
11
|
-
sqrl.
|
|
11
|
+
sqrl.param_exists to determine the conditions to execute certain blocks of code.
|
|
12
12
|
"""
|
|
13
13
|
if sqrl.param_exists("group_by"):
|
|
14
14
|
group_by_param = sqrl.prms["group_by"]
|
|
@@ -16,84 +16,65 @@ def main(ctx: dict[str, Any], sqrl: ContextArgs) -> None:
|
|
|
16
16
|
|
|
17
17
|
columns = group_by_param.get_selected("columns")
|
|
18
18
|
aliases = group_by_param.get_selected("aliases", default_field="columns")
|
|
19
|
-
assert isinstance(columns, list) and isinstance(aliases, list)
|
|
19
|
+
assert isinstance(columns, list) and isinstance(aliases, list) and len(columns) == len(aliases)
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
ctx["group_by_cols"] = ", ".join(columns)
|
|
23
|
-
ctx["order_by_cols"] = ", ".join((x+" DESC") for x in aliases)
|
|
24
|
-
ctx["order_by_cols_list"] = aliases
|
|
25
|
-
|
|
26
|
-
if sqrl.param_exists("description_filter"):
|
|
27
|
-
descript_param = sqrl.prms["description_filter"]
|
|
28
|
-
assert isinstance(descript_param, p.TextParameter)
|
|
29
|
-
|
|
30
|
-
desc_pattern = descript_param.get_entered_text().apply_percent_wrap()
|
|
31
|
-
|
|
32
|
-
sqrl.set_placeholder("desc_pattern", desc_pattern)
|
|
21
|
+
column_to_alias_mapping = {x: y for x, y in zip(columns, aliases) if not y.startswith("_")}
|
|
33
22
|
|
|
23
|
+
ctx["group_by_cols"] = columns
|
|
24
|
+
ctx["select_dim_cols"] = list(x+" as "+y for x, y in column_to_alias_mapping.items())
|
|
25
|
+
ctx["order_by_cols"] = list(column_to_alias_mapping.values())
|
|
26
|
+
ctx["order_by_cols_desc"] = list(x+" DESC" for x in ctx["order_by_cols"])
|
|
27
|
+
ctx["column_to_alias_mapping"] = column_to_alias_mapping
|
|
28
|
+
|
|
34
29
|
if sqrl.param_exists("start_date"):
|
|
35
30
|
start_date_param = sqrl.prms["start_date"]
|
|
36
31
|
assert isinstance(start_date_param, p.DateParameter)
|
|
37
32
|
|
|
38
|
-
start_date = start_date_param.get_selected_date()
|
|
39
|
-
|
|
40
|
-
sqrl.set_placeholder("start_date", start_date)
|
|
33
|
+
ctx["start_date"] = start_date_param.get_selected_date()
|
|
41
34
|
|
|
42
35
|
if sqrl.param_exists("end_date"):
|
|
43
36
|
end_date_param = sqrl.prms["end_date"]
|
|
44
37
|
assert isinstance(end_date_param, p.DateParameter)
|
|
45
38
|
|
|
46
|
-
end_date = end_date_param.get_selected_date()
|
|
47
|
-
|
|
48
|
-
sqrl.set_placeholder("end_date", end_date)
|
|
39
|
+
ctx["end_date"] = end_date_param.get_selected_date()
|
|
49
40
|
|
|
50
41
|
if sqrl.param_exists("date_range"):
|
|
51
42
|
date_range_param = sqrl.prms["date_range"]
|
|
52
43
|
assert isinstance(date_range_param, p.DateRangeParameter)
|
|
53
44
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
sqrl.set_placeholder("start_date", start_date)
|
|
58
|
-
sqrl.set_placeholder("end_date", end_date)
|
|
45
|
+
ctx["start_date_from_range"] = date_range_param.get_selected_start_date()
|
|
46
|
+
ctx["end_date_from_range"] = date_range_param.get_selected_end_date()
|
|
59
47
|
|
|
60
48
|
if sqrl.param_exists("category"):
|
|
61
49
|
category_param = sqrl.prms["category"]
|
|
62
50
|
assert isinstance(category_param, p.MultiSelectParameter)
|
|
63
51
|
|
|
64
52
|
ctx["has_categories"] = category_param.has_non_empty_selection()
|
|
65
|
-
ctx["categories"] = category_param.
|
|
53
|
+
ctx["categories"] = category_param.get_selected_ids_as_list()
|
|
66
54
|
|
|
67
55
|
if sqrl.param_exists("subcategory"):
|
|
68
56
|
subcategory_param = sqrl.prms["subcategory"]
|
|
69
57
|
assert isinstance(subcategory_param, p.MultiSelectParameter)
|
|
70
58
|
|
|
71
59
|
ctx["has_subcategories"] = subcategory_param.has_non_empty_selection()
|
|
72
|
-
ctx["subcategories"] = subcategory_param.
|
|
60
|
+
ctx["subcategories"] = subcategory_param.get_selected_ids_as_list()
|
|
73
61
|
|
|
74
62
|
if sqrl.param_exists("min_filter"):
|
|
75
63
|
min_amount_filter = sqrl.prms["min_filter"]
|
|
76
64
|
assert isinstance(min_amount_filter, p.NumberParameter)
|
|
77
65
|
|
|
78
|
-
min_amount = min_amount_filter.get_selected_value()
|
|
79
|
-
|
|
80
|
-
sqrl.set_placeholder("min_amount", min_amount)
|
|
66
|
+
ctx["min_amount"] = min_amount_filter.get_selected_value()
|
|
81
67
|
|
|
82
68
|
if sqrl.param_exists("max_filter"):
|
|
83
69
|
max_amount_filter = sqrl.prms["max_filter"]
|
|
84
70
|
assert isinstance(max_amount_filter, p.NumberParameter)
|
|
85
71
|
|
|
86
|
-
max_amount = max_amount_filter.get_selected_value()
|
|
87
|
-
|
|
88
|
-
sqrl.set_placeholder("max_amount", max_amount)
|
|
72
|
+
ctx["max_amount"] = max_amount_filter.get_selected_value()
|
|
89
73
|
|
|
90
74
|
if sqrl.param_exists("between_filter"):
|
|
91
75
|
between_filter = sqrl.prms["between_filter"]
|
|
92
76
|
assert isinstance(between_filter, p.NumberRangeParameter)
|
|
93
77
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
sqrl.set_placeholder("min_amount", min_amount)
|
|
98
|
-
sqrl.set_placeholder("max_amount", max_amount)
|
|
78
|
+
ctx["min_amount_from_range"] = between_filter.get_selected_lower_value()
|
|
79
|
+
ctx["max_amount_from_range"] = between_filter.get_selected_upper_value()
|
|
99
80
|
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
from squirrels import parameters as p, parameter_options as po, data_sources as ds
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
## Example of creating SingleSelectParameter and specifying each option by code
|
|
5
|
+
@p.SingleSelectParameter.create_with_options(
|
|
6
|
+
name="group_by", label="Group By",
|
|
7
|
+
description="Dimension(s) to aggregate by",
|
|
8
|
+
user_attribute="access_level"
|
|
9
|
+
)
|
|
10
|
+
def group_by_options():
|
|
11
|
+
return [
|
|
12
|
+
po.SelectParameterOption(
|
|
13
|
+
id="trans", label="Transaction",
|
|
14
|
+
columns=["id","date","category","subcategory","description"],
|
|
15
|
+
aliases=["_id","date","category","subcategory","description"], # in context.py, any alias starting with "_" will not be selected
|
|
16
|
+
user_groups=["admin"]
|
|
17
|
+
),
|
|
18
|
+
po.SelectParameterOption(
|
|
19
|
+
id="day", label="Day",
|
|
20
|
+
columns=["date"],
|
|
21
|
+
aliases=["day"],
|
|
22
|
+
user_groups=["admin","member"]
|
|
23
|
+
),
|
|
24
|
+
po.SelectParameterOption(
|
|
25
|
+
id="month", label="Month",
|
|
26
|
+
columns=["month"],
|
|
27
|
+
user_groups=["admin","member","guest"]
|
|
28
|
+
),
|
|
29
|
+
po.SelectParameterOption(
|
|
30
|
+
id="cat", label="Category",
|
|
31
|
+
columns=["category"],
|
|
32
|
+
user_groups=["admin","member","guest"]
|
|
33
|
+
),
|
|
34
|
+
po.SelectParameterOption(
|
|
35
|
+
id="subcat", label="Subcategory",
|
|
36
|
+
columns=["category","subcategory"],
|
|
37
|
+
user_groups=["admin","member","guest"]
|
|
38
|
+
),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
## Example of creating DateParameter
|
|
43
|
+
@p.DateParameter.create_from_source(
|
|
44
|
+
name="start_date", label="Start Date",
|
|
45
|
+
description="Start date to filter transactions by"
|
|
46
|
+
)
|
|
47
|
+
def start_date_source():
|
|
48
|
+
return ds.DateDataSource(
|
|
49
|
+
table_or_query="SELECT min(date) AS min_date, max(date) AS max_date FROM expenses",
|
|
50
|
+
default_date_col="min_date",
|
|
51
|
+
min_date_col="min_date", max_date_col="max_date",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
## Example of creating DateParameter from list of DateParameterOption's
|
|
56
|
+
@p.DateParameter.create_with_options(
|
|
57
|
+
name="end_date", label="End Date",
|
|
58
|
+
description="End date to filter transactions by"
|
|
59
|
+
)
|
|
60
|
+
def end_date_options():
|
|
61
|
+
return [
|
|
62
|
+
po.DateParameterOption(
|
|
63
|
+
default_date="2024-12-31", min_date="2024-01-01", max_date="2024-12-31"
|
|
64
|
+
)
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
## Example of creating DateRangeParameter
|
|
69
|
+
@p.DateRangeParameter.create_simple(
|
|
70
|
+
name="date_range", label="Date Range",
|
|
71
|
+
default_start_date="2024-01-01", default_end_date="2024-12-31",
|
|
72
|
+
min_date="2024-01-01", max_date="2024-12-31",
|
|
73
|
+
description="Date range to filter transactions by"
|
|
74
|
+
)
|
|
75
|
+
def date_range_options():
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## Example of creating MultiSelectParameter from lookup query/table
|
|
80
|
+
@p.MultiSelectParameter.create_from_source(
|
|
81
|
+
name="category", label="Category Filter",
|
|
82
|
+
description="The expense categories to filter transactions by"
|
|
83
|
+
)
|
|
84
|
+
def category_source():
|
|
85
|
+
return ds.SelectDataSource(
|
|
86
|
+
table_or_query="seed_categories",
|
|
87
|
+
id_col="category_id",
|
|
88
|
+
options_col="category",
|
|
89
|
+
source=ds.SourceEnum.SEEDS
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
## Example of creating MultiSelectParameter with parent from lookup query/table
|
|
94
|
+
@p.MultiSelectParameter.create_from_source(
|
|
95
|
+
name="subcategory", label="Subcategory Filter",
|
|
96
|
+
description="The expense subcategories to filter transactions by (available options are based on selected value(s) of 'Category Filter')",
|
|
97
|
+
parent_name="category"
|
|
98
|
+
)
|
|
99
|
+
def subcategory_source():
|
|
100
|
+
return ds.SelectDataSource(
|
|
101
|
+
table_or_query="seed_subcategories",
|
|
102
|
+
id_col="subcategory_id",
|
|
103
|
+
options_col="subcategory",
|
|
104
|
+
source=ds.SourceEnum.SEEDS,
|
|
105
|
+
parent_id_col="category_id"
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
## Example of creating NumberParameter
|
|
110
|
+
@p.NumberParameter.create_simple(
|
|
111
|
+
name="min_filter", label="Amounts Greater Than",
|
|
112
|
+
min_value=0, max_value=300, increment=10,
|
|
113
|
+
description="Number to filter on transactions with an amount greater than this value"
|
|
114
|
+
)
|
|
115
|
+
def min_filter_options():
|
|
116
|
+
pass
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
## Example of creating NumberParameter from lookup query/table
|
|
120
|
+
@p.NumberParameter.create_from_source(
|
|
121
|
+
name="max_filter", label="Amounts Less Than",
|
|
122
|
+
description="Number to filter on transactions with an amount less than this value"
|
|
123
|
+
)
|
|
124
|
+
def max_filter_source():
|
|
125
|
+
return ds.NumberDataSource(
|
|
126
|
+
table_or_query="SELECT 0 as min_value, 300 as max_value, 10 as increment",
|
|
127
|
+
min_value_col="min_value", max_value_col="max_value",
|
|
128
|
+
increment_col="increment",
|
|
129
|
+
default_value_col="max_value"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
## Example of creating NumberRangeParameter
|
|
134
|
+
@p.NumberRangeParameter.create_simple(
|
|
135
|
+
name="between_filter", label="Amounts Between",
|
|
136
|
+
min_value=0, max_value=300,
|
|
137
|
+
default_lower_value=0, default_upper_value=300,
|
|
138
|
+
description="Number range to filter on transactions with an amount within this range"
|
|
139
|
+
)
|
|
140
|
+
def between_filter_options():
|
|
141
|
+
pass
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
from squirrels import auth, arguments as args
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CustomUserFields(auth.CustomUserFields):
|
|
6
|
+
"""
|
|
7
|
+
Extend the CustomUserFields class to add custom user attributes.
|
|
8
|
+
- Only the following types are supported: [str, int, float, bool, typing.Literal]
|
|
9
|
+
- Add "| None" after the type to make it nullable.
|
|
10
|
+
- Always set a default value for the field (use None if default is null).
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
organization: str | None = None
|
|
14
|
+
"""
|
|
15
|
+
role: Literal["manager", "employee"] = "employee"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# @auth.provider(name="google", label="Google", icon="https://www.google.com/favicon.ico")
|
|
19
|
+
def google_auth_provider(sqrl: args.AuthProviderArgs) -> auth.ProviderConfigs:
|
|
20
|
+
"""
|
|
21
|
+
Provider configs for authenticating a user using Google credentials.
|
|
22
|
+
|
|
23
|
+
See the following page for setting up the CLIENT_ID and CLIENT_SECRET for Google specifically:
|
|
24
|
+
https://support.google.com/googleapi/answer/6158849?hl=en
|
|
25
|
+
"""
|
|
26
|
+
def get_sqrl_user(claims: dict) -> auth.RegisteredUser:
|
|
27
|
+
custom_fields = CustomUserFields(role="employee")
|
|
28
|
+
return auth.RegisteredUser(
|
|
29
|
+
username=claims["email"],
|
|
30
|
+
access_level="member",
|
|
31
|
+
custom_fields=custom_fields
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# TODO: Add GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET to the .env file
|
|
35
|
+
# Then, uncomment the @auth.provider decorator above and set the client_id and client_secret below
|
|
36
|
+
provider_configs = auth.ProviderConfigs(
|
|
37
|
+
client_id="", # sqrl.env_vars["GOOGLE_CLIENT_ID"],
|
|
38
|
+
client_secret="", # sqrl.env_vars["GOOGLE_CLIENT_SECRET"],
|
|
39
|
+
server_url="https://accounts.google.com",
|
|
40
|
+
client_kwargs={"scope": "openid email profile"},
|
|
41
|
+
get_user=get_sqrl_user
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
return provider_configs
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
description: |
|
|
2
|
+
Lookup table for the category IDs and names of transactions.
|
|
3
|
+
|
|
4
|
+
cast_column_types: true # optional, default is false - setting SQRL_SEEDS__INFER_SCHEMA is ignored for this seed if this is set to true
|
|
5
|
+
|
|
6
|
+
columns:
|
|
7
|
+
- name: category_id
|
|
8
|
+
type: string
|
|
9
|
+
description: The category ID
|
|
10
|
+
category: dimension
|
|
11
|
+
|
|
12
|
+
- name: category
|
|
13
|
+
type: string
|
|
14
|
+
description: The human-readable category name
|
|
15
|
+
category: dimension
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"subcategory_id","subcategory","category_id"
|
|
2
|
+
"0","Dining Out","0"
|
|
3
|
+
"1","Groceries","0"
|
|
4
|
+
"2","Utilities","1"
|
|
5
|
+
"3","Electronics","2"
|
|
6
|
+
"4","Ride Sharing","3"
|
|
7
|
+
"5","Mobile","1"
|
|
8
|
+
"6","Home Decor","2"
|
|
9
|
+
"7","Internet","1"
|
|
10
|
+
"8","Theater","4"
|
|
11
|
+
"9","Movies","4"
|
|
12
|
+
"10","Sports","2"
|
|
13
|
+
"11","Public Transit","3"
|
|
14
|
+
"12","Clothing","2"
|
|
15
|
+
"13","Concerts","4"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
description: |
|
|
2
|
+
Lookup table for the subcategory IDs and names of transactions.
|
|
3
|
+
|
|
4
|
+
cast_column_types: true # optional, default is false - setting SQRL_SEEDS__INFER_SCHEMA is ignored for this seed if this is set to true
|
|
5
|
+
|
|
6
|
+
columns:
|
|
7
|
+
- name: subcategory_id
|
|
8
|
+
type: string
|
|
9
|
+
description: The subcategory ID
|
|
10
|
+
category: dimension
|
|
11
|
+
|
|
12
|
+
- name: subcategory
|
|
13
|
+
type: string
|
|
14
|
+
description: The human-readable subcategory name
|
|
15
|
+
category: dimension
|
|
16
|
+
|
|
17
|
+
- name: category_id
|
|
18
|
+
type: string
|
|
19
|
+
description: The category ID that the subcategory belongs to
|
|
20
|
+
category: dimension
|
|
21
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
project_variables:
|
|
2
|
+
name: sample_expenses
|
|
3
|
+
label: "Sample Expenses"
|
|
4
|
+
description: This is a sample squirrels project for analyzing expense transactions
|
|
5
|
+
major_version: 1
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
packages: []
|
|
9
|
+
|
|
10
|
+
## Example for packages section:
|
|
11
|
+
# packages:
|
|
12
|
+
# - git: https://.../myrepo.git
|
|
13
|
+
# revision: v0.1.0
|
|
14
|
+
# directory: custom_name ## optional
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
{{ connections -}}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
{{ parameters -}}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
datasets:
|
|
24
|
+
- name: dbview_dataset_example ## model name uses same name unless "model" field is specified
|
|
25
|
+
label: Example Dataset from DBView Model
|
|
26
|
+
description: Aggregated expense transactions by month using dbview_example model
|
|
27
|
+
model: dbview_example
|
|
28
|
+
scope: private ## optional - one of 'public' (default), 'protected', or 'private'
|
|
29
|
+
parameters: ## optional - if not specified, then all parameters are used
|
|
30
|
+
- start_date
|
|
31
|
+
- end_date
|
|
32
|
+
- min_filter
|
|
33
|
+
- max_filter
|
|
34
|
+
|
|
35
|
+
- name: federate_dataset_example
|
|
36
|
+
label: Example Dataset from Federate Model
|
|
37
|
+
description: Aggregated expense transactions by custom dimension using federate_example model
|
|
38
|
+
model: federate_example
|
|
39
|
+
scope: public ## using an auth.py file is suggested for protected or private datasets
|
|
40
|
+
parameters:
|
|
41
|
+
- group_by
|
|
42
|
+
- date_range
|
|
43
|
+
- category
|
|
44
|
+
- subcategory
|
|
45
|
+
- between_filter
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
selection_test_sets:
|
|
49
|
+
- name: set_start_date
|
|
50
|
+
parameters: ## optional section - if not provided, then default value is used for all parameters
|
|
51
|
+
start_date: 2024-07-01 ## this parameter is only used by model "dbview_example"
|
|
52
|
+
|
|
53
|
+
- name: set_date_range
|
|
54
|
+
parameters:
|
|
55
|
+
date_range: [2024-02-01,2024-11-30] ## this parameter is only used by model "federate_example"
|
|
56
|
+
|
|
57
|
+
- name: use_admin_privileged_group_by
|
|
58
|
+
user:
|
|
59
|
+
access_level: admin
|
|
60
|
+
parameters:
|
|
61
|
+
group_by: trans
|