tinybird 0.0.1.dev32__tar.gz → 0.0.1.dev34__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 tinybird might be problematic. Click here for more details.

Files changed (100) hide show
  1. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/PKG-INFO +1 -1
  2. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/__cli__.py +2 -2
  3. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/build.py +25 -2
  4. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/build_client.py +1 -15
  5. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/cli.py +1 -1
  6. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/build.py +2 -2
  7. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/common.py +63 -2
  8. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/parse_datasource.py +7 -5
  9. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/parse_pipe.py +7 -1
  10. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/deploy.py +22 -19
  11. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/local.py +15 -3
  12. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/local_common.py +8 -2
  13. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/mock.py +6 -1
  14. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/test.py +3 -1
  15. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird.egg-info/PKG-INFO +1 -1
  16. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/setup.cfg +0 -0
  17. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/__cli__.py +0 -0
  18. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/ch_utils/constants.py +0 -0
  19. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/ch_utils/engine.py +0 -0
  20. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/check_pypi.py +0 -0
  21. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/client.py +0 -0
  22. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/config.py +0 -0
  23. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/connectors.py +0 -0
  24. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/context.py +0 -0
  25. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/datafile.py +0 -0
  26. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/datatypes.py +0 -0
  27. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/feedback_manager.py +0 -0
  28. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/git_settings.py +0 -0
  29. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/prompts.py +0 -0
  30. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/sql.py +0 -0
  31. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/sql_template.py +0 -0
  32. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/sql_template_fmt.py +0 -0
  33. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/sql_toolset.py +0 -0
  34. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/syncasync.py +0 -0
  35. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/cli.py +0 -0
  36. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/auth.py +0 -0
  37. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/cicd.py +0 -0
  38. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/common.py +0 -0
  39. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/config.py +0 -0
  40. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/connection.py +0 -0
  41. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/create.py +0 -0
  42. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/build_common.py +0 -0
  43. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
  44. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
  45. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/diff.py +0 -0
  46. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/exceptions.py +0 -0
  47. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/fixture.py +0 -0
  48. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/format_common.py +0 -0
  49. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
  50. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
  51. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
  52. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datafile/pull.py +0 -0
  53. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/datasource.py +0 -0
  54. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/exceptions.py +0 -0
  55. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/feedback_manager.py +0 -0
  56. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/fmt.py +0 -0
  57. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/job.py +0 -0
  58. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/llm.py +0 -0
  59. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/llm_utils.py +0 -0
  60. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/login.py +0 -0
  61. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/pipe.py +0 -0
  62. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/regions.py +0 -0
  63. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/shell.py +0 -0
  64. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/table.py +0 -0
  65. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/tag.py +0 -0
  66. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/telemetry.py +0 -0
  67. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
  68. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
  69. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/token.py +0 -0
  70. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/update.py +0 -0
  71. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/watch.py +0 -0
  72. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/workspace.py +0 -0
  73. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb/modules/workspace_members.py +0 -0
  74. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli.py +0 -0
  75. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/auth.py +0 -0
  76. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/branch.py +0 -0
  77. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/cicd.py +0 -0
  78. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/cli.py +0 -0
  79. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/common.py +0 -0
  80. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/config.py +0 -0
  81. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/connection.py +0 -0
  82. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/datasource.py +0 -0
  83. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/exceptions.py +0 -0
  84. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/fmt.py +0 -0
  85. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/job.py +0 -0
  86. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/pipe.py +0 -0
  87. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/regions.py +0 -0
  88. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/tag.py +0 -0
  89. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/telemetry.py +0 -0
  90. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/test.py +0 -0
  91. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  92. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  93. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/workspace.py +0 -0
  94. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  95. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird/tornado_template.py +0 -0
  96. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird.egg-info/SOURCES.txt +0 -0
  97. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird.egg-info/dependency_links.txt +0 -0
  98. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird.egg-info/entry_points.txt +0 -0
  99. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird.egg-info/requires.txt +0 -0
  100. {tinybird-0.0.1.dev32 → tinybird-0.0.1.dev34}/tinybird.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird
3
- Version: 0.0.1.dev32
3
+ Version: 0.0.1.dev34
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -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__ = '0.0.1.dev32'
8
- __revision__ = 'fc755d1'
7
+ __version__ = '0.0.1.dev34'
8
+ __revision__ = '08098c9'
@@ -11,6 +11,7 @@ import requests
11
11
 
12
12
  from tinybird.client import TinyB
13
13
  from tinybird.tb.modules.cli import cli
14
+ from tinybird.tb.modules.common import push_data
14
15
  from tinybird.tb.modules.feedback_manager import FeedbackManager
15
16
  from tinybird.tb.modules.local_common import get_tinybird_local_client
16
17
  from tinybird.tb.modules.shell import Shell
@@ -61,6 +62,7 @@ def build_project(folder: str, tb_client: TinyB) -> None:
61
62
  ".pipe": "text/plain",
62
63
  }
63
64
  TINYBIRD_API_URL = tb_client.host + "/v1/build"
65
+ logging.debug(TINYBIRD_API_URL)
64
66
  TINYBIRD_API_KEY = tb_client.token
65
67
  try:
66
68
  files = [
@@ -78,7 +80,12 @@ def build_project(folder: str, tb_client: TinyB) -> None:
78
80
  HEADERS = {"Authorization": f"Bearer {TINYBIRD_API_KEY}"}
79
81
 
80
82
  r = requests.post(TINYBIRD_API_URL, files=files, headers=HEADERS)
81
- result = r.json()
83
+ try:
84
+ result = r.json()
85
+ except Exception as e:
86
+ logging.debug(e, exc_info=True)
87
+ click.echo(FeedbackManager.error(message="Couldn't parse response from server"))
88
+ return
82
89
 
83
90
  logging.debug(json.dumps(result, indent=2))
84
91
 
@@ -90,7 +97,7 @@ def build_project(folder: str, tb_client: TinyB) -> None:
90
97
  build_errors = result.get("errors")
91
98
  for build_error in build_errors:
92
99
  filename_bit = f"{build_error.get('filename', '')}"
93
- error_msg = (filename_bit + "\n\n") if filename_bit else "" + build_error.get("error")
100
+ error_msg = ((filename_bit + "\n\n") if filename_bit else "") + build_error.get("error")
94
101
  click.echo(FeedbackManager.error(message=error_msg))
95
102
  else:
96
103
  click.echo(FeedbackManager.error(message=f"Unknown build result. Error: {result.get('error')}"))
@@ -99,3 +106,19 @@ def build_project(folder: str, tb_client: TinyB) -> None:
99
106
  finally:
100
107
  for fd in fds:
101
108
  fd.close()
109
+
110
+
111
+ async def append_fixture(
112
+ tb_client: TinyB,
113
+ datasource_name: str,
114
+ url: str,
115
+ ):
116
+ await tb_client.datasource_truncate(datasource_name)
117
+ await push_data(
118
+ tb_client,
119
+ datasource_name,
120
+ url,
121
+ mode="append",
122
+ concurrency=1,
123
+ silent=True,
124
+ )
@@ -172,21 +172,7 @@ def build_client(
172
172
  build_ok = asyncio.run(build_once(filenames))
173
173
 
174
174
  if watch:
175
- paths = [Path(f) for f in get_project_filenames(folder, with_vendor=True)]
176
-
177
- datasource_paths = [f for f in paths if f.suffix == ".datasource"]
178
- datasources = [f.stem for f in datasource_paths if not is_vendor(f)]
179
- shared_datasources = [f"{get_vendor_workspace(f)}.{f.stem}" for f in datasource_paths if is_vendor(f)]
180
- pipes = [f.stem for f in paths if is_pipe(f) and not is_endpoint(f)]
181
- endpoints = [f.stem for f in paths if is_endpoint(f)]
182
- shell = Shell(
183
- folder=folder,
184
- client=tb_client,
185
- datasources=datasources,
186
- shared_datasources=shared_datasources,
187
- pipes=pipes,
188
- endpoints=endpoints,
189
- )
175
+ shell = Shell(folder=folder, client=tb_client)
190
176
  click.echo(FeedbackManager.gray(message="\nWatching for changes..."))
191
177
  watcher_thread = threading.Thread(
192
178
  target=watch_files, args=(filenames, process, shell, folder, build_ok), daemon=True
@@ -94,7 +94,7 @@ VERSION = f"{__cli__.__version__} (rev {__cli__.__revision__})"
94
94
  "--with-headers", help="Flag to enable connector to export with headers", is_flag=True, default=False, hidden=True
95
95
  )
96
96
  @click.option("--show-tokens", is_flag=True, default=False, help="Enable the output of tokens")
97
- @click.option("--prod", is_flag=True, default=False, help="Run against production")
97
+ @click.option("--prod/--local", is_flag=True, default=False, help="Run against production or local")
98
98
  @click.version_option(version=VERSION)
99
99
  @click.pass_context
100
100
  @coro
@@ -44,7 +44,7 @@ from tinybird.tb.modules.datafile.exceptions import AlreadyExistsException, Incl
44
44
  from tinybird.tb.modules.datafile.parse_datasource import parse_datasource
45
45
  from tinybird.tb.modules.datafile.parse_pipe import parse_pipe
46
46
  from tinybird.tb.modules.feedback_manager import FeedbackManager
47
- from tinybird.tb.modules.local_common import get_tinybird_local_config
47
+ from tinybird.tb.modules.local_common import get_client_config_for_build
48
48
 
49
49
 
50
50
  async def folder_build(
@@ -58,7 +58,7 @@ async def folder_build(
58
58
  local_ws: Optional[Dict[str, Any]] = None,
59
59
  watch: bool = False,
60
60
  ):
61
- config = await get_tinybird_local_config(folder)
61
+ config = await get_client_config_for_build(folder)
62
62
  build = True
63
63
  dry_run = False
64
64
  force = True
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import functools
2
4
  import glob
3
5
  import itertools
@@ -9,8 +11,9 @@ import shlex
9
11
  import string
10
12
  import textwrap
11
13
  import traceback
12
- from collections import namedtuple
14
+ from collections import Counter, namedtuple
13
15
  from dataclasses import dataclass
16
+ from enum import Enum
14
17
  from io import StringIO
15
18
  from pathlib import Path
16
19
  from string import Template
@@ -29,6 +32,9 @@ from tinybird.tb.modules.feedback_manager import FeedbackManager
29
32
  # from tinybird.sql import parse_indexes_structure, parse_table_structure, schema_to_sql_columns
30
33
 
31
34
 
35
+ class DatafileValidationError(Exception): ...
36
+
37
+
32
38
  class DatafileSyntaxError(Exception):
33
39
  def __init__(self, message: str, lineno: int, pos: int, hint: Optional[str] = None):
34
40
  super().__init__(message)
@@ -155,6 +161,22 @@ valid_chars_name: str = string.ascii_letters + string.digits + "._`*<>+-'"
155
161
  valid_chars_fn: str = valid_chars_name + "[](),=!?:/ \n\t\r"
156
162
 
157
163
 
164
+ class UnkownExtensionerror(Exception): ...
165
+
166
+
167
+ class DatafileKind(Enum):
168
+ pipe = "pipe"
169
+ datasource = "datasource"
170
+
171
+ @classmethod
172
+ def from_extension(cls, extension: str) -> DatafileKind:
173
+ if extension == ".pipe":
174
+ return cls.pipe
175
+ elif extension == ".datasource":
176
+ return cls.datasource
177
+ raise UnkownExtensionerror(f"Unknown extension {extension} for data file")
178
+
179
+
158
180
  class Datafile:
159
181
  def __init__(self) -> None:
160
182
  self.maintainer: Optional[str] = None
@@ -167,6 +189,7 @@ class Datafile:
167
189
  self.shared_with: List[str] = []
168
190
  self.warnings: List[str] = []
169
191
  self.filtering_tags: Optional[List[str]] = None
192
+ self.kind: Optional[DatafileKind] = None
170
193
 
171
194
  def is_equal(self, other):
172
195
  if len(self.nodes) != len(other.nodes):
@@ -174,6 +197,40 @@ class Datafile:
174
197
 
175
198
  return all(self.nodes[i] == other.nodes[i] for i, _ in enumerate(self.nodes))
176
199
 
200
+ def set_kind(self, kind: DatafileKind):
201
+ self.kind = kind
202
+
203
+ def validate(self):
204
+ if self.kind == DatafileKind.pipe:
205
+ # TODO(eclbg):
206
+ # [x] node names are unique
207
+ # [ ] ...
208
+ repeated_node_names = [
209
+ name for name, count in filter(lambda x: x[1] > 1, Counter(n["name"] for n in self.nodes).items())
210
+ ]
211
+ if repeated_node_names:
212
+ raise DatafileValidationError(
213
+ f"Pipe node names must be unique. These names are repeated: {repeated_node_names}"
214
+ )
215
+ pass
216
+ elif self.kind == DatafileKind.datasource:
217
+ # TODO(eclbg):
218
+ # [x] Just one node
219
+ # [x] Engine is present
220
+ # [ ] ...
221
+ if len(self.nodes) > 1:
222
+ # Our users are not aware of data source data files being a single-node data file, hence this error
223
+ # message which might be confusing for us devs
224
+ raise DatafileValidationError("Datasource files cannot have nodes defined")
225
+ node = self.nodes[0]
226
+ if "schema" not in node:
227
+ raise DatafileValidationError("SCHEMA is mandatory")
228
+ if "engine" not in node:
229
+ raise DatafileValidationError("ENGINE is mandatory")
230
+ else:
231
+ # We cannot validate a datafile whose kind is unknown
232
+ pass
233
+
177
234
 
178
235
  def format_filename(filename: str, hide_folders: bool = False):
179
236
  return os.path.basename(filename) if hide_folders else filename
@@ -1016,6 +1073,7 @@ def parse(
1016
1073
  basepath: str = ".",
1017
1074
  replace_includes: bool = True,
1018
1075
  skip_eval: bool = False,
1076
+ kind: Optional[DatafileKind] = None,
1019
1077
  ) -> Datafile:
1020
1078
  """
1021
1079
  Parses `s` string into a document
@@ -1032,6 +1090,8 @@ def parse(
1032
1090
  lines = list(StringIO(s, newline=None))
1033
1091
 
1034
1092
  doc = Datafile()
1093
+ if kind is not None:
1094
+ doc.set_kind(kind)
1035
1095
  doc.raw = list(StringIO(s, newline=None))
1036
1096
 
1037
1097
  parser_state = namedtuple(
@@ -1098,7 +1158,8 @@ def parse(
1098
1158
  except IndexesSyntaxError as e:
1099
1159
  raise e
1100
1160
  except Exception as e:
1101
- # TODO(eclbg): We get here when an unidentified error happens but we still report a parsing error. We could rething this.
1161
+ # TODO(eclbg): We get here when an unidentified error happens but we still report a parsing error. We should
1162
+ # rethink this.
1102
1163
  raise ParseException(FeedbackManager.error_parsing_indices(line=kwargs["lineno"], error=e))
1103
1164
 
1104
1165
  parser_state.current_node["indexes"] = indexes
@@ -5,6 +5,7 @@ import click
5
5
 
6
6
  from tinybird.tb.modules.datafile.common import (
7
7
  Datafile,
8
+ DatafileKind,
8
9
  DatafileSyntaxError,
9
10
  format_filename,
10
11
  parse,
@@ -31,20 +32,21 @@ def parse_datasource(
31
32
 
32
33
  filename = format_filename(filename, hide_folders)
33
34
  try:
34
- doc = parse(s, "default", basepath, replace_includes=replace_includes, skip_eval=skip_eval)
35
+ doc = parse(
36
+ s, "default", basepath, replace_includes=replace_includes, skip_eval=skip_eval, kind=DatafileKind.datasource
37
+ )
38
+ doc.validate()
35
39
  except DatafileSyntaxError as e:
36
40
  try:
37
41
  if add_context_to_datafile_syntax_errors:
38
42
  e.get_context_from_file_contents(s)
39
43
  finally:
40
44
  raise e
45
+ # TODO(eclbg): all these exceptions that trigger a ClickException shouldn't be here, as this code will only run in
46
+ # the server soon
41
47
  except ParseException as e:
42
48
  raise click.ClickException(
43
49
  FeedbackManager.error_parsing_file(filename=filename, lineno=e.lineno, error=e)
44
50
  ) from None
45
51
 
46
- if len(doc.nodes) > 1:
47
- # TODO(eclbg): Turn this into a custom exception with a better message
48
- raise ValueError(f"{filename}: datasources can't have more than one node")
49
-
50
52
  return doc
@@ -6,6 +6,7 @@ import click
6
6
  from tinybird.sql_template import get_template_and_variables, render_sql_template
7
7
  from tinybird.tb.modules.datafile.common import (
8
8
  Datafile,
9
+ DatafileKind,
9
10
  DatafileSyntaxError,
10
11
  format_filename,
11
12
  parse,
@@ -35,7 +36,10 @@ def parse_pipe(
35
36
  try:
36
37
  sql = ""
37
38
  try:
38
- doc = parse(s, basepath=basepath, replace_includes=replace_includes, skip_eval=skip_eval)
39
+ doc = parse(
40
+ s, basepath=basepath, replace_includes=replace_includes, skip_eval=skip_eval, kind=DatafileKind.pipe
41
+ )
42
+ doc.validate()
39
43
  except DatafileSyntaxError as e:
40
44
  try:
41
45
  if add_context_to_datafile_syntax_errors:
@@ -53,6 +57,8 @@ def parse_pipe(
53
57
  from tinybird.sql_toolset import format_sql as toolset_format_sql
54
58
 
55
59
  toolset_format_sql(sql)
60
+ # TODO(eclbg): all these exceptions that trigger a ClickException shouldn't be here, as this code will only run in
61
+ # the server soon
56
62
  except ParseException as e:
57
63
  raise click.ClickException(
58
64
  FeedbackManager.error_parsing_file(
@@ -10,7 +10,6 @@ import requests
10
10
 
11
11
  from tinybird.tb.modules.cli import cli
12
12
  from tinybird.tb.modules.common import echo_safe_humanfriendly_tables_format_smart_table
13
- from tinybird.tb.modules.config import CLIConfig
14
13
  from tinybird.tb.modules.feedback_manager import FeedbackManager
15
14
 
16
15
 
@@ -128,7 +127,8 @@ def deploy_group() -> None:
128
127
  default=False,
129
128
  help="Auto-promote the deployment. Only works if --wait is enabled. Disabled by default.",
130
129
  )
131
- def create(project_path: Path, wait: bool, auto: bool) -> None:
130
+ @click.pass_context
131
+ def create(ctx: click.Context, project_path: Path, wait: bool, auto: bool) -> None:
132
132
  """
133
133
  Validate and deploy the project server side.
134
134
  """
@@ -140,9 +140,9 @@ def create(project_path: Path, wait: bool, auto: bool) -> None:
140
140
  ".pipe": "text/plain",
141
141
  }
142
142
 
143
- config = CLIConfig.get_project_config(str(project_path))
144
- TINYBIRD_API_URL = f"{config.get_host()}/v1/deploy"
145
- TINYBIRD_API_KEY = config.get_token()
143
+ client = ctx.ensure_object(dict)["client"]
144
+ TINYBIRD_API_URL = f"{client.host}/v1/deploy"
145
+ TINYBIRD_API_KEY = client.token
146
146
 
147
147
  files = [
148
148
  ("context://", ("cli-version", "1.0.0", "text/plain")),
@@ -186,7 +186,7 @@ def create(project_path: Path, wait: bool, auto: bool) -> None:
186
186
  if deployment and wait:
187
187
  while deployment.get("status") != "data_ready":
188
188
  time.sleep(5)
189
- TINYBIRD_API_URL = f"{config.get_host()}/v1/deployments/{deployment.get('id')}"
189
+ TINYBIRD_API_URL = f"{client.host}/v1/deployments/{deployment.get('id')}"
190
190
  r = requests.get(TINYBIRD_API_URL, headers=HEADERS)
191
191
  result = r.json()
192
192
  deployment = result.get("deployment")
@@ -197,20 +197,21 @@ def create(project_path: Path, wait: bool, auto: bool) -> None:
197
197
  click.echo(FeedbackManager.success(message="Deployment is ready"))
198
198
 
199
199
  if auto:
200
- promote_deployment(config.get_host(), HEADERS)
200
+ promote_deployment(client.host, HEADERS)
201
201
 
202
202
 
203
203
  @deploy_group.command(name="list")
204
204
  @click.argument("project_path", type=click.Path(exists=True), default=Path.cwd())
205
- def deploy_list(project_path: Path) -> None:
205
+ @click.pass_context
206
+ def deploy_list(ctx: click.Context, project_path: Path) -> None:
206
207
  """
207
208
  List all the deployments you have in the project.
208
209
  """
209
- config = CLIConfig.get_project_config(str(project_path))
210
+ client = ctx.ensure_object(dict)["client"]
210
211
 
211
- TINYBIRD_API_KEY = config.get_token()
212
+ TINYBIRD_API_KEY = client.token
212
213
  HEADERS = {"Authorization": f"Bearer {TINYBIRD_API_KEY}"}
213
- TINYBIRD_API_URL = f"{config.get_host()}/v1/deployments"
214
+ TINYBIRD_API_URL = f"{client.host}/v1/deployments"
214
215
 
215
216
  r = requests.get(TINYBIRD_API_URL, headers=HEADERS)
216
217
  result = r.json()
@@ -228,27 +229,29 @@ def deploy_list(project_path: Path) -> None:
228
229
 
229
230
  @deploy_group.command(name="promote")
230
231
  @click.argument("project_path", type=click.Path(exists=True), default=Path.cwd())
231
- def deploy_promote(project_path: Path) -> None:
232
+ @click.pass_context
233
+ def deploy_promote(ctx: click.Context, project_path: Path) -> None:
232
234
  """
233
235
  Promote last deploy to ready and remove old one.
234
236
  """
235
- config = CLIConfig.get_project_config(str(project_path))
237
+ client = ctx.ensure_object(dict)["client"]
236
238
 
237
- TINYBIRD_API_KEY = config.get_token()
239
+ TINYBIRD_API_KEY = client.token
238
240
  HEADERS = {"Authorization": f"Bearer {TINYBIRD_API_KEY}"}
239
241
 
240
- promote_deployment(config.get_host(), HEADERS)
242
+ promote_deployment(client.host, HEADERS)
241
243
 
242
244
 
243
245
  @deploy_group.command(name="rollback")
244
246
  @click.argument("project_path", type=click.Path(exists=True), default=Path.cwd())
245
- def deploy_rollback(project_path: Path) -> None:
247
+ @click.pass_context
248
+ def deploy_rollback(ctx: click.Context, project_path: Path) -> None:
246
249
  """
247
250
  Rollback to the previous deployment.
248
251
  """
249
- config = CLIConfig.get_project_config(str(project_path))
252
+ client = ctx.ensure_object(dict)["client"]
250
253
 
251
- TINYBIRD_API_KEY = config.get_token()
254
+ TINYBIRD_API_KEY = client.token
252
255
  HEADERS = {"Authorization": f"Bearer {TINYBIRD_API_KEY}"}
253
256
 
254
- rollback_deployment(config.get_host(), HEADERS)
257
+ rollback_deployment(client.host, HEADERS)
@@ -1,5 +1,6 @@
1
1
  import os
2
2
  import re
3
+ import subprocess
3
4
  import time
4
5
 
5
6
  import click
@@ -82,7 +83,9 @@ def get_docker_client():
82
83
  client.ping()
83
84
  return client
84
85
  except Exception:
85
- raise CLIException("No container runtime is running. Make sure a Docker-compatible runtime is installed and running.")
86
+ raise CLIException(
87
+ "No container runtime is running. Make sure a Docker-compatible runtime is installed and running."
88
+ )
86
89
 
87
90
 
88
91
  def stop_tinybird_local(docker_client):
@@ -107,8 +110,17 @@ def remove_tinybird_local(docker_client):
107
110
  def upgrade():
108
111
  """Upgrade Tinybird CLI to the latest version"""
109
112
  click.echo(FeedbackManager.highlight(message="» Upgrading Tinybird CLI..."))
110
- os.system(f"{os.getenv('HOME')}/.local/bin/uv tool upgrade tinybird")
111
- click.echo(FeedbackManager.success(message=" Tinybird CLI upgraded"))
113
+ process = subprocess.Popen(
114
+ [f"{os.getenv('HOME')}/.local/bin/uv", "tool", "upgrade", "tinybird"],
115
+ stdout=subprocess.PIPE,
116
+ stderr=subprocess.PIPE,
117
+ text=True,
118
+ )
119
+ stdout, stderr = process.communicate()
120
+ if "Nothing to upgrade" not in stdout + stderr:
121
+ click.echo(FeedbackManager.success(message="✓ Tinybird CLI upgraded"))
122
+ else:
123
+ click.echo(FeedbackManager.info(message="✓ Tinybird CLI is already up to date"))
112
124
 
113
125
 
114
126
  @cli.group()
@@ -1,4 +1,5 @@
1
1
  import hashlib
2
+ import logging
2
3
  import os
3
4
  from typing import Optional
4
5
 
@@ -16,11 +17,15 @@ TB_LOCAL_HOST = f"http://localhost:{TB_LOCAL_PORT}"
16
17
 
17
18
  async def get_tinybird_local_client(path: Optional[str] = None) -> TinyB:
18
19
  """Get a Tinybird client connected to the local environment."""
19
- config = await get_tinybird_local_config(path)
20
+ config = await get_client_config_for_build(path)
20
21
  return config.get_client(host=TB_LOCAL_HOST)
21
22
 
22
23
 
23
- async def get_tinybird_local_config(path: Optional[str] = None) -> CLIConfig:
24
+ async def get_client_config_for_build(path: Optional[str] = None) -> CLIConfig:
25
+ """Craft a client config with a workspace name based on the path of the project files
26
+
27
+ It uses the tokens from tinybird local
28
+ """
24
29
  config = CLIConfig.get_project_config(path)
25
30
  try:
26
31
  # ruff: noqa: ASYNC210
@@ -37,6 +42,7 @@ async def get_tinybird_local_config(path: Optional[str] = None) -> CLIConfig:
37
42
  user_client = config.get_client(host=TB_LOCAL_HOST, token=user_token)
38
43
 
39
44
  ws_name = f"Tinybird_Local_Build_{folder_hash}"
45
+ logging.debug(f"Workspace used for build: {ws_name}")
40
46
 
41
47
  user_workspaces = await user_client.user_workspaces()
42
48
  ws = next((ws for ws in user_workspaces["workspaces"] if ws["name"] == ws_name), None)
@@ -18,7 +18,12 @@ from tinybird.tb.modules.local_common import get_tinybird_local_client
18
18
  @cli.command()
19
19
  @click.argument("datasource", type=str)
20
20
  @click.option("--rows", type=int, default=10, help="Number of events to send")
21
- @click.option("--prompt", type=str, default="", help="Extra context to use for data generation")
21
+ @click.option(
22
+ "--prompt",
23
+ type=str,
24
+ default="Use the datasource schema to generate sample data",
25
+ help="Extra context to use for data generation",
26
+ )
22
27
  @click.option("--folder", type=str, default=".", help="Folder where datafiles will be placed")
23
28
  @coro
24
29
  async def mock(datasource: str, rows: int, prompt: str, folder: str) -> None:
@@ -68,7 +68,9 @@ def test(ctx: click.Context) -> None:
68
68
  type=click.Path(exists=True, file_okay=False),
69
69
  help="Folder where datafiles will be placed",
70
70
  )
71
- @click.option("--prompt", type=str, default="", help="Prompt to be used to create the test")
71
+ @click.option(
72
+ "--prompt", type=str, default="Create a test for the selected pipe", help="Prompt to be used to create the test"
73
+ )
72
74
  @coro
73
75
  async def test_create(name_or_filename: str, prompt: str, folder: str) -> None:
74
76
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird
3
- Version: 0.0.1.dev32
3
+ Version: 0.0.1.dev34
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
File without changes