squirrels 0.4.1__tar.gz → 0.5.0b2__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.

Potentially problematic release.


This version of squirrels might be problematic. Click here for more details.

Files changed (100) hide show
  1. squirrels-0.5.0b2/.gitignore +81 -0
  2. {squirrels-0.4.1 → squirrels-0.5.0b2}/LICENSE +1 -1
  3. {squirrels-0.4.1 → squirrels-0.5.0b2}/PKG-INFO +41 -48
  4. {squirrels-0.4.1 → squirrels-0.5.0b2}/README.md +11 -17
  5. squirrels-0.4.1/squirrels/dateutils.py → squirrels-0.5.0b2/dateutils/__init__.py +3 -5
  6. squirrels-0.5.0b2/pyproject.toml +75 -0
  7. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/__init__.py +10 -6
  8. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/_api_response_models.py +93 -44
  9. squirrels-0.5.0b2/squirrels/_api_server.py +904 -0
  10. squirrels-0.5.0b2/squirrels/_auth.py +451 -0
  11. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/_command_line.py +69 -24
  12. squirrels-0.5.0b2/squirrels/_connection_set.py +93 -0
  13. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/_constants.py +44 -34
  14. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/_dashboards_io.py +34 -16
  15. squirrels-0.5.0b2/squirrels/_exceptions.py +57 -0
  16. squirrels-0.5.0b2/squirrels/_initializer.py +313 -0
  17. squirrels-0.5.0b2/squirrels/_manifest.py +279 -0
  18. squirrels-0.5.0b2/squirrels/_model_builder.py +113 -0
  19. squirrels-0.5.0b2/squirrels/_model_configs.py +74 -0
  20. squirrels-0.5.0b2/squirrels/_model_queries.py +52 -0
  21. squirrels-0.5.0b2/squirrels/_models.py +1056 -0
  22. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/_package_loader.py +8 -4
  23. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/_parameter_configs.py +45 -65
  24. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/_parameter_sets.py +15 -13
  25. squirrels-0.5.0b2/squirrels/_project.py +561 -0
  26. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/_py_module.py +4 -3
  27. squirrels-0.5.0b2/squirrels/_seeds.py +58 -0
  28. squirrels-0.5.0b2/squirrels/_sources.py +106 -0
  29. squirrels-0.5.0b2/squirrels/_utils.py +359 -0
  30. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/_version.py +1 -1
  31. squirrels-0.5.0b2/squirrels/arguments/init_time_args.py +103 -0
  32. squirrels-0.5.0b2/squirrels/arguments/run_time_args.py +169 -0
  33. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/dashboards.py +4 -4
  34. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/data_sources.py +94 -162
  35. squirrels-0.5.0b2/squirrels/dataset_result.py +86 -0
  36. squirrels-0.5.0b2/squirrels/package_data/base_project/.env +30 -0
  37. squirrels-0.5.0b2/squirrels/package_data/base_project/.env.example +30 -0
  38. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/package_data/base_project/.gitignore +3 -2
  39. squirrels-0.5.0b2/squirrels/package_data/base_project/assets/expenses.db +0 -0
  40. squirrels-0.5.0b2/squirrels/package_data/base_project/connections.yml +15 -0
  41. squirrels-0.5.0b2/squirrels/package_data/base_project/dashboards/dashboard_example.py +34 -0
  42. squirrels-0.5.0b2/squirrels/package_data/base_project/dashboards/dashboard_example.yml +22 -0
  43. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/package_data/base_project/docker/.dockerignore +5 -2
  44. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/package_data/base_project/docker/Dockerfile +3 -3
  45. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/package_data/base_project/docker/compose.yml +1 -1
  46. squirrels-0.5.0b2/squirrels/package_data/base_project/duckdb_init.sql +9 -0
  47. squirrels-0.5.0b2/squirrels/package_data/base_project/macros/macros_example.sql +15 -0
  48. squirrels-0.5.0b2/squirrels/package_data/base_project/models/builds/build_example.py +26 -0
  49. squirrels-0.5.0b2/squirrels/package_data/base_project/models/builds/build_example.sql +16 -0
  50. squirrels-0.5.0b2/squirrels/package_data/base_project/models/builds/build_example.yml +57 -0
  51. squirrels-0.5.0b2/squirrels/package_data/base_project/models/dbviews/dbview_example.sql +12 -0
  52. squirrels-0.5.0b2/squirrels/package_data/base_project/models/dbviews/dbview_example.yml +26 -0
  53. squirrels-0.5.0b2/squirrels/package_data/base_project/models/federates/federate_example.py +44 -0
  54. squirrels-0.5.0b2/squirrels/package_data/base_project/models/federates/federate_example.sql +17 -0
  55. squirrels-0.5.0b2/squirrels/package_data/base_project/models/federates/federate_example.yml +65 -0
  56. squirrels-0.5.0b2/squirrels/package_data/base_project/models/sources.yml +39 -0
  57. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/package_data/base_project/parameters.yml +36 -21
  58. squirrels-0.5.0b2/squirrels/package_data/base_project/pyconfigs/connections.py +14 -0
  59. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/package_data/base_project/pyconfigs/context.py +20 -33
  60. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/package_data/base_project/pyconfigs/parameters.py +19 -21
  61. squirrels-0.5.0b2/squirrels/package_data/base_project/pyconfigs/user.py +23 -0
  62. squirrels-0.5.0b2/squirrels/package_data/base_project/seeds/seed_categories.yml +15 -0
  63. squirrels-0.5.0b2/squirrels/package_data/base_project/seeds/seed_subcategories.csv +15 -0
  64. squirrels-0.5.0b2/squirrels/package_data/base_project/seeds/seed_subcategories.yml +21 -0
  65. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/package_data/base_project/squirrels.yml.j2 +17 -40
  66. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/parameters.py +20 -20
  67. squirrels-0.4.1/pyproject.toml +0 -54
  68. squirrels-0.4.1/squirrels/_api_server.py +0 -552
  69. squirrels-0.4.1/squirrels/_authenticator.py +0 -85
  70. squirrels-0.4.1/squirrels/_connection_set.py +0 -80
  71. squirrels-0.4.1/squirrels/_environcfg.py +0 -84
  72. squirrels-0.4.1/squirrels/_initializer.py +0 -221
  73. squirrels-0.4.1/squirrels/_manifest.py +0 -217
  74. squirrels-0.4.1/squirrels/_models.py +0 -548
  75. squirrels-0.4.1/squirrels/_seeds.py +0 -39
  76. squirrels-0.4.1/squirrels/_utils.py +0 -256
  77. squirrels-0.4.1/squirrels/arguments/init_time_args.py +0 -40
  78. squirrels-0.4.1/squirrels/arguments/run_time_args.py +0 -208
  79. squirrels-0.4.1/squirrels/package_data/assets/favicon.ico +0 -0
  80. squirrels-0.4.1/squirrels/package_data/assets/index.css +0 -1
  81. squirrels-0.4.1/squirrels/package_data/assets/index.js +0 -58
  82. squirrels-0.4.1/squirrels/package_data/base_project/assets/expenses.db +0 -0
  83. squirrels-0.4.1/squirrels/package_data/base_project/connections.yml +0 -7
  84. squirrels-0.4.1/squirrels/package_data/base_project/dashboards/dashboard_example.py +0 -32
  85. squirrels-0.4.1/squirrels/package_data/base_project/dashboards.yml +0 -10
  86. squirrels-0.4.1/squirrels/package_data/base_project/env.yml +0 -29
  87. squirrels-0.4.1/squirrels/package_data/base_project/models/dbviews/dbview_example.py +0 -47
  88. squirrels-0.4.1/squirrels/package_data/base_project/models/dbviews/dbview_example.sql +0 -22
  89. squirrels-0.4.1/squirrels/package_data/base_project/models/federates/federate_example.py +0 -21
  90. squirrels-0.4.1/squirrels/package_data/base_project/models/federates/federate_example.sql +0 -3
  91. squirrels-0.4.1/squirrels/package_data/base_project/pyconfigs/auth.py +0 -45
  92. squirrels-0.4.1/squirrels/package_data/base_project/pyconfigs/connections.py +0 -19
  93. squirrels-0.4.1/squirrels/package_data/base_project/seeds/seed_subcategories.csv +0 -15
  94. squirrels-0.4.1/squirrels/package_data/templates/index.html +0 -18
  95. squirrels-0.4.1/squirrels/project.py +0 -378
  96. squirrels-0.4.1/squirrels/user_base.py +0 -55
  97. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/package_data/base_project/assets/weather.db +0 -0
  98. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/package_data/base_project/seeds/seed_categories.csv +0 -0
  99. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/package_data/base_project/tmp/.gitignore +0 -0
  100. {squirrels-0.4.1 → squirrels-0.5.0b2}/squirrels/parameter_options.py +0 -0
@@ -0,0 +1,81 @@
1
+ sandbox*
2
+ playground*
3
+ site/
4
+ .venv/
5
+
6
+ # pyenv files
7
+ .python-version
8
+
9
+ # Pipenv files
10
+ Pipfile
11
+ Pipfile.lock
12
+
13
+ ### PythonVanilla ###
14
+ # Byte-compiled / optimized / DLL files
15
+ __pycache__/
16
+ *.py[cod]
17
+ *$py.class
18
+
19
+ # C extensions
20
+ *.so
21
+
22
+ # Distribution / packaging
23
+ .Python
24
+ build/
25
+ develop-eggs/
26
+ dist/
27
+ downloads/
28
+ eggs/
29
+ .eggs/
30
+ lib/
31
+ lib64/
32
+ parts/
33
+ sdist/
34
+ var/
35
+ wheels/
36
+ share/python-wheels/
37
+ *.egg-info/
38
+ .installed.cfg
39
+ *.egg
40
+ MANIFEST
41
+
42
+ # Installer logs
43
+ pip-log.txt
44
+ pip-delete-this-directory.txt
45
+
46
+ # Unit test / coverage reports
47
+ htmlcov/
48
+ .tox/
49
+ .nox/
50
+ .coverage
51
+ .coverage.*
52
+ .cache
53
+ nosetests.xml
54
+ coverage.xml
55
+ *.cover
56
+ *.py,cover
57
+ .hypothesis/
58
+ .pytest_cache/
59
+ cover/
60
+
61
+ # Translations
62
+ *.mo
63
+ *.pot
64
+
65
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
66
+ __pypackages__/
67
+
68
+
69
+ ### VisualStudioCode ###
70
+ .vscode
71
+
72
+ # Local History for Visual Studio Code
73
+ .history/
74
+
75
+ # Built Visual Studio Code Extensions
76
+ *.vsix
77
+
78
+ ### VisualStudioCode Patch ###
79
+ # Ignore all local history of files
80
+ .history
81
+ .ionide
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright 2024 Tim Huang
189
+ Copyright 2025 Tim Huang
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
@@ -1,39 +1,39 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: squirrels
3
- Version: 0.4.1
3
+ Version: 0.5.0b2
4
4
  Summary: Squirrels - API Framework for Data Analytics
5
- Home-page: https://squirrels-analytics.github.io
6
- License: Apache-2.0
7
- Author: Tim Huang
8
- Author-email: tim.yuting@hotmail.com
9
- Requires-Python: >=3.10,<4.0
5
+ Project-URL: Homepage, https://squirrels-analytics.github.io
6
+ Project-URL: Repository, https://github.com/squirrels-analytics/squirrels
7
+ Project-URL: Documentation, https://squirrels-analytics.github.io
8
+ Author-email: Tim Huang <tim.yuting@hotmail.com>
9
+ License-Expression: Apache-2.0
10
+ License-File: LICENSE
10
11
  Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: Apache Software License
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.10
14
- Classifier: Programming Language :: Python :: 3.11
15
- Classifier: Programming Language :: Python :: 3.12
16
12
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
17
13
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
14
  Classifier: Typing :: Typed
19
- Provides-Extra: duckdb
20
- Requires-Dist: cachetools (>=5.3.2,<6.0.0)
21
- Requires-Dist: duckdb-engine (>=0.13.0,<1.0.0) ; extra == "duckdb"
22
- Requires-Dist: fastapi (>=0.112.1,<0.113.0)
23
- Requires-Dist: gitpython (>=3.1.41,<4.0.0)
24
- Requires-Dist: inquirer (>=3.2.1,<4.0.0)
25
- Requires-Dist: jinja2 (>=3.1.3,<4.0.0)
26
- Requires-Dist: matplotlib (>=3.8.3,<4.0.0)
27
- Requires-Dist: networkx (>=3.2.1,<4.0.0)
28
- Requires-Dist: pandas (>=2.1.4,<3.0.0)
29
- Requires-Dist: pydantic (>=2.8.2,<3.0.0)
30
- Requires-Dist: pyjwt (>=2.8.0,<3.0.0)
31
- Requires-Dist: python-multipart (>=0.0.9,<0.0.10)
32
- Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
33
- Requires-Dist: sqlalchemy (>=2.0.25,<3.0.0)
34
- Requires-Dist: uvicorn (>=0.30.6,<0.31.0)
35
- Project-URL: Documentation, https://squirrels-analytics.github.io
36
- Project-URL: Repository, https://github.com/squirrels-analytics/squirrels
15
+ Requires-Python: ~=3.10
16
+ Requires-Dist: bcrypt<5,>=4.0.1
17
+ Requires-Dist: cachetools<6,>=5.3.2
18
+ Requires-Dist: duckdb<2,>=1.1.3
19
+ Requires-Dist: fastapi<1,>=0.112.1
20
+ Requires-Dist: gitpython<4,>=3.1.41
21
+ Requires-Dist: inquirer<4,>=3.2.1
22
+ Requires-Dist: jinja2<4,>=3.1.3
23
+ Requires-Dist: libpass<2,>=1.9.0
24
+ Requires-Dist: matplotlib<4,>=3.8.3
25
+ Requires-Dist: networkx<4,>=3.2.1
26
+ Requires-Dist: pandas<3,>=2.1.4
27
+ Requires-Dist: polars<2,>=1.14.0
28
+ Requires-Dist: pyarrow>=19.0.1
29
+ Requires-Dist: pydantic<3,>=2.8.2
30
+ Requires-Dist: pyjwt<3,>=2.8.0
31
+ Requires-Dist: python-dotenv<2,>=1.0.1
32
+ Requires-Dist: python-multipart<1,>=0.0.9
33
+ Requires-Dist: pyyaml<7,>=6.0.1
34
+ Requires-Dist: sqlalchemy<3,>=2.0.25
35
+ Requires-Dist: sqlglot>=26.12.1
36
+ Requires-Dist: uvicorn<1,>=0.30.6
37
37
  Description-Content-Type: text/markdown
38
38
 
39
39
  # Squirrels
@@ -60,10 +60,10 @@ Here are a few of the things that squirrels can do:
60
60
  - Connect to any database by specifying its SQLAlchemy url (in `squirrels.yml`) or by using its native connector library in python (in `connections.py`).
61
61
  - Configure API routes for datasets (in `squirrels.yml`) without writing code.
62
62
  - Configure parameter widgets (types include single-select, multi-select, date, number, etc.) for your datasets (in `parameters.py`).
63
- - Use Jinja SQL templates (just like dbt!) or python functions (that return a pandas dataframe) to define dynamic query logic based on parameter selections.
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 an interactive UI or by a command line that generates rendered sql queries and results (for a given set of parameter selections).
66
- - Define authentication logic (in `auth.py`) and authorize privacy scope per dataset (in `squirrels.yml`). The user's attributes can even be used in your query logic!
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 build tool `poetry`. Information on setting up poetry can be found at: https://python-poetry.org/docs/.
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
- poetry install
84
+ ```bash
85
+ uv sync
86
86
  ```
87
87
 
88
- And activate the virtual environment created by poetry with:
88
+ And activate the virtual environment with:
89
89
 
90
- ```
91
- poetry shell
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
- In poetry's virtual environment, run `pytest`.
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,8 +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.
117
-
@@ -22,10 +22,10 @@ Here are a few of the things that squirrels can do:
22
22
  - Connect to any database by specifying its SQLAlchemy url (in `squirrels.yml`) or by using its native connector library in python (in `connections.py`).
23
23
  - Configure API routes for datasets (in `squirrels.yml`) without writing code.
24
24
  - Configure parameter widgets (types include single-select, multi-select, date, number, etc.) for your datasets (in `parameters.py`).
25
- - Use Jinja SQL templates (just like dbt!) or python functions (that return a pandas dataframe) to define dynamic query logic based on parameter selections.
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 an interactive UI or by a command line that generates rendered sql queries and results (for a given set of parameter selections).
28
- - Define authentication logic (in `auth.py`) and authorize privacy scope per dataset (in `squirrels.yml`). The user's attributes can even be used in your query logic!
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 build tool `poetry`. Information on setting up poetry can be found at: https://python-poetry.org/docs/.
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
- poetry install
46
+ ```bash
47
+ uv sync
48
48
  ```
49
49
 
50
- And activate the virtual environment created by poetry with:
50
+ And activate the virtual environment with:
51
51
 
52
- ```
53
- poetry shell
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
- In poetry's virtual environment, run `pytest`.
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.
@@ -5,8 +5,6 @@ from dateutil.relativedelta import relativedelta
5
5
  from abc import ABCMeta, abstractmethod
6
6
  from enum import Enum
7
7
 
8
- from . import _utils as _u
9
-
10
8
 
11
9
  class DayOfWeek(Enum):
12
10
  Sunday = 0
@@ -62,7 +60,7 @@ class _DayIdxOfCalendarUnit(DateModifier):
62
60
  super().__init__()
63
61
  self.idx = idx
64
62
  if self.idx == 0:
65
- raise _u.ConfigurationError(f"For constructors of class names that start with DayIdxOf_, idx cannot be zero")
63
+ raise ValueError(f"For constructors of class names that start with DayIdxOf_, idx cannot be zero")
66
64
  self.incr = self.idx - 1 if self.idx > 0 else self.idx
67
65
 
68
66
 
@@ -84,7 +82,7 @@ class DayIdxOfMonthsCycle(_DayIdxOfCalendarUnit):
84
82
  self._num_months_in_cycle = num_months_in_cycle
85
83
  self._first_month_of_cycle = first_month_of_cycle
86
84
  if 12 % self._num_months_in_cycle != 0:
87
- raise _u.ConfigurationError(f"Value X must fit evenly in 12")
85
+ raise ValueError(f"Value X must fit evenly in 12")
88
86
  self.first_month_of_first_cycle = (self._first_month_of_cycle.value - 1) % self._num_months_in_cycle + 1
89
87
 
90
88
  def modify(self, date: Date) -> Date:
@@ -302,7 +300,7 @@ class DateModPipeline(DateModifier):
302
300
  """
303
301
  assert isinstance(step, _OffsetUnits)
304
302
  if step.offset == 0:
305
- raise _u.ConfigurationError(f"The length of 'step' must not be zero")
303
+ raise ValueError(f"The length of 'step' must not be zero")
306
304
 
307
305
  output: Sequence[Date] = []
308
306
  end_date = self.modify(start_date)
@@ -0,0 +1,75 @@
1
+ [project]
2
+ name = "squirrels"
3
+ version = "0.5.0b2"
4
+ description = "Squirrels - API Framework for Data Analytics"
5
+ authors = [{ name = "Tim Huang", email = "tim.yuting@hotmail.com" }]
6
+ requires-python = "~=3.10"
7
+ readme = "README.md"
8
+ license = "Apache-2.0"
9
+ classifiers = [
10
+ "Intended Audience :: Developers",
11
+ "Topic :: Software Development :: Libraries :: Application Frameworks",
12
+ "Topic :: Software Development :: Libraries :: Python Modules",
13
+ "Typing :: Typed",
14
+ ]
15
+ dependencies = [
16
+ "cachetools>=5.3.2,<6",
17
+ "fastapi>=0.112.1,<1",
18
+ "gitpython>=3.1.41,<4",
19
+ "inquirer>=3.2.1,<4",
20
+ "jinja2>=3.1.3,<4",
21
+ "matplotlib>=3.8.3,<4",
22
+ "networkx>=3.2.1,<4",
23
+ "pandas>=2.1.4,<3",
24
+ "pydantic>=2.8.2,<3",
25
+ "pyjwt>=2.8.0,<3",
26
+ "python-multipart>=0.0.9,<1",
27
+ "pyyaml>=6.0.1,<7",
28
+ "sqlalchemy>=2.0.25,<3",
29
+ "uvicorn>=0.30.6,<1",
30
+ "polars>=1.14.0,<2",
31
+ "pyarrow>=19.0.1",
32
+ "duckdb>=1.1.3,<2",
33
+ "sqlglot>=26.12.1",
34
+ "bcrypt>=4.0.1,<5",
35
+ "python-dotenv>=1.0.1,<2",
36
+ "libpass>=1.9.0,<2",
37
+ ]
38
+
39
+ [project.urls]
40
+ Homepage = "https://squirrels-analytics.github.io"
41
+ Repository = "https://github.com/squirrels-analytics/squirrels"
42
+ Documentation = "https://squirrels-analytics.github.io"
43
+
44
+ [project.scripts]
45
+ squirrels = "squirrels._command_line:main"
46
+ sqrl = "squirrels._command_line:main"
47
+
48
+ [dependency-groups]
49
+ test = ["pytest>=7.4.4,<8"]
50
+ dev = [
51
+ "ipykernel>=6.29.4,<7",
52
+ "plotly>=5.24.0,<6",
53
+ "psycopg2-binary>=2.9.10,<3",
54
+ "adbc-driver-postgresql>=1.3.0,<2",
55
+ "adbc-driver-sqlite>=1.3.0,<2",
56
+ "connectorx>=0.4.0,<0.5",
57
+ "faker>=33.1.0,<34",
58
+ "tqdm>=4.67.1,<5",
59
+ ]
60
+
61
+ [tool.hatch.build.targets.sdist]
62
+ include = ["squirrels", "dateutils"]
63
+
64
+ [tool.hatch.build.targets.wheel]
65
+ include = ["squirrels", "dateutils"]
66
+
67
+ [tool.uv]
68
+ default-groups = [
69
+ "test",
70
+ "dev",
71
+ ]
72
+
73
+ [build-system]
74
+ requires = ["hatchling"]
75
+ build-backend = "hatchling.build"
@@ -1,7 +1,7 @@
1
1
  from ._version import __version__
2
2
 
3
- from .arguments.init_time_args import ConnectionsArgs, ParametersArgs
4
- from .arguments.run_time_args import AuthArgs, ContextArgs, ModelDepsArgs, ModelArgs, DashboardArgs
3
+ from .arguments.init_time_args import ConnectionsArgs, ParametersArgs, BuildModelArgs
4
+ from .arguments.run_time_args import AuthLoginArgs, AuthTokenArgs, ContextArgs, ModelArgs, DashboardArgs
5
5
 
6
6
  from .parameter_options import SelectParameterOption, DateParameterOption, DateRangeParameterOption
7
7
  from .parameter_options import NumberParameterOption, NumberRangeParameterOption, TextParameterOption
@@ -9,11 +9,15 @@ from .parameter_options import NumberParameterOption, NumberRangeParameterOption
9
9
  from .parameters import SingleSelectParameter, MultiSelectParameter, DateParameter, DateRangeParameter
10
10
  from .parameters import NumberParameter, NumberRangeParameter, TextParameter, TextValue
11
11
 
12
- from .data_sources import SingleSelectDataSource, MultiSelectDataSource, SelectDataSource, DateDataSource, DateRangeDataSource
12
+ from .data_sources import SelectDataSource, DateDataSource, DateRangeDataSource
13
13
  from .data_sources import NumberDataSource, NumberRangeDataSource, TextDataSource
14
14
 
15
- from .user_base import User, WrongPassword
16
-
17
15
  from .dashboards import PngDashboard, HtmlDashboard
18
16
 
19
- from .project import SquirrelsProject
17
+ from ._auth import BaseUser
18
+
19
+ from ._manifest import ConnectionProperties, ConnectionType
20
+
21
+ from ._project import SquirrelsProject
22
+
23
+ from .dataset_result import DatasetResult
@@ -1,43 +1,18 @@
1
- from typing import Annotated
1
+ from typing import Annotated, Literal
2
2
  from pydantic import BaseModel, Field
3
3
  from datetime import datetime, date
4
4
 
5
+ from . import _model_configs as mc, _sources as s
6
+
5
7
 
6
8
  class LoginReponse(BaseModel):
7
9
  access_token: Annotated[str, Field(examples=["encoded_jwt_token"], description="An encoded JSON web token to use subsequent API requests")]
8
10
  token_type: Annotated[str, Field(examples=["bearer"], description='Always "bearer" for Bearer token')]
9
11
  username: Annotated[str, Field(examples=["johndoe"], description='The username authenticated with from the form data')]
12
+ is_admin: Annotated[bool, Field(examples=[False], description="A boolean for whether the user is an admin")]
10
13
  expiry_time: Annotated[datetime, Field(examples=["2023-08-01T12:00:00.000000Z"], description="The expiry time of the access token in yyyy-MM-dd'T'hh:mm:ss.SSSSSS'Z' format")]
11
14
 
12
15
 
13
- ## Datasets / Dashboards Catalog Response Models
14
-
15
- name_description = "The name of the dataset / dashboard (usually in snake case)"
16
- label_description = "The human-friendly display name for the dataset / dashboard"
17
- description_description = "The description of the dataset / dashboard"
18
- parameters_path_description = "The API path to the parameters for the dataset / dashboard"
19
- result_path_description = "The API path to the results for the dataset / dashboard"
20
-
21
- class DatasetItemModel(BaseModel):
22
- name: Annotated[str, Field(examples=["mydataset"], description=name_description)]
23
- label: Annotated[str, Field(examples=["My Dataset"], description=label_description)]
24
- description: Annotated[str, Field(examples=[""], description=description_description)]
25
- parameters_path: Annotated[str, Field(examples=["/squirrels-v0/myproject/v1/dataset/mydataset/parameters"], description=parameters_path_description)]
26
- result_path: Annotated[str, Field(examples=["/squirrels-v0/myproject/v1/dataset/mydataset"], description=result_path_description)]
27
-
28
- class DashboardItemModel(BaseModel):
29
- name: Annotated[str, Field(examples=["mydashboard"], description=name_description)]
30
- label: Annotated[str, Field(examples=["My Dashboard"], description=label_description)]
31
- description: Annotated[str, Field(examples=[""], description=description_description)]
32
- parameters_path: Annotated[str, Field(examples=["/squirrels-v0/myproject/v1/dashboard/mydashboard/parameters"], description=parameters_path_description)]
33
- result_path: Annotated[str, Field(examples=["/squirrels-v0/myproject/v1/dashboard/mydashboard"], description=result_path_description)]
34
- result_format: Annotated[str, Field(examples=["png", "html"], description="The format of the dashboard's result API response (one of 'png' or 'html')")]
35
-
36
- class CatalogModel(BaseModel):
37
- datasets: Annotated[list[DatasetItemModel], Field(description="The list of accessible datasets")]
38
- dashboards: Annotated[list[DashboardItemModel], Field(description="The list of accessible dashboards")]
39
-
40
-
41
16
  ## Parameters Response Models
42
17
 
43
18
  class ParameterOptionModel(BaseModel):
@@ -45,7 +20,7 @@ class ParameterOptionModel(BaseModel):
45
20
  label: Annotated[str, Field(examples=["My Option"], description="The human-friendly display name for the option")]
46
21
 
47
22
  class ParameterModelBase(BaseModel):
48
- widget_type: Annotated[str, Field(examples=["none"], description="The parameter type (set to 'none' for this model)")]
23
+ widget_type: Annotated[str, Field(examples=["disabled"], description="The parameter type")]
49
24
  name: Annotated[str, Field(examples=["my_unique_param_name"], description="The name of the parameter. Use this as the key when providing the API request parameters")]
50
25
  label: Annotated[str, Field(examples=["My Parameter"], description="The human-friendly display name for the parameter")]
51
26
  description: Annotated[str, Field(examples=[""], description="The description of the parameter")]
@@ -102,27 +77,101 @@ class TextParameterModel(ParameterModelBase):
102
77
  description='A string for the input type (one of "text", "textarea", "number", "date", "datetime-local", "month", "time", "color", or "password")'
103
78
  )]
104
79
 
80
+ ParametersListType = list[
81
+ NoneParameterModel | SingleSelectParameterModel | MultiSelectParameterModel | DateParameterModel | DateRangeParameterModel |
82
+ NumberParameterModel | NumberRangeParameterModel | TextParameterModel
83
+ ]
84
+
105
85
  class ParametersModel(BaseModel):
106
- parameters: list[
107
- NoneParameterModel | SingleSelectParameterModel | MultiSelectParameterModel | DateParameterModel | DateRangeParameterModel |
108
- NumberParameterModel | NumberRangeParameterModel | TextParameterModel
109
- ]
86
+ parameters: Annotated[ParametersListType, Field(description="The list of parameters for the dataset / dashboard")]
110
87
 
111
88
 
112
- ## Dataset Results Response Models
89
+ ## Datasets / Dashboards Catalog Response Models
90
+
91
+ name_description = "The name of the dataset / dashboard (usually in snake case)"
92
+ label_description = "The human-friendly display name for the dataset / dashboard"
93
+ description_description = "The description of the dataset / dashboard"
94
+ parameters_path_description = "The API path to the parameters for the dataset / dashboard"
95
+ metadata_path_description = "The API path to the metadata (i.e., description and schema) for the dataset"
96
+ result_path_description = "The API path to the results for the dataset / dashboard"
113
97
 
114
98
  class ColumnModel(BaseModel):
115
99
  name: Annotated[str, Field(examples=["mycol"], description="Name of column")]
116
- type: Annotated[str, Field(examples=["string", "number", "integer", "boolean", "datetime"], description='Column type. One of "string", "number", "integer", "boolean", and "datetime"')]
100
+ type: Annotated[str, Field(examples=["string", "integer", "boolean", "datetime"], description='Column type (such as "string", "integer", "boolean", "datetime", etc.)')]
101
+ description: Annotated[str, Field(examples=["My column description"], description="The description of the column")]
102
+ category: Annotated[str, Field(examples=["dimension", "measure", "misc"], description="The category of the column (such as 'dimension', 'measure', or 'misc')")]
103
+
104
+ class ColumnWithConditionModel(ColumnModel):
105
+ condition: Annotated[str | None, Field(None, examples=["My condition"], description="The condition of when the column is included (such as based on a parameter selection)")]
117
106
 
118
107
  class SchemaModel(BaseModel):
119
108
  fields: Annotated[list[ColumnModel], Field(description="A list of JSON objects containing the 'name' and 'type' for each of the columns in the result")]
120
- dimensions: Annotated[list[str], Field(examples=[["mycol"]], description="A list of column names that are dimensions")]
109
+
110
+ class SchemaWithConditionModel(BaseModel):
111
+ fields: Annotated[list[ColumnWithConditionModel], Field(description="A list of JSON objects containing the 'name' and 'type' for each of the columns in the result")]
112
+
113
+ class DatasetItemModel(BaseModel):
114
+ name: Annotated[str, Field(examples=["mydataset"], description=name_description)]
115
+ label: Annotated[str, Field(examples=["My Dataset"], description=label_description)]
116
+ description: Annotated[str, Field(examples=[""], description=description_description)]
117
+ parameters: Annotated[list[str], Field(examples=["myparam1", "myparam2"], description="The list of parameter names used by the dataset")]
118
+ data_schema: Annotated[SchemaWithConditionModel, Field(alias="schema", description="JSON object describing the schema of the dataset")]
119
+ parameters_path: Annotated[str, Field(examples=["/squirrels-v0/myproject/v1/dataset/mydataset/parameters"], description=parameters_path_description)]
120
+ result_path: Annotated[str, Field(examples=["/squirrels-v0/myproject/v1/dataset/mydataset"], description=result_path_description)]
121
+
122
+ class DashboardItemModel(ParametersModel):
123
+ name: Annotated[str, Field(examples=["mydashboard"], description=name_description)]
124
+ label: Annotated[str, Field(examples=["My Dashboard"], description=label_description)]
125
+ description: Annotated[str, Field(examples=[""], description=description_description)]
126
+ parameters: Annotated[list[str], Field(examples=["myparam1", "myparam2"], description="The list of parameter names used by the dashboard")]
127
+ parameters_path: Annotated[str, Field(examples=["/squirrels-v0/myproject/v1/dashboard/mydashboard/parameters"], description=parameters_path_description)]
128
+ result_path: Annotated[str, Field(examples=["/squirrels-v0/myproject/v1/dashboard/mydashboard"], description=result_path_description)]
129
+ result_format: Annotated[str, Field(examples=["png", "html"], description="The format of the dashboard's result API response (one of 'png' or 'html')")]
130
+
131
+ ModelConfigType = mc.ModelConfig | s.Source | mc.SeedConfig | mc.BuildModelConfig | mc.DbviewModelConfig | mc.FederateModelConfig
132
+
133
+ class ConnectionItemModel(BaseModel):
134
+ name: Annotated[str, Field(examples=["myconnection"], description="The name of the connection")]
135
+ label: Annotated[str, Field(examples=["My Connection"], description="The human-friendly display name for the connection")]
136
+
137
+ class DataModelItem(BaseModel):
138
+ name: Annotated[str, Field(examples=["model_name"], description="The name of the model")]
139
+ model_type: Annotated[Literal["source", "dbview", "federate", "seed", "build"], Field(
140
+ examples=["source", "dbview", "federate", "seed", "build"], description="The type of the model"
141
+ )]
142
+ config: Annotated[ModelConfigType, Field(description="The configuration of the model")]
143
+ is_queryable: Annotated[bool, Field(examples=[True], description="Whether the model is queryable")]
144
+
145
+ class LineageNode(BaseModel):
146
+ name: str
147
+ type: Literal["model", "dataset", "dashboard"]
148
+
149
+ class LineageRelation(BaseModel):
150
+ type: Literal["buildtime", "runtime"]
151
+ source: LineageNode
152
+ target: LineageNode
153
+
154
+ class CatalogModel(BaseModel):
155
+ parameters: Annotated[ParametersListType, Field(description="The list of all parameters in the project")]
156
+ datasets: Annotated[list[DatasetItemModel], Field(description="The list of accessible datasets")]
157
+ dashboards: Annotated[list[DashboardItemModel], Field(description="The list of accessible dashboards")]
158
+ connections: Annotated[list[ConnectionItemModel], Field(description="The list of connections in the project (only provided for admin users)")]
159
+ models: Annotated[list[DataModelItem], Field(description="The list of data models in the project (only provided for admin users)")]
160
+ lineage: Annotated[list[LineageRelation], Field(description="The lineage information between data assets (only provided for admin users)")]
161
+
162
+
163
+ ## Dataset Results Response Models
164
+
165
+ class DataDetailsModel(BaseModel):
166
+ num_rows: Annotated[int, Field(examples=[2], description="The number of rows in the data field")]
167
+ orientation: Annotated[Literal["records", "rows", "columns"], Field(examples=["records", "rows", "columns"], description="The orientation of the data field")]
121
168
 
122
169
  class DatasetResultModel(BaseModel):
123
170
  data_schema: Annotated[SchemaModel, Field(alias="schema", description="JSON object describing the schema of the dataset")]
124
- data: Annotated[list[dict], Field(
125
- examples=[[{"mycol": "myval"}]],
171
+ total_num_rows: Annotated[int, Field(examples=[2], description="The total number of rows for the dataset")]
172
+ data_details: Annotated[DataDetailsModel, Field(description="A JSON object containing the details of the data field")]
173
+ data: Annotated[list[dict] | list[list] | dict[str, list], Field(
174
+ examples=[[{"mycol": "col_value1"}, {"mycol": "col_value2"}], [["col_value1"], ["col_value2"]], {"mycol": ["col_value1", "col_value2"]}],
126
175
  description="A list of JSON objects where each object is a row of the tabular results. The keys and values of the object are column names (described in fields) and values of the row."
127
176
  )]
128
177
 
@@ -130,12 +179,12 @@ class DatasetResultModel(BaseModel):
130
179
  ## Project Metadata Response Models
131
180
 
132
181
  class ProjectVersionModel(BaseModel):
133
- major_version: int
134
- minor_versions: list[int]
135
- token_path: Annotated[str, Field(examples=["/squirrels-v0/myproject/v1/token"])]
136
- data_catalog_path: Annotated[str, Field(examples=["/squirrels-v0/myproject/v1/datasets"])]
182
+ major_version: Annotated[int, Field(examples=[1])]
183
+ data_catalog_path: Annotated[str, Field(examples=["/squirrels-v0/project/myproject/v1/data-catalog"])]
137
184
 
138
185
  class ProjectModel(BaseModel):
139
186
  name: Annotated[str, Field(examples=["myproject"])]
187
+ version: Annotated[str, Field(examples=["v1"])]
140
188
  label: Annotated[str, Field(examples=["My Project"])]
141
- versions: list[ProjectVersionModel]
189
+ description: Annotated[str, Field(examples=["My project description"])]
190
+ squirrels_version: Annotated[str, Field(examples=["0.1.0"])]