tinybird-cli 5.9.1.dev0__tar.gz → 5.9.1.dev2__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.
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/PKG-INFO +7 -1
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/__cli__.py +2 -2
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/ch_utils/constants.py +1 -1
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/datafile.py +35 -7
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/feedback_manager.py +3 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/sql.py +80 -1
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/sql_template.py +17 -4
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/branch.py +0 -1
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird_cli.egg-info/PKG-INFO +7 -1
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird_cli.egg-info/requires.txt +1 -1
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/setup.cfg +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/check_pypi.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/client.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/config.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/connectors.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/context.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/datatypes.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/git_settings.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/sql_toolset.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/syncasync.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/token.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tornado_template.py +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird_cli.egg-info/SOURCES.txt +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird_cli.egg-info/dependency_links.txt +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird_cli.egg-info/entry_points.txt +0 -0
- {tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tinybird-cli
|
|
3
|
-
Version: 5.9.1.
|
|
3
|
+
Version: 5.9.1.dev2
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/cli/introduction.html
|
|
6
6
|
Author: Tinybird
|
|
@@ -18,6 +18,12 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
18
18
|
Changelog
|
|
19
19
|
----------
|
|
20
20
|
|
|
21
|
+
5.9.1.dev2
|
|
22
|
+
***********
|
|
23
|
+
|
|
24
|
+
- `Changed` Upgrade clickhouse-toolset to 0.32.dev0
|
|
25
|
+
- `Added` new "File not found" error to `tb check` when including files from missing paths.
|
|
26
|
+
|
|
21
27
|
5.9.0
|
|
22
28
|
***********
|
|
23
29
|
|
|
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
|
|
|
4
4
|
__url__ = 'https://www.tinybird.co/docs/cli/introduction.html'
|
|
5
5
|
__author__ = 'Tinybird'
|
|
6
6
|
__author_email__ = 'support@tinybird.co'
|
|
7
|
-
__version__ = '5.9.1.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '5.9.1.dev2'
|
|
8
|
+
__revision__ = '4f458c3'
|
|
@@ -6,7 +6,7 @@ SNAPSHOT_WS_NAME = "snapshot"
|
|
|
6
6
|
ENABLED_TABLE_FUNCTIONS = {"generateRandom", "null", "numbers", "numbers_mt", "values", "zeros", "zeros_mt"}
|
|
7
7
|
# there's a workspace limit allowed_table_functions used in the APIs limit in cheriff
|
|
8
8
|
COPY_ENABLED_TABLE_FUNCTIONS = frozenset(
|
|
9
|
-
["postgresql", "mysql", "mongodb", "url", "azureBlobStorage", "gcs", "iceberg", "s3"]
|
|
9
|
+
["postgresql", "mysql", "mongodb", "url", "azureBlobStorage", "gcs", "iceberg", "s3", "deltaLake"]
|
|
10
10
|
)
|
|
11
11
|
|
|
12
12
|
ENABLED_SYSTEM_TABLES = {
|
|
@@ -278,7 +278,9 @@ class ParseException(Exception):
|
|
|
278
278
|
|
|
279
279
|
|
|
280
280
|
class IncludeFileNotFoundException(Exception):
|
|
281
|
-
|
|
281
|
+
def __init__(self, err: str, lineno: int = -1):
|
|
282
|
+
self.lineno: int = lineno
|
|
283
|
+
super().__init__(err)
|
|
282
284
|
|
|
283
285
|
|
|
284
286
|
class ValidationException(Exception):
|
|
@@ -307,6 +309,10 @@ def is_shared_datasource(ds_name: str) -> bool:
|
|
|
307
309
|
return "." in ds_name
|
|
308
310
|
|
|
309
311
|
|
|
312
|
+
def format_filename(filename: str, hide_folders: bool = False):
|
|
313
|
+
return os.path.basename(filename) if hide_folders else filename
|
|
314
|
+
|
|
315
|
+
|
|
310
316
|
class CLIGitRelease:
|
|
311
317
|
NO_DATAFILES_PATHS = ["vendor/", "tests/", "scripts/", ".diff_tmp/"]
|
|
312
318
|
DATAFILES_SUFFIXES = [".datasource", ".pipe", ".incl", ".token"]
|
|
@@ -783,7 +789,11 @@ class Datafile:
|
|
|
783
789
|
|
|
784
790
|
|
|
785
791
|
def parse_datasource(
|
|
786
|
-
filename: str,
|
|
792
|
+
filename: str,
|
|
793
|
+
replace_includes: bool = True,
|
|
794
|
+
content: Optional[str] = None,
|
|
795
|
+
skip_eval: bool = False,
|
|
796
|
+
hide_folders: bool = False,
|
|
787
797
|
) -> Datafile:
|
|
788
798
|
basepath = ""
|
|
789
799
|
if not content:
|
|
@@ -793,6 +803,7 @@ def parse_datasource(
|
|
|
793
803
|
else:
|
|
794
804
|
s = content
|
|
795
805
|
|
|
806
|
+
filename = format_filename(filename, hide_folders)
|
|
796
807
|
try:
|
|
797
808
|
doc = parse(s, "default", basepath, replace_includes=replace_includes, skip_eval=skip_eval)
|
|
798
809
|
except ParseException as e:
|
|
@@ -807,7 +818,11 @@ def parse_datasource(
|
|
|
807
818
|
|
|
808
819
|
|
|
809
820
|
def parse_pipe(
|
|
810
|
-
filename: str,
|
|
821
|
+
filename: str,
|
|
822
|
+
replace_includes: bool = True,
|
|
823
|
+
content: Optional[str] = None,
|
|
824
|
+
skip_eval: bool = False,
|
|
825
|
+
hide_folders: bool = False,
|
|
811
826
|
) -> Datafile:
|
|
812
827
|
basepath = ""
|
|
813
828
|
if not content:
|
|
@@ -817,6 +832,7 @@ def parse_pipe(
|
|
|
817
832
|
else:
|
|
818
833
|
s = content
|
|
819
834
|
|
|
835
|
+
filename = format_filename(filename, hide_folders)
|
|
820
836
|
try:
|
|
821
837
|
sql = ""
|
|
822
838
|
doc = parse(s, basepath=basepath, replace_includes=replace_includes, skip_eval=skip_eval)
|
|
@@ -849,13 +865,19 @@ def parse_pipe(
|
|
|
849
865
|
raise click.ClickException(
|
|
850
866
|
FeedbackManager.error_parsing_node_with_unclosed_if(node=e.node, pipe=filename, lineno=e.lineno, sql=e.sql)
|
|
851
867
|
)
|
|
868
|
+
except IncludeFileNotFoundException as e:
|
|
869
|
+
raise click.ClickException(FeedbackManager.error_not_found_include(filename=e, lineno=e.lineno))
|
|
852
870
|
except ModuleNotFoundError:
|
|
853
871
|
pass
|
|
854
872
|
return doc
|
|
855
873
|
|
|
856
874
|
|
|
857
875
|
def parse_token(
|
|
858
|
-
filename: str,
|
|
876
|
+
filename: str,
|
|
877
|
+
replace_includes: bool = True,
|
|
878
|
+
content: Optional[str] = None,
|
|
879
|
+
skip_eval: bool = False,
|
|
880
|
+
hide_folders: bool = False,
|
|
859
881
|
) -> Datafile:
|
|
860
882
|
if not content:
|
|
861
883
|
with open(filename) as file:
|
|
@@ -864,6 +886,7 @@ def parse_token(
|
|
|
864
886
|
else:
|
|
865
887
|
s = content
|
|
866
888
|
|
|
889
|
+
filename = format_filename(filename, hide_folders)
|
|
867
890
|
try:
|
|
868
891
|
sql = ""
|
|
869
892
|
doc = parse(s, basepath=basepath, replace_includes=replace_includes, skip_eval=skip_eval)
|
|
@@ -1091,7 +1114,7 @@ def parse(
|
|
|
1091
1114
|
StringIO(Template(file.read()).safe_substitute(attrs), newline=None)
|
|
1092
1115
|
)
|
|
1093
1116
|
except FileNotFoundError:
|
|
1094
|
-
raise IncludeFileNotFoundException(f)
|
|
1117
|
+
raise IncludeFileNotFoundException(f, lineno)
|
|
1095
1118
|
|
|
1096
1119
|
def version(*args: str, **kwargs: Any) -> None:
|
|
1097
1120
|
if len(args) < 1:
|
|
@@ -1279,7 +1302,7 @@ def parse(
|
|
|
1279
1302
|
else:
|
|
1280
1303
|
raise ValidationException(f"Validation error, found {line} in line {str(lineno)}: {str(e)}", lineno=lineno)
|
|
1281
1304
|
except IncludeFileNotFoundException as e:
|
|
1282
|
-
raise e
|
|
1305
|
+
raise IncludeFileNotFoundException(str(e), lineno=lineno)
|
|
1283
1306
|
except Exception as e:
|
|
1284
1307
|
traceback.print_tb(e.__traceback__)
|
|
1285
1308
|
raise ParseException(f"Unexpected error: {e}", lineno=lineno)
|
|
@@ -4165,6 +4188,7 @@ async def folder_push(
|
|
|
4165
4188
|
check_backfill_required: bool = False,
|
|
4166
4189
|
use_main: bool = False,
|
|
4167
4190
|
check_outdated: bool = True,
|
|
4191
|
+
hide_folders: bool = False,
|
|
4168
4192
|
): # noqa: C901
|
|
4169
4193
|
workspaces: List[Dict[str, Any]] = (await tb_client.user_workspaces_and_branches()).get("workspaces", [])
|
|
4170
4194
|
current_ws: Dict[str, Any] = next(
|
|
@@ -4361,8 +4385,12 @@ async def folder_push(
|
|
|
4361
4385
|
)
|
|
4362
4386
|
)
|
|
4363
4387
|
except Exception as e:
|
|
4388
|
+
filename = (
|
|
4389
|
+
os.path.basename(to_run[name]["filename"]) if hide_folders else to_run[name]["filename"]
|
|
4390
|
+
)
|
|
4364
4391
|
exception = FeedbackManager.error_push_file_exception(
|
|
4365
|
-
filename=
|
|
4392
|
+
filename=filename,
|
|
4393
|
+
error=e,
|
|
4366
4394
|
)
|
|
4367
4395
|
raise click.ClickException(exception)
|
|
4368
4396
|
else:
|
|
@@ -242,6 +242,9 @@ class FeedbackManager:
|
|
|
242
242
|
error_deleted_include = error_message(
|
|
243
243
|
"Related include file {include_file} was deleted and it's used in {filename}. Delete or remove dependency from {filename}."
|
|
244
244
|
)
|
|
245
|
+
error_not_found_include = error_message(
|
|
246
|
+
"Included file {filename} at line {lineno} not found. Check if the file exists and the path is correct."
|
|
247
|
+
)
|
|
245
248
|
error_branch = error_message(
|
|
246
249
|
"Branch {branch} not found. use 'tb branch ls' to list your Branches, make sure you are authenticated using the right workspace token"
|
|
247
250
|
)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
import re
|
|
2
3
|
import string
|
|
3
4
|
from collections import namedtuple
|
|
@@ -401,10 +402,84 @@ def parse_table_structure(schema: str) -> List[Dict[str, Any]]:
|
|
|
401
402
|
[{'name': 'a', 'type': 'String', 'codec': None, 'default_value': None, 'jsonpath': None, 'nullable': False, 'normalized_name': 'a'}]
|
|
402
403
|
>>> parse_table_structure('`index` String, INDEX index_name a TYPE set(100, 1) GRANULARITY 100')
|
|
403
404
|
[{'name': 'index', 'type': 'String', 'codec': None, 'default_value': None, 'jsonpath': None, 'nullable': False, 'normalized_name': 'index'}]
|
|
405
|
+
>>> parse_table_structure('`a2` String `json:$.a--2`, `a3` String `json:$.a3`\\n')
|
|
406
|
+
[{'name': 'a2', 'type': 'String', 'codec': None, 'default_value': None, 'jsonpath': '$.a--2', 'nullable': False, 'normalized_name': 'a2'}, {'name': 'a3', 'type': 'String', 'codec': None, 'default_value': None, 'jsonpath': '$.a3', 'nullable': False, 'normalized_name': 'a3'}]
|
|
404
407
|
"""
|
|
405
408
|
return _parse_table_structure(schema)
|
|
406
409
|
|
|
407
410
|
|
|
411
|
+
def clean_comments(schema_to_clean: str) -> str:
|
|
412
|
+
"""Remove the comments from the schema
|
|
413
|
+
if the comments are between backticks, they will not be removed
|
|
414
|
+
>>> clean_comments(None) is None
|
|
415
|
+
True
|
|
416
|
+
>>> clean_comments('')
|
|
417
|
+
''
|
|
418
|
+
>>> clean_comments(' ')
|
|
419
|
+
''
|
|
420
|
+
>>> clean_comments('\\n')
|
|
421
|
+
''
|
|
422
|
+
>>> clean_comments('\\n\\n\\n\\n')
|
|
423
|
+
''
|
|
424
|
+
>>> clean_comments('c Float32')
|
|
425
|
+
'c Float32'
|
|
426
|
+
>>> clean_comments('c Float32\\n')
|
|
427
|
+
'c Float32'
|
|
428
|
+
>>> clean_comments('c Float32\\n--this is a comment')
|
|
429
|
+
'c Float32'
|
|
430
|
+
>>> clean_comments('c Float32\\n--this is a comment\\n')
|
|
431
|
+
'c Float32'
|
|
432
|
+
>>> clean_comments('c Float32\\t-- this is a comment\\t\\n')
|
|
433
|
+
'c Float32'
|
|
434
|
+
>>> clean_comments('c Float32\\n--this is a comment\\r\\n')
|
|
435
|
+
'c Float32'
|
|
436
|
+
>>> clean_comments('c Float32\\n--this is a comment\\n--this is a comment2\\n')
|
|
437
|
+
'c Float32'
|
|
438
|
+
>>> clean_comments('c Float32\\n--this is a ```comment\\n')
|
|
439
|
+
'c Float32'
|
|
440
|
+
>>> clean_comments('c Float32\\n--this is a ```comment\\n')
|
|
441
|
+
'c Float32'
|
|
442
|
+
>>> clean_comments('c Float32, -- comment\\nd Float32 -- comment2')
|
|
443
|
+
'c Float32,\\nd Float32'
|
|
444
|
+
>>> clean_comments('c Float32, -- comment\\n -- comment \\nd Float32 -- comment2')
|
|
445
|
+
'c Float32,\\nd Float32'
|
|
446
|
+
>>> clean_comments('c Float32 `json:$.aa--aa`\\n--this is a ```comment\\n')
|
|
447
|
+
'c Float32 `json:$.aa--aa`'
|
|
448
|
+
>>> clean_comments('c Float32 `json:$.cc--cc`\\nd Float32 `json:$.dd--dd`\\n--this is a ```comment\\n')
|
|
449
|
+
'c Float32 `json:$.cc--cc`\\nd Float32 `json:$.dd--dd`'
|
|
450
|
+
>>> clean_comments('c--c Float32 `json:$.cc--cc`\\n')
|
|
451
|
+
'c'
|
|
452
|
+
>>> clean_comments('`c--c` Float32 `json:$.cc--cc`\\n')
|
|
453
|
+
'`c'
|
|
454
|
+
"""
|
|
455
|
+
|
|
456
|
+
def clean_line_comments(line: str) -> str:
|
|
457
|
+
if not line:
|
|
458
|
+
return line
|
|
459
|
+
i = 0
|
|
460
|
+
inside_json_path = False
|
|
461
|
+
while i < len(line):
|
|
462
|
+
if i + 1 < len(line) and line[i] == "-" and line[i + 1] == "-" and not inside_json_path:
|
|
463
|
+
return line[:i].strip()
|
|
464
|
+
|
|
465
|
+
if not inside_json_path and line[i:].startswith("`json:"):
|
|
466
|
+
inside_json_path = True
|
|
467
|
+
elif inside_json_path and line[i] == "`":
|
|
468
|
+
inside_json_path = False
|
|
469
|
+
i += 1
|
|
470
|
+
return line
|
|
471
|
+
|
|
472
|
+
if schema_to_clean is None:
|
|
473
|
+
return schema_to_clean
|
|
474
|
+
|
|
475
|
+
cleaned_schema = ""
|
|
476
|
+
for line in schema_to_clean.splitlines():
|
|
477
|
+
cleaned_line = clean_line_comments(line)
|
|
478
|
+
if cleaned_line:
|
|
479
|
+
cleaned_schema += cleaned_line + "\n"
|
|
480
|
+
return cleaned_schema.strip()
|
|
481
|
+
|
|
482
|
+
|
|
408
483
|
SyntaxExpr = namedtuple("SyntaxExpr", ["name", "regex"])
|
|
409
484
|
|
|
410
485
|
NULL = SyntaxExpr("NULL", re.compile(r"\s+NULL([^a-z0-9_]|$)", re.IGNORECASE))
|
|
@@ -426,7 +501,11 @@ REGEX_COMMENT = re.compile(r"\-\-[^\n\r]*[\n\r]")
|
|
|
426
501
|
def _parse_table_structure(schema: str) -> List[Dict[str, Any]]: # noqa: C901
|
|
427
502
|
# CH syntax from https://clickhouse.com/docs/en/sql-reference/statements/create/table/
|
|
428
503
|
# name1 [type1] [NULL|NOT NULL] [DEFAULT|MATERIALIZED|ALIAS expr1] [compression_codec] [TTL expr1]
|
|
429
|
-
|
|
504
|
+
try:
|
|
505
|
+
schema = clean_comments(schema + "\n")
|
|
506
|
+
except Exception as e:
|
|
507
|
+
logging.exception(f"Error cleaning comments: {e}")
|
|
508
|
+
schema = REGEX_COMMENT.sub(" ", schema + "\n").strip()
|
|
430
509
|
|
|
431
510
|
if REGEX_WHITESPACE.fullmatch(schema):
|
|
432
511
|
return []
|
|
@@ -750,6 +750,20 @@ def _parse_datetime(date_string, date_format, backup_date_format=None):
|
|
|
750
750
|
|
|
751
751
|
|
|
752
752
|
def json_type(x, default=None):
|
|
753
|
+
"""
|
|
754
|
+
>>> json_type(None, '[]')
|
|
755
|
+
[]
|
|
756
|
+
>>> json_type(None)
|
|
757
|
+
{}
|
|
758
|
+
>>> json_type('{"a": 1}')
|
|
759
|
+
{'a': 1}
|
|
760
|
+
>>> json_type('[{"a": 1}]')
|
|
761
|
+
[{'a': 1}]
|
|
762
|
+
>>> json_type({"a": 1})
|
|
763
|
+
{'a': 1}
|
|
764
|
+
>>> json_type([{"a": 1}])
|
|
765
|
+
[{'a': 1}]
|
|
766
|
+
"""
|
|
753
767
|
if isinstance(x, Placeholder):
|
|
754
768
|
if default:
|
|
755
769
|
x = default
|
|
@@ -764,15 +778,14 @@ def json_type(x, default=None):
|
|
|
764
778
|
x = "{}"
|
|
765
779
|
|
|
766
780
|
value = "" # used for exception message
|
|
767
|
-
if isinstance(x, str):
|
|
781
|
+
if isinstance(x, (str, bytes, bytearray)):
|
|
768
782
|
if len(x) > 16:
|
|
769
783
|
value = x[:16] + "..."
|
|
770
784
|
else:
|
|
771
785
|
value = x
|
|
772
786
|
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
787
|
+
parsed = loads(x)
|
|
788
|
+
x = parsed
|
|
776
789
|
except Exception as e:
|
|
777
790
|
msg = f"Error parsing JSON: '{value}' - {str(e)}"
|
|
778
791
|
raise SQLTemplateException(msg)
|
|
@@ -47,7 +47,6 @@ def release() -> None:
|
|
|
47
47
|
@coro
|
|
48
48
|
async def release_ls() -> None:
|
|
49
49
|
"""List current available Releases in the Workspace"""
|
|
50
|
-
click.echo(FeedbackManager.warning_deprecated_releases())
|
|
51
50
|
config = CLIConfig.get_project_config()
|
|
52
51
|
_ = await try_update_config_with_remote(config, only_if_needed=True)
|
|
53
52
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tinybird-cli
|
|
3
|
-
Version: 5.9.1.
|
|
3
|
+
Version: 5.9.1.dev2
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/cli/introduction.html
|
|
6
6
|
Author: Tinybird
|
|
@@ -18,6 +18,12 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
18
18
|
Changelog
|
|
19
19
|
----------
|
|
20
20
|
|
|
21
|
+
5.9.1.dev2
|
|
22
|
+
***********
|
|
23
|
+
|
|
24
|
+
- `Changed` Upgrade clickhouse-toolset to 0.32.dev0
|
|
25
|
+
- `Added` new "File not found" error to `tb check` when including files from missing paths.
|
|
26
|
+
|
|
21
27
|
5.9.0
|
|
22
28
|
***********
|
|
23
29
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/tinyunit/tinyunit.py
RENAMED
|
File without changes
|
{tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird/tb_cli_modules/workspace_members.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-cli-5.9.1.dev0 → tinybird-cli-5.9.1.dev2}/tinybird_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|