tinybird 0.0.1.dev55__tar.gz → 0.0.1.dev57__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 (102) hide show
  1. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/PKG-INFO +1 -1
  2. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/__cli__.py +2 -2
  3. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/build.py +22 -20
  4. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/create.py +3 -9
  5. tinybird-0.0.1.dev57/tinybird/tb/modules/datafile/fixture.py +30 -0
  6. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/login.py +19 -12
  7. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/mock.py +3 -4
  8. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/token.py +2 -1
  9. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/watch.py +4 -116
  10. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird.egg-info/PKG-INFO +1 -1
  11. tinybird-0.0.1.dev55/tinybird/tb/modules/datafile/fixture.py +0 -57
  12. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/setup.cfg +0 -0
  13. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/__cli__.py +0 -0
  14. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/ch_utils/constants.py +0 -0
  15. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/ch_utils/engine.py +0 -0
  16. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/check_pypi.py +0 -0
  17. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/client.py +0 -0
  18. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/config.py +0 -0
  19. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/connectors.py +0 -0
  20. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/context.py +0 -0
  21. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/datafile.py +0 -0
  22. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/datatypes.py +0 -0
  23. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/feedback_manager.py +0 -0
  24. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/git_settings.py +0 -0
  25. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/prompts.py +0 -0
  26. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/sql.py +0 -0
  27. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/sql_template.py +0 -0
  28. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/sql_template_fmt.py +0 -0
  29. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/sql_toolset.py +0 -0
  30. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/syncasync.py +0 -0
  31. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/cli.py +0 -0
  32. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/auth.py +0 -0
  33. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/cicd.py +0 -0
  34. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/cli.py +0 -0
  35. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/common.py +0 -0
  36. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/config.py +0 -0
  37. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/copy.py +0 -0
  38. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/build.py +0 -0
  39. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/build_common.py +0 -0
  40. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
  41. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
  42. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/common.py +0 -0
  43. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/diff.py +0 -0
  44. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/exceptions.py +0 -0
  45. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/format_common.py +0 -0
  46. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
  47. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
  48. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/parse_datasource.py +0 -0
  49. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/parse_pipe.py +0 -0
  50. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
  51. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/pull.py +0 -0
  52. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datasource.py +0 -0
  53. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/deployment.py +0 -0
  54. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/endpoint.py +0 -0
  55. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/exceptions.py +0 -0
  56. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/feedback_manager.py +0 -0
  57. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/fmt.py +0 -0
  58. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/job.py +0 -0
  59. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/llm.py +0 -0
  60. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/llm_utils.py +0 -0
  61. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/local.py +0 -0
  62. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/local_common.py +0 -0
  63. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/materialization.py +0 -0
  64. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/pipe.py +0 -0
  65. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/project.py +0 -0
  66. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/regions.py +0 -0
  67. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/shell.py +0 -0
  68. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/table.py +0 -0
  69. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/tag.py +0 -0
  70. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/telemetry.py +0 -0
  71. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/test.py +0 -0
  72. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
  73. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
  74. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/workspace.py +0 -0
  75. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/workspace_members.py +0 -0
  76. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli.py +0 -0
  77. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/auth.py +0 -0
  78. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/branch.py +0 -0
  79. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/cicd.py +0 -0
  80. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/cli.py +0 -0
  81. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/common.py +0 -0
  82. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/config.py +0 -0
  83. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/connection.py +0 -0
  84. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/datasource.py +0 -0
  85. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/exceptions.py +0 -0
  86. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/fmt.py +0 -0
  87. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/job.py +0 -0
  88. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/pipe.py +0 -0
  89. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/regions.py +0 -0
  90. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/tag.py +0 -0
  91. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/telemetry.py +0 -0
  92. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/test.py +0 -0
  93. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  94. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  95. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/workspace.py +0 -0
  96. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  97. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tornado_template.py +0 -0
  98. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird.egg-info/SOURCES.txt +0 -0
  99. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird.egg-info/dependency_links.txt +0 -0
  100. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird.egg-info/entry_points.txt +0 -0
  101. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird.egg-info/requires.txt +0 -0
  102. {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/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.dev55
3
+ Version: 0.0.1.dev57
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.dev55'
8
- __revision__ = 'cc01364'
7
+ __version__ = '0.0.1.dev57'
8
+ __revision__ = '0af16b9'
@@ -14,7 +14,7 @@ from tinybird.client import TinyB
14
14
  from tinybird.tb.modules.cli import cli
15
15
  from tinybird.tb.modules.common import push_data
16
16
  from tinybird.tb.modules.datafile.build import folder_build
17
- from tinybird.tb.modules.datafile.fixture import build_fixture_name, get_fixture_dir
17
+ from tinybird.tb.modules.datafile.fixture import get_fixture_dir
18
18
  from tinybird.tb.modules.feedback_manager import FeedbackManager
19
19
  from tinybird.tb.modules.project import Project
20
20
  from tinybird.tb.modules.shell import Shell, print_table_formatted
@@ -31,13 +31,18 @@ def build(ctx: click.Context, watch: bool) -> None:
31
31
  project: Project = ctx.ensure_object(dict)["project"]
32
32
  tb_client: TinyB = ctx.ensure_object(dict)["client"]
33
33
  click.echo(FeedbackManager.highlight_building_project())
34
- time_start = time.time()
35
34
 
36
- def process(file_changed: Optional[str] = None, diff: Optional[str] = None) -> None:
35
+ def process(watch: bool, file_changed: Optional[str] = None, diff: Optional[str] = None) -> None:
36
+ time_start = time.time()
37
+ build_failed = False
37
38
  if file_changed and file_changed.endswith(".ndjson"):
38
39
  rebuild_fixture(project, tb_client, file_changed)
39
40
  else:
40
- build_project(project, tb_client, file_changed)
41
+ try:
42
+ build_project(project, tb_client, file_changed)
43
+ except click.ClickException as e:
44
+ click.echo(e)
45
+ build_failed = True
41
46
  try:
42
47
  if file_changed:
43
48
  asyncio.run(folder_build(project, tb_client, filenames=[file_changed]))
@@ -45,16 +50,18 @@ def build(ctx: click.Context, watch: bool) -> None:
45
50
  except Exception:
46
51
  pass
47
52
 
48
- try:
49
- process()
50
- except click.ClickException as e:
51
- click.echo(e)
52
- if not watch:
53
- sys.exit(1)
54
- else:
55
53
  time_end = time.time()
56
54
  elapsed_time = time_end - time_start
57
- click.echo(FeedbackManager.success(message=f"\n✓ Build completed in {elapsed_time:.1f}s"))
55
+
56
+ rebuild_str = "Rebuild" if watch else "Build"
57
+ if build_failed:
58
+ click.echo(FeedbackManager.error(message=f"\n✗ {rebuild_str} failed"))
59
+ if not watch:
60
+ sys.exit(1)
61
+ else:
62
+ click.echo(FeedbackManager.success(message=f"\n✓ {rebuild_str} completed in {elapsed_time:.1f}s"))
63
+
64
+ process(watch=watch)
58
65
 
59
66
  if watch:
60
67
  shell = Shell(project=project, tb_client=tb_client)
@@ -134,18 +141,13 @@ def build_project(project: Project, tb_client: TinyB, file_changed: Optional[str
134
141
  if filename.endswith(".datasource"):
135
142
  ds_path = Path(filename)
136
143
  ds_name = ds_path.stem
137
- name = build_fixture_name(filename, ds_name, ds_path.read_text())
138
144
  fixture_folder = get_fixture_dir(project.folder)
139
- fixture_path = fixture_folder / f"{name}.ndjson"
140
-
141
- if not fixture_path.exists():
142
- fixture_path = fixture_folder / f"{ds_name}.ndjson"
143
-
145
+ fixture_path = fixture_folder / f"{ds_name}.ndjson"
144
146
  if fixture_path.exists():
145
147
  append_fixture(tb_client, ds_name, str(fixture_path))
146
148
 
147
- except Exception:
148
- pass
149
+ except Exception as e:
150
+ click.echo(FeedbackManager.error_exception(error=f"Error appending fixtures for '{ds_name}': {e}"))
149
151
 
150
152
  feedback = result.get("feedback", [])
151
153
  for f in feedback:
@@ -12,7 +12,7 @@ from tinybird.tb.modules.cicd import init_cicd
12
12
  from tinybird.tb.modules.cli import cli
13
13
  from tinybird.tb.modules.common import _generate_datafile, check_user_token_with_client, coro, generate_datafile
14
14
  from tinybird.tb.modules.config import CLIConfig
15
- from tinybird.tb.modules.datafile.fixture import build_fixture_name, persist_fixture
15
+ from tinybird.tb.modules.datafile.fixture import persist_fixture
16
16
  from tinybird.tb.modules.exceptions import CLIException
17
17
  from tinybird.tb.modules.feedback_manager import FeedbackManager
18
18
  from tinybird.tb.modules.llm import LLM
@@ -108,11 +108,8 @@ async def create(
108
108
  ds_name = os.path.basename(data.split(".")[0])
109
109
  data_content = Path(data).read_text()
110
110
  datasource_path = Path(folder) / "datasources" / f"{ds_name}.datasource"
111
- fixture_name = build_fixture_name(
112
- datasource_path.absolute().as_posix(), ds_name, datasource_path.read_text()
113
- )
114
111
  click.echo(FeedbackManager.info(message=f"✓ /fixtures/{ds_name}"))
115
- persist_fixture(fixture_name, data_content, folder)
112
+ persist_fixture(ds_name, data_content, folder)
116
113
  elif prompt and user_token:
117
114
  datasource_files = [f for f in os.listdir(Path(folder) / "datasources") if f.endswith(".datasource")]
118
115
  for datasource_file in datasource_files:
@@ -128,11 +125,8 @@ async def create(
128
125
  sql = sql.split("FORMAT")[0]
129
126
  query_result = await local_client.query(f"{sql} FORMAT JSON")
130
127
  data = query_result.get("data", [])
131
- fixture_name = build_fixture_name(
132
- datasource_path.absolute().as_posix(), datasource_name, datasource_content
133
- )
134
128
  if data:
135
- persist_fixture(fixture_name, data, folder)
129
+ persist_fixture(datasource_name, data, folder)
136
130
  click.echo(FeedbackManager.info(message=f"✓ /fixtures/{datasource_name}"))
137
131
  except Exception as e:
138
132
  click.echo(FeedbackManager.error(message=f"Error: {str(e)}"))
@@ -0,0 +1,30 @@
1
+ from pathlib import Path
2
+ from typing import Any, Dict, List, Union
3
+
4
+ from tinybird.tb.modules.common import format_data_to_ndjson
5
+
6
+
7
+ def get_fixture_dir(folder: str) -> Path:
8
+ fixture_dir = Path(folder) / "fixtures"
9
+ if not fixture_dir.exists():
10
+ fixture_dir.mkdir()
11
+ return fixture_dir
12
+
13
+
14
+ def persist_fixture(fixture_name: str, data: Union[List[Dict[str, Any]], str], folder: str, format="ndjson") -> Path:
15
+ fixture_dir = get_fixture_dir(folder)
16
+ fixture_file = fixture_dir / f"{fixture_name}.{format}"
17
+ fixture_file.write_text(data if isinstance(data, str) else format_data_to_ndjson(data))
18
+ return fixture_file
19
+
20
+
21
+ def load_fixture(
22
+ fixture_name: str,
23
+ folder: str,
24
+ format="ndjson",
25
+ ) -> Union[Path, None]:
26
+ fixture_dir = get_fixture_dir(folder)
27
+ fixture_file = fixture_dir / f"{fixture_name}.{format}"
28
+ if not fixture_file.exists():
29
+ return None
30
+ return fixture_file
@@ -21,11 +21,12 @@ class AuthHandler(http.server.SimpleHTTPRequestHandler):
21
21
  self.send_response(200)
22
22
  self.send_header("Content-type", "text/html")
23
23
  self.end_headers()
24
- self.wfile.write(b"""
24
+ self.wfile.write(
25
+ """
25
26
  <html>
26
27
  <head>
27
28
  <style>
28
- body {
29
+ body {{
29
30
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
30
31
  background: #f5f5f5;
31
32
  display: flex;
@@ -33,7 +34,7 @@ class AuthHandler(http.server.SimpleHTTPRequestHandler):
33
34
  justify-content: center;
34
35
  height: 100vh;
35
36
  margin: 0;
36
- }
37
+ }}
37
38
  </style>
38
39
  </head>
39
40
  <body>
@@ -41,14 +42,16 @@ class AuthHandler(http.server.SimpleHTTPRequestHandler):
41
42
  const searchParams = new URLSearchParams(window.location.search);
42
43
  const code = searchParams.get('code');
43
44
  const workspace = searchParams.get('workspace');
44
- fetch('/?code=' + code, {method: 'POST'})
45
- .then(() => {
46
- window.location.href = "https://cloud.tinybird.co/cli-login?workspace=" + workspace;
47
- });
45
+ const host = "{auth_host}";
46
+ fetch('/?code=' + code, {{method: 'POST'}})
47
+ .then(() => {{
48
+ window.location.href = host + "/cli-login?workspace=" + workspace;
49
+ }});
48
50
  </script>
49
51
  </body>
50
52
  </html>
51
- """)
53
+ """.format(auth_host=self.server.auth_host).encode() # type: ignore
54
+ )
52
55
 
53
56
  def do_POST(self):
54
57
  parsed_path = urllib.parse.urlparse(self.path)
@@ -75,13 +78,14 @@ AUTH_SERVER_PORT = 49160
75
78
  class AuthServer(socketserver.TCPServer):
76
79
  allow_reuse_address = True
77
80
 
78
- def __init__(self, server_address, RequestHandlerClass, auth_callback):
81
+ def __init__(self, server_address, RequestHandlerClass, auth_callback, auth_host):
79
82
  self.auth_callback = auth_callback
83
+ self.auth_host = auth_host
80
84
  super().__init__(server_address, RequestHandlerClass)
81
85
 
82
86
 
83
- def start_server(auth_callback):
84
- with AuthServer(("", AUTH_SERVER_PORT), AuthHandler, auth_callback) as httpd:
87
+ def start_server(auth_callback, auth_host):
88
+ with AuthServer(("", AUTH_SERVER_PORT), AuthHandler, auth_callback, auth_host) as httpd:
85
89
  httpd.timeout = 30
86
90
  start_time = time.time()
87
91
  while time.time() - start_time < 60: # Run for a maximum of 60 seconds
@@ -109,6 +113,9 @@ async def login(host: str, auth_host: str, workspace: str):
109
113
  auth_event = threading.Event()
110
114
  auth_code: list[str] = [] # Using a list to store the code, as it's mutable
111
115
 
116
+ if auth_host == "https://cloud.tinybird.co" and "wadus" in host:
117
+ auth_host = "https://cloud-wadus.tinybird.co"
118
+
112
119
  def auth_callback(code):
113
120
  auth_code.append(code)
114
121
  auth_event.set()
@@ -116,7 +123,7 @@ async def login(host: str, auth_host: str, workspace: str):
116
123
  click.echo(FeedbackManager.highlight(message="» Opening browser for authentication..."))
117
124
 
118
125
  # Start the local server in a separate thread
119
- server_thread = threading.Thread(target=start_server, args=(auth_callback,))
126
+ server_thread = threading.Thread(target=start_server, args=(auth_callback, auth_host))
120
127
  server_thread.daemon = True
121
128
  server_thread.start()
122
129
 
@@ -10,7 +10,7 @@ from tinybird.prompts import mock_prompt
10
10
  from tinybird.tb.modules.cli import cli
11
11
  from tinybird.tb.modules.common import CLIException, check_user_token_with_client, coro
12
12
  from tinybird.tb.modules.config import CLIConfig
13
- from tinybird.tb.modules.datafile.fixture import build_fixture_name, persist_fixture
13
+ from tinybird.tb.modules.datafile.fixture import persist_fixture
14
14
  from tinybird.tb.modules.feedback_manager import FeedbackManager
15
15
  from tinybird.tb.modules.llm import LLM
16
16
  from tinybird.tb.modules.llm_utils import extract_xml
@@ -99,9 +99,8 @@ async def mock(ctx: click.Context, datasource: str, rows: int, prompt: str, skip
99
99
  sql = extract_xml(response, "sql")
100
100
  result = await tb_client.query(f"{sql} FORMAT JSON")
101
101
  data = result.get("data", [])[:rows]
102
- fixture_name = build_fixture_name(str(datasource_path), datasource_name, datasource_content)
103
- fixture_path = persist_fixture(fixture_name, data, folder)
104
- click.echo(FeedbackManager.info(message=f"✓ /fixtures/{fixture_name}.ndjson created"))
102
+ fixture_path = persist_fixture(datasource_name, data, folder)
103
+ click.echo(FeedbackManager.info(message=f"✓ /fixtures/{datasource_name}.ndjson created"))
105
104
 
106
105
  if os.environ.get("TB_DEBUG", "") != "":
107
106
  logging.debug(sql)
@@ -301,7 +301,8 @@ async def create_static_token(ctx, name: str):
301
301
  if current_scope:
302
302
  scopes.append(current_scope)
303
303
  current_scope = {}
304
- current_scope = {"scope": args[i + 1]}
304
+ unsafe_scope = args[i + 1]
305
+ current_scope = {"scope": unsafe_scope.upper() if isinstance(unsafe_scope, str) else unsafe_scope}
305
306
  i += 2
306
307
  elif args[i] == "--resource":
307
308
  if current_scope is None:
@@ -1,16 +1,12 @@
1
- import asyncio
2
1
  import os
3
2
  import time
4
3
  from pathlib import Path
5
- from typing import Any, Callable, List, Optional, Union
4
+ from typing import Any, Callable, Optional, Union
6
5
 
7
6
  import click
8
7
  from watchdog.events import (
9
8
  DirDeletedEvent,
10
- DirMovedEvent,
11
9
  FileDeletedEvent,
12
- FileMovedEvent,
13
- FileSystemEventHandler,
14
10
  PatternMatchingEventHandler,
15
11
  )
16
12
  from watchdog.observers import Observer
@@ -21,113 +17,12 @@ from tinybird.tb.modules.project import Project
21
17
  from tinybird.tb.modules.shell import Shell
22
18
 
23
19
 
24
- class FileChangeHandler(FileSystemEventHandler):
25
- def __init__(self, filenames: List[str], process: Callable[[List[str]], None], build_ok: bool):
26
- self.unprocessed_filenames = [os.path.abspath(f) for f in filenames]
27
- self.process = process
28
- self.build_ok = build_ok
29
-
30
- @property
31
- def filenames(self) -> List[str]:
32
- return [f for f in self.unprocessed_filenames if os.path.exists(f)]
33
-
34
- def should_process(self, event: Any) -> Optional[str]:
35
- if event.is_directory:
36
- return None
37
-
38
- def should_process_path(path: str) -> bool:
39
- if not os.path.exists(path):
40
- return False
41
- is_vendor = "vendor/" in path
42
- if is_vendor:
43
- return False
44
- return any(path.endswith(ext) for ext in [".datasource", ".pipe", ".ndjson"])
45
-
46
- if should_process_path(event.src_path):
47
- return event.src_path
48
-
49
- if should_process_path(event.dest_path):
50
- return event.dest_path
51
-
52
- return None
53
-
54
- def on_modified(self, event: Any) -> None:
55
- if path := self.should_process(event):
56
- filename = path.split("/")[-1]
57
- click.echo(FeedbackManager.highlight(message=f"\n\n⟲ Changes detected in {filename}\n"))
58
- try:
59
- to_process = [path] if self.build_ok else self.filenames
60
- self.process(to_process)
61
- self.build_ok = True
62
- except Exception as e:
63
- click.echo(FeedbackManager.error_exception(error=e))
64
-
65
- def on_moved(self, event: Union[DirMovedEvent, FileMovedEvent]) -> None:
66
- if path := self.should_process(event):
67
- is_new_file = False
68
- if path not in self.unprocessed_filenames:
69
- is_new_file = True
70
- self.unprocessed_filenames.append(path)
71
-
72
- filename = path.split("/")[-1]
73
- if is_new_file:
74
- click.echo(FeedbackManager.highlight(message=f"\n\n⟲ New file detected: {filename}\n"))
75
- else:
76
- click.echo(FeedbackManager.highlight(message=f"\n\n⟲ Changes detected in {filename}\n"))
77
- try:
78
- should_rebuild_all = is_new_file or not self.build_ok
79
- to_process = self.filenames if should_rebuild_all else [path]
80
- self.process(to_process)
81
- self.build_ok = True
82
- except Exception as e:
83
- click.echo(FeedbackManager.error_exception(error=e))
84
-
85
-
86
- def watch_files(
87
- filenames: List[str],
88
- process: Callable,
89
- shell: Shell,
90
- project: Project,
91
- build_ok: bool,
92
- ) -> None:
93
- # Handle both sync and async process functions
94
- async def process_wrapper(files: List[str]) -> None:
95
- click.echo(FeedbackManager.highlight(message="» Rebuilding project..."))
96
- time_start = time.time()
97
- if asyncio.iscoroutinefunction(process):
98
- await process(files, watch=True)
99
- else:
100
- process(files, watch=True)
101
- time_end = time.time()
102
- elapsed_time = time_end - time_start
103
- click.echo(
104
- FeedbackManager.success(message="\n✓ ")
105
- + FeedbackManager.gray(message=f"Rebuild completed in {elapsed_time:.1f}s")
106
- )
107
- shell.reprint_prompt()
108
-
109
- event_handler = FileChangeHandler(filenames, lambda f: asyncio.run(process_wrapper(f)), build_ok)
110
- observer = Observer()
111
-
112
- observer.schedule(event_handler, path=str(project.path), recursive=True)
113
-
114
- observer.start()
115
-
116
- try:
117
- while True:
118
- time.sleep(1)
119
- except KeyboardInterrupt:
120
- observer.stop()
121
-
122
- observer.join()
123
-
124
-
125
20
  class WatchProjectHandler(PatternMatchingEventHandler):
126
21
  def __init__(
127
22
  self,
128
23
  shell: Shell,
129
24
  project: Project,
130
- process: Callable[[Optional[str], Optional[str]], None],
25
+ process: Callable[[bool, Optional[str], Optional[str]], None],
131
26
  ):
132
27
  self.shell = shell
133
28
  self.project = project
@@ -156,14 +51,7 @@ class WatchProjectHandler(PatternMatchingEventHandler):
156
51
 
157
52
  def _process(self, path: Optional[str] = None) -> None:
158
53
  click.echo(FeedbackManager.highlight(message="» Rebuilding project..."))
159
- time_start = time.time()
160
- self.process(path, self.diff(path))
161
- time_end = time.time()
162
- elapsed_time = time_end - time_start
163
- click.echo(
164
- FeedbackManager.success(message="\n✓ ")
165
- + FeedbackManager.gray(message=f"Rebuild completed in {elapsed_time:.1f}s")
166
- )
54
+ self.process(True, path, self.diff(path))
167
55
  self.shell.reprint_prompt()
168
56
 
169
57
  def diff(self, path: Optional[str] = None) -> Optional[str]:
@@ -225,7 +113,7 @@ class WatchProjectHandler(PatternMatchingEventHandler):
225
113
 
226
114
  def watch_project(
227
115
  shell: Shell,
228
- process: Callable[[Optional[str], Optional[str]], None],
116
+ process: Callable[[bool, Optional[str], Optional[str]], None],
229
117
  project: Project,
230
118
  ) -> None:
231
119
  event_handler = WatchProjectHandler(shell=shell, project=project, process=process)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird
3
- Version: 0.0.1.dev55
3
+ Version: 0.0.1.dev57
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -1,57 +0,0 @@
1
- import hashlib
2
- from pathlib import Path
3
- from typing import Any, Dict, List, Union
4
-
5
- from tinybird.tb.modules.common import format_data_to_ndjson
6
- from tinybird.tb.modules.datafile.parse_datasource import parse_datasource
7
-
8
-
9
- def build_fixture_name(filename: str, datasource_name: str, datasource_content: str) -> str:
10
- """Generate a unique fixture name based on datasource properties.
11
-
12
- Args:
13
- datasource_name: Name of the datasource
14
- datasource_content: Content of the datasource file
15
- row_count: Number of rows requested
16
-
17
- Returns:
18
- str: A unique fixture name combining a hash of the inputs with the datasource name
19
- """
20
-
21
- doc = parse_datasource(filename, content=datasource_content)
22
- schema = doc.nodes[0].get("schema", "").strip()
23
- # Combine all inputs into a single string
24
- combined = f"{datasource_name}{schema}"
25
-
26
- # Generate hash
27
- hash_obj = hashlib.sha256(combined.encode())
28
- hash_str = hash_obj.hexdigest()[:8]
29
-
30
- # Return fixture name with hash
31
- return f"{datasource_name}_{hash_str}"
32
-
33
-
34
- def get_fixture_dir(folder: str) -> Path:
35
- fixture_dir = Path(folder) / "fixtures"
36
- if not fixture_dir.exists():
37
- fixture_dir.mkdir()
38
- return fixture_dir
39
-
40
-
41
- def persist_fixture(fixture_name: str, data: Union[List[Dict[str, Any]], str], folder: str, format="ndjson") -> Path:
42
- fixture_dir = get_fixture_dir(folder)
43
- fixture_file = fixture_dir / f"{fixture_name}.{format}"
44
- fixture_file.write_text(data if isinstance(data, str) else format_data_to_ndjson(data))
45
- return fixture_file
46
-
47
-
48
- def load_fixture(
49
- fixture_name: str,
50
- folder: str,
51
- format="ndjson",
52
- ) -> Union[Path, None]:
53
- fixture_dir = get_fixture_dir(folder)
54
- fixture_file = fixture_dir / f"{fixture_name}.{format}"
55
- if not fixture_file.exists():
56
- return None
57
- return fixture_file
File without changes