squirrels 0.3.3__py3-none-any.whl → 0.4.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.
- squirrels/__init__.py +7 -3
- squirrels/_api_response_models.py +96 -72
- squirrels/_api_server.py +375 -201
- squirrels/_authenticator.py +23 -22
- squirrels/_command_line.py +70 -46
- squirrels/_connection_set.py +23 -25
- squirrels/_constants.py +29 -78
- squirrels/_dashboards_io.py +61 -0
- squirrels/_environcfg.py +53 -50
- squirrels/_initializer.py +184 -141
- squirrels/_manifest.py +168 -195
- squirrels/_models.py +159 -292
- squirrels/_package_loader.py +7 -8
- squirrels/_parameter_configs.py +173 -141
- squirrels/_parameter_sets.py +49 -38
- squirrels/_py_module.py +7 -7
- squirrels/_seeds.py +13 -12
- squirrels/_utils.py +114 -54
- squirrels/_version.py +1 -1
- squirrels/arguments/init_time_args.py +16 -10
- squirrels/arguments/run_time_args.py +89 -24
- squirrels/dashboards.py +82 -0
- squirrels/data_sources.py +212 -232
- squirrels/dateutils.py +29 -26
- squirrels/package_data/assets/index.css +1 -1
- squirrels/package_data/assets/index.js +27 -18
- squirrels/package_data/base_project/.gitignore +2 -2
- squirrels/package_data/base_project/connections.yml +1 -1
- squirrels/package_data/base_project/dashboards/dashboard_example.py +32 -0
- squirrels/package_data/base_project/dashboards.yml +10 -0
- squirrels/package_data/base_project/docker/.dockerignore +9 -4
- squirrels/package_data/base_project/docker/Dockerfile +7 -6
- squirrels/package_data/base_project/docker/compose.yml +1 -1
- squirrels/package_data/base_project/env.yml +2 -2
- squirrels/package_data/base_project/models/dbviews/{database_view1.py → dbview_example.py} +2 -1
- squirrels/package_data/base_project/models/dbviews/{database_view1.sql → dbview_example.sql} +3 -2
- squirrels/package_data/base_project/models/federates/{dataset_example.py → federate_example.py} +6 -6
- squirrels/package_data/base_project/models/federates/{dataset_example.sql → federate_example.sql} +1 -1
- squirrels/package_data/base_project/parameters.yml +6 -4
- squirrels/package_data/base_project/pyconfigs/auth.py +1 -1
- squirrels/package_data/base_project/pyconfigs/connections.py +1 -1
- squirrels/package_data/base_project/pyconfigs/context.py +38 -10
- squirrels/package_data/base_project/pyconfigs/parameters.py +15 -7
- squirrels/package_data/base_project/squirrels.yml.j2 +14 -7
- squirrels/package_data/templates/index.html +3 -3
- squirrels/parameter_options.py +103 -106
- squirrels/parameters.py +347 -195
- squirrels/project.py +378 -0
- squirrels/user_base.py +14 -6
- {squirrels-0.3.3.dist-info → squirrels-0.4.1.dist-info}/METADATA +9 -21
- squirrels-0.4.1.dist-info/RECORD +60 -0
- squirrels/_timer.py +0 -23
- squirrels-0.3.3.dist-info/RECORD +0 -56
- {squirrels-0.3.3.dist-info → squirrels-0.4.1.dist-info}/LICENSE +0 -0
- {squirrels-0.3.3.dist-info → squirrels-0.4.1.dist-info}/WHEEL +0 -0
- {squirrels-0.3.3.dist-info → squirrels-0.4.1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from squirrels import DashboardArgs, dashboards as d
|
|
2
|
+
from matplotlib import pyplot as plt, figure as f, axes as a
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
async def main(sqrl: DashboardArgs) -> d.PngDashboard:
|
|
6
|
+
"""
|
|
7
|
+
Create a dashboard by retrieving datasets using "sqrl.dataset" method and transform the datasets to return as a PngDashboard or a HtmlDashboard.
|
|
8
|
+
- The PngDashboard constructor takes a single argument for either a matplotlib.figure.Figure or io.BytesIO/bytes of PNG data
|
|
9
|
+
- The HtmlDashboard constructor takes a single argument for a io.StringIO/string of HTML data
|
|
10
|
+
|
|
11
|
+
It is imperative to set the correct return type in the function signature for "main" above! It allows Squirrels to provide the correct format to
|
|
12
|
+
the data catalog without having to run this function.
|
|
13
|
+
"""
|
|
14
|
+
spending_by_month_df = await sqrl.dataset("dataset_example", fixed_parameters={"group_by": "g4"})
|
|
15
|
+
spending_by_subcategory_df = await sqrl.dataset("dataset_example", fixed_parameters={"group_by": "g3"})
|
|
16
|
+
|
|
17
|
+
# Create a figure with two subplots
|
|
18
|
+
fig, (ax0, ax1) = plt.subplots(2, 1, figsize=(8, 8), height_ratios=(1, 2))
|
|
19
|
+
fig: f.Figure; ax0: a.Axes; ax1: a.Axes
|
|
20
|
+
fig.tight_layout(pad=4, h_pad=6)
|
|
21
|
+
|
|
22
|
+
# Create a bar chart of spending by month
|
|
23
|
+
spending_by_month_df.sort_values("month").plot(x="month", y="total_amount", ax=ax0)
|
|
24
|
+
ax0.set_title("Spending by Month")
|
|
25
|
+
|
|
26
|
+
# Create a pie chart of spending by subcategory
|
|
27
|
+
df_by_subcategory = spending_by_subcategory_df.set_index("subcategory").sort_values("total_amount", ascending=False)
|
|
28
|
+
autopct = lambda pct: ('%.1f%%' % pct) if pct > 6 else ''
|
|
29
|
+
df_by_subcategory.plot(y="total_amount", kind='pie', ax=ax1, autopct=autopct, legend=False, ylabel="")
|
|
30
|
+
ax1.set_title("Spending by Subcategory")
|
|
31
|
+
|
|
32
|
+
return d.PngDashboard(fig)
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
__pycache__
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
**/__pycache__/
|
|
2
|
+
|
|
3
|
+
# common virtual environment names
|
|
4
|
+
.venv/
|
|
4
5
|
|
|
5
6
|
# squirrels files to ignore
|
|
6
|
-
|
|
7
|
+
env.yml
|
|
7
8
|
target/
|
|
8
9
|
sqrl_packages/
|
|
10
|
+
|
|
11
|
+
# additional files for docker to ignore
|
|
12
|
+
Dockerfile
|
|
13
|
+
.git/
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
# Change here to use different python version (ex. 3.
|
|
2
|
-
FROM python:3.
|
|
1
|
+
# Change here to use different python version (ex. 3.11-slim for version 3.11)
|
|
2
|
+
FROM python:3.12-slim
|
|
3
3
|
WORKDIR /app
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
COPY . .
|
|
6
|
+
|
|
7
|
+
# Only needed if there are python dependencies installed using git, or for the
|
|
8
|
+
# "sqrl deps" command if there are packages defined in "squirrels.yml"
|
|
7
9
|
RUN apt-get update && apt-get install -y git
|
|
8
10
|
|
|
9
|
-
COPY requirements-lock.txt .
|
|
10
11
|
RUN pip install --no-cache-dir -r requirements-lock.txt
|
|
11
12
|
|
|
12
|
-
COPY . .
|
|
13
13
|
RUN squirrels deps
|
|
14
14
|
|
|
15
|
+
EXPOSE 4465
|
|
15
16
|
CMD ["squirrels", "run", "--host", "0.0.0.0", "--port", "4465"]
|
|
@@ -7,7 +7,7 @@ users:
|
|
|
7
7
|
is_internal: True
|
|
8
8
|
password: I<3Squirrels
|
|
9
9
|
full_name: Alice Doe
|
|
10
|
-
role:
|
|
10
|
+
role: manager
|
|
11
11
|
bob:
|
|
12
12
|
is_internal: False
|
|
13
13
|
password: abcd5678
|
|
@@ -16,7 +16,7 @@ users:
|
|
|
16
16
|
|
|
17
17
|
## Custom environment variables / secrets
|
|
18
18
|
env_vars:
|
|
19
|
-
sqlite_conn_str: sqlite://{username}:{password}
|
|
19
|
+
sqlite_conn_str: sqlite://{username}:{password}@/{project_path}/assets/expenses.db
|
|
20
20
|
|
|
21
21
|
## Database credentials
|
|
22
22
|
credentials:
|
|
@@ -24,7 +24,8 @@ def main(sqrl: ModelArgs) -> pd.DataFrame:
|
|
|
24
24
|
WITH
|
|
25
25
|
transactions_with_masked_id AS (
|
|
26
26
|
SELECT *,
|
|
27
|
-
{masked_id} as masked_id
|
|
27
|
+
{masked_id} as masked_id,
|
|
28
|
+
STRFTIME('%Y-%m', date) AS month
|
|
28
29
|
FROM transactions
|
|
29
30
|
)
|
|
30
31
|
SELECT {sqrl.ctx["select_dim_cols"]}
|
squirrels/package_data/base_project/models/dbviews/{database_view1.sql → dbview_example.sql}
RENAMED
|
@@ -5,11 +5,12 @@ transactions_with_masked_id AS (
|
|
|
5
5
|
id as masked_id
|
|
6
6
|
{%- else %}
|
|
7
7
|
'***' as masked_id
|
|
8
|
-
{%- endif %}
|
|
8
|
+
{%- endif %},
|
|
9
|
+
STRFTIME('%Y-%m', date) AS month
|
|
9
10
|
FROM transactions
|
|
10
11
|
)
|
|
11
12
|
SELECT {{ ctx.select_dim_cols }}
|
|
12
|
-
,
|
|
13
|
+
, SUM(-amount) as total_amount
|
|
13
14
|
FROM transactions_with_masked_id
|
|
14
15
|
WHERE date >= :start_date
|
|
15
16
|
AND date <= :end_date
|
squirrels/package_data/base_project/models/federates/{dataset_example.py → federate_example.py}
RENAMED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Sequence
|
|
2
2
|
from squirrels import ModelDepsArgs, ModelArgs
|
|
3
3
|
import pandas as pd
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
def dependencies(sqrl: ModelDepsArgs) ->
|
|
6
|
+
def dependencies(sqrl: ModelDepsArgs) -> Sequence[str]:
|
|
7
7
|
"""
|
|
8
8
|
Define list of dependent models here. This will determine the dependencies first, at compile-time,
|
|
9
9
|
before running the model.
|
|
10
10
|
"""
|
|
11
|
-
return ["
|
|
11
|
+
return ["dbview_example"]
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def main(sqrl: ModelArgs) -> pd.DataFrame:
|
|
@@ -16,6 +16,6 @@ def main(sqrl: ModelArgs) -> pd.DataFrame:
|
|
|
16
16
|
Create federated models by joining/processing dependent database views and/or other federated models to
|
|
17
17
|
form and return the result as a new pandas DataFrame.
|
|
18
18
|
"""
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return df.sort_values(
|
|
19
|
+
(DBVIEW_EXAMPLE,) = dependencies(sqrl)
|
|
20
|
+
df = sqrl.ref(DBVIEW_EXAMPLE)
|
|
21
|
+
return df.sort_values(sqrl.ctx["order_by_cols_list"], ascending=False)
|
|
@@ -36,14 +36,16 @@ parameters:
|
|
|
36
36
|
- parent_option_ids: g0
|
|
37
37
|
|
|
38
38
|
- type: DateParameter
|
|
39
|
-
factory:
|
|
39
|
+
factory: CreateFromSource
|
|
40
40
|
arguments:
|
|
41
41
|
name: start_date
|
|
42
42
|
label: Start Date
|
|
43
43
|
description: Start date to filter transactions by
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
data_source:
|
|
45
|
+
table_or_query: SELECT min(date) AS min_date, max(date) AS max_date FROM transactions
|
|
46
|
+
default_date_col: min_date
|
|
47
|
+
min_date_col: min_date
|
|
48
|
+
max_date_col: max_date
|
|
47
49
|
|
|
48
50
|
- type: DateParameter
|
|
49
51
|
factory: CreateWithOptions
|
|
@@ -18,7 +18,7 @@ def get_user_if_valid(sqrl: AuthArgs) -> Union[User, WrongPassword, None]:
|
|
|
18
18
|
Return:
|
|
19
19
|
- User instance - if username and password are correct
|
|
20
20
|
- WrongPassword() - if username exists but password is incorrect
|
|
21
|
-
- None - if the username doesn't exist (and search for username will continue for "fake users" configured in
|
|
21
|
+
- None - if the username doesn't exist (and search for username will continue for "fake users" configured in env.yml)
|
|
22
22
|
"""
|
|
23
23
|
mock_users_db = {
|
|
24
24
|
"johndoe": {
|
|
@@ -10,7 +10,7 @@ def main(connections: dict[str, Engine], sqrl: ConnectionsArgs) -> None:
|
|
|
10
10
|
## SQLAlchemy URL for a connection engine
|
|
11
11
|
conn_str = 'sqlite:///./assets/expenses.db'
|
|
12
12
|
|
|
13
|
-
## Can also leverage environment variables and credentials in the
|
|
13
|
+
## Can also leverage environment variables and credentials in the env.yml file for connection details
|
|
14
14
|
# conn_str_raw: str = sqrl.env_vars["sqlite_conn_str"]
|
|
15
15
|
# username, password = sqrl.get_credential('my_key')
|
|
16
16
|
# conn_str = conn_str_raw.format(username=username, password=password)
|
|
@@ -11,9 +11,12 @@ def main(ctx: dict[str, Any], sqrl: ContextArgs) -> None:
|
|
|
11
11
|
sqrl.prms and/or sqrl.traits to determine the conditions to execute certain blocks of code.
|
|
12
12
|
"""
|
|
13
13
|
if sqrl.param_exists("group_by"):
|
|
14
|
-
group_by_param
|
|
14
|
+
group_by_param = sqrl.prms["group_by"]
|
|
15
|
+
assert isinstance(group_by_param, p.SingleSelectParameter)
|
|
16
|
+
|
|
15
17
|
columns = group_by_param.get_selected("columns")
|
|
16
18
|
aliases = group_by_param.get_selected("aliases", default_field="columns")
|
|
19
|
+
assert isinstance(columns, list) and isinstance(aliases, list)
|
|
17
20
|
|
|
18
21
|
ctx["select_dim_cols"] = ", ".join(x+" as "+y for x, y in zip(columns, aliases))
|
|
19
22
|
ctx["group_by_cols"] = ", ".join(columns)
|
|
@@ -21,51 +24,76 @@ def main(ctx: dict[str, Any], sqrl: ContextArgs) -> None:
|
|
|
21
24
|
ctx["order_by_cols_list"] = aliases
|
|
22
25
|
|
|
23
26
|
if sqrl.param_exists("description_filter"):
|
|
24
|
-
descript_param
|
|
27
|
+
descript_param = sqrl.prms["description_filter"]
|
|
28
|
+
assert isinstance(descript_param, p.TextParameter)
|
|
29
|
+
|
|
25
30
|
desc_pattern = descript_param.get_entered_text().apply_percent_wrap()
|
|
31
|
+
|
|
26
32
|
sqrl.set_placeholder("desc_pattern", desc_pattern)
|
|
27
33
|
|
|
28
34
|
if sqrl.param_exists("start_date"):
|
|
29
|
-
start_date_param
|
|
35
|
+
start_date_param = sqrl.prms["start_date"]
|
|
36
|
+
assert isinstance(start_date_param, p.DateParameter)
|
|
37
|
+
|
|
30
38
|
start_date = start_date_param.get_selected_date()
|
|
39
|
+
|
|
31
40
|
sqrl.set_placeholder("start_date", start_date)
|
|
32
41
|
|
|
33
42
|
if sqrl.param_exists("end_date"):
|
|
34
|
-
end_date_param
|
|
43
|
+
end_date_param = sqrl.prms["end_date"]
|
|
44
|
+
assert isinstance(end_date_param, p.DateParameter)
|
|
45
|
+
|
|
35
46
|
end_date = end_date_param.get_selected_date()
|
|
47
|
+
|
|
36
48
|
sqrl.set_placeholder("end_date", end_date)
|
|
37
49
|
|
|
38
50
|
if sqrl.param_exists("date_range"):
|
|
39
|
-
date_range_param
|
|
51
|
+
date_range_param = sqrl.prms["date_range"]
|
|
52
|
+
assert isinstance(date_range_param, p.DateRangeParameter)
|
|
53
|
+
|
|
40
54
|
start_date = date_range_param.get_selected_start_date()
|
|
41
55
|
end_date = date_range_param.get_selected_end_date()
|
|
56
|
+
|
|
42
57
|
sqrl.set_placeholder("start_date", start_date)
|
|
43
58
|
sqrl.set_placeholder("end_date", end_date)
|
|
44
59
|
|
|
45
60
|
if sqrl.param_exists("category"):
|
|
46
|
-
category_param
|
|
61
|
+
category_param = sqrl.prms["category"]
|
|
62
|
+
assert isinstance(category_param, p.MultiSelectParameter)
|
|
63
|
+
|
|
47
64
|
ctx["has_categories"] = category_param.has_non_empty_selection()
|
|
48
65
|
ctx["categories"] = category_param.get_selected_labels_quoted_joined()
|
|
49
66
|
|
|
50
67
|
if sqrl.param_exists("subcategory"):
|
|
51
|
-
subcategory_param
|
|
68
|
+
subcategory_param = sqrl.prms["subcategory"]
|
|
69
|
+
assert isinstance(subcategory_param, p.MultiSelectParameter)
|
|
70
|
+
|
|
52
71
|
ctx["has_subcategories"] = subcategory_param.has_non_empty_selection()
|
|
53
72
|
ctx["subcategories"] = subcategory_param.get_selected_labels_quoted_joined()
|
|
54
73
|
|
|
55
74
|
if sqrl.param_exists("min_filter"):
|
|
56
|
-
min_amount_filter
|
|
75
|
+
min_amount_filter = sqrl.prms["min_filter"]
|
|
76
|
+
assert isinstance(min_amount_filter, p.NumberParameter)
|
|
77
|
+
|
|
57
78
|
min_amount = min_amount_filter.get_selected_value()
|
|
79
|
+
|
|
58
80
|
sqrl.set_placeholder("min_amount", min_amount)
|
|
59
81
|
|
|
60
82
|
if sqrl.param_exists("max_filter"):
|
|
61
|
-
max_amount_filter
|
|
83
|
+
max_amount_filter = sqrl.prms["max_filter"]
|
|
84
|
+
assert isinstance(max_amount_filter, p.NumberParameter)
|
|
85
|
+
|
|
62
86
|
max_amount = max_amount_filter.get_selected_value()
|
|
87
|
+
|
|
63
88
|
sqrl.set_placeholder("max_amount", max_amount)
|
|
64
89
|
|
|
65
90
|
if sqrl.param_exists("between_filter"):
|
|
66
|
-
between_filter
|
|
91
|
+
between_filter = sqrl.prms["between_filter"]
|
|
92
|
+
assert isinstance(between_filter, p.NumberRangeParameter)
|
|
93
|
+
|
|
67
94
|
min_amount = between_filter.get_selected_lower_value()
|
|
68
95
|
max_amount = between_filter.get_selected_upper_value()
|
|
96
|
+
|
|
69
97
|
sqrl.set_placeholder("min_amount", min_amount)
|
|
70
98
|
sqrl.set_placeholder("max_amount", max_amount)
|
|
71
99
|
|
|
@@ -20,6 +20,7 @@ def main(sqrl: ParametersArgs) -> None:
|
|
|
20
20
|
group_by_options = [
|
|
21
21
|
po.SelectParameterOption("g0", "Transaction", columns=["masked_id", "date", "description"], aliases=["id", "date", "description"]),
|
|
22
22
|
po.SelectParameterOption("g1", "Date", columns=["date"]),
|
|
23
|
+
po.SelectParameterOption("g4", "Month", columns=["month"]),
|
|
23
24
|
po.SelectParameterOption("g2", "Category", columns=["category"]),
|
|
24
25
|
po.SelectParameterOption("g3", "Subcategory", columns=["category", "subcategory"]),
|
|
25
26
|
]
|
|
@@ -29,26 +30,33 @@ def main(sqrl: ParametersArgs) -> None:
|
|
|
29
30
|
|
|
30
31
|
## Example of creating a TextParameter
|
|
31
32
|
parent_name = "group_by"
|
|
32
|
-
|
|
33
|
+
description_text_options = [
|
|
34
|
+
po.TextParameterOption(parent_option_ids="g0")
|
|
35
|
+
]
|
|
33
36
|
p.TextParameter.CreateWithOptions(
|
|
34
|
-
"description_filter", "Description Contains",
|
|
37
|
+
"description_filter", "Description Contains", description_text_options, parent_name=parent_name,
|
|
35
38
|
description="Substring of description to filter transactions by"
|
|
36
39
|
)
|
|
37
40
|
|
|
38
|
-
## Example of creating DateParameter
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
+
## Example of creating DateParameter from lookup query/table
|
|
42
|
+
start_date_source = ds.DateDataSource(
|
|
43
|
+
"SELECT min(date) AS min_date, max(date) AS max_date FROM transactions",
|
|
44
|
+
default_date_col="min_date", min_date_col="min_date", max_date_col="max_date"
|
|
45
|
+
)
|
|
46
|
+
p.DateParameter.CreateFromSource(
|
|
47
|
+
"start_date", "Start Date", start_date_source, description="Start date to filter transactions by"
|
|
41
48
|
)
|
|
42
49
|
|
|
43
50
|
## Example of creating DateParameter from list of DateParameterOption's
|
|
44
|
-
end_date_option = [po.DateParameterOption("2023-12-31")]
|
|
51
|
+
end_date_option = [po.DateParameterOption("2023-12-31", min_date="2023-01-01", max_date="2023-12-31")]
|
|
45
52
|
p.DateParameter.CreateWithOptions(
|
|
46
53
|
"end_date", "End Date", end_date_option, description="End date to filter transactions by"
|
|
47
54
|
)
|
|
48
55
|
|
|
49
56
|
## Example of creating DateRangeParameter
|
|
50
57
|
p.DateRangeParameter.CreateSimple(
|
|
51
|
-
"date_range", "Date Range", "2023-01-01", "2023-12-31",
|
|
58
|
+
"date_range", "Date Range", "2023-01-01", "2023-12-31", min_date="2023-01-01", max_date="2023-12-31",
|
|
59
|
+
description="Date range to filter transactions by"
|
|
52
60
|
)
|
|
53
61
|
|
|
54
62
|
## Example of creating MultiSelectParameter from lookup query/table
|
|
@@ -6,10 +6,11 @@ project_variables:
|
|
|
6
6
|
|
|
7
7
|
packages: []
|
|
8
8
|
|
|
9
|
-
## Example
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
9
|
+
## Example for packages section:
|
|
10
|
+
# packages:
|
|
11
|
+
# - git: https://.../myrepo.git
|
|
12
|
+
# revision: v0.1.0
|
|
13
|
+
# directory: custom_name ## optional
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
{{ connections -}}
|
|
@@ -21,6 +22,7 @@ packages: []
|
|
|
21
22
|
datasets:
|
|
22
23
|
- name: dataset_example ## model name uses same name unless "model" field is specified
|
|
23
24
|
label: Dataset Example
|
|
25
|
+
model: federate_example ## optional - if not specified, then the "name" field is used
|
|
24
26
|
scope: public ## optional - one of 'public' (default), 'protected', or 'private'
|
|
25
27
|
parameters: ## optional - if not specified, then all parameters are used
|
|
26
28
|
- group_by
|
|
@@ -35,7 +37,7 @@ datasets:
|
|
|
35
37
|
|
|
36
38
|
- name: protected_dataset_example ## requires auth.py file to work
|
|
37
39
|
label: Dataset Example 2
|
|
38
|
-
model:
|
|
40
|
+
model: federate_example
|
|
39
41
|
scope: protected
|
|
40
42
|
parameters:
|
|
41
43
|
- group_by
|
|
@@ -47,6 +49,9 @@ datasets:
|
|
|
47
49
|
default_test_set: auth_test1 ## optional - if not specified, uses setting 'selection_test_sets.default_name_used'
|
|
48
50
|
|
|
49
51
|
|
|
52
|
+
{{ dashboards -}}
|
|
53
|
+
|
|
54
|
+
|
|
50
55
|
selection_test_sets:
|
|
51
56
|
- name: no_auth_test1
|
|
52
57
|
datasets: ## optional section - if not provided, then test set is applicable for any dataset
|
|
@@ -77,8 +82,10 @@ settings: {}
|
|
|
77
82
|
# auth.token.expire_minutes: 30
|
|
78
83
|
# parameters.cache.size: 1024
|
|
79
84
|
# parameters.cache.ttl_minutes: 60
|
|
80
|
-
#
|
|
81
|
-
#
|
|
85
|
+
# datasets.cache.size: 128
|
|
86
|
+
# datasets.cache.ttl_minutes: 60
|
|
87
|
+
# dashboards.cache.size: 128
|
|
88
|
+
# dashboards.cache.ttl_minutes: 60
|
|
82
89
|
# selection_test_sets.default_name_used: default
|
|
83
90
|
# connections.default_name_used: default
|
|
84
91
|
# defaults.federates.materialized: table
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<script>
|
|
8
8
|
const hostname = '';
|
|
9
|
-
const
|
|
9
|
+
const projectMetadataURL = '{{ project_metadata_path }}';
|
|
10
10
|
</script>
|
|
11
11
|
<title>Squirrels Testing UI</title>
|
|
12
|
-
<script type="module" crossorigin src="/assets/index.js"></script>
|
|
13
|
-
<link rel="stylesheet" crossorigin href="/assets/index.css">
|
|
12
|
+
<script type="module" crossorigin src="/assets/index.js?version=0.4.1"></script>
|
|
13
|
+
<link rel="stylesheet" crossorigin href="/assets/index.css?version=0.4.1">
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|
|
16
16
|
<div id="root"></div>
|