squirrels 0.5.0b1__tar.gz → 0.5.0b3__tar.gz
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.
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/PKG-INFO +11 -17
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/README.md +10 -16
- squirrels-0.5.0b3/dateutils/__init__.py +6 -0
- squirrels-0.5.0b3/dateutils/_enums.py +25 -0
- squirrels-0.5.0b1/squirrels/dateutils.py → squirrels-0.5.0b3/dateutils/_implementation.py +58 -111
- squirrels-0.5.0b3/dateutils/types.py +6 -0
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/pyproject.toml +7 -1
- squirrels-0.5.0b3/squirrels/__init__.py +17 -0
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_api_server.py +5 -5
- squirrels-0.5.0b1/squirrels/arguments/init_time_args.py → squirrels-0.5.0b3/squirrels/_arguments/_init_time_args.py +2 -2
- squirrels-0.5.0b1/squirrels/arguments/run_time_args.py → squirrels-0.5.0b3/squirrels/_arguments/_run_time_args.py +4 -26
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_auth.py +2 -2
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_command_line.py +13 -9
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_connection_set.py +5 -5
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_constants.py +1 -1
- squirrels-0.5.0b1/squirrels/dashboards.py → squirrels-0.5.0b3/squirrels/_dashboard_types.py +12 -12
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_dashboards_io.py +2 -2
- squirrels-0.5.0b1/squirrels/data_sources.py → squirrels-0.5.0b3/squirrels/_data_sources.py +56 -55
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_exceptions.py +1 -1
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_initializer.py +82 -58
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_manifest.py +5 -5
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_model_builder.py +2 -0
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_model_configs.py +3 -3
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_model_queries.py +1 -1
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_models.py +28 -14
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/dashboards/dashboard_example.py +4 -4
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/dashboards/dashboard_example.yml +2 -2
- squirrels-0.5.0b3/squirrels/_package_data/base_project/macros/macros_example.sql +17 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/models/builds/build_example.py +2 -2
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/models/builds/build_example.sql +1 -1
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/models/builds/build_example.yml +2 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/models/dbviews/dbview_example.sql +1 -1
- squirrels-0.5.0b3/squirrels/_package_data/base_project/models/federates/federate_example.py +41 -0
- squirrels-0.5.0b3/squirrels/_package_data/base_project/models/federates/federate_example.sql +25 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/models/federates/federate_example.yml +6 -6
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/parameters.yml +9 -8
- squirrels-0.5.0b3/squirrels/_package_data/base_project/pyconfigs/connections.py +14 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/pyconfigs/context.py +14 -16
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/pyconfigs/parameters.py +13 -8
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/pyconfigs/user.py +2 -2
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_parameter_configs.py +34 -34
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_parameter_sets.py +18 -18
- squirrels-0.5.0b1/squirrels/parameters.py → squirrels-0.5.0b3/squirrels/_parameters.py +54 -54
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_project.py +37 -12
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_utils.py +5 -3
- squirrels-0.5.0b3/squirrels/arguments.py +2 -0
- squirrels-0.5.0b3/squirrels/connections.py +1 -0
- squirrels-0.5.0b3/squirrels/dashboards.py +1 -0
- squirrels-0.5.0b3/squirrels/data_sources.py +8 -0
- squirrels-0.5.0b3/squirrels/parameter_options.py +8 -0
- squirrels-0.5.0b3/squirrels/parameters.py +9 -0
- squirrels-0.5.0b3/squirrels/types.py +11 -0
- squirrels-0.5.0b1/.cursorignore +0 -2
- squirrels-0.5.0b1/.github/workflows/python-publish.yml +0 -45
- squirrels-0.5.0b1/database_elt/expenses/.gitignore +0 -1
- squirrels-0.5.0b1/database_elt/expenses/create-expenses.py +0 -90
- squirrels-0.5.0b1/database_elt/expenses/create-lookups.py +0 -55
- squirrels-0.5.0b1/database_elt/seattle_weather/create_db.py +0 -13
- squirrels-0.5.0b1/database_elt/seattle_weather/seattle-weather.csv +0 -1462
- squirrels-0.5.0b1/squirrels/__init__.py +0 -23
- squirrels-0.5.0b1/squirrels/package_data/base_project/macros/macros_example.sql +0 -15
- squirrels-0.5.0b1/squirrels/package_data/base_project/models/federates/federate_example.py +0 -44
- squirrels-0.5.0b1/squirrels/package_data/base_project/models/federates/federate_example.sql +0 -17
- squirrels-0.5.0b1/squirrels/package_data/base_project/pyconfigs/connections.py +0 -14
- squirrels-0.5.0b1/tests/__init__.py +0 -0
- squirrels-0.5.0b1/tests/_auth_test.py +0 -166
- squirrels-0.5.0b1/tests/_connection_set_test.py +0 -46
- squirrels-0.5.0b1/tests/_manifest_test.py +0 -290
- squirrels-0.5.0b1/tests/_model_builder_test.py +0 -168
- squirrels-0.5.0b1/tests/_model_configs_test.py +0 -16
- squirrels-0.5.0b1/tests/_models_basic_test.py +0 -152
- squirrels-0.5.0b1/tests/_models_test.py +0 -167
- squirrels-0.5.0b1/tests/_seeds_test.py +0 -124
- squirrels-0.5.0b1/tests/_sources_test.py +0 -151
- squirrels-0.5.0b1/tests/_utils_test.py +0 -22
- squirrels-0.5.0b1/tests/arguments/run_time_args_test.py +0 -16
- squirrels-0.5.0b1/tests/conftest.py +0 -19
- squirrels-0.5.0b1/tests/data_sources_test.py +0 -206
- squirrels-0.5.0b1/tests/dateutils_test.py +0 -132
- squirrels-0.5.0b1/tests/parameter_configs_tests/_parameter_configs_test.py +0 -184
- squirrels-0.5.0b1/tests/parameter_configs_tests/_parameter_sets_test.py +0 -237
- squirrels-0.5.0b1/tests/parameter_configs_tests/conftest.py +0 -111
- squirrels-0.5.0b1/tests/parameter_options_test.py +0 -122
- squirrels-0.5.0b1/tests/parameters_test.py +0 -386
- squirrels-0.5.0b1/uv.lock +0 -2164
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/.gitignore +0 -0
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/LICENSE +0 -0
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_api_response_models.py +0 -0
- /squirrels-0.5.0b1/squirrels/dataset_result.py → /squirrels-0.5.0b3/squirrels/_dataset_types.py +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/.env +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/.env.example +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/assets/expenses.db +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/assets/weather.db +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/connections.yml +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/docker/.dockerignore +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/docker/Dockerfile +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/docker/compose.yml +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/duckdb_init.sql +0 -0
- /squirrels-0.5.0b1/squirrels/package_data/base_project/.gitignore → /squirrels-0.5.0b3/squirrels/_package_data/base_project/gitignore +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/models/dbviews/dbview_example.yml +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/models/sources.yml +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/seeds/seed_categories.csv +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/seeds/seed_categories.yml +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/seeds/seed_subcategories.csv +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/seeds/seed_subcategories.yml +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/squirrels.yml.j2 +0 -0
- {squirrels-0.5.0b1/squirrels/package_data → squirrels-0.5.0b3/squirrels/_package_data}/base_project/tmp/.gitignore +0 -0
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_package_loader.py +0 -0
- /squirrels-0.5.0b1/squirrels/parameter_options.py → /squirrels-0.5.0b3/squirrels/_parameter_options.py +0 -0
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_py_module.py +0 -0
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_seeds.py +0 -0
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_sources.py +0 -0
- {squirrels-0.5.0b1 → squirrels-0.5.0b3}/squirrels/_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: squirrels
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.0b3
|
|
4
4
|
Summary: Squirrels - API Framework for Data Analytics
|
|
5
5
|
Project-URL: Homepage, https://squirrels-analytics.github.io
|
|
6
6
|
Project-URL: Repository, https://github.com/squirrels-analytics/squirrels
|
|
@@ -62,8 +62,8 @@ Here are a few of the things that squirrels can do:
|
|
|
62
62
|
- Configure parameter widgets (types include single-select, multi-select, date, number, etc.) for your datasets (in `parameters.py`).
|
|
63
63
|
- Use Jinja SQL templates (just like dbt!) or python functions (that return a Python dataframe such as polars or pandas) to define dynamic query logic based on parameter selections.
|
|
64
64
|
- Query multiple databases and join the results together in a final view in one API endpoint/dataset!
|
|
65
|
-
- Test your API endpoints with
|
|
66
|
-
- Define
|
|
65
|
+
- Test your API endpoints with Squirrels Studio or by a command line that generates rendered sql queries and results (for a given set of parameter selections).
|
|
66
|
+
- Define User model (in `user.py`) and authorize privacy scope per dataset (in `squirrels.yml`). The user's attributes can even be used in your query logic!
|
|
67
67
|
|
|
68
68
|
## License
|
|
69
69
|
|
|
@@ -77,18 +77,18 @@ The sections below describe how to set up your local environment for squirrels d
|
|
|
77
77
|
|
|
78
78
|
### Setup
|
|
79
79
|
|
|
80
|
-
This project requires python version 3.10 or above to be installed. It also uses the python
|
|
80
|
+
This project requires python version 3.10 or above to be installed. It also uses the python package manager `uv`. Information on setting up poetry can be found at: https://docs.astral.sh/uv/getting-started/installation/.
|
|
81
81
|
|
|
82
|
-
Then, to install all dependencies, run:
|
|
82
|
+
Then, to install all dependencies in a virtual environment, run:
|
|
83
83
|
|
|
84
|
-
```
|
|
85
|
-
|
|
84
|
+
```bash
|
|
85
|
+
uv sync
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
And activate the virtual environment
|
|
88
|
+
And activate the virtual environment with:
|
|
89
89
|
|
|
90
|
-
```
|
|
91
|
-
|
|
90
|
+
```bash
|
|
91
|
+
source .venv/bin/activate
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
To confirm that the setup worked, run the following to show the help page for all squirrels CLI commands:
|
|
@@ -97,11 +97,9 @@ To confirm that the setup worked, run the following to show the help page for al
|
|
|
97
97
|
sqrl -h
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
You can enter `exit` to exit the virtual environment shell. You can also run `poetry run sqrl -h` to run squirrels commands without activating the virtual environment.
|
|
101
|
-
|
|
102
100
|
### Testing
|
|
103
101
|
|
|
104
|
-
|
|
102
|
+
Run `uv run pytest`. Or if you have the virtual environment activated, simply run `pytest`.
|
|
105
103
|
|
|
106
104
|
### Project Structure
|
|
107
105
|
|
|
@@ -110,7 +108,3 @@ From the root of the git repo, the source code can be found in the `squirrels` f
|
|
|
110
108
|
To understand what a specific squirrels command is doing, start from the `_command_line.py` file as your entry point.
|
|
111
109
|
|
|
112
110
|
The library version is maintained in both the `pyproject.toml` and the `squirrels/_version.py` files.
|
|
113
|
-
|
|
114
|
-
When a user initializes a squirrels project using `sqrl init`, the files are copied from the `squirrels/package_data/base_project` folder. The contents in the `database` subfolder were constructed from the scripts in the `database_elt` folder.
|
|
115
|
-
|
|
116
|
-
For the Squirrels UI activated by `sqrl run`, the HTML, CSS, and Javascript files can be found in the `static` and `templates` subfolders of `squirrels/package_data`. The CSS and Javascript files are minified and built from the source files in this project: https://github.com/squirrels-analytics/squirrels-testing-ui.
|
|
@@ -24,8 +24,8 @@ Here are a few of the things that squirrels can do:
|
|
|
24
24
|
- Configure parameter widgets (types include single-select, multi-select, date, number, etc.) for your datasets (in `parameters.py`).
|
|
25
25
|
- Use Jinja SQL templates (just like dbt!) or python functions (that return a Python dataframe such as polars or pandas) to define dynamic query logic based on parameter selections.
|
|
26
26
|
- Query multiple databases and join the results together in a final view in one API endpoint/dataset!
|
|
27
|
-
- Test your API endpoints with
|
|
28
|
-
- Define
|
|
27
|
+
- Test your API endpoints with Squirrels Studio or by a command line that generates rendered sql queries and results (for a given set of parameter selections).
|
|
28
|
+
- Define User model (in `user.py`) and authorize privacy scope per dataset (in `squirrels.yml`). The user's attributes can even be used in your query logic!
|
|
29
29
|
|
|
30
30
|
## License
|
|
31
31
|
|
|
@@ -39,18 +39,18 @@ The sections below describe how to set up your local environment for squirrels d
|
|
|
39
39
|
|
|
40
40
|
### Setup
|
|
41
41
|
|
|
42
|
-
This project requires python version 3.10 or above to be installed. It also uses the python
|
|
42
|
+
This project requires python version 3.10 or above to be installed. It also uses the python package manager `uv`. Information on setting up poetry can be found at: https://docs.astral.sh/uv/getting-started/installation/.
|
|
43
43
|
|
|
44
|
-
Then, to install all dependencies, run:
|
|
44
|
+
Then, to install all dependencies in a virtual environment, run:
|
|
45
45
|
|
|
46
|
-
```
|
|
47
|
-
|
|
46
|
+
```bash
|
|
47
|
+
uv sync
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
And activate the virtual environment
|
|
50
|
+
And activate the virtual environment with:
|
|
51
51
|
|
|
52
|
-
```
|
|
53
|
-
|
|
52
|
+
```bash
|
|
53
|
+
source .venv/bin/activate
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
To confirm that the setup worked, run the following to show the help page for all squirrels CLI commands:
|
|
@@ -59,11 +59,9 @@ To confirm that the setup worked, run the following to show the help page for al
|
|
|
59
59
|
sqrl -h
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
You can enter `exit` to exit the virtual environment shell. You can also run `poetry run sqrl -h` to run squirrels commands without activating the virtual environment.
|
|
63
|
-
|
|
64
62
|
### Testing
|
|
65
63
|
|
|
66
|
-
|
|
64
|
+
Run `uv run pytest`. Or if you have the virtual environment activated, simply run `pytest`.
|
|
67
65
|
|
|
68
66
|
### Project Structure
|
|
69
67
|
|
|
@@ -72,7 +70,3 @@ From the root of the git repo, the source code can be found in the `squirrels` f
|
|
|
72
70
|
To understand what a specific squirrels command is doing, start from the `_command_line.py` file as your entry point.
|
|
73
71
|
|
|
74
72
|
The library version is maintained in both the `pyproject.toml` and the `squirrels/_version.py` files.
|
|
75
|
-
|
|
76
|
-
When a user initializes a squirrels project using `sqrl init`, the files are copied from the `squirrels/package_data/base_project` folder. The contents in the `database` subfolder were constructed from the scripts in the `database_elt` folder.
|
|
77
|
-
|
|
78
|
-
For the Squirrels UI activated by `sqrl run`, the HTML, CSS, and Javascript files can be found in the `static` and `templates` subfolders of `squirrels/package_data`. The CSS and Javascript files are minified and built from the source files in this project: https://github.com/squirrels-analytics/squirrels-testing-ui.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
from ._enums import DayOfWeekEnum, MonthEnum
|
|
2
|
+
from ._implementation import (
|
|
3
|
+
DayIdxOfMonthsCycle, DayIdxOfYear, DayIdxOfQuarter, DayIdxOfMonth, DayIdxOfWeek,
|
|
4
|
+
OffsetYears, OffsetMonths, OffsetWeeks, OffsetDays,
|
|
5
|
+
DateModPipeline, DateStringModifier, TimestampModifier
|
|
6
|
+
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DayOfWeekEnum(Enum):
|
|
5
|
+
Sunday = 0
|
|
6
|
+
Monday = 1
|
|
7
|
+
Tuesday = 2
|
|
8
|
+
Wednesday = 3
|
|
9
|
+
Thursday = 4
|
|
10
|
+
Friday = 5
|
|
11
|
+
Saturday = 6
|
|
12
|
+
|
|
13
|
+
class MonthEnum(Enum):
|
|
14
|
+
January = 1
|
|
15
|
+
February = 2
|
|
16
|
+
March = 3
|
|
17
|
+
April = 4
|
|
18
|
+
May = 5
|
|
19
|
+
June = 6
|
|
20
|
+
July = 7
|
|
21
|
+
August = 8
|
|
22
|
+
September = 9
|
|
23
|
+
October = 10
|
|
24
|
+
November = 11
|
|
25
|
+
December = 12
|
|
@@ -3,33 +3,8 @@ from dataclasses import dataclass
|
|
|
3
3
|
from datetime import date as Date, datetime
|
|
4
4
|
from dateutil.relativedelta import relativedelta
|
|
5
5
|
from abc import ABCMeta, abstractmethod
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
from . import _utils as u
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class DayOfWeek(Enum):
|
|
12
|
-
Sunday = 0
|
|
13
|
-
Monday = 1
|
|
14
|
-
Tuesday = 2
|
|
15
|
-
Wednesday = 3
|
|
16
|
-
Thursday = 4
|
|
17
|
-
Friday = 5
|
|
18
|
-
Saturday = 6
|
|
19
|
-
|
|
20
|
-
class Month(Enum):
|
|
21
|
-
January = 1
|
|
22
|
-
February = 2
|
|
23
|
-
March = 3
|
|
24
|
-
April = 4
|
|
25
|
-
May = 5
|
|
26
|
-
June = 6
|
|
27
|
-
July = 7
|
|
28
|
-
August = 8
|
|
29
|
-
September = 9
|
|
30
|
-
October = 10
|
|
31
|
-
November = 11
|
|
32
|
-
December = 12
|
|
6
|
+
|
|
7
|
+
from ._enums import DayOfWeekEnum, MonthEnum
|
|
33
8
|
|
|
34
9
|
|
|
35
10
|
class DateModifier(metaclass=ABCMeta):
|
|
@@ -54,20 +29,21 @@ class DateModifier(metaclass=ABCMeta):
|
|
|
54
29
|
return datetype(year, month, day)
|
|
55
30
|
|
|
56
31
|
|
|
57
|
-
|
|
32
|
+
@dataclass
|
|
33
|
+
class DayIdxOfCalendarUnit(DateModifier):
|
|
58
34
|
"""
|
|
59
35
|
Interface for adjusting a date to some day of calendar unit
|
|
60
36
|
"""
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
37
|
+
idx: int
|
|
38
|
+
|
|
39
|
+
def __post_init__(self) -> None:
|
|
64
40
|
if self.idx == 0:
|
|
65
|
-
raise
|
|
41
|
+
raise ValueError(f"For constructors of class names that start with DayIdxOf_, idx cannot be zero")
|
|
66
42
|
self.incr = self.idx - 1 if self.idx > 0 else self.idx
|
|
67
43
|
|
|
68
44
|
|
|
69
45
|
@dataclass
|
|
70
|
-
class DayIdxOfMonthsCycle(
|
|
46
|
+
class DayIdxOfMonthsCycle(DayIdxOfCalendarUnit):
|
|
71
47
|
"""
|
|
72
48
|
DateModifier class to get the idx-th day of a cycle of months for an input date
|
|
73
49
|
|
|
@@ -76,23 +52,21 @@ class DayIdxOfMonthsCycle(_DayIdxOfCalendarUnit):
|
|
|
76
52
|
num_months_in_cycle: 2 for one 6th of year, 3 for Quarter, 4 for one 3rd of year, 6 for half year, 12 for full year. Must fit evenly in 12
|
|
77
53
|
first_month_of_cycle: The first month of months cycle of year. Default is January
|
|
78
54
|
"""
|
|
79
|
-
|
|
80
|
-
|
|
55
|
+
num_months_in_cycle: int
|
|
56
|
+
first_month_of_cycle: MonthEnum = MonthEnum.January
|
|
81
57
|
|
|
82
|
-
def
|
|
83
|
-
super().
|
|
84
|
-
self.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
raise u.ConfigurationError(f"Value X must fit evenly in 12")
|
|
88
|
-
self.first_month_of_first_cycle = (self._first_month_of_cycle.value - 1) % self._num_months_in_cycle + 1
|
|
58
|
+
def __post_init__(self) -> None:
|
|
59
|
+
super().__post_init__()
|
|
60
|
+
if 12 % self.num_months_in_cycle != 0:
|
|
61
|
+
raise ValueError(f"Argument 'num_months_in_cycle' must fit evenly in 12")
|
|
62
|
+
self.first_month_of_first_cycle = (self.first_month_of_cycle.value - 1) % self.num_months_in_cycle + 1
|
|
89
63
|
|
|
90
64
|
def modify(self, date: Date) -> Date:
|
|
91
|
-
current_cycle = (date.month - self.first_month_of_first_cycle) % 12 // self.
|
|
92
|
-
first_month_of_curr_cycle = current_cycle * self.
|
|
65
|
+
current_cycle = (date.month - self.first_month_of_first_cycle) % 12 // self.num_months_in_cycle
|
|
66
|
+
first_month_of_curr_cycle = current_cycle * self.num_months_in_cycle + self.first_month_of_first_cycle
|
|
93
67
|
year = date.year if date.month >= first_month_of_curr_cycle else date.year - 1
|
|
94
68
|
first_day = self._get_date(type(date), year, first_month_of_curr_cycle, 1)
|
|
95
|
-
ref_date = first_day if self.idx > 0 else first_day + relativedelta(months=self.
|
|
69
|
+
ref_date = first_day if self.idx > 0 else first_day + relativedelta(months=self.num_months_in_cycle)
|
|
96
70
|
return ref_date + relativedelta(days=self.incr)
|
|
97
71
|
|
|
98
72
|
|
|
@@ -106,7 +80,7 @@ class DayIdxOfYear(DayIdxOfMonthsCycle):
|
|
|
106
80
|
first_month_of_year: The first month of year. Default is January
|
|
107
81
|
"""
|
|
108
82
|
|
|
109
|
-
def __init__(self, idx: int, first_month_of_year:
|
|
83
|
+
def __init__(self, idx: int, first_month_of_year: MonthEnum = MonthEnum.January):
|
|
110
84
|
super().__init__(idx, num_months_in_cycle=12, first_month_of_cycle=first_month_of_year)
|
|
111
85
|
|
|
112
86
|
|
|
@@ -120,12 +94,12 @@ class DayIdxOfQuarter(DayIdxOfMonthsCycle):
|
|
|
120
94
|
first_month_of_quarter: The first month of first quarter. Default is January
|
|
121
95
|
"""
|
|
122
96
|
|
|
123
|
-
def __init__(self, idx: int, first_month_of_quarter:
|
|
97
|
+
def __init__(self, idx: int, first_month_of_quarter: MonthEnum = MonthEnum.January):
|
|
124
98
|
super().__init__(idx, num_months_in_cycle=3, first_month_of_cycle=first_month_of_quarter)
|
|
125
99
|
|
|
126
100
|
|
|
127
101
|
@dataclass
|
|
128
|
-
class DayIdxOfMonth(
|
|
102
|
+
class DayIdxOfMonth(DayIdxOfCalendarUnit):
|
|
129
103
|
"""
|
|
130
104
|
DateModifier class to get the idx-th day of month of an input date
|
|
131
105
|
|
|
@@ -133,9 +107,6 @@ class DayIdxOfMonth(_DayIdxOfCalendarUnit):
|
|
|
133
107
|
idx: 1 for first, 2 for second, etc. Or, -1 for last, -2 for second last, etc. Must not be 0
|
|
134
108
|
"""
|
|
135
109
|
|
|
136
|
-
def __init__(self, idx: int) -> None:
|
|
137
|
-
super().__init__(idx)
|
|
138
|
-
|
|
139
110
|
def modify(self, date: Date) -> Date:
|
|
140
111
|
first_day = self._get_date(type(date), date.year, date.month, 1)
|
|
141
112
|
ref_date = first_day if self.idx > 0 else first_day + relativedelta(months=1)
|
|
@@ -143,7 +114,7 @@ class DayIdxOfMonth(_DayIdxOfCalendarUnit):
|
|
|
143
114
|
|
|
144
115
|
|
|
145
116
|
@dataclass
|
|
146
|
-
class DayIdxOfWeek(
|
|
117
|
+
class DayIdxOfWeek(DayIdxOfCalendarUnit):
|
|
147
118
|
"""
|
|
148
119
|
DateModifier class to get the idx-th day of week of an input date
|
|
149
120
|
|
|
@@ -151,12 +122,11 @@ class DayIdxOfWeek(_DayIdxOfCalendarUnit):
|
|
|
151
122
|
idx: 1 for first, 2 for second, etc. Or, -1 for last, -2 for second last, etc. Must not be 0
|
|
152
123
|
first_day_of_week: The day of week identified as the "first". Default is Monday
|
|
153
124
|
"""
|
|
154
|
-
|
|
125
|
+
first_day_of_week: DayOfWeekEnum = DayOfWeekEnum.Monday
|
|
155
126
|
|
|
156
|
-
def
|
|
157
|
-
super().
|
|
158
|
-
self.
|
|
159
|
-
self.first_dow_num = self._first_day_of_week.value
|
|
127
|
+
def __post_init__(self) -> None:
|
|
128
|
+
super().__post_init__()
|
|
129
|
+
self.first_dow_num = self.first_day_of_week.value
|
|
160
130
|
|
|
161
131
|
def modify(self, date: Date) -> Date:
|
|
162
132
|
distance_from_first_day = (1 + date.weekday() - self.first_dow_num) % 7
|
|
@@ -164,17 +134,16 @@ class DayIdxOfWeek(_DayIdxOfCalendarUnit):
|
|
|
164
134
|
return date + relativedelta(days=total_incr)
|
|
165
135
|
|
|
166
136
|
|
|
167
|
-
|
|
137
|
+
@dataclass
|
|
138
|
+
class OffsetUnits(DateModifier):
|
|
168
139
|
"""
|
|
169
140
|
Abstract DateModifier class to offset an input date by some number of some calendar unit
|
|
170
141
|
"""
|
|
171
|
-
|
|
172
|
-
super().__init__()
|
|
173
|
-
self.offset = offset
|
|
142
|
+
offset: int
|
|
174
143
|
|
|
175
144
|
|
|
176
145
|
@dataclass
|
|
177
|
-
class OffsetYears(
|
|
146
|
+
class OffsetYears(OffsetUnits):
|
|
178
147
|
"""
|
|
179
148
|
DateModifier class to offset an input date by some number of years
|
|
180
149
|
|
|
@@ -182,15 +151,12 @@ class OffsetYears(_OffsetUnits):
|
|
|
182
151
|
offset: The number of years to offset the input date.
|
|
183
152
|
"""
|
|
184
153
|
|
|
185
|
-
def __init__(self, offset: int) -> None:
|
|
186
|
-
super().__init__(offset)
|
|
187
|
-
|
|
188
154
|
def modify(self, date: Date) -> Date:
|
|
189
155
|
return date + relativedelta(years=self.offset)
|
|
190
156
|
|
|
191
157
|
|
|
192
158
|
@dataclass
|
|
193
|
-
class OffsetMonths(
|
|
159
|
+
class OffsetMonths(OffsetUnits):
|
|
194
160
|
"""
|
|
195
161
|
DateModifier class to offset an input date by some number of months
|
|
196
162
|
|
|
@@ -198,15 +164,12 @@ class OffsetMonths(_OffsetUnits):
|
|
|
198
164
|
offset: The number of months to offset the input date.
|
|
199
165
|
"""
|
|
200
166
|
|
|
201
|
-
def __init__(self, offset: int) -> None:
|
|
202
|
-
super().__init__(offset)
|
|
203
|
-
|
|
204
167
|
def modify(self, date: Date) -> Date:
|
|
205
168
|
return date + relativedelta(months=self.offset)
|
|
206
169
|
|
|
207
170
|
|
|
208
171
|
@dataclass
|
|
209
|
-
class OffsetWeeks(
|
|
172
|
+
class OffsetWeeks(OffsetUnits):
|
|
210
173
|
"""
|
|
211
174
|
DateModifier class to offset an input date by some number of weeks
|
|
212
175
|
|
|
@@ -214,15 +177,12 @@ class OffsetWeeks(_OffsetUnits):
|
|
|
214
177
|
offset: The number of weeks to offset the input date.
|
|
215
178
|
"""
|
|
216
179
|
|
|
217
|
-
def __init__(self, offset: int) -> None:
|
|
218
|
-
super().__init__(offset)
|
|
219
|
-
|
|
220
180
|
def modify(self, date: Date) -> Date:
|
|
221
181
|
return date + relativedelta(weeks=self.offset)
|
|
222
182
|
|
|
223
183
|
|
|
224
184
|
@dataclass
|
|
225
|
-
class OffsetDays(
|
|
185
|
+
class OffsetDays(OffsetUnits):
|
|
226
186
|
"""
|
|
227
187
|
DateModifier class to offset an input date by some number of days
|
|
228
188
|
|
|
@@ -230,9 +190,6 @@ class OffsetDays(_OffsetUnits):
|
|
|
230
190
|
offset: The number of days to offset the input date.
|
|
231
191
|
"""
|
|
232
192
|
|
|
233
|
-
def __init__(self, offset: int) -> None:
|
|
234
|
-
super().__init__(offset)
|
|
235
|
-
|
|
236
193
|
def modify(self, date: Date) -> Date:
|
|
237
194
|
return date + relativedelta(days=self.offset)
|
|
238
195
|
|
|
@@ -245,14 +202,10 @@ class DateModPipeline(DateModifier):
|
|
|
245
202
|
Attributes:
|
|
246
203
|
modifiers: The list of DateModifier's to apply in sequence.
|
|
247
204
|
"""
|
|
248
|
-
|
|
205
|
+
date_modifiers: Sequence[DateModifier]
|
|
249
206
|
|
|
250
|
-
def __init__(self, date_modifiers: Sequence[DateModifier]) -> None:
|
|
251
|
-
super().__init__()
|
|
252
|
-
self._date_modifiers = tuple(date_modifiers)
|
|
253
|
-
|
|
254
207
|
def modify(self, date: Date) -> Date:
|
|
255
|
-
for modifier in self.
|
|
208
|
+
for modifier in self.date_modifiers:
|
|
256
209
|
date = modifier.modify(date)
|
|
257
210
|
return date
|
|
258
211
|
|
|
@@ -267,7 +220,7 @@ class DateModPipeline(DateModifier):
|
|
|
267
220
|
Returns:
|
|
268
221
|
A new sequence of DateModifier
|
|
269
222
|
"""
|
|
270
|
-
joined_modifiers = tuple(self.
|
|
223
|
+
joined_modifiers = tuple(self.date_modifiers) + tuple(date_modifiers)
|
|
271
224
|
return joined_modifiers
|
|
272
225
|
|
|
273
226
|
def with_more_modifiers(self, date_modifiers: Sequence[DateModifier]):
|
|
@@ -300,9 +253,9 @@ class DateModPipeline(DateModifier):
|
|
|
300
253
|
Returns:
|
|
301
254
|
A list of datetime objects
|
|
302
255
|
"""
|
|
303
|
-
assert isinstance(step,
|
|
256
|
+
assert isinstance(step, OffsetUnits)
|
|
304
257
|
if step.offset == 0:
|
|
305
|
-
raise
|
|
258
|
+
raise ValueError(f"The length of 'step' must not be zero")
|
|
306
259
|
|
|
307
260
|
output: Sequence[Date] = []
|
|
308
261
|
end_date = self.modify(start_date)
|
|
@@ -315,12 +268,15 @@ class DateModPipeline(DateModifier):
|
|
|
315
268
|
return output
|
|
316
269
|
|
|
317
270
|
|
|
318
|
-
|
|
271
|
+
@dataclass
|
|
272
|
+
class DateRepresentationModifier(metaclass=ABCMeta):
|
|
319
273
|
"""
|
|
320
274
|
Abstract class for modifying other representations of dates (such as string or unix timestemp)
|
|
321
275
|
"""
|
|
322
|
-
|
|
323
|
-
|
|
276
|
+
date_modifiers: Sequence[DateModifier]
|
|
277
|
+
|
|
278
|
+
def __post_init__(self) -> None:
|
|
279
|
+
self.date_mod_pipeline = DateModPipeline(self.date_modifiers)
|
|
324
280
|
|
|
325
281
|
@abstractmethod
|
|
326
282
|
def with_more_modifiers(self, date_modifiers: Sequence[DateModifier]):
|
|
@@ -328,7 +284,7 @@ class _DateRepresentationModifier(metaclass=ABCMeta):
|
|
|
328
284
|
|
|
329
285
|
|
|
330
286
|
@dataclass
|
|
331
|
-
class DateStringModifier(
|
|
287
|
+
class DateStringModifier(DateRepresentationModifier):
|
|
332
288
|
"""
|
|
333
289
|
Class to modify a string representation of a date given a DateModifier
|
|
334
290
|
|
|
@@ -336,12 +292,7 @@ class DateStringModifier(_DateRepresentationModifier):
|
|
|
336
292
|
date_modifier: The DateModifier to apply on datetime objects
|
|
337
293
|
date_format: Format of the output date string. Default is '%Y-%m-%d'
|
|
338
294
|
"""
|
|
339
|
-
|
|
340
|
-
_date_format: str
|
|
341
|
-
|
|
342
|
-
def __init__(self, date_modifiers: Sequence[DateModifier], date_format: str = '%Y-%m-%d'):
|
|
343
|
-
super().__init__(date_modifiers)
|
|
344
|
-
self._date_format = date_format
|
|
295
|
+
date_format: str = '%Y-%m-%d'
|
|
345
296
|
|
|
346
297
|
def with_more_modifiers(self, date_modifiers: Sequence[DateModifier]):
|
|
347
298
|
"""
|
|
@@ -353,11 +304,11 @@ class DateStringModifier(_DateRepresentationModifier):
|
|
|
353
304
|
Returns:
|
|
354
305
|
A new DateStringModifier
|
|
355
306
|
"""
|
|
356
|
-
joined_modifiers = self.
|
|
357
|
-
return DateStringModifier(joined_modifiers, self.
|
|
307
|
+
joined_modifiers = self.date_mod_pipeline.get_joined_modifiers(date_modifiers)
|
|
308
|
+
return DateStringModifier(joined_modifiers, self.date_format)
|
|
358
309
|
|
|
359
310
|
def _get_input_date_obj(self, date_str: str, input_format: str | None = None) -> Date:
|
|
360
|
-
input_format = self.
|
|
311
|
+
input_format = self.date_format if input_format is None else input_format
|
|
361
312
|
return datetime.strptime(date_str, input_format).date()
|
|
362
313
|
|
|
363
314
|
def modify(self, date_str: str, input_format: str | None = None) -> str:
|
|
@@ -372,7 +323,7 @@ class DateStringModifier(_DateRepresentationModifier):
|
|
|
372
323
|
The resulting date string
|
|
373
324
|
"""
|
|
374
325
|
date_obj = self._get_input_date_obj(date_str, input_format)
|
|
375
|
-
return self.
|
|
326
|
+
return self.date_mod_pipeline.modify(date_obj).strftime(self.date_format)
|
|
376
327
|
|
|
377
328
|
def get_date_list(self, start_date_str: str, step: DateModifier, input_format: str | None = None) -> Sequence[str]:
|
|
378
329
|
"""
|
|
@@ -392,14 +343,14 @@ class DateStringModifier(_DateRepresentationModifier):
|
|
|
392
343
|
Returns:
|
|
393
344
|
A list of date strings
|
|
394
345
|
"""
|
|
395
|
-
assert isinstance(step,
|
|
346
|
+
assert isinstance(step, OffsetUnits)
|
|
396
347
|
curr_date = self._get_input_date_obj(start_date_str, input_format)
|
|
397
|
-
output = self.
|
|
398
|
-
return [x.strftime(self.
|
|
348
|
+
output = self.date_mod_pipeline.get_date_list(curr_date, step)
|
|
349
|
+
return [x.strftime(self.date_format) for x in output]
|
|
399
350
|
|
|
400
351
|
|
|
401
352
|
@dataclass
|
|
402
|
-
class TimestampModifier(
|
|
353
|
+
class TimestampModifier(DateRepresentationModifier):
|
|
403
354
|
"""
|
|
404
355
|
Class to modify a numeric representation of a date (as Unix/Epoch/POSIX timestamp) given a DateModifier
|
|
405
356
|
|
|
@@ -407,10 +358,6 @@ class TimestampModifier(_DateRepresentationModifier):
|
|
|
407
358
|
date_modifier: The DateModifier to apply on datetime objects
|
|
408
359
|
date_format: Format of the date string. Default is '%Y-%m-%d'
|
|
409
360
|
"""
|
|
410
|
-
_date_modifiers: Sequence[DateModifier]
|
|
411
|
-
|
|
412
|
-
def __init__(self, date_modifiers: Sequence[DateModifier]):
|
|
413
|
-
super().__init__(date_modifiers)
|
|
414
361
|
|
|
415
362
|
def with_more_modifiers(self, date_modifiers: Sequence[DateModifier]):
|
|
416
363
|
"""
|
|
@@ -422,7 +369,7 @@ class TimestampModifier(_DateRepresentationModifier):
|
|
|
422
369
|
Returns:
|
|
423
370
|
A new TimestampModifier
|
|
424
371
|
"""
|
|
425
|
-
joined_modifiers = self.
|
|
372
|
+
joined_modifiers = self.date_mod_pipeline.get_joined_modifiers(date_modifiers)
|
|
426
373
|
return TimestampModifier(joined_modifiers)
|
|
427
374
|
|
|
428
375
|
def modify(self, timestamp: float) -> float:
|
|
@@ -436,7 +383,7 @@ class TimestampModifier(_DateRepresentationModifier):
|
|
|
436
383
|
The resulting timestamp
|
|
437
384
|
"""
|
|
438
385
|
date_obj = datetime.fromtimestamp(timestamp).date()
|
|
439
|
-
modified_date = self.
|
|
386
|
+
modified_date = self.date_mod_pipeline.modify(date_obj)
|
|
440
387
|
modified_datetime = datetime.combine(modified_date, datetime.min.time())
|
|
441
388
|
return modified_datetime.timestamp()
|
|
442
389
|
|
|
@@ -458,5 +405,5 @@ class TimestampModifier(_DateRepresentationModifier):
|
|
|
458
405
|
A list of timestamp as floats
|
|
459
406
|
"""
|
|
460
407
|
curr_date = datetime.fromtimestamp(start_timestamp).date()
|
|
461
|
-
output = self.
|
|
408
|
+
output = self.date_mod_pipeline.get_date_list(curr_date, step)
|
|
462
409
|
return [datetime.combine(x, datetime.min.time()).timestamp() for x in output]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "squirrels"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.0b3"
|
|
4
4
|
description = "Squirrels - API Framework for Data Analytics"
|
|
5
5
|
authors = [{ name = "Tim Huang", email = "tim.yuting@hotmail.com" }]
|
|
6
6
|
requires-python = "~=3.10"
|
|
@@ -58,6 +58,12 @@ dev = [
|
|
|
58
58
|
"tqdm>=4.67.1,<5",
|
|
59
59
|
]
|
|
60
60
|
|
|
61
|
+
[tool.hatch.build.targets.sdist]
|
|
62
|
+
include = ["squirrels", "dateutils"]
|
|
63
|
+
|
|
64
|
+
[tool.hatch.build.targets.wheel]
|
|
65
|
+
include = ["squirrels", "dateutils"]
|
|
66
|
+
|
|
61
67
|
[tool.uv]
|
|
62
68
|
default-groups = [
|
|
63
69
|
"test",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from ._version import __version__
|
|
2
|
+
|
|
3
|
+
from .arguments import *
|
|
4
|
+
|
|
5
|
+
from .connections import *
|
|
6
|
+
|
|
7
|
+
from .parameter_options import *
|
|
8
|
+
|
|
9
|
+
from .parameters import *
|
|
10
|
+
|
|
11
|
+
from .data_sources import *
|
|
12
|
+
|
|
13
|
+
from .dashboards import *
|
|
14
|
+
|
|
15
|
+
from .types import *
|
|
16
|
+
|
|
17
|
+
from ._project import SquirrelsProject
|
|
@@ -17,9 +17,9 @@ from ._version import __version__, sq_major_version
|
|
|
17
17
|
from ._manifest import PermissionScope
|
|
18
18
|
from ._auth import BaseUser, AccessToken, UserField
|
|
19
19
|
from ._parameter_sets import ParameterSet
|
|
20
|
-
from .
|
|
20
|
+
from ._dashboard_types import Dashboard
|
|
21
21
|
from ._project import SquirrelsProject
|
|
22
|
-
from .
|
|
22
|
+
from ._dataset_types import DatasetResult
|
|
23
23
|
from ._parameter_configs import APIParamFieldInfo
|
|
24
24
|
|
|
25
25
|
mimetypes.add_type('application/javascript', '.js')
|
|
@@ -189,17 +189,17 @@ class ApiServer:
|
|
|
189
189
|
traceback.print_exception(exc.error, file=buffer)
|
|
190
190
|
buffer.write(str(exc))
|
|
191
191
|
response = JSONResponse(
|
|
192
|
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content={"message": f"An unexpected error occurred", "blame": "Squirrels project"}
|
|
192
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content={"message": f"An unexpected server error occurred", "blame": "Squirrels project"}
|
|
193
193
|
)
|
|
194
194
|
except ConfigurationError as exc:
|
|
195
195
|
traceback.print_exc(file=buffer)
|
|
196
196
|
response = JSONResponse(
|
|
197
|
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content={"message": f"An unexpected error occurred", "blame": "Squirrels project"}
|
|
197
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content={"message": f"An unexpected server error occurred", "blame": "Squirrels project"}
|
|
198
198
|
)
|
|
199
199
|
except Exception as exc:
|
|
200
200
|
traceback.print_exc(file=buffer)
|
|
201
201
|
response = JSONResponse(
|
|
202
|
-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content={"message": f"An unexpected error occurred", "blame": "Squirrels framework"}
|
|
202
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content={"message": f"An unexpected server error occurred", "blame": "Squirrels framework"}
|
|
203
203
|
)
|
|
204
204
|
|
|
205
205
|
err_msg = buffer.getvalue()
|
|
@@ -88,14 +88,14 @@ class BuildModelArgs(_WithConnectionDictArgs):
|
|
|
88
88
|
|
|
89
89
|
def run_sql_on_dataframes(self, sql_query: str, *, dataframes: dict[str, pl.LazyFrame] | None = None, **kwargs) -> pl.DataFrame:
|
|
90
90
|
"""
|
|
91
|
-
Uses a dictionary of dataframes to execute a SQL query in an embedded in-memory database
|
|
91
|
+
Uses a dictionary of dataframes to execute a SQL query in an embedded in-memory DuckDB database
|
|
92
92
|
|
|
93
93
|
Arguments:
|
|
94
94
|
sql_query: The SQL query to run
|
|
95
95
|
dataframes: A dictionary of table names to their polars LazyFrame. If None, uses results of dependent models
|
|
96
96
|
|
|
97
97
|
Returns:
|
|
98
|
-
The result as a polars
|
|
98
|
+
The result as a polars DataFrame from running the query
|
|
99
99
|
"""
|
|
100
100
|
if dataframes is None:
|
|
101
101
|
dataframes = {x: self.ref(x) for x in self._dependencies}
|