squirrels 0.4.1__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.1.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.1.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.1.dist-info/METADATA +0 -117
- squirrels-0.4.1.dist-info/RECORD +0 -60
- squirrels-0.4.1.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
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Custom environment variables
|
|
2
|
+
SQLITE_URI="sqlite:///{project_path}/assets/expenses.db"
|
|
3
|
+
|
|
4
|
+
# Secrets used by the Squirrels framework that are NOT SAFE TO INCLUDE IN VERSION CONTROL
|
|
5
|
+
# Required if your project uses authentication. Otherwise, optional.
|
|
6
|
+
SQRL_SECRET__KEY="{{ random_secret_key }}"
|
|
7
|
+
SQRL_SECRET__ADMIN_PASSWORD="{{ random_admin_password }}"
|
|
8
|
+
|
|
9
|
+
# Optional variables used by the Squirrels framework that are safe to include in version control if desired
|
|
10
|
+
# (default values are shown below)
|
|
11
|
+
SQRL_AUTH__DB_FILE_PATH="{project_path}/target/auth.sqlite"
|
|
12
|
+
SQRL_AUTH__TOKEN_EXPIRE_MINUTES="30"
|
|
13
|
+
SQRL_AUTH__ALLOWED_ORIGINS_FOR_COOKIES="https://squirrels-analytics.github.io"
|
|
14
|
+
|
|
15
|
+
SQRL_PARAMETERS__CACHE_SIZE="1024"
|
|
16
|
+
SQRL_PARAMETERS__CACHE_TTL_MINUTES="60"
|
|
17
|
+
SQRL_PARAMETERS__DATASOURCE_REFRESH_MINUTES="60"
|
|
18
|
+
|
|
19
|
+
SQRL_DATASETS__CACHE_SIZE="128"
|
|
20
|
+
SQRL_DATASETS__CACHE_TTL_MINUTES="60"
|
|
21
|
+
SQRL_DATASETS__MAX_ROWS_FOR_AI="100"
|
|
22
|
+
|
|
23
|
+
SQRL_DASHBOARDS__CACHE_SIZE="128"
|
|
24
|
+
SQRL_DASHBOARDS__CACHE_TTL_MINUTES="60"
|
|
25
|
+
|
|
26
|
+
SQRL_PERMISSIONS__ELEVATED_ACCESS_LEVEL="admin" # one of "admin", "member", "guest"
|
|
27
|
+
|
|
28
|
+
SQRL_SEEDS__INFER_SCHEMA="true"
|
|
29
|
+
SQRL_SEEDS__NA_VALUES=["NA"] # must be a JSON list
|
|
30
|
+
|
|
31
|
+
SQRL_CONNECTIONS__DEFAULT_NAME_USED="default"
|
|
32
|
+
|
|
33
|
+
SQRL_VDL__CATALOG_DB_PATH="ducklake:{project_path}/target/vdl_catalog.duckdb"
|
|
34
|
+
SQRL_VDL__DATA_PATH="{project_path}/target/vdl_data/"
|
|
35
|
+
|
|
36
|
+
SQRL_STUDIO__BASE_URL="https://squirrels-analytics.github.io/squirrels-studio-v1"
|
|
37
|
+
|
|
38
|
+
SQRL_LOGGING__LOG_LEVEL="INFO" # one of "DEBUG", "INFO", "WARNING"
|
|
39
|
+
SQRL_LOGGING__LOG_FORMAT="text"
|
|
40
|
+
SQRL_LOGGING__LOG_TO_FILE="false"
|
|
41
|
+
SQRL_LOGGING__LOG_FILE_SIZE_MB="50"
|
|
42
|
+
SQRL_LOGGING__LOG_FILE_BACKUP_COUNT="1"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Custom environment variables
|
|
2
|
+
SQLITE_URI="sqlite:///{project_path}/assets/expenses.db"
|
|
3
|
+
|
|
4
|
+
# Secrets used by the Squirrels framework that are NOT SAFE TO INCLUDE IN VERSION CONTROL
|
|
5
|
+
# Required if your project uses authentication. Otherwise, optional.
|
|
6
|
+
SQRL_SECRET__KEY="" # a random 32 byte hex string - one way to generate this is by running "openssl rand -hex 32" in bash
|
|
7
|
+
SQRL_SECRET__ADMIN_PASSWORD=""
|
|
8
|
+
|
|
9
|
+
# Optional variables used by the Squirrels framework that are safe to include in version control if desired
|
|
10
|
+
# (default values are shown below)
|
|
11
|
+
SQRL_AUTH__DB_FILE_PATH="target/auth.sqlite"
|
|
12
|
+
SQRL_AUTH__TOKEN_EXPIRE_MINUTES="30"
|
|
13
|
+
SQRL_AUTH__ALLOWED_ORIGINS_FOR_COOKIES="https://squirrels-analytics.github.io"
|
|
14
|
+
|
|
15
|
+
SQRL_PARAMETERS__CACHE_SIZE="1024"
|
|
16
|
+
SQRL_PARAMETERS__CACHE_TTL_MINUTES="60"
|
|
17
|
+
SQRL_PARAMETERS__DATASOURCE_REFRESH_MINUTES="60"
|
|
18
|
+
|
|
19
|
+
SQRL_DATASETS__CACHE_SIZE="128"
|
|
20
|
+
SQRL_DATASETS__CACHE_TTL_MINUTES="60"
|
|
21
|
+
SQRL_DATASETS__MAX_ROWS_FOR_AI="100"
|
|
22
|
+
|
|
23
|
+
SQRL_DASHBOARDS__CACHE_SIZE="128"
|
|
24
|
+
SQRL_DASHBOARDS__CACHE_TTL_MINUTES="60"
|
|
25
|
+
|
|
26
|
+
SQRL_PERMISSIONS__ELEVATED_ACCESS_LEVEL="admin" # one of "admin", "member", "guest"
|
|
27
|
+
|
|
28
|
+
SQRL_SEEDS__INFER_SCHEMA="true"
|
|
29
|
+
SQRL_SEEDS__NA_VALUES=["NA"] # must be a JSON list
|
|
30
|
+
|
|
31
|
+
SQRL_CONNECTIONS__DEFAULT_NAME_USED="default"
|
|
32
|
+
|
|
33
|
+
SQRL_VDL__CATALOG_DB_PATH="ducklake:{project_path}/target/vdl_catalog.duckdb"
|
|
34
|
+
SQRL_VDL__DATA_PATH="{project_path}/target/vdl_data/"
|
|
35
|
+
|
|
36
|
+
SQRL_STUDIO__BASE_URL="https://squirrels-analytics.github.io/squirrels-studio-v1"
|
|
37
|
+
|
|
38
|
+
SQRL_LOGGING__LOG_LEVEL="INFO" # one of "DEBUG", "INFO", "WARNING"
|
|
39
|
+
SQRL_LOGGING__LOG_FORMAT="text"
|
|
40
|
+
SQRL_LOGGING__LOG_TO_FILE="false"
|
|
41
|
+
SQRL_LOGGING__LOG_FILE_SIZE_MB="50"
|
|
42
|
+
SQRL_LOGGING__LOG_FILE_BACKUP_COUNT="1"
|
|
Binary file
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
## Connection URIs are usually in format "dialect://username:password@host:port/database" for database connections
|
|
2
|
+
## However, subtle differences exist depending on the "type" specified. For example, sqlite URIs are slightly different.
|
|
3
|
+
## sqlalchemy: sqlite:///{project_path}/relative/path/to/database.db
|
|
4
|
+
## connectorx/adbc: sqlite://{project_path}/relative/path/to/database.db (adbc URI format matches connectorx)
|
|
5
|
+
## duckdb: sqlite:{project_path}/relative/path/to/database.db
|
|
6
|
+
## Refer to specific documentation for supported databases by type (with URI examples):
|
|
7
|
+
## sqlalchemy: https://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls
|
|
8
|
+
## connectorx: https://sfu-db.github.io/connector-x/databases.html
|
|
9
|
+
## adbc: https://arrow.apache.org/adbc/ (see connectorx documentation for URI examples)
|
|
10
|
+
connections:
|
|
11
|
+
- name: default
|
|
12
|
+
label: SQLite Expenses Database
|
|
13
|
+
type: sqlalchemy ## one of: sqlalchemy, connectorx, adbc, or duckdb
|
|
14
|
+
uri: {{ env_vars.SQLITE_URI }} ## using Jinja to substitute environment variables
|
|
15
|
+
|
|
16
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from squirrels import arguments as args, dashboards as d
|
|
2
|
+
from matplotlib import pyplot as plt, figure as f, axes as a
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
async def main(sqrl: args.DashboardArgs) -> d.PngDashboard:
|
|
6
|
+
spending_by_month_df = await sqrl.dataset("federate_dataset_example", fixed_parameters={"group_by": "month"})
|
|
7
|
+
spending_by_subcategory_df = await sqrl.dataset("federate_dataset_example", fixed_parameters={"group_by": "subcat"})
|
|
8
|
+
|
|
9
|
+
# Create a figure with two subplots
|
|
10
|
+
fig, (ax0, ax1) = plt.subplots(2, 1, figsize=(8, 8), height_ratios=(1, 2))
|
|
11
|
+
fig: f.Figure; ax0: a.Axes; ax1: a.Axes
|
|
12
|
+
fig.tight_layout(pad=4, h_pad=6)
|
|
13
|
+
|
|
14
|
+
# Create a bar chart of spending by month
|
|
15
|
+
|
|
16
|
+
# Convert to pandas and ensure total_amount is numeric
|
|
17
|
+
spending_by_month_pandas = spending_by_month_df.sort("month").to_pandas()
|
|
18
|
+
spending_by_month_pandas["total_amount"] = spending_by_month_pandas["total_amount"].astype(float)
|
|
19
|
+
|
|
20
|
+
spending_by_month_pandas.plot(x="month", y="total_amount", ax=ax0)
|
|
21
|
+
ax0.set_title("Spending by Month")
|
|
22
|
+
|
|
23
|
+
# Create a pie chart of spending by subcategory
|
|
24
|
+
|
|
25
|
+
# Convert to pandas and ensure total_amount is numeric
|
|
26
|
+
subcategory_pandas = spending_by_subcategory_df.sort("total_amount", descending=True).to_pandas()
|
|
27
|
+
subcategory_pandas["total_amount"] = subcategory_pandas["total_amount"].astype(float)
|
|
28
|
+
subcategory_pandas.set_index("subcategory", inplace=True)
|
|
29
|
+
|
|
30
|
+
autopct = lambda pct: ('%.1f%%' % pct) if pct > 6 else ''
|
|
31
|
+
subcategory_pandas.plot(y="total_amount", kind='pie', ax=ax1, autopct=autopct, legend=False, ylabel="")
|
|
32
|
+
ax1.set_title("Spending by Subcategory")
|
|
33
|
+
|
|
34
|
+
return d.PngDashboard(fig)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
label: Dashboard Example
|
|
2
|
+
|
|
3
|
+
description: This is an example dashboard
|
|
4
|
+
|
|
5
|
+
scope: protected
|
|
6
|
+
|
|
7
|
+
format: png
|
|
8
|
+
|
|
9
|
+
parameters:
|
|
10
|
+
- date_range
|
|
11
|
+
- category
|
|
12
|
+
|
|
13
|
+
depends_on:
|
|
14
|
+
- name: dataset_example_month
|
|
15
|
+
dataset: federate_dataset_example
|
|
16
|
+
fixed_parameters:
|
|
17
|
+
- group_by: month (Month)
|
|
18
|
+
|
|
19
|
+
- name: dataset_example_subcategory
|
|
20
|
+
dataset: federate_dataset_example
|
|
21
|
+
fixed_parameters:
|
|
22
|
+
- group_by: subcat (Subcategory)
|
|
@@ -8,9 +8,9 @@ COPY . .
|
|
|
8
8
|
# "sqrl deps" command if there are packages defined in "squirrels.yml"
|
|
9
9
|
RUN apt-get update && apt-get install -y git
|
|
10
10
|
|
|
11
|
-
RUN pip install --no-cache-dir -r requirements
|
|
11
|
+
RUN pip install --no-cache-dir -r requirements.txt
|
|
12
12
|
|
|
13
|
-
RUN
|
|
13
|
+
RUN sqrl deps
|
|
14
14
|
|
|
15
15
|
EXPOSE 4465
|
|
16
|
-
CMD ["
|
|
16
|
+
CMD ["sqrl", "run", "--build", "--host", "0.0.0.0", "--port", "4465"]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
-- SQL statements that run at the start of every DuckDB session
|
|
2
|
+
-- If the VDL catalog path is provided, the project will ATTACH it as 'vdl' (READ_ONLY)
|
|
3
|
+
|
|
4
|
+
-- Example:
|
|
5
|
+
|
|
6
|
+
-- SET threads = 4;
|
|
7
|
+
|
|
8
|
+
-- SET temp_directory = '/path/to/tmp/';
|
|
9
|
+
|
|
10
|
+
-- CREATE SECRET (TYPE S3, PROVIDER CREDENTIAL_CHAIN);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{%- macro date_and_amount_filters(use_from_range) -%}
|
|
2
|
+
{%- if use_from_range -%}
|
|
3
|
+
|
|
4
|
+
date >= {{ ctx.start_date_from_range | quote }}
|
|
5
|
+
AND date <= {{ ctx.end_date_from_range | quote }}
|
|
6
|
+
AND amount >= {{ ctx.min_amount_from_range }}
|
|
7
|
+
AND amount <= {{ ctx.max_amount_from_range }}
|
|
8
|
+
|
|
9
|
+
{%- else -%}
|
|
10
|
+
|
|
11
|
+
date >= {{ ctx.start_date | quote }}
|
|
12
|
+
AND date <= {{ ctx.end_date | quote }}
|
|
13
|
+
AND amount >= {{ ctx.min_amount }}
|
|
14
|
+
AND amount <= {{ ctx.max_amount }}
|
|
15
|
+
|
|
16
|
+
{%- endif -%}
|
|
17
|
+
{%- endmacro -%}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from squirrels import arguments as args
|
|
2
|
+
import polars as pl, pandas as pd
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def main(sqrl: args.BuildModelArgs) -> pl.LazyFrame | pl.DataFrame | pd.DataFrame:
|
|
6
|
+
"""
|
|
7
|
+
Create a build model by joining/processing sources or other build models to form a new
|
|
8
|
+
Python DataFrame (using polars LazyFrame, polars DataFrame, or pandas DataFrame).
|
|
9
|
+
"""
|
|
10
|
+
# sqrl.ref() can be used on a sources, seeds, or other build models
|
|
11
|
+
expenses_df = sqrl.ref("src_transactions")
|
|
12
|
+
categories_df = sqrl.ref("seed_categories")
|
|
13
|
+
subcategories_df = sqrl.ref("seed_subcategories")
|
|
14
|
+
|
|
15
|
+
df = expenses_df \
|
|
16
|
+
.join(subcategories_df, on="subcategory_id", how="left") \
|
|
17
|
+
.join(categories_df, on="category_id", how="left")
|
|
18
|
+
|
|
19
|
+
df = df.with_columns(
|
|
20
|
+
pl.col("date").dt.strftime("%Y-%m").alias("month"),
|
|
21
|
+
pl.col("date").dt.strftime("%Y-%m-%d").alias("date"),
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
return df.select(
|
|
25
|
+
"id", "date", "month", "category_id", "category", "subcategory_id", "subcategory", "amount", "description"
|
|
26
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{#- DuckDB dialect -#}
|
|
2
|
+
|
|
3
|
+
SELECT a.id,
|
|
4
|
+
STRFTIME(a.date, '%Y-%m-%d') AS date,
|
|
5
|
+
STRFTIME(a.date, '%Y-%m') AS month,
|
|
6
|
+
c.category_id,
|
|
7
|
+
c.category,
|
|
8
|
+
b.subcategory_id,
|
|
9
|
+
b.subcategory,
|
|
10
|
+
a.amount,
|
|
11
|
+
a.description
|
|
12
|
+
|
|
13
|
+
{# ref() can be used on a sources, seeds, or other build models -#}
|
|
14
|
+
FROM {{ ref("src_transactions") }} AS a
|
|
15
|
+
LEFT JOIN {{ ref("seed_subcategories") }} AS b ON a.subcategory_id = b.subcategory_id
|
|
16
|
+
LEFT JOIN {{ ref("seed_categories") }} AS c ON b.category_id = c.category_id
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
description: |
|
|
2
|
+
This is an example of a build model. It adds a new column called "month" to the source table "src_transactions".
|
|
3
|
+
|
|
4
|
+
materialization: TABLE # optional - defaults to "VIEW" for SQL models, ignored and always a "TABLE" for Python models
|
|
5
|
+
|
|
6
|
+
depends_on: # optional for SQL models - the "ref" macro also adds to this set
|
|
7
|
+
- src_transactions
|
|
8
|
+
- seed_categories
|
|
9
|
+
- seed_subcategories
|
|
10
|
+
|
|
11
|
+
columns:
|
|
12
|
+
- name: id
|
|
13
|
+
depends_on:
|
|
14
|
+
- src_transactions.id
|
|
15
|
+
pass_through: true
|
|
16
|
+
|
|
17
|
+
- name: date
|
|
18
|
+
type: string
|
|
19
|
+
description: The day of the transaction as a string in 'YYYY-MM-DD' format
|
|
20
|
+
depends_on:
|
|
21
|
+
- src_transactions.date
|
|
22
|
+
|
|
23
|
+
- name: month
|
|
24
|
+
type: string
|
|
25
|
+
description: The month of the transaction as a string in 'YYYY-MM' format
|
|
26
|
+
depends_on:
|
|
27
|
+
- src_transactions.date
|
|
28
|
+
|
|
29
|
+
- name: category_id
|
|
30
|
+
depends_on:
|
|
31
|
+
- seed_categories.category_id
|
|
32
|
+
pass_through: true
|
|
33
|
+
|
|
34
|
+
- name: category
|
|
35
|
+
depends_on:
|
|
36
|
+
- seed_categories.category
|
|
37
|
+
pass_through: true
|
|
38
|
+
|
|
39
|
+
- name: subcategory_id
|
|
40
|
+
depends_on:
|
|
41
|
+
- seed_subcategories.subcategory_id
|
|
42
|
+
pass_through: true
|
|
43
|
+
|
|
44
|
+
- name: subcategory
|
|
45
|
+
depends_on:
|
|
46
|
+
- seed_subcategories.subcategory
|
|
47
|
+
pass_through: true
|
|
48
|
+
|
|
49
|
+
- name: amount
|
|
50
|
+
depends_on:
|
|
51
|
+
- src_transactions.amount
|
|
52
|
+
pass_through: true
|
|
53
|
+
|
|
54
|
+
- name: description
|
|
55
|
+
depends_on:
|
|
56
|
+
- src_transactions.description
|
|
57
|
+
pass_through: true
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{#- SQLite dialect (based on connection used) -#}
|
|
2
|
+
|
|
3
|
+
SELECT STRFTIME('%Y-%m', date) AS month
|
|
4
|
+
, printf('%.2f', SUM(amount)) as total_amount
|
|
5
|
+
|
|
6
|
+
FROM {{ source("src_transactions") }}
|
|
7
|
+
|
|
8
|
+
WHERE {{ date_and_amount_filters(use_from_range=false) }}
|
|
9
|
+
|
|
10
|
+
GROUP BY 1
|
|
11
|
+
|
|
12
|
+
ORDER BY 1 DESC
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
description: |
|
|
2
|
+
This is an example of a database view model. It finds the total amount spent by month.
|
|
3
|
+
|
|
4
|
+
Parameters are available to filter the date and amount of the transactions.
|
|
5
|
+
|
|
6
|
+
connection: default # optional - if not provided, will use default connection specified in the SQRL_CONNECTIONS__DEFAULT_NAME_USED setting
|
|
7
|
+
|
|
8
|
+
translate_to_duckdb: true # optional - default is false - if true, then the model will be translated to duckdb for supported dialects
|
|
9
|
+
|
|
10
|
+
depends_on: # optional - the "source" macro also adds to this set
|
|
11
|
+
- src_transactions
|
|
12
|
+
|
|
13
|
+
columns:
|
|
14
|
+
- name: month
|
|
15
|
+
type: string
|
|
16
|
+
description: The months for which the amount is aggregated by, in descending order
|
|
17
|
+
category: dimension
|
|
18
|
+
depends_on:
|
|
19
|
+
- src_transactions.date
|
|
20
|
+
|
|
21
|
+
- name: total_amount
|
|
22
|
+
type: float
|
|
23
|
+
description: The total amount spent by month
|
|
24
|
+
category: measure
|
|
25
|
+
depends_on:
|
|
26
|
+
- src_transactions.amount
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from squirrels import arguments as args
|
|
2
|
+
import polars as pl, pandas as pd
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def main(sqrl: args.ModelArgs) -> pl.LazyFrame | pl.DataFrame | pd.DataFrame:
|
|
6
|
+
"""
|
|
7
|
+
Create federated models by joining/processing dependent models (sources, seeds, builds, dbviews, other federates, etc.) to
|
|
8
|
+
form a new Python DataFrame (using polars LazyFrame, polars DataFrame, or pandas DataFrame).
|
|
9
|
+
"""
|
|
10
|
+
df = sqrl.ref("build_example")
|
|
11
|
+
|
|
12
|
+
df = df.filter(
|
|
13
|
+
(pl.col("date") >= sqrl.ctx["start_date_from_range"]) &
|
|
14
|
+
(pl.col("date") <= sqrl.ctx["end_date_from_range"]) &
|
|
15
|
+
(pl.col("amount") >= sqrl.ctx["min_amount_from_range"]) &
|
|
16
|
+
(pl.col("amount") <= sqrl.ctx["max_amount_from_range"])
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
if sqrl.ctx["has_categories"]:
|
|
20
|
+
categories: list[str] = sqrl.ctx["categories"]
|
|
21
|
+
df = df.filter(pl.col("category_id").is_in(categories))
|
|
22
|
+
|
|
23
|
+
if sqrl.ctx["has_subcategories"]:
|
|
24
|
+
subcategories: list[str] = sqrl.ctx["subcategories"]
|
|
25
|
+
df = df.filter(pl.col("subcategory_id").is_in(subcategories))
|
|
26
|
+
|
|
27
|
+
dimension_cols: list[str] = sqrl.ctx["group_by_cols"]
|
|
28
|
+
df = df.group_by(dimension_cols).agg(
|
|
29
|
+
pl.sum("amount").cast(pl.Decimal(precision=15, scale=2)).alias("total_amount")
|
|
30
|
+
)
|
|
31
|
+
df = df.rename(sqrl.ctx["column_to_alias_mapping"])
|
|
32
|
+
|
|
33
|
+
order_by_cols: list[str] = sqrl.ctx["order_by_cols"]
|
|
34
|
+
df = df.select(*order_by_cols, "total_amount") \
|
|
35
|
+
.sort(order_by_cols, descending=True)
|
|
36
|
+
|
|
37
|
+
return df
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{#- DuckDB dialect -#}
|
|
2
|
+
|
|
3
|
+
SELECT {{ ctx.select_dim_cols | join }}
|
|
4
|
+
, CAST(SUM(amount) AS DECIMAL(15, 2)) as total_amount
|
|
5
|
+
|
|
6
|
+
{# ref() can be used on a sources, seeds, builds, dbviews, or other federate models -#}
|
|
7
|
+
FROM {{ ref("build_example") }} AS a
|
|
8
|
+
|
|
9
|
+
WHERE {{ date_and_amount_filters(use_from_range=true) }}
|
|
10
|
+
{%- if ctx.has_categories %}
|
|
11
|
+
AND category_id IN ({{ ctx.categories | quote_and_join }})
|
|
12
|
+
{%- endif %}
|
|
13
|
+
{%- if ctx.has_subcategories %}
|
|
14
|
+
AND subcategory_id IN ({{ ctx.subcategories | quote_and_join }})
|
|
15
|
+
{%- endif %}
|
|
16
|
+
|
|
17
|
+
GROUP BY {{ ctx.group_by_cols | join }}
|
|
18
|
+
|
|
19
|
+
ORDER BY {{ ctx.order_by_cols_desc | join }}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
description: |
|
|
2
|
+
This is an example of a federate view model. It takes the build example model and groups or filters the results based on the parameter selections provided.
|
|
3
|
+
|
|
4
|
+
Parameters are available to specify the group by dimension and filter by date, amount of the transaction, category, and subcategory.
|
|
5
|
+
|
|
6
|
+
depends_on: # optional for SQL models - the "ref" macro also adds to this set
|
|
7
|
+
- build_example
|
|
8
|
+
|
|
9
|
+
eager: false # optional - defaults to false. Only applies to SQL models.
|
|
10
|
+
|
|
11
|
+
columns:
|
|
12
|
+
- name: date
|
|
13
|
+
type: string
|
|
14
|
+
condition: parameter 'group_by' (Group By) is 'trans' (Transaction)
|
|
15
|
+
description: The date of the transaction in 'YYYY-MM-DD' format, in descending order
|
|
16
|
+
category: dimension
|
|
17
|
+
depends_on:
|
|
18
|
+
- build_example.date
|
|
19
|
+
|
|
20
|
+
- name: description
|
|
21
|
+
type: string
|
|
22
|
+
condition: parameter 'group_by' (Group By) is 'trans' (Transaction)
|
|
23
|
+
description: The description of the transaction
|
|
24
|
+
category: dimension
|
|
25
|
+
depends_on:
|
|
26
|
+
- build_example.description
|
|
27
|
+
|
|
28
|
+
- name: day
|
|
29
|
+
type: string
|
|
30
|
+
condition: parameter 'group_by' (Group By) is 'day' (Day)
|
|
31
|
+
description: The day for which the amount is aggregated by, in descending order
|
|
32
|
+
category: dimension
|
|
33
|
+
depends_on:
|
|
34
|
+
- build_example.date
|
|
35
|
+
|
|
36
|
+
- name: month
|
|
37
|
+
type: string
|
|
38
|
+
condition: parameter 'group_by' (Group By) is 'month' (Month)
|
|
39
|
+
description: The month for which the amount is aggregated by, in descending order
|
|
40
|
+
category: dimension
|
|
41
|
+
depends_on:
|
|
42
|
+
- build_example.month
|
|
43
|
+
|
|
44
|
+
- name: category
|
|
45
|
+
type: string
|
|
46
|
+
condition: parameter `group_by` (Group By) is `trans` (Transaction), `cat` (Category), or `subcat` (Subcategory)
|
|
47
|
+
description: The category for which the amount is aggregated by
|
|
48
|
+
category: dimension
|
|
49
|
+
depends_on:
|
|
50
|
+
- build_example.category
|
|
51
|
+
|
|
52
|
+
- name: subcategory
|
|
53
|
+
type: string
|
|
54
|
+
condition: parameter `group_by` (Group By) is `trans` (Transaction) or `subcat` (Subcategory)
|
|
55
|
+
description: The subcategory for which the amount is aggregated by
|
|
56
|
+
category: dimension
|
|
57
|
+
depends_on:
|
|
58
|
+
- build_example.subcategory
|
|
59
|
+
|
|
60
|
+
- name: total_amount
|
|
61
|
+
type: float
|
|
62
|
+
description: The total amount spent by the group by dimension
|
|
63
|
+
category: measure
|
|
64
|
+
depends_on:
|
|
65
|
+
- build_example.total_amount
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
sources:
|
|
2
|
+
- name: src_transactions
|
|
3
|
+
description: "The source table for transactions" # optional
|
|
4
|
+
connection: default # optional - if not provided, will use the connection named "default" or the default connection specified in settings
|
|
5
|
+
table: expenses # optional - if not provided, will use the "name" field of the source
|
|
6
|
+
load_to_vdl: true # optional - default is false - other than dbview models (with translate_to_duckdb set to false), other models can only reference this source if load_to_vdl is true or connection type is duckdb
|
|
7
|
+
|
|
8
|
+
update_hints:
|
|
9
|
+
increasing_column: date # optional - if not provided, will always do full refresh, otherwise uses this column for incremental loads
|
|
10
|
+
strictly_increasing: false # optional - default is true - if false, then maximum value of column is removed before incremental load is performed
|
|
11
|
+
|
|
12
|
+
primary_key: [id] # optional - if not provided, then this is an insert-only table for incremental loads
|
|
13
|
+
|
|
14
|
+
columns: # optional - if load_to_vdl is true, then only the columns listed here are loaded to the Virtual Data Lake (VDL)
|
|
15
|
+
- name: id
|
|
16
|
+
type: string
|
|
17
|
+
description: The unique identifier for the transaction
|
|
18
|
+
category: dimension
|
|
19
|
+
|
|
20
|
+
- name: date
|
|
21
|
+
type: date
|
|
22
|
+
description: The date of the transaction
|
|
23
|
+
category: dimension
|
|
24
|
+
|
|
25
|
+
- name: subcategory_id
|
|
26
|
+
type: string
|
|
27
|
+
description: The ID of the subcategory of the transaction
|
|
28
|
+
category: dimension
|
|
29
|
+
|
|
30
|
+
- name: amount
|
|
31
|
+
type: float
|
|
32
|
+
description: The amount of the transaction
|
|
33
|
+
category: measure
|
|
34
|
+
|
|
35
|
+
- name: description
|
|
36
|
+
type: string
|
|
37
|
+
description: The description of the transaction
|
|
38
|
+
category: dimension
|