tinybird 0.0.1.dev0__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 tinybird might be problematic. Click here for more details.

Files changed (45) hide show
  1. tinybird/__cli__.py +8 -0
  2. tinybird/ch_utils/constants.py +244 -0
  3. tinybird/ch_utils/engine.py +855 -0
  4. tinybird/check_pypi.py +25 -0
  5. tinybird/client.py +1281 -0
  6. tinybird/config.py +117 -0
  7. tinybird/connectors.py +428 -0
  8. tinybird/context.py +23 -0
  9. tinybird/datafile.py +5589 -0
  10. tinybird/datatypes.py +434 -0
  11. tinybird/feedback_manager.py +1022 -0
  12. tinybird/git_settings.py +145 -0
  13. tinybird/sql.py +865 -0
  14. tinybird/sql_template.py +2343 -0
  15. tinybird/sql_template_fmt.py +281 -0
  16. tinybird/sql_toolset.py +350 -0
  17. tinybird/syncasync.py +682 -0
  18. tinybird/tb_cli.py +25 -0
  19. tinybird/tb_cli_modules/auth.py +252 -0
  20. tinybird/tb_cli_modules/branch.py +1043 -0
  21. tinybird/tb_cli_modules/cicd.py +434 -0
  22. tinybird/tb_cli_modules/cli.py +1571 -0
  23. tinybird/tb_cli_modules/common.py +2082 -0
  24. tinybird/tb_cli_modules/config.py +344 -0
  25. tinybird/tb_cli_modules/connection.py +803 -0
  26. tinybird/tb_cli_modules/datasource.py +900 -0
  27. tinybird/tb_cli_modules/exceptions.py +91 -0
  28. tinybird/tb_cli_modules/fmt.py +91 -0
  29. tinybird/tb_cli_modules/job.py +85 -0
  30. tinybird/tb_cli_modules/pipe.py +858 -0
  31. tinybird/tb_cli_modules/regions.py +9 -0
  32. tinybird/tb_cli_modules/tag.py +100 -0
  33. tinybird/tb_cli_modules/telemetry.py +310 -0
  34. tinybird/tb_cli_modules/test.py +107 -0
  35. tinybird/tb_cli_modules/tinyunit/tinyunit.py +340 -0
  36. tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +71 -0
  37. tinybird/tb_cli_modules/token.py +349 -0
  38. tinybird/tb_cli_modules/workspace.py +269 -0
  39. tinybird/tb_cli_modules/workspace_members.py +212 -0
  40. tinybird/tornado_template.py +1194 -0
  41. tinybird-0.0.1.dev0.dist-info/METADATA +2815 -0
  42. tinybird-0.0.1.dev0.dist-info/RECORD +45 -0
  43. tinybird-0.0.1.dev0.dist-info/WHEEL +5 -0
  44. tinybird-0.0.1.dev0.dist-info/entry_points.txt +2 -0
  45. tinybird-0.0.1.dev0.dist-info/top_level.txt +4 -0
tinybird/datatypes.py ADDED
@@ -0,0 +1,434 @@
1
+ import ast
2
+ import decimal
3
+ import re
4
+ from decimal import Decimal
5
+
6
+ datetime64_patterns = [
7
+ r"\d\d\d\d.\d\d.\d\d(T|\s)\d\d:\d\d:\d\d.\d\d\d",
8
+ r"\d\d.\d\d.\d\d\d\d.\d{1,2}:\d{1,2}:\d{1,2}.\d{1,3}",
9
+ ]
10
+
11
+ datetime_patterns = [r"\d\d\d\d.\d\d.\d\d(T|\s)\d\d:\d\d:\d\d", r"\d\d.\d\d.\d\d\d\d.\d{1,2}:\d{1,2}:\d{1,2}"]
12
+
13
+ int_8_max = 2**7
14
+ int16_max = 2**15
15
+ int32_max = 2**31
16
+ int64_max = 2**63
17
+ int128_max = 2**127
18
+ int256_max = 2**255
19
+ uint_8_max = 2**8
20
+ uint16_max = 2**16
21
+ uint32_max = 2**32
22
+ uint64_max = 2**64
23
+ uint128_max = 2**128
24
+ uint256_max = 2**256
25
+ intx_re = r"^[+-]?\d+$"
26
+ uintx_re = r"^\d+$"
27
+ float32_max = 2**23 # 23 bits is the fractional part of float 32 ieee754
28
+ float64_max = 2**52 # 51 bits is the fractional part of float 64 ieee754
29
+
30
+ datetime64_type_pattern = r"^DateTime64(\([1-9](, ?'.+')?\))?$"
31
+ datetime_type_pattern = r"^DateTime(\(('.+')?)?\)?$"
32
+
33
+ # List from https://github.com/tinybirdco/ClickHousePrivate/blob/153473d9c1c871974688a1d72dcff7a13fc2076c/src/DataTypes/Serializations/SerializationBool.cpp#L216
34
+ bool_allowed_values = {
35
+ "true",
36
+ "false",
37
+ "True",
38
+ "False",
39
+ "T",
40
+ "F",
41
+ "Y",
42
+ "N",
43
+ "Yes",
44
+ "No",
45
+ "On",
46
+ "Off",
47
+ "Enable",
48
+ "Disable",
49
+ "Enabled",
50
+ "Disabled",
51
+ "1",
52
+ "0",
53
+ }
54
+
55
+
56
+ def is_type_datetime64(type_to_check):
57
+ """
58
+ >>> is_type_datetime64('DateTime64')
59
+ True
60
+ >>> is_type_datetime64('DateTime64(1)')
61
+ True
62
+ >>> is_type_datetime64('DateTime64(3)')
63
+ True
64
+ >>> is_type_datetime64("DateTime64(3,'Madrid')")
65
+ True
66
+ >>> is_type_datetime64("DateTime64(3, 'Madrid/Moscow')")
67
+ True
68
+ >>> is_type_datetime64("DateTime64()")
69
+ False
70
+ >>> is_type_datetime64("datetime64")
71
+ False
72
+ """
73
+ return re.match(datetime64_type_pattern, type_to_check) is not None
74
+
75
+
76
+ def is_type_datetime(type_to_check):
77
+ """
78
+ >>> is_type_datetime('DateTime')
79
+ True
80
+ >>> is_type_datetime('DateTime()')
81
+ True
82
+ >>> is_type_datetime("DateTime('Madrid')")
83
+ True
84
+ >>> is_type_datetime("DateTime(3)")
85
+ False
86
+ >>> is_type_datetime("datetime")
87
+ False
88
+ """
89
+ return re.match(datetime_type_pattern, type_to_check) is not None
90
+
91
+
92
+ def string_test(x):
93
+ return True
94
+
95
+
96
+ def date_test(x):
97
+ return re.match(r"\d\d\d\d-\d\d-\d\d$", x)
98
+
99
+
100
+ def datetime64_test(x):
101
+ return any([re.match(p, x) for p in datetime64_patterns])
102
+
103
+
104
+ def datetime_test(x):
105
+ return any([re.match(p, x) for p in datetime_patterns])
106
+
107
+
108
+ def int_8_test(x):
109
+ return re.match(intx_re, x) and -int_8_max <= int(x) < int_8_max
110
+
111
+
112
+ def int16_test(x):
113
+ return re.match(intx_re, x) and -int16_max <= int(x) < int16_max
114
+
115
+
116
+ def int32_test(x):
117
+ return re.match(intx_re, x) and -int32_max <= int(x) < int32_max
118
+
119
+
120
+ def int64_test(x):
121
+ return re.match(intx_re, x) and -int64_max <= int(x) < int64_max
122
+
123
+
124
+ def int128_test(x):
125
+ return re.match(intx_re, x) and -int128_max <= int(x) < int128_max
126
+
127
+
128
+ def int256_test(x):
129
+ return re.match(intx_re, x) and -int256_max <= int(x) < int256_max
130
+
131
+
132
+ def uint_8_test(x):
133
+ return re.match(uintx_re, x) and 0 <= int(x) < uint_8_max
134
+
135
+
136
+ def uint16_test(x):
137
+ return re.match(uintx_re, x) and 0 <= int(x) < uint16_max
138
+
139
+
140
+ def uint32_test(x):
141
+ return re.match(uintx_re, x) and 0 <= int(x) < uint32_max
142
+
143
+
144
+ def uint64_test(x):
145
+ return re.match(uintx_re, x) and 0 <= int(x) < uint64_max
146
+
147
+
148
+ def uint128_test(x):
149
+ return re.match(intx_re, x) and 0 <= int(x) < uint128_max
150
+
151
+
152
+ def uint256_test(x):
153
+ return re.match(intx_re, x) and 0 <= int(x) < uint256_max
154
+
155
+
156
+ def float_test(x):
157
+ return "_" not in x and type_test(x, float)
158
+
159
+
160
+ def float32_test(x):
161
+ return "_" not in x and type_test(x, float) and -float32_max <= float(x) < float32_max
162
+
163
+
164
+ def float64_test(x):
165
+ return "_" not in x and type_test(x, float) and -float64_max < float(x) < float64_max
166
+
167
+
168
+ def bool_test(x):
169
+ return x in bool_allowed_values
170
+
171
+
172
+ def test_numeric_testers(fn, n):
173
+ """
174
+ >>> test_numeric_testers(int32_test, (2**31)-1)
175
+ True
176
+ >>> test_numeric_testers(int32_test, -(2**31))
177
+ True
178
+ >>> test_numeric_testers(int32_test, -(2**31)-1)
179
+ False
180
+ >>> test_numeric_testers(int32_test, 2**31)
181
+ False
182
+
183
+ >>> test_numeric_testers(int64_test, (2**63)-1)
184
+ True
185
+ >>> test_numeric_testers(int64_test, -(2**63))
186
+ True
187
+ >>> test_numeric_testers(int64_test, -(2**63)-1)
188
+ False
189
+ >>> test_numeric_testers(int64_test, 2**63)
190
+ False
191
+ """
192
+ return fn(str(n))
193
+
194
+
195
+ def array_test(_type_test):
196
+ """
197
+ >>> array_test(str)("['blabla']")
198
+ True
199
+ >>> array_test(str)('["blabla"]')
200
+ True
201
+ >>> array_test(str)('["blabla","bloblo"]')
202
+ True
203
+ >>> array_test(str)('["blabla, bloblo"]')
204
+ True
205
+ >>> array_test(str)("[ W ]")
206
+ False
207
+ >>> array_test(int)("[1]")
208
+ True
209
+ >>> array_test(int)('[1]')
210
+ True
211
+ >>> array_test(int)('[1,2]')
212
+ True
213
+ >>> array_test(float)("[1.2]")
214
+ True
215
+ >>> array_test(float)('[1.2]')
216
+ True
217
+ >>> array_test(float)('[1.2,2.1]')
218
+ True
219
+ >>> array_test(float)('["1.2","2.1"]')
220
+ False
221
+ """
222
+
223
+ def _test(x):
224
+ if x[0] != "[":
225
+ return False
226
+ try:
227
+ k = ast.literal_eval(x)
228
+ except Exception:
229
+ return False
230
+ if isinstance(k, list):
231
+ return all(isinstance(x, _type_test) for x in k)
232
+ return False
233
+
234
+ return _test
235
+
236
+
237
+ numbers_types = (
238
+ "Int8",
239
+ "UInt8",
240
+ "Int16",
241
+ "UInt16",
242
+ "UInt32",
243
+ "Int32",
244
+ "Int64",
245
+ "UInt64",
246
+ "Int128",
247
+ "UInt128",
248
+ "Int256",
249
+ "UInt256",
250
+ "Float32",
251
+ "Float64",
252
+ )
253
+
254
+ # Use guessers for discovering types
255
+ # I.e., when you have to take into consideration things like float precision
256
+ guessers = {
257
+ "DateTime64": datetime64_test,
258
+ "DateTime": datetime_test,
259
+ "Date": date_test,
260
+ "Int8": int_8_test,
261
+ "UInt8": uint_8_test,
262
+ "Int16": int16_test,
263
+ "UInt16": uint16_test,
264
+ "Int32": int32_test,
265
+ "UInt32": uint32_test,
266
+ "Int64": int64_test,
267
+ "UInt64": uint64_test,
268
+ "Float32": float32_test,
269
+ "Float64": float64_test,
270
+ "Array(Int32)": array_test(int),
271
+ "Array(Float32)": array_test(float),
272
+ "Array(String)": array_test(str),
273
+ }
274
+
275
+ # Use testers validating a value against a type
276
+ # I.e., you already know the type and you need to check if a value fits there
277
+ testers = {
278
+ "DateTime64": datetime64_test,
279
+ "DateTime": datetime_test,
280
+ "Date": date_test,
281
+ "Int8": int_8_test,
282
+ "UInt8": uint_8_test,
283
+ "Int16": int16_test,
284
+ "UInt16": uint16_test,
285
+ "Int32": int32_test,
286
+ "UInt32": uint32_test,
287
+ "Int64": int64_test,
288
+ "UInt64": uint64_test,
289
+ "Int128": int128_test,
290
+ "UInt128": uint128_test,
291
+ "Int256": int256_test,
292
+ "UInt256": uint256_test,
293
+ "Float32": float_test,
294
+ "Float64": float_test,
295
+ "Bool": bool_test,
296
+ "Array(Int32)": array_test(int),
297
+ "Array(Float32)": array_test(float),
298
+ "Array(String)": array_test(str),
299
+ }
300
+
301
+
302
+ # Search for `canBeInsideNullable` under CH code and see which ones are true.
303
+ nullable_types = [
304
+ "Date",
305
+ "Date32",
306
+ "DateTime",
307
+ "DateTime32",
308
+ "DateTime64",
309
+ "Decimal",
310
+ "Decimal128",
311
+ "Decimal256",
312
+ "Decimal32",
313
+ "Decimal64",
314
+ "Enum",
315
+ "Enum16",
316
+ "Enum8",
317
+ "FixedString",
318
+ "Float32",
319
+ "Float64",
320
+ "IPv4",
321
+ "IPv6",
322
+ "Int128",
323
+ "Int16",
324
+ "Int256",
325
+ "Int32",
326
+ "Int64",
327
+ "Int8",
328
+ "MultiPolygon",
329
+ "Point",
330
+ "Polygon",
331
+ "Ring",
332
+ "String",
333
+ "UInt128",
334
+ "UInt16",
335
+ "UInt256",
336
+ "UInt32",
337
+ "UInt64",
338
+ "UInt8",
339
+ "UUID",
340
+ ]
341
+
342
+
343
+ def type_test(i, t):
344
+ try:
345
+ t(i)
346
+ return True
347
+ except Exception:
348
+ return False
349
+
350
+
351
+ def parse_decimal_type(typ):
352
+ """
353
+ >>> parse_decimal_type("decimal")
354
+
355
+ >>> parse_decimal_type('Decimal')
356
+ (64, 10, 0)
357
+ >>> parse_decimal_type('Decimal()')
358
+
359
+ >>> parse_decimal_type('Decimal(2)')
360
+ (32, 2, 0)
361
+ >>> parse_decimal_type('Decimal(5,2)')
362
+ (32, 5, 2)
363
+ >>> parse_decimal_type('Decimal( 9 , 2 )')
364
+ (32, 9, 2)
365
+ >>> parse_decimal_type('Decimal(10,2)')
366
+ (64, 10, 2)
367
+ >>> parse_decimal_type('Decimal(19,2)')
368
+ (128, 19, 2)
369
+ >>> parse_decimal_type('Decimal(39,2)')
370
+ (256, 39, 2)
371
+ >>> parse_decimal_type('Decimal32(9)')
372
+ (32, 9, 9)
373
+ >>> parse_decimal_type('Decimal32(10)')
374
+
375
+ >>> parse_decimal_type('Decimal(10,10)')
376
+ (64, 10, 10)
377
+ >>> parse_decimal_type('Decimal(10,11)')
378
+
379
+ >>> parse_decimal_type('Decimal32(5, 2)')
380
+
381
+ >>> parse_decimal_type('Decimal64(2)')
382
+ (64, 18, 2)
383
+ >>> parse_decimal_type('Decimal128(2)')
384
+ (128, 38, 2)
385
+ >>> parse_decimal_type('Decimal256(2)')
386
+ (256, 76, 2)
387
+ """
388
+ # Obtained from https://clickhouse.com/docs/en/sql-reference/data-types/decimal
389
+ max_digits_by_bit_width = {32: 9, 64: 18, 128: 38, 256: 76}
390
+
391
+ # Check if type is Decimal, Decimal(P), or Decimal(P, S) with whitespace support
392
+ # Regex contains two capturing groups. First capturing P. Second capturing S.
393
+ if m := re.match(r"^Decimal\s*(?:\(\s*(\d+)(?:\s*,\s*(\d+))?\s*\))?$", typ):
394
+ p, s = int(m.group(1) or 10), int(m.group(2) or 0)
395
+ b = min(bit_width for bit_width, max_digits in max_digits_by_bit_width.items() if max_digits >= p)
396
+ if p < s or b is None:
397
+ return None
398
+ # Check if type is Decimal32(S), Decimal64(S), Decimal128(S), or Decimal256(S) with whitespace support.
399
+ # Regex contains 2 capturing groups. First capturing 32, 64, 128 or 256. Second capturing S.
400
+ elif m := re.match(r"^Decimal(32|64|128|256)\s*\(\s*(\d+)\s*\)$", typ):
401
+ b, s = int(m.group(1)), int(m.group(2))
402
+ p = max_digits_by_bit_width[int(b)]
403
+ if p < s:
404
+ return None
405
+ else:
406
+ return None
407
+ return b, p, s
408
+
409
+
410
+ def is_type_decimal(type_to_check):
411
+ """
412
+ >>> is_type_decimal('Decimal')
413
+ True
414
+ >>> is_type_decimal("Decimal(10, 2)")
415
+ True
416
+ >>> is_type_decimal("decimal")
417
+ False
418
+ """
419
+ return parse_decimal_type(type_to_check) is not None
420
+
421
+
422
+ def get_decimal_limits(p, s):
423
+ """
424
+ >>> get_decimal_limits(1, 0)
425
+ (Decimal('-9'), Decimal('9'))
426
+ >>> get_decimal_limits(5, 5)
427
+ (Decimal('-0.99999'), Decimal('0.99999'))
428
+ >>> get_decimal_limits(76, 38)
429
+ (Decimal('-99999999999999999999999999999999999999.99999999999999999999999999999999999999'), Decimal('99999999999999999999999999999999999999.99999999999999999999999999999999999999'))
430
+ """
431
+ with decimal.localcontext(prec=p + 2):
432
+ max_value = Decimal((10**p) - 1) / (10**s)
433
+ min_value = -max_value
434
+ return min_value, max_value