tinybird 0.0.1.dev17__py3-none-any.whl → 0.0.1.dev19__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.

@@ -6,6 +6,7 @@ import click
6
6
  from tinybird.feedback_manager import FeedbackManager
7
7
  from tinybird.tb.modules.datafile.common import (
8
8
  Datafile,
9
+ DatafileSyntaxError,
9
10
  format_filename,
10
11
  parse,
11
12
  )
@@ -18,6 +19,7 @@ def parse_datasource(
18
19
  content: Optional[str] = None,
19
20
  skip_eval: bool = False,
20
21
  hide_folders: bool = False,
22
+ add_context_to_datafile_syntax_errors: bool = True,
21
23
  ) -> Datafile:
22
24
  basepath = ""
23
25
  if not content:
@@ -30,6 +32,12 @@ def parse_datasource(
30
32
  filename = format_filename(filename, hide_folders)
31
33
  try:
32
34
  doc = parse(s, "default", basepath, replace_includes=replace_includes, skip_eval=skip_eval)
35
+ except DatafileSyntaxError as e:
36
+ try:
37
+ if add_context_to_datafile_syntax_errors:
38
+ e.get_context_from_file_contents(s)
39
+ finally:
40
+ raise e
33
41
  except ParseException as e:
34
42
  raise click.ClickException(
35
43
  FeedbackManager.error_parsing_file(filename=filename, lineno=e.lineno, error=e)
@@ -7,6 +7,7 @@ from tinybird.feedback_manager import FeedbackManager
7
7
  from tinybird.sql_template import get_template_and_variables, render_sql_template
8
8
  from tinybird.tb.modules.datafile.common import (
9
9
  Datafile,
10
+ DatafileSyntaxError,
10
11
  format_filename,
11
12
  parse,
12
13
  )
@@ -20,6 +21,7 @@ def parse_pipe(
20
21
  content: Optional[str] = None,
21
22
  skip_eval: bool = False,
22
23
  hide_folders: bool = False,
24
+ add_context_to_datafile_syntax_errors: bool = True,
23
25
  ) -> Datafile:
24
26
  basepath = ""
25
27
  if not content:
@@ -32,7 +34,14 @@ def parse_pipe(
32
34
  filename = format_filename(filename, hide_folders)
33
35
  try:
34
36
  sql = ""
35
- doc = parse(s, basepath=basepath, replace_includes=replace_includes, skip_eval=skip_eval)
37
+ try:
38
+ doc = parse(s, basepath=basepath, replace_includes=replace_includes, skip_eval=skip_eval)
39
+ except DatafileSyntaxError as e:
40
+ try:
41
+ if add_context_to_datafile_syntax_errors:
42
+ e.get_context_from_file_contents(s)
43
+ finally:
44
+ raise e
36
45
  for node in doc.nodes:
37
46
  sql = node.get("sql", "")
38
47
  if sql.strip()[0] == "%":
@@ -26,7 +26,6 @@ class TestExpectation(BaseModel):
26
26
  name: str
27
27
  description: str
28
28
  parameters: str
29
- expected_result: str
30
29
 
31
30
 
32
31
  class TestExpectations(BaseModel):
@@ -69,11 +68,11 @@ class LLM:
69
68
  except Exception:
70
69
  return DataProject(datasources=[], pipes=[])
71
70
 
72
- async def generate_sql_sample_data(self, schema: str, rows: int = 20, context: str = "") -> str:
71
+ async def generate_sql_sample_data(self, schema: str, rows: int = 20, prompt: str = "") -> str:
73
72
  response = await self.user_client._req(
74
73
  "/v0/llm/mock",
75
74
  method="POST",
76
- data=f'{{"schema": "{urllib.parse.quote(schema)}", "rows": {rows}, "context": "{urllib.parse.quote(context)}"}}',
75
+ data=f'{{"schema": "{urllib.parse.quote(schema)}", "rows": {rows}, "context": "{prompt}"}}',
77
76
  headers={"Content-Type": "application/json"},
78
77
  )
79
78
  return response.get("result", "")
@@ -90,6 +89,8 @@ class LLM:
90
89
  {"role": "system", "content": create_test_calls_prompt.format(context=context)},
91
90
  {"role": "user", "content": f"Pipe content: {pipe_content}\nPipe params: {pipe_params}"},
92
91
  ],
92
+ temperature=0.2,
93
+ seed=42,
93
94
  response_format=TestExpectations,
94
95
  )
95
96
  return completion.choices[0].message.parsed or TestExpectations(tests=[])
@@ -9,7 +9,7 @@ from tinybird.tb.modules.config import CLIConfig
9
9
  from tinybird.tb.modules.exceptions import CLIException
10
10
 
11
11
  # TODO: Use the official Tinybird image once it's available 'tinybirdco/tinybird-local:latest'
12
- TB_IMAGE_NAME = "registry.gitlab.com/tinybird/analytics/tinybird-local-jammy-3.11:latest"
12
+ TB_IMAGE_NAME = "tinybirdco/tinybird-local:latest"
13
13
  TB_CONTAINER_NAME = "tinybird-local"
14
14
  TB_LOCAL_PORT = int(os.getenv("TB_LOCAL_PORT", 80))
15
15
  TB_LOCAL_HOST = f"http://localhost:{TB_LOCAL_PORT}"
@@ -11,6 +11,7 @@ import requests
11
11
 
12
12
  from tinybird.feedback_manager import FeedbackManager
13
13
  from tinybird.tb.modules.cli import CLIConfig, cli
14
+ from tinybird.tb.modules.common import coro
14
15
 
15
16
 
16
17
  class AuthHandler(http.server.SimpleHTTPRequestHandler):
@@ -115,11 +116,11 @@ def start_server(auth_callback):
115
116
  "--workspace",
116
117
  help="Set the workspace to authenticate to. If not set, the default workspace will be used.",
117
118
  )
118
- def login(host: str, workspace: str):
119
+ @coro
120
+ async def login(host: str, workspace: str):
119
121
  """Authenticate via browser."""
120
122
  auth_event = threading.Event()
121
123
  auth_code = [None] # Using a list to store the code, as it's mutable
122
- config = CLIConfig.get_project_config()
123
124
  host = host or "https://api.tinybird.co"
124
125
 
125
126
  def auth_callback(code):
@@ -150,19 +151,25 @@ def login(host: str, workspace: str):
150
151
  params = {}
151
152
  if workspace:
152
153
  params["workspace_id"] = workspace
153
- response = requests.get(
154
- f"https://api.tinybird.co/v0/user/tokens?{urlencode(params)}",
154
+ response = requests.get( # noqa: ASYNC210
155
+ f"{host}/v0/user/tokens?{urlencode(params)}",
155
156
  headers={"Authorization": f"Bearer {auth_code[0]}"},
156
157
  )
158
+
157
159
  data = response.json()
158
160
  cli_config = CLIConfig.get_project_config()
159
- workspace_token = data["workspace_token"]
160
- user_token = data["user_token"]
161
- cli_config.set_token(workspace_token)
162
- cli_config.set_token_for_host(workspace_token, host)
163
- cli_config.set_user_token(user_token)
164
- config.set_host(host)
161
+ cli_config.set_token(data["workspace_token"])
162
+ cli_config.set_token_for_host(data["workspace_token"], host)
163
+ cli_config.set_user_token(data["user_token"])
164
+ cli_config.set_host(host)
165
+
166
+ response = await cli_config.get_client().workspace_info()
167
+ for k in ("id", "name", "user_email", "user_id", "scope"):
168
+ if k in response:
169
+ cli_config[k] = response[k]
170
+
165
171
  cli_config.persist_to_file()
172
+
166
173
  click.echo(FeedbackManager.success(message="✓ Authentication successful!"))
167
174
  else:
168
175
  click.echo(FeedbackManager.error(message="Authentication failed or timed out."))
@@ -15,10 +15,10 @@ from tinybird.tb.modules.local_common import get_tinybird_local_client
15
15
  @cli.command()
16
16
  @click.argument("datasource", type=str)
17
17
  @click.option("--rows", type=int, default=10, help="Number of events to send")
18
- @click.option("--context", type=str, default="", help="Extra context to use for data generation")
18
+ @click.option("--prompt", type=str, default="", help="Extra context to use for data generation")
19
19
  @click.option("--folder", type=str, default=".", help="Folder where datafiles will be placed")
20
20
  @coro
21
- async def mock(datasource: str, rows: int, context: str, folder: str) -> None:
21
+ async def mock(datasource: str, rows: int, prompt: str, folder: str) -> None:
22
22
  """Load sample data into a Data Source.
23
23
 
24
24
  Args:
@@ -35,15 +35,15 @@ async def mock(datasource: str, rows: int, context: str, folder: str) -> None:
35
35
  datasource_path = Path("datasources", f"{datasource}.datasource")
36
36
  datasource_path = Path(folder) / datasource_path
37
37
 
38
- context_path = Path(folder) / "fixtures" / f"{datasource_name}.prompt"
39
- if not context:
40
- # load the context from the fixture.prompt file if it exists
41
- if context_path.exists():
42
- click.echo(FeedbackManager.gray(message=f"Using context for {context_path}..."))
43
- context = context_path.read_text()
38
+ prompt_path = Path(folder) / "fixtures" / f"{datasource_name}.prompt"
39
+ if not prompt:
40
+ # load the prompt from the fixture.prompt file if it exists
41
+ if prompt_path.exists():
42
+ click.echo(FeedbackManager.gray(message=f"Using prompt for {prompt_path}..."))
43
+ prompt = prompt_path.read_text()
44
44
  else:
45
- click.echo(FeedbackManager.gray(message=f"Overriding context for {datasource_name}..."))
46
- context_path.write_text(context)
45
+ click.echo(FeedbackManager.gray(message=f"Overriding prompt for {datasource_name}..."))
46
+ prompt_path.write_text(prompt)
47
47
 
48
48
  click.echo(FeedbackManager.gray(message=f"Creating fixture for {datasource_name}..."))
49
49
  datasource_content = datasource_path.read_text()
@@ -52,7 +52,9 @@ async def mock(datasource: str, rows: int, context: str, folder: str) -> None:
52
52
  user_client.token = config.get_user_token()
53
53
  llm = LLM(client=user_client)
54
54
  tb_client = await get_tinybird_local_client(os.path.abspath(folder))
55
- sql = await llm.generate_sql_sample_data(datasource_content, rows=rows, context=context)
55
+ sql = await llm.generate_sql_sample_data(datasource_content, rows=rows, prompt=prompt)
56
+ if os.environ.get('TB_DEBUG', '') != '':
57
+ print(sql)
56
58
  result = await tb_client.query(f"{sql} FORMAT JSON")
57
59
  data = result.get("data", [])[:rows]
58
60
  fixture_name = build_fixture_name(datasource_path.absolute(), datasource_name, datasource_content)
@@ -60,4 +62,4 @@ async def mock(datasource: str, rows: int, context: str, folder: str) -> None:
60
62
  click.echo(FeedbackManager.success(message="✓ Done!"))
61
63
 
62
64
  except Exception as e:
63
- raise CLIException(FeedbackManager.error(message=str(e)))
65
+ raise CLIException(FeedbackManager.error_exception(error=e))
@@ -20,6 +20,32 @@ from tinybird.tb.modules.exceptions import CLIException
20
20
  from tinybird.tb.modules.llm import LLM, TestExpectation
21
21
  from tinybird.tb.modules.local_common import get_tinybird_local_client
22
22
 
23
+ yaml.SafeDumper.org_represent_str = yaml.SafeDumper.represent_str
24
+
25
+
26
+ def repr_str(dumper, data):
27
+ if "\n" in data:
28
+ return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|")
29
+ return dumper.org_represent_str(data)
30
+
31
+
32
+ yaml.add_representer(str, repr_str, Dumper=yaml.SafeDumper)
33
+
34
+
35
+ def generate_test_file(pipe_name: str, tests: List[TestExpectation], folder: Optional[str], mode: str = "w"):
36
+ base = Path("tests")
37
+ if folder:
38
+ base = Path(folder) / base
39
+
40
+ base.mkdir(parents=True, exist_ok=True)
41
+
42
+ yaml_str = yaml.safe_dump(tests, sort_keys=False)
43
+ formatted_yaml = yaml_str.replace("- name:", "\n- name:")
44
+
45
+ path = base / f"{pipe_name}.yaml"
46
+ with open(path, mode) as f:
47
+ f.write(formatted_yaml)
48
+
23
49
 
24
50
  @cli.group()
25
51
  @click.pass_context
@@ -46,16 +72,6 @@ async def test_create(ctx: click.Context, pipe: str, prompt: Optional[str], fold
46
72
  Create a test for an existing endpoint
47
73
  """
48
74
 
49
- def generate_test_file(pipe_name: str, tests: List[TestExpectation]):
50
- base = Path("tests")
51
- if folder:
52
- base = Path(folder) / base
53
- base.mkdir(parents=True, exist_ok=True)
54
-
55
- path = base / f"{pipe_name}.yaml"
56
- with open(path, "w") as f:
57
- yaml.dump(tests, f)
58
-
59
75
  try:
60
76
  pipe_path = Path(pipe)
61
77
  pipe_name = pipe
@@ -82,52 +98,128 @@ async def test_create(ctx: click.Context, pipe: str, prompt: Optional[str], fold
82
98
  )
83
99
  valid_test_expectations = []
84
100
  for test in test_expectations.tests:
85
- test_params = test.parameters if test.parameters.startswith("?") else f"?{test.parameters}"
101
+ valid_test = test.model_dump()
102
+ test_params = (
103
+ valid_test["parameters"] if valid_test["parameters"].startswith("?") else f"?{valid_test['parameters']}"
104
+ )
105
+
106
+ response = None
86
107
  try:
87
- response = await client._req(f"/v0/pipes/{pipe_name}.ndjson{test_params}")
108
+ response = await client._req_raw(f"/v0/pipes/{pipe_name}.ndjson{test_params}")
88
109
  except Exception:
89
110
  continue
90
111
 
91
- test.expected_result = response
92
- valid_test_expectations.append(test.model_dump())
112
+ if response.status_code >= 400:
113
+ valid_test["expected_http_status"] = response.status_code
114
+ valid_test["expected_result"] = response.json()["error"]
115
+ else:
116
+ if "expected_http_status" in valid_test:
117
+ del valid_test["expected_http_status"]
118
+ valid_test["expected_result"] = response.text or ""
119
+
120
+ valid_test_expectations.append(valid_test)
93
121
  if valid_test_expectations:
94
- generate_test_file(pipe_name, valid_test_expectations)
122
+ generate_test_file(pipe_name, valid_test_expectations, folder, mode="a")
95
123
  click.echo(FeedbackManager.info(message=f"✓ /tests/{pipe_name}.yaml"))
96
124
  click.echo(FeedbackManager.success(message="✓ Done!\n"))
97
125
  except Exception as e:
98
126
  raise CLIException(FeedbackManager.error_exception(error=e))
99
127
 
100
128
 
129
+ @test.command(
130
+ name="update",
131
+ help="Update the test expectations for a file or a test.",
132
+ )
133
+ @click.argument("pipe", type=str)
134
+ @click.option(
135
+ "--folder",
136
+ default=".",
137
+ type=click.Path(exists=True, file_okay=False),
138
+ help="Folder where datafiles will be placed",
139
+ )
140
+ @click.pass_context
141
+ @coro
142
+ async def test_update(ctx: click.Context, pipe: str, folder: Optional[str]) -> None:
143
+ client = await get_tinybird_local_client(os.path.abspath(folder))
144
+
145
+ pipe_tests_path = Path(pipe)
146
+ pipe_name = pipe
147
+ if pipe_tests_path.suffix == ".yaml":
148
+ pipe_name = pipe_tests_path.stem
149
+ else:
150
+ pipe_tests_path = Path("tests", f"{pipe}.yaml")
151
+
152
+ click.echo(FeedbackManager.gray(message=f"\nUpdating tests expectations for {pipe_name} endpoint..."))
153
+ pipe_tests_path = Path(folder) / pipe_tests_path
154
+ pipe_tests_content = yaml.safe_load(pipe_tests_path.read_text())
155
+ for test in pipe_tests_content:
156
+ test_params = test["parameters"] if test["parameters"].startswith("?") else f"?{test['parameters']}"
157
+ response = None
158
+ try:
159
+ response = await client._req_raw(f"/v0/pipes/{pipe_name}.ndjson{test_params}")
160
+ except Exception:
161
+ continue
162
+
163
+ if response.status_code >= 400:
164
+ test["expected_http_status"] = response.status_code
165
+ test["expected_result"] = response.json()["error"]
166
+ else:
167
+ if "expected_http_status" in test:
168
+ del test["expected_http_status"]
169
+
170
+ test["expected_result"] = response.text or ""
171
+
172
+ generate_test_file(pipe_name, pipe_tests_content, folder)
173
+ click.echo(FeedbackManager.info(message=f"✓ /tests/{pipe_name}.yaml"))
174
+ click.echo(FeedbackManager.success(message="✓ Done!\n"))
175
+
176
+
101
177
  @test.command(
102
178
  name="run",
103
- help="Run the test suite, a file, or a test. To skip test to run in branches and CI put them in a 'skip_in_branch' folder.",
179
+ help="Run the test suite, a file, or a test.",
104
180
  )
105
- @click.argument("file", nargs=-1)
181
+ @click.argument("name", nargs=-1)
106
182
  @click.option(
107
183
  "--folder",
108
184
  default=".",
109
185
  type=click.Path(exists=True, file_okay=False),
110
186
  help="Folder where tests will be placed",
111
187
  )
112
- @click.pass_context
113
188
  @coro
114
- async def test_run(ctx: click.Context, file: Tuple[str, ...], folder: Optional[str]) -> None:
189
+ async def test_run(name: Tuple[str, ...], folder: Optional[str]) -> None:
115
190
  client = await get_tinybird_local_client(os.path.abspath(folder))
116
- file_list: Iterable[str] = file if len(file) > 0 else glob.glob("./tests/**/*.y*ml", recursive=True)
191
+ paths = [Path(n) for n in name]
192
+ endpoints = [f"./tests/{p.stem}.yaml" for p in paths]
193
+ file_list: Iterable[str] = endpoints if len(endpoints) > 0 else glob.glob("./tests/**/*.y*ml", recursive=True)
117
194
 
118
195
  async def run_test(test_file):
119
196
  test_file_path = Path(test_file)
120
197
  test_file_content = yaml.safe_load(test_file_path.read_text())
121
198
  for test in test_file_content:
122
199
  try:
123
- response = await client._req(f"/v0/pipes/{test_file_path.stem}.ndjson?{test['parameters']}")
124
- if test["expected_result"] != response:
200
+ test_params = test["parameters"] if test["parameters"].startswith("?") else f"?{test['parameters']}"
201
+
202
+ response = None
203
+ try:
204
+ response = await client._req_raw(f"/v0/pipes/{test_file_path.stem}.ndjson{test_params}")
205
+ except Exception:
206
+ raise Exception("Expected to not fail but got an error")
207
+
208
+ expected_result = response.text
209
+ if response.status_code >= 400:
210
+ expected_result = response.json()["error"]
211
+ if "expected_http_status" not in test:
212
+ raise Exception("Expected to not fail but got an error")
213
+ if test["expected_http_status"] != response.status_code:
214
+ raise Exception(f"Expected {test['expected_http_status']} but got {response.status_code}")
215
+
216
+ if test["expected_result"] != expected_result:
125
217
  diff = difflib.ndiff(
126
- test["expected_result"].splitlines(keepends=True), response.splitlines(keepends=True)
218
+ test["expected_result"].splitlines(keepends=True), expected_result.splitlines(keepends=True)
127
219
  )
128
220
  printable_diff = "".join(diff)
129
221
  raise Exception(
130
- f"\nExpected: \n{test['expected_result']}\nGot: \n{response}\nDiff: \n{printable_diff}"
222
+ f"\nExpected: \n{test['expected_result']}\nGot: \n{expected_result}\nDiff: \n{printable_diff}"
131
223
  )
132
224
  click.echo(FeedbackManager.success(message=f"✓ {test_file_path.name} - {test['name']}"))
133
225
  except Exception as e:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird
3
- Version: 0.0.1.dev17
3
+ Version: 0.0.1.dev19
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -16,6 +16,7 @@ Requires-Dist: croniter (==1.3.8)
16
16
  Requires-Dist: docker (==7.1.0)
17
17
  Requires-Dist: GitPython (~=3.1.32)
18
18
  Requires-Dist: humanfriendly (~=8.2)
19
+ Requires-Dist: prompt-toolkit (==3.0.48)
19
20
  Requires-Dist: pydantic (~=2.8.0)
20
21
  Requires-Dist: pyperclip (==1.8.2)
21
22
  Requires-Dist: pyyaml (<6.1,>=6.0)
@@ -1,5 +1,5 @@
1
1
  tinybird/__cli__.py,sha256=pgYsVLcqL16wtSn6KtKweNZYoYJdEksTgSvQAW7hH64,250
2
- tinybird/client.py,sha256=_voHMgKOwOhmncSaPH6DL94X6YPqKJJzcY-EKp8xLug,50810
2
+ tinybird/client.py,sha256=iPtpEhKB3alvo0o4kKMePrt1N7VbwtrKvH10OSWFAaA,51498
3
3
  tinybird/config.py,sha256=Z-BX9FrjgsLw1YwcCdF0IztLB97Zpc70VVPplO_pDSY,6089
4
4
  tinybird/connectors.py,sha256=lkpVSUmSuViEZBa4QjTK7YmPHUop0a5UFoTrSmlVq6k,15244
5
5
  tinybird/context.py,sha256=kutUQ0kCwparowI74_YLXx6wtTzGLRouJ6oGHVBPzBo,1291
@@ -15,31 +15,32 @@ tinybird/syncasync.py,sha256=fAvq0qkRgqXqXMKwbY2iJNYqLT_r6mDsh1MRpGKrdRU,27763
15
15
  tinybird/tornado_template.py,sha256=o2HguxrL1Evnt8o3IvrsI8Zm6JtRQ3zhLJKf1XyR3SQ,41965
16
16
  tinybird/ch_utils/constants.py,sha256=aYvg2C_WxYWsnqPdZB1ZFoIr8ZY-XjUXYyHKE9Ansj0,3890
17
17
  tinybird/ch_utils/engine.py,sha256=OXkBhlzGjZotjD0vaT-rFIbSGV4tpiHxE8qO_ip0SyQ,40454
18
+ tinybird/tb/__cli__.py,sha256=Rkdf_rWmJCmGhDIUL6WoCdXi5BDn2cZHjhBCqPvzpu8,251
18
19
  tinybird/tb/cli.py,sha256=onCxcKvTV4RuokC5V3t82OXWAIwgU6pMWs8rpWOUi_o,815
19
20
  tinybird/tb/modules/auth.py,sha256=hynZ-Temot8YBsySUWKSFzZlYadtFPxG3o6lCSu1n6E,9018
20
- tinybird/tb/modules/build.py,sha256=3YEcUBSsp8DREyox5x27BabcdYHFEokGnQ-f8-etDmo,8412
21
- tinybird/tb/modules/build_shell.py,sha256=jN06ZT7BK3lHtMgBjaOn4sD6yooUy9v8uuZnE-jjmlU,5485
22
- tinybird/tb/modules/cicd.py,sha256=KCFfywFfvGRh24GZwqrhICiTK_arHelPs_X4EB-pXIw,7331
23
- tinybird/tb/modules/cli.py,sha256=PRURYKphzjqVltMG647D8ADGS-YFR2rAkDNEwUTTDjk,53082
24
- tinybird/tb/modules/common.py,sha256=ZvkuI1JYVVwBZOZ9VDiNLR_-HHRavTHqSe6uVPJ8MS4,76431
21
+ tinybird/tb/modules/build.py,sha256=oVHv9kbim6ZhupLtCIxfgeZOCriqfH4Oz9S5Komv_9c,9409
22
+ tinybird/tb/modules/build_shell.py,sha256=3ec18FWyyF5lWgrf8F2n8-3ngQccJUmN2cwB9-_S_1g,14083
23
+ tinybird/tb/modules/cicd.py,sha256=Xa3M7Egq4eDS6QIhrx8C8Ixf-R7oiZpO-5ZBPqYAKtI,5344
24
+ tinybird/tb/modules/cli.py,sha256=hN5_DijZZ-E2OtLe0tgnu4a_5KCzY9EeOjE-bEJefos,53169
25
+ tinybird/tb/modules/common.py,sha256=XfpzFVT9xJZ_HH7EZRLAjRMkTtz5rP7Njld5-EwMqiA,72400
25
26
  tinybird/tb/modules/config.py,sha256=ri4Gwyzqol6-NofTjHnWquuDzJOjHbkaAnboO8JNENY,11499
26
27
  tinybird/tb/modules/connection.py,sha256=ZSqBGoRiJedjHKEyB_fr1ybucOHtaad8d7uqGa2Q92M,28668
27
- tinybird/tb/modules/create.py,sha256=fr418rucTn9etxcOfdBViV9dk_mIQJpB_L0XO8NF4e0,10059
28
+ tinybird/tb/modules/create.py,sha256=jSVh8ysT5OoQ0EUg3ETU3VtKZayqFWBjPjcQSdYa7Sc,9882
28
29
  tinybird/tb/modules/datasource.py,sha256=rX7RnrXl4xxPwGxkj1DgLr521wjNXEixAeAyxMrkJJk,35472
29
30
  tinybird/tb/modules/exceptions.py,sha256=4A2sSjCEqKUMqpP3WI00zouCWW4uLaghXXLZBSw04mY,3363
30
31
  tinybird/tb/modules/fmt.py,sha256=UszEQO15fdzQ49QEj7Unhu68IKwSuKPsOrKhk2p2TAg,3547
31
32
  tinybird/tb/modules/job.py,sha256=eoBVyA24lYIPonU88Jn7FF9hBKz1kScy9_w_oWreuc4,2952
32
- tinybird/tb/modules/llm.py,sha256=duwf3r1caLaKzuOJC_stI_Hx54ncr-5uWaWeZ3HN65o,3099
33
+ tinybird/tb/modules/llm.py,sha256=OcyRzQ0V392XsiGFwrrpjkCuV6AdE6cnhh6cDKPQt7U,3102
33
34
  tinybird/tb/modules/local.py,sha256=hV2fvHPaVHVzKwVoVDFAIbJZslOX1_COx96DZrR-dW8,5151
34
- tinybird/tb/modules/local_common.py,sha256=Z2JYIE5HIJVNuzdIv1_NFxSEs8DOsLoCzbmT1iy0-HU,2172
35
- tinybird/tb/modules/login.py,sha256=vIeysdttfGDBMkf_i3cqAVNR5s0X0D6exATcRsDdWiA,5849
36
- tinybird/tb/modules/mock.py,sha256=5xhR_djr1-_JwJPI-Oy1exI3ndz7srmmvlei0DMQCAk,2824
35
+ tinybird/tb/modules/local_common.py,sha256=PsQu0Sg8BruusPzlzvs6dd2WlomvOcks-B37A798-Ls,2133
36
+ tinybird/tb/modules/login.py,sha256=ydyn64fbz3BOlSf5SZuIFvgsCpxQAQir8nJQSdMeq94,6011
37
+ tinybird/tb/modules/mock.py,sha256=cpEmfSv5Osy_YF5eaFcAlpAYi0oVlX1NQH4mnAKvlUI,2884
37
38
  tinybird/tb/modules/pipe.py,sha256=P_W5HW1-UEidWlw0pty-n_qYvCAyMlNorBmWzmCP7cU,30906
38
39
  tinybird/tb/modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
39
40
  tinybird/tb/modules/table.py,sha256=hG-PRDVuFp2uph41WpoLRV1yjp3RI2fi_iGGiI0rdxU,7695
40
41
  tinybird/tb/modules/tag.py,sha256=1qQWyk1p3Btv3LzM8VbJG-k7x2-pFuAlYCg3QL6QewI,3480
41
42
  tinybird/tb/modules/telemetry.py,sha256=iEGnMuCuNhvF6ln__j6X9MSTwL_0Hm-GgFHHHvhfknk,10466
42
- tinybird/tb/modules/test.py,sha256=wWOg9FFyAiJkF7qjYapJUne5SVyXwmmhStfpCAZwZ80,5383
43
+ tinybird/tb/modules/test.py,sha256=Br0gXS9FrpFEnA6mnSm5fRbYnaw10AL_Z0gbaDfvDoM,8857
43
44
  tinybird/tb/modules/token.py,sha256=r0oeG1RpOOzHtqbUaHBiOmhE55HfNIvReAAWyKl9fJg,12695
44
45
  tinybird/tb/modules/workspace.py,sha256=FVlh-kbiZp5Gvp6dGFxi0UD8ail77rMamXLhqdVwrZ0,10916
45
46
  tinybird/tb/modules/workspace_members.py,sha256=08W0onEYkKLEC5TkAI07cxN9XSquEm7HnL7OkHAVDjo,8715
@@ -47,15 +48,15 @@ tinybird/tb/modules/datafile/build.py,sha256=rFdK_GerPDgPfyPfZ4EZ0-cQqWfHd6htS0l
47
48
  tinybird/tb/modules/datafile/build_common.py,sha256=74547h5ja4C66DAwDMabj75FA_BUTJxTJv-24tSFmrs,4551
48
49
  tinybird/tb/modules/datafile/build_datasource.py,sha256=fquzEGwk9NL_0K5YYG86Xtvgn4J5YHtRUoKJxbQGO0s,17344
49
50
  tinybird/tb/modules/datafile/build_pipe.py,sha256=V5u21NEpSCWNVl46Cdn_I_bOojxpgSrg1MnScPDqx4U,27648
50
- tinybird/tb/modules/datafile/common.py,sha256=NkoCdj4p-Ak3n80DJB5a33Ucw2WTcSYa8iqw4KsRZGs,81082
51
+ tinybird/tb/modules/datafile/common.py,sha256=3CwspnffLUOlbfHMzjEvNebX--5sOC8DUKOC__3_fTA,75702
51
52
  tinybird/tb/modules/datafile/diff.py,sha256=-iaP7GvAzZtZSa8jPgVpOFlTRutxgxRBLBcGL1_RFr4,6743
52
53
  tinybird/tb/modules/datafile/exceptions.py,sha256=8rw2umdZjtby85QbuRKFO5ETz_eRHwUY5l7eHsy1wnI,556
53
54
  tinybird/tb/modules/datafile/fixture.py,sha256=YHlL4tojmPwm343Y8KO6r7d5Bhsk7U3lKP-oLMeBMsY,1771
54
55
  tinybird/tb/modules/datafile/format_common.py,sha256=zNWDXvwSKC9_T5e9R92LLj9ekDflVWwsllhGQilZsnY,2184
55
56
  tinybird/tb/modules/datafile/format_datasource.py,sha256=tsnCjONISvhFuucKNbIHkT__UmlUbcswx5mwI9hiDQc,6216
56
57
  tinybird/tb/modules/datafile/format_pipe.py,sha256=R5tnlEccLn3KX6ehtC_H2sGQNrthuJUiVSN9z_-KGCY,7474
57
- tinybird/tb/modules/datafile/parse_datasource.py,sha256=YKt4Sy830p2jqXW5jN1Bf60AM5o4gZ3QcZjxnyWIeBg,1190
58
- tinybird/tb/modules/datafile/parse_pipe.py,sha256=STgA12LOLUnnb_cvVvZeEE4ka-nfk0jsNzxJhWj94cY,2599
58
+ tinybird/tb/modules/datafile/parse_datasource.py,sha256=mAGN72mviRS0rtpAD0kODhlu-N8j1fX2kp5D1GUzP6U,1464
59
+ tinybird/tb/modules/datafile/parse_pipe.py,sha256=9_j-wB4gsWtrXY8Gypt4EkOH6BepJpZkjFdZfbW-H50,2914
59
60
  tinybird/tb/modules/datafile/pipe_checker.py,sha256=cp80Bru41GlyMRvyERpdJNXns2MjmtIAWFnBLF4cPXs,24667
60
61
  tinybird/tb/modules/datafile/pull.py,sha256=wBXBAZIruIyCRQZvfYxMc7h1q35NlKF-hFIF-bUm4iY,5956
61
62
  tinybird/tb/modules/tinyunit/tinyunit.py,sha256=IkjRCvb8HnNEE84rtl0I1b9gQVpE_zCE8MvFFet51sg,11716
@@ -66,8 +67,8 @@ tinybird/tb_cli_modules/config.py,sha256=6NTgIdwf0X132A1j6G_YrdPep87ymZ9b5pABabK
66
67
  tinybird/tb_cli_modules/exceptions.py,sha256=pmucP4kTF4irIt7dXiG-FcnI-o3mvDusPmch1L8RCWk,3367
67
68
  tinybird/tb_cli_modules/regions.py,sha256=QjsL5H6Kg-qr0aYVLrvb1STeJ5Sx_sjvbOYO0LrEGMk,166
68
69
  tinybird/tb_cli_modules/telemetry.py,sha256=iEGnMuCuNhvF6ln__j6X9MSTwL_0Hm-GgFHHHvhfknk,10466
69
- tinybird-0.0.1.dev17.dist-info/METADATA,sha256=eu-lIaxe76zXyzD78jMIjloB-BEVztY_wQeN3mJFoOI,2405
70
- tinybird-0.0.1.dev17.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
71
- tinybird-0.0.1.dev17.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
72
- tinybird-0.0.1.dev17.dist-info/top_level.txt,sha256=pgw6AzERHBcW3YTi2PW4arjxLkulk2msOz_SomfOEuc,45
73
- tinybird-0.0.1.dev17.dist-info/RECORD,,
70
+ tinybird-0.0.1.dev19.dist-info/METADATA,sha256=AxNU0bAKXE2-n882WlwLmg8drAgVN4uLrnhCqGHhqxY,2446
71
+ tinybird-0.0.1.dev19.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
72
+ tinybird-0.0.1.dev19.dist-info/entry_points.txt,sha256=LwdHU6TfKx4Qs7BqqtaczEZbImgU7Abe9Lp920zb_fo,43
73
+ tinybird-0.0.1.dev19.dist-info/top_level.txt,sha256=pgw6AzERHBcW3YTi2PW4arjxLkulk2msOz_SomfOEuc,45
74
+ tinybird-0.0.1.dev19.dist-info/RECORD,,