squirrels 0.4.0__py3-none-any.whl → 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (125) hide show
  1. dateutils/__init__.py +6 -0
  2. dateutils/_enums.py +25 -0
  3. squirrels/dateutils.py → dateutils/_implementation.py +58 -111
  4. dateutils/types.py +6 -0
  5. squirrels/__init__.py +13 -11
  6. squirrels/_api_routes/__init__.py +5 -0
  7. squirrels/_api_routes/auth.py +271 -0
  8. squirrels/_api_routes/base.py +165 -0
  9. squirrels/_api_routes/dashboards.py +150 -0
  10. squirrels/_api_routes/data_management.py +145 -0
  11. squirrels/_api_routes/datasets.py +257 -0
  12. squirrels/_api_routes/oauth2.py +298 -0
  13. squirrels/_api_routes/project.py +252 -0
  14. squirrels/_api_server.py +256 -450
  15. squirrels/_arguments/__init__.py +0 -0
  16. squirrels/_arguments/init_time_args.py +108 -0
  17. squirrels/_arguments/run_time_args.py +147 -0
  18. squirrels/_auth.py +960 -0
  19. squirrels/_command_line.py +126 -45
  20. squirrels/_compile_prompts.py +147 -0
  21. squirrels/_connection_set.py +48 -26
  22. squirrels/_constants.py +68 -38
  23. squirrels/_dashboards.py +160 -0
  24. squirrels/_data_sources.py +570 -0
  25. squirrels/_dataset_types.py +84 -0
  26. squirrels/_exceptions.py +29 -0
  27. squirrels/_initializer.py +177 -80
  28. squirrels/_logging.py +115 -0
  29. squirrels/_manifest.py +208 -79
  30. squirrels/_model_builder.py +69 -0
  31. squirrels/_model_configs.py +74 -0
  32. squirrels/_model_queries.py +52 -0
  33. squirrels/_models.py +926 -367
  34. squirrels/_package_data/base_project/.env +42 -0
  35. squirrels/_package_data/base_project/.env.example +42 -0
  36. squirrels/_package_data/base_project/assets/expenses.db +0 -0
  37. squirrels/_package_data/base_project/connections.yml +16 -0
  38. squirrels/_package_data/base_project/dashboards/dashboard_example.py +34 -0
  39. squirrels/_package_data/base_project/dashboards/dashboard_example.yml +22 -0
  40. squirrels/{package_data → _package_data}/base_project/docker/.dockerignore +5 -2
  41. squirrels/{package_data → _package_data}/base_project/docker/Dockerfile +3 -3
  42. squirrels/{package_data → _package_data}/base_project/docker/compose.yml +1 -1
  43. squirrels/_package_data/base_project/duckdb_init.sql +10 -0
  44. squirrels/{package_data/base_project/.gitignore → _package_data/base_project/gitignore} +3 -2
  45. squirrels/_package_data/base_project/macros/macros_example.sql +17 -0
  46. squirrels/_package_data/base_project/models/builds/build_example.py +26 -0
  47. squirrels/_package_data/base_project/models/builds/build_example.sql +16 -0
  48. squirrels/_package_data/base_project/models/builds/build_example.yml +57 -0
  49. squirrels/_package_data/base_project/models/dbviews/dbview_example.sql +12 -0
  50. squirrels/_package_data/base_project/models/dbviews/dbview_example.yml +26 -0
  51. squirrels/_package_data/base_project/models/federates/federate_example.py +37 -0
  52. squirrels/_package_data/base_project/models/federates/federate_example.sql +19 -0
  53. squirrels/_package_data/base_project/models/federates/federate_example.yml +65 -0
  54. squirrels/_package_data/base_project/models/sources.yml +38 -0
  55. squirrels/{package_data → _package_data}/base_project/parameters.yml +56 -40
  56. squirrels/_package_data/base_project/pyconfigs/connections.py +14 -0
  57. squirrels/{package_data → _package_data}/base_project/pyconfigs/context.py +21 -40
  58. squirrels/_package_data/base_project/pyconfigs/parameters.py +141 -0
  59. squirrels/_package_data/base_project/pyconfigs/user.py +44 -0
  60. squirrels/_package_data/base_project/seeds/seed_categories.yml +15 -0
  61. squirrels/_package_data/base_project/seeds/seed_subcategories.csv +15 -0
  62. squirrels/_package_data/base_project/seeds/seed_subcategories.yml +21 -0
  63. squirrels/_package_data/base_project/squirrels.yml.j2 +61 -0
  64. squirrels/_package_data/templates/dataset_results.html +112 -0
  65. squirrels/_package_data/templates/oauth_login.html +271 -0
  66. squirrels/_package_data/templates/squirrels_studio.html +20 -0
  67. squirrels/_package_loader.py +8 -4
  68. squirrels/_parameter_configs.py +104 -103
  69. squirrels/_parameter_options.py +348 -0
  70. squirrels/_parameter_sets.py +57 -47
  71. squirrels/_parameters.py +1664 -0
  72. squirrels/_project.py +721 -0
  73. squirrels/_py_module.py +7 -5
  74. squirrels/_schemas/__init__.py +0 -0
  75. squirrels/_schemas/auth_models.py +167 -0
  76. squirrels/_schemas/query_param_models.py +75 -0
  77. squirrels/{_api_response_models.py → _schemas/response_models.py} +126 -47
  78. squirrels/_seeds.py +35 -16
  79. squirrels/_sources.py +110 -0
  80. squirrels/_utils.py +248 -73
  81. squirrels/_version.py +1 -1
  82. squirrels/arguments.py +7 -0
  83. squirrels/auth.py +4 -0
  84. squirrels/connections.py +3 -0
  85. squirrels/dashboards.py +2 -81
  86. squirrels/data_sources.py +14 -631
  87. squirrels/parameter_options.py +13 -348
  88. squirrels/parameters.py +14 -1266
  89. squirrels/types.py +16 -0
  90. squirrels-0.5.0.dist-info/METADATA +113 -0
  91. squirrels-0.5.0.dist-info/RECORD +97 -0
  92. {squirrels-0.4.0.dist-info → squirrels-0.5.0.dist-info}/WHEEL +1 -1
  93. squirrels-0.5.0.dist-info/entry_points.txt +3 -0
  94. {squirrels-0.4.0.dist-info → squirrels-0.5.0.dist-info/licenses}/LICENSE +1 -1
  95. squirrels/_authenticator.py +0 -85
  96. squirrels/_dashboards_io.py +0 -61
  97. squirrels/_environcfg.py +0 -84
  98. squirrels/arguments/init_time_args.py +0 -40
  99. squirrels/arguments/run_time_args.py +0 -208
  100. squirrels/package_data/assets/favicon.ico +0 -0
  101. squirrels/package_data/assets/index.css +0 -1
  102. squirrels/package_data/assets/index.js +0 -58
  103. squirrels/package_data/base_project/assets/expenses.db +0 -0
  104. squirrels/package_data/base_project/connections.yml +0 -7
  105. squirrels/package_data/base_project/dashboards/dashboard_example.py +0 -32
  106. squirrels/package_data/base_project/dashboards.yml +0 -10
  107. squirrels/package_data/base_project/env.yml +0 -29
  108. squirrels/package_data/base_project/models/dbviews/dbview_example.py +0 -47
  109. squirrels/package_data/base_project/models/dbviews/dbview_example.sql +0 -22
  110. squirrels/package_data/base_project/models/federates/federate_example.py +0 -21
  111. squirrels/package_data/base_project/models/federates/federate_example.sql +0 -3
  112. squirrels/package_data/base_project/pyconfigs/auth.py +0 -45
  113. squirrels/package_data/base_project/pyconfigs/connections.py +0 -19
  114. squirrels/package_data/base_project/pyconfigs/parameters.py +0 -95
  115. squirrels/package_data/base_project/seeds/seed_subcategories.csv +0 -15
  116. squirrels/package_data/base_project/squirrels.yml.j2 +0 -94
  117. squirrels/package_data/templates/index.html +0 -18
  118. squirrels/project.py +0 -378
  119. squirrels/user_base.py +0 -55
  120. squirrels-0.4.0.dist-info/METADATA +0 -117
  121. squirrels-0.4.0.dist-info/RECORD +0 -60
  122. squirrels-0.4.0.dist-info/entry_points.txt +0 -4
  123. /squirrels/{package_data → _package_data}/base_project/assets/weather.db +0 -0
  124. /squirrels/{package_data → _package_data}/base_project/seeds/seed_categories.csv +0 -0
  125. /squirrels/{package_data → _package_data}/base_project/tmp/.gitignore +0 -0
@@ -0,0 +1,112 @@
1
+ <style>
2
+ .dataset-results {
3
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
4
+ background: white;
5
+ border-radius: 8px;
6
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
7
+ overflow: hidden;
8
+ max-width: 100%;
9
+ }
10
+
11
+ .dataset-results .table-container {
12
+ overflow: auto;
13
+ max-height: 400px;
14
+ background: white;
15
+ }
16
+
17
+ .dataset-results .data-table {
18
+ width: 100%;
19
+ border-collapse: collapse;
20
+ font-size: 13px;
21
+ }
22
+
23
+ .dataset-results .data-table thead {
24
+ background: #f8f9fa;
25
+ position: sticky;
26
+ top: 0;
27
+ z-index: 10;
28
+ }
29
+
30
+ .dataset-results .data-table th {
31
+ padding: 8px 12px;
32
+ text-align: left;
33
+ font-weight: 600;
34
+ color: #374151;
35
+ border-bottom: 2px solid #e1e5e9;
36
+ white-space: nowrap;
37
+ font-size: 12px;
38
+ }
39
+
40
+ .dataset-results .data-table th .column-type {
41
+ display: block;
42
+ font-size: 10px;
43
+ color: #6b7280;
44
+ font-weight: 400;
45
+ margin-top: 1px;
46
+ }
47
+
48
+ .dataset-results .data-table td {
49
+ padding: 8px 12px;
50
+ border-bottom: 1px solid #f3f4f6;
51
+ color: #374151;
52
+ vertical-align: top;
53
+ font-size: 12px;
54
+ }
55
+
56
+ .dataset-results .data-table tbody tr:hover {
57
+ background: #f8f9fa;
58
+ }
59
+
60
+ .dataset-results .data-table tbody tr:nth-child(even) {
61
+ background: #fafbfc;
62
+ }
63
+
64
+ .dataset-results .data-table tbody tr:nth-child(even):hover {
65
+ background: #f1f3f4;
66
+ }
67
+
68
+ .dataset-results .empty-state {
69
+ text-align: center;
70
+ padding: 40px 20px;
71
+ color: #6b7280;
72
+ }
73
+
74
+ .dataset-results .empty-state h3 {
75
+ font-size: 16px;
76
+ margin-bottom: 6px;
77
+ color: #374151;
78
+ }
79
+ </style>
80
+
81
+ <div class="dataset-results">
82
+ {% if schema.fields and data %}
83
+ <div class="table-container">
84
+ <table class="data-table">
85
+ <thead>
86
+ <tr>
87
+ {% for field in schema.fields %}
88
+ <th>
89
+ {{ field.name }}
90
+ <span class="column-type">{{ field.type | upper }}</span>
91
+ </th>
92
+ {% endfor %}
93
+ </tr>
94
+ </thead>
95
+ <tbody>
96
+ {% for row in data %}
97
+ <tr>
98
+ {% for cell in row %}
99
+ <td>{{ cell if cell is not none else '' }}</td>
100
+ {% endfor %}
101
+ </tr>
102
+ {% endfor %}
103
+ </tbody>
104
+ </table>
105
+ </div>
106
+ {% else %}
107
+ <div class="empty-state">
108
+ <h3>No Data Available</h3>
109
+ <p>This dataset returned no results.</p>
110
+ </div>
111
+ {% endif %}
112
+ </div>
@@ -0,0 +1,271 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Login - OAuth Authorization</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
16
+ background: #f5f7fa;
17
+ min-height: 100vh;
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ padding: 20px;
22
+ }
23
+
24
+ .login-container {
25
+ background: white;
26
+ border-radius: 12px;
27
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
28
+ padding: 40px;
29
+ width: 100%;
30
+ max-width: 450px;
31
+ position: relative;
32
+ }
33
+
34
+ .logo {
35
+ text-align: center;
36
+ margin-bottom: 30px;
37
+ }
38
+
39
+ .logo h1 {
40
+ color: #1f2937;
41
+ font-size: 24px;
42
+ font-weight: 700;
43
+ margin-bottom: 8px;
44
+ line-height: 1.3;
45
+ }
46
+
47
+ .logo .brand {
48
+ color: #1f2937;
49
+ font-weight: 700;
50
+ }
51
+
52
+ .logo .project {
53
+ color: #6b7280;
54
+ font-weight: 600;
55
+ font-size: 20px;
56
+ }
57
+
58
+ .logo p {
59
+ color: #6b7280;
60
+ font-size: 14px;
61
+ }
62
+
63
+ .client-info {
64
+ background: #f8f9fa;
65
+ border-radius: 8px;
66
+ padding: 16px;
67
+ margin-bottom: 24px;
68
+ border-left: 4px solid #2563eb;
69
+ }
70
+
71
+ .client-info h3 {
72
+ color: #333;
73
+ font-size: 16px;
74
+ margin-bottom: 4px;
75
+ }
76
+
77
+ .client-info p {
78
+ color: #666;
79
+ font-size: 14px;
80
+ }
81
+
82
+ .form-group {
83
+ margin-bottom: 20px;
84
+ }
85
+
86
+ .form-group label {
87
+ display: block;
88
+ margin-bottom: 6px;
89
+ color: #333;
90
+ font-weight: 500;
91
+ font-size: 14px;
92
+ }
93
+
94
+ .form-group input {
95
+ width: 100%;
96
+ padding: 12px 16px;
97
+ border: 2px solid #e1e5e9;
98
+ border-radius: 8px;
99
+ font-size: 16px;
100
+ transition: border-color 0.3s ease;
101
+ background-color: #fff;
102
+ }
103
+
104
+ .form-group input:focus {
105
+ outline: none;
106
+ border-color: #2563eb;
107
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
108
+ }
109
+
110
+ .btn {
111
+ width: 100%;
112
+ padding: 12px 16px;
113
+ border: none;
114
+ border-radius: 8px;
115
+ font-size: 16px;
116
+ font-weight: 600;
117
+ cursor: pointer;
118
+ transition: all 0.3s ease;
119
+ text-decoration: none;
120
+ display: inline-block;
121
+ text-align: center;
122
+ }
123
+
124
+ .btn-primary {
125
+ background: #2563eb;
126
+ color: white;
127
+ }
128
+
129
+ .btn-primary:hover {
130
+ background: #1d4ed8;
131
+ transform: translateY(-1px);
132
+ box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
133
+ }
134
+
135
+ .btn-provider {
136
+ background: #fff;
137
+ color: #333;
138
+ border: 2px solid #e1e5e9;
139
+ margin-bottom: 12px;
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ gap: 12px;
144
+ }
145
+
146
+ .btn-provider:hover {
147
+ border-color: #2563eb;
148
+ background: #f8f9fa;
149
+ transform: translateY(-1px);
150
+ }
151
+
152
+ .provider-icon {
153
+ width: 20px;
154
+ height: 20px;
155
+ border-radius: 50%;
156
+ }
157
+
158
+ .divider {
159
+ text-align: center;
160
+ margin: 24px 0;
161
+ position: relative;
162
+ color: #666;
163
+ font-size: 14px;
164
+ }
165
+
166
+ .divider::before {
167
+ content: '';
168
+ position: absolute;
169
+ top: 50%;
170
+ left: 0;
171
+ right: 0;
172
+ height: 1px;
173
+ background: #e1e5e9;
174
+ z-index: 1;
175
+ }
176
+
177
+ .divider span {
178
+ background: white;
179
+ padding: 0 16px;
180
+ position: relative;
181
+ z-index: 2;
182
+ }
183
+
184
+ .error-message {
185
+ background: #fee;
186
+ border: 1px solid #fcc;
187
+ color: #c33;
188
+ padding: 12px;
189
+ border-radius: 8px;
190
+ margin-bottom: 20px;
191
+ font-size: 14px;
192
+ }
193
+
194
+ .info-message {
195
+ background: #e3f2fd;
196
+ border: 1px solid #bbdefb;
197
+ color: #1976d2;
198
+ padding: 12px;
199
+ border-radius: 8px;
200
+ margin-bottom: 20px;
201
+ font-size: 14px;
202
+ }
203
+
204
+ @media (max-width: 480px) {
205
+ .login-container {
206
+ padding: 24px;
207
+ }
208
+
209
+ .logo h1 {
210
+ font-size: 24px;
211
+ }
212
+ }
213
+ </style>
214
+ </head>
215
+ <body>
216
+ <div class="login-container">
217
+ <div class="logo">
218
+ <h1>
219
+ <span class="brand">Squirrels Project</span>
220
+ {% if project_name %}
221
+ <br>
222
+ <span class="project">{{ project_name }}</span>
223
+ {% endif %}
224
+ </h1>
225
+ <p>Please sign in to continue</p>
226
+ </div>
227
+
228
+ {% if client_name %}
229
+ <div class="client-info">
230
+ <h3>{{ client_name }}</h3>
231
+ <p>wants to access your account</p>
232
+ </div>
233
+ {% endif %}
234
+
235
+ <!-- Username/Password Login Form -->
236
+ <form method="post" action="{{ login_url }}?redirect_url={{ return_url | urlencode }}">
237
+ <div class="form-group">
238
+ <label for="username">Username</label>
239
+ <input type="text" id="username" name="username" required autocomplete="username">
240
+ </div>
241
+
242
+ <div class="form-group">
243
+ <label for="password">Password</label>
244
+ <input type="password" id="password" name="password" required autocomplete="current-password">
245
+ </div>
246
+
247
+ <input type="hidden" name="redirect_url" value="{{ return_url }}">
248
+
249
+ <button type="submit" class="btn btn-primary">
250
+ Sign In
251
+ </button>
252
+ </form>
253
+
254
+ {% if providers and providers|length > 0 %}
255
+ <div class="divider">
256
+ <span>or</span>
257
+ </div>
258
+
259
+ <!-- OAuth Provider Login Options -->
260
+ <div class="providers-section">
261
+ {% for provider in providers %}
262
+ <a href="{{ provider.login_url }}?redirect_url={{ return_url | urlencode }}" class="btn btn-provider">
263
+ <img src="{{ provider.icon }}" alt="{{ provider.label }}" class="provider-icon" onerror="this.style.display='none'">
264
+ <span>Continue with {{ provider.label }}</span>
265
+ </a>
266
+ {% endfor %}
267
+ </div>
268
+ {% endif %}
269
+ </div>
270
+ </body>
271
+ </html>
@@ -0,0 +1,20 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link id="favicon" rel="icon" type="image/x-icon" href="{{ sqrl_studio_base_url }}/favicon.ico" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Squirrels Studio</title>
8
+ <script>
9
+ // Optional: Set global defaults for project parameters
10
+ window.DEFAULT_HOSTNAME = '';
11
+ window.DEFAULT_PROJECT_NAME = '{{ project_name }}';
12
+ window.DEFAULT_PROJECT_VERSION = '{{ project_version }}';
13
+ </script>
14
+ <script type="module" crossorigin src="{{ sqrl_studio_base_url }}/assets/index.js"></script>
15
+ <link rel="stylesheet" crossorigin href="{{ sqrl_studio_base_url }}/assets/index.css">
16
+ </head>
17
+ <body>
18
+ <div id="root"></div>
19
+ </body>
20
+ </html>
@@ -1,14 +1,18 @@
1
- import git, shutil, os, time
1
+ import shutil, os, time
2
2
 
3
- from . import _constants as c, _utils as _u
3
+ from . import _constants as c, _utils as u
4
4
  from ._manifest import ManifestConfig
5
5
 
6
6
 
7
7
  class PackageLoaderIO:
8
8
 
9
9
  @classmethod
10
- def load_packages(cls, logger: _u.Logger, manifest_cfg: ManifestConfig, *, reload: bool = False) -> None:
10
+ def load_packages(cls, logger: u.Logger, manifest_cfg: ManifestConfig, *, reload: bool = False) -> None:
11
11
  start = time.time()
12
+
13
+ # Importing git here avoids requirement of having git installed on system if not needed
14
+ import git
15
+
12
16
  # If reload, delete the modules directory (if it exists). It will be recreated later
13
17
  if reload and os.path.exists(c.PACKAGES_FOLDER):
14
18
  shutil.rmtree(c.PACKAGES_FOLDER)
@@ -20,6 +24,6 @@ class PackageLoaderIO:
20
24
  try:
21
25
  git.Repo.clone_from(repo.git, target_dir, branch=repo.revision, depth=1)
22
26
  except git.GitCommandError as e:
23
- raise _u.ConfigurationError(f"Git clone of package failed for this repository: {repo.git}") from e
27
+ raise u.ConfigurationError(f"Git clone of package failed for this repository: {repo.git}") from e
24
28
 
25
29
  logger.log_activity_time("loading packages", start)