tinybird 0.0.1.dev22__tar.gz → 0.0.1.dev23__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 (97) hide show
  1. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/PKG-INFO +1 -1
  2. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/__cli__.py +2 -2
  3. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/build.py +1 -1
  4. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/common.py +23 -0
  5. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/config.py +2 -6
  6. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/create.py +13 -10
  7. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/build.py +2 -2
  8. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/build_pipe.py +10 -1
  9. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/common.py +4 -5
  10. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/local_common.py +7 -2
  11. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/mock.py +3 -3
  12. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/test.py +11 -1
  13. tinybird-0.0.1.dev23/tinybird/tb/modules/watch.py +112 -0
  14. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird.egg-info/PKG-INFO +1 -1
  15. tinybird-0.0.1.dev22/tinybird/tb/modules/watch.py +0 -72
  16. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/setup.cfg +0 -0
  17. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/__cli__.py +0 -0
  18. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/ch_utils/constants.py +0 -0
  19. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/ch_utils/engine.py +0 -0
  20. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/check_pypi.py +0 -0
  21. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/client.py +0 -0
  22. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/config.py +0 -0
  23. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/connectors.py +0 -0
  24. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/context.py +0 -0
  25. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/datafile.py +0 -0
  26. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/datatypes.py +0 -0
  27. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/feedback_manager.py +0 -0
  28. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/git_settings.py +0 -0
  29. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/prompts.py +0 -0
  30. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/sql.py +0 -0
  31. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/sql_template.py +0 -0
  32. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/sql_template_fmt.py +0 -0
  33. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/sql_toolset.py +0 -0
  34. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/syncasync.py +0 -0
  35. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/cli.py +0 -0
  36. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/auth.py +0 -0
  37. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/cicd.py +0 -0
  38. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/cli.py +0 -0
  39. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/connection.py +0 -0
  40. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/build_common.py +0 -0
  41. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
  42. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/diff.py +0 -0
  43. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/exceptions.py +0 -0
  44. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/fixture.py +0 -0
  45. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/format_common.py +0 -0
  46. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
  47. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
  48. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/parse_datasource.py +0 -0
  49. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/parse_pipe.py +0 -0
  50. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
  51. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datafile/pull.py +0 -0
  52. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/datasource.py +0 -0
  53. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/exceptions.py +0 -0
  54. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/feedback_manager.py +0 -0
  55. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/fmt.py +0 -0
  56. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/job.py +0 -0
  57. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/llm.py +0 -0
  58. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/local.py +0 -0
  59. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/login.py +0 -0
  60. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/pipe.py +0 -0
  61. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/regions.py +0 -0
  62. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/shell.py +0 -0
  63. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/table.py +0 -0
  64. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/tag.py +0 -0
  65. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/telemetry.py +0 -0
  66. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
  67. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
  68. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/token.py +0 -0
  69. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/workspace.py +0 -0
  70. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb/modules/workspace_members.py +0 -0
  71. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli.py +0 -0
  72. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/auth.py +0 -0
  73. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/branch.py +0 -0
  74. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/cicd.py +0 -0
  75. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/cli.py +0 -0
  76. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/common.py +0 -0
  77. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/config.py +0 -0
  78. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/connection.py +0 -0
  79. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/datasource.py +0 -0
  80. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/exceptions.py +0 -0
  81. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/fmt.py +0 -0
  82. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/job.py +0 -0
  83. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/pipe.py +0 -0
  84. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/regions.py +0 -0
  85. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/tag.py +0 -0
  86. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/telemetry.py +0 -0
  87. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/test.py +0 -0
  88. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  89. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  90. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/workspace.py +0 -0
  91. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  92. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird/tornado_template.py +0 -0
  93. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird.egg-info/SOURCES.txt +0 -0
  94. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird.egg-info/dependency_links.txt +0 -0
  95. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird.egg-info/entry_points.txt +0 -0
  96. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/tinybird.egg-info/requires.txt +0 -0
  97. {tinybird-0.0.1.dev22 → tinybird-0.0.1.dev23}/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.dev22
3
+ Version: 0.0.1.dev23
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.dev22'
8
- __revision__ = 'fad51ec'
7
+ __version__ = '0.0.1.dev23'
8
+ __revision__ = '944a540'
@@ -120,7 +120,7 @@ def build(
120
120
  click.echo(FeedbackManager.success(message=f"\n✓ Build completed in {elapsed_time:.1f}s\n"))
121
121
  ok = True
122
122
  except Exception as e:
123
- click.echo(FeedbackManager.error(message=str(e)))
123
+ click.echo(FeedbackManager.error_exception(error=e))
124
124
  ok = False
125
125
  return ok
126
126
 
@@ -529,6 +529,29 @@ async def check_user_token(ctx: Context, token: str):
529
529
  )
530
530
 
531
531
 
532
+ async def check_user_token_with_client(client: TinyB, token: str):
533
+ try:
534
+ user_client: TinyB = deepcopy(client)
535
+ user_client.token = token
536
+
537
+ is_authenticated = await user_client.check_auth_login()
538
+ except Exception as e:
539
+ raise CLIWorkspaceException(FeedbackManager.error_exception(error=str(e)))
540
+
541
+ if not is_authenticated.get("is_valid", False):
542
+ raise CLIWorkspaceException(
543
+ FeedbackManager.error_exception(
544
+ error='Invalid token. Please, be sure you are using the "user token" instead of the "admin your@email" token.'
545
+ )
546
+ )
547
+ if is_authenticated.get("is_valid") and not is_authenticated.get("is_user", False):
548
+ raise CLIWorkspaceException(
549
+ FeedbackManager.error_exception(
550
+ error='Invalid user authentication. Please, be sure you are using the "user token" instead of the "admin your@email" token.'
551
+ )
552
+ )
553
+
554
+
532
555
  async def get_available_starterkits(ctx: Context) -> List[Dict[str, Any]]:
533
556
  ctx_dict = ctx.ensure_object(dict)
534
557
  available_starterkits = ctx_dict.get("available_starterkits", None)
@@ -321,12 +321,8 @@ class CLIConfig:
321
321
  The data is cached between calls, given the same `working_dir`.
322
322
  """
323
323
  working_dir = working_dir or os.getcwd()
324
- result = CLIConfig._projects.get(working_dir)
325
- if not result:
326
- path: str = os.path.join(working_dir, ".tinyb")
327
- result = CLIConfig(path, parent=CLIConfig.get_global_config())
328
- CLIConfig._projects[working_dir] = result
329
- return result
324
+ path: str = os.path.join(working_dir, ".tinyb")
325
+ return CLIConfig(path, parent=CLIConfig.get_global_config())
330
326
 
331
327
  @staticmethod
332
328
  def get_llm_config(working_dir: Optional[str] = None) -> Dict[str, Any]:
@@ -9,7 +9,7 @@ import requests
9
9
  from tinybird.client import TinyB
10
10
  from tinybird.tb.modules.cicd import init_cicd
11
11
  from tinybird.tb.modules.cli import cli
12
- from tinybird.tb.modules.common import _generate_datafile, check_user_token, coro, generate_datafile
12
+ from tinybird.tb.modules.common import _generate_datafile, check_user_token_with_client, coro, generate_datafile
13
13
  from tinybird.tb.modules.config import CLIConfig
14
14
  from tinybird.tb.modules.datafile.fixture import build_fixture_name, persist_fixture
15
15
  from tinybird.tb.modules.exceptions import CLIException
@@ -37,7 +37,7 @@ from tinybird.tb.modules.llm import LLM
37
37
  )
38
38
  @click.option(
39
39
  "--folder",
40
- default=None,
40
+ default=".",
41
41
  type=click.Path(exists=True, file_okay=False),
42
42
  help="Folder where datafiles will be placed",
43
43
  )
@@ -56,21 +56,24 @@ async def create(
56
56
  folder = folder or getcwd()
57
57
  try:
58
58
  config = CLIConfig.get_project_config(folder)
59
+ tb_client = config.get_client()
59
60
  user_token: Optional[str] = None
60
-
61
61
  if prompt:
62
62
  try:
63
63
  user_token = config.get_user_token()
64
64
  if not user_token:
65
65
  raise CLIException("No user token found")
66
- await check_user_token(ctx, token=user_token)
67
- except Exception:
68
- click.echo(FeedbackManager.error(message="This action requires authentication. Run 'tb login' first."))
66
+ await check_user_token_with_client(tb_client, token=user_token)
67
+ except Exception as e:
68
+ click.echo(
69
+ FeedbackManager.error(
70
+ message=f"This action requires authentication. Run 'tb login' first. Error: {e}"
71
+ )
72
+ )
69
73
  return
70
-
71
- tb_client = config.get_client()
74
+ local_client: TinyB = ctx.ensure_object(dict)["client"]
72
75
  click.echo(FeedbackManager.gray(message="Creating new project structure..."))
73
- await project_create(tb_client, user_token, data, prompt, folder)
76
+ await project_create(local_client, user_token, data, prompt, folder)
74
77
  click.echo(FeedbackManager.success(message="✓ Scaffolding completed!\n"))
75
78
 
76
79
  click.echo(FeedbackManager.gray(message="\nCreating CI/CD files for GitHub and GitLab..."))
@@ -156,7 +159,7 @@ async def create(
156
159
  has_json_path = "`json:" in datasource_content
157
160
  if has_json_path:
158
161
  sql = await llm.generate_sql_sample_data(schema=datasource_content, rows=rows, prompt=prompt)
159
- result = await tb_client.query(f"{sql} FORMAT JSON")
162
+ result = await local_client.query(f"{sql} FORMAT JSON")
160
163
  data = result.get("data", [])
161
164
  fixture_name = build_fixture_name(
162
165
  datasource_path.absolute().as_posix(), datasource_name, datasource_content
@@ -15,7 +15,6 @@ from tinybird.client import TinyB
15
15
  from tinybird.sql import parse_table_structure, schema_to_sql_columns
16
16
  from tinybird.sql_template import get_used_tables_in_template, render_sql_template
17
17
  from tinybird.tb.modules.common import get_ca_pem_content
18
- from tinybird.tb.modules.config import CLIConfig
19
18
  from tinybird.tb.modules.datafile.build_common import update_tags_in_resource
20
19
  from tinybird.tb.modules.datafile.build_datasource import is_datasource, new_ds
21
20
  from tinybird.tb.modules.datafile.build_pipe import (
@@ -45,6 +44,7 @@ from tinybird.tb.modules.datafile.exceptions import AlreadyExistsException, Incl
45
44
  from tinybird.tb.modules.datafile.parse_datasource import parse_datasource
46
45
  from tinybird.tb.modules.datafile.parse_pipe import parse_pipe
47
46
  from tinybird.tb.modules.feedback_manager import FeedbackManager
47
+ from tinybird.tb.modules.local_common import get_tinybird_local_config
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 = CLIConfig.get_project_config()
61
+ config = await get_tinybird_local_config(folder)
62
62
  build = True
63
63
  dry_run = False
64
64
  force = True
@@ -624,8 +624,17 @@ def is_endpoint_with_no_dependencies(
624
624
 
625
625
 
626
626
  def is_endpoint(resource: Optional[Dict[str, Any]]) -> bool:
627
- if resource and len(resource.get("tokens", [])) != 0 and resource.get("resource") == "pipes":
627
+ if not resource:
628
+ return False
629
+ if resource.get("resource") != "pipes":
630
+ return False
631
+
632
+ if len(resource.get("tokens", [])) != 0:
628
633
  return True
634
+
635
+ if any(node.get("params", {}).get("type", None) == "endpoint" for node in resource.get("nodes", [])):
636
+ return True
637
+
629
638
  return False
630
639
 
631
640
 
@@ -1664,11 +1664,10 @@ def find_file_by_name(
1664
1664
  if os.path.isfile(os.path.join(folder, pipe)):
1665
1665
  return pipe, None
1666
1666
 
1667
- if os.path.isfile(f / "endpoints" / pipe):
1668
- return pipe, None
1669
-
1670
- if os.path.isfile(f / "pipes" / pipe):
1671
- return pipe, None
1667
+ pipe_paths = ["endpoints", "materializations", "sinks", "copies", "playgrounds", "pipes"]
1668
+ for pipe_path in pipe_paths:
1669
+ if os.path.isfile(f / pipe_path / pipe):
1670
+ return pipe, None
1672
1671
 
1673
1672
  token = name + ".token"
1674
1673
  if os.path.isfile(f / "tokens" / token):
@@ -16,7 +16,12 @@ TB_LOCAL_HOST = f"http://localhost:{TB_LOCAL_PORT}"
16
16
 
17
17
  async def get_tinybird_local_client(path: Optional[str] = None) -> TinyB:
18
18
  """Get a Tinybird client connected to the local environment."""
19
- config = CLIConfig.get_project_config()
19
+ config = await get_tinybird_local_config(path)
20
+ return config.get_client(host=TB_LOCAL_HOST)
21
+
22
+
23
+ async def get_tinybird_local_config(path: Optional[str] = None) -> CLIConfig:
24
+ config = CLIConfig.get_project_config(path)
20
25
  try:
21
26
  # ruff: noqa: ASYNC210
22
27
  tokens = requests.get(f"{TB_LOCAL_HOST}/tokens").json()
@@ -52,4 +57,4 @@ async def get_tinybird_local_client(path: Optional[str] = None) -> TinyB:
52
57
  config.set_token_for_host(TB_LOCAL_HOST, default_token)
53
58
 
54
59
  config.set_user_token(user_token)
55
- return config.get_client(host=TB_LOCAL_HOST)
60
+ return config
@@ -5,7 +5,7 @@ from pathlib import Path
5
5
  import click
6
6
 
7
7
  from tinybird.tb.modules.cli import cli
8
- from tinybird.tb.modules.common import CLIException, check_user_token, coro
8
+ from tinybird.tb.modules.common import CLIException, check_user_token_with_client, coro
9
9
  from tinybird.tb.modules.config import CLIConfig
10
10
  from tinybird.tb.modules.datafile.fixture import build_fixture_name, persist_fixture
11
11
  from tinybird.tb.modules.feedback_manager import FeedbackManager
@@ -55,11 +55,11 @@ async def mock(ctx: click.Context, datasource: str, rows: int, prompt: str, fold
55
55
  try:
56
56
  if not user_token:
57
57
  raise CLIException("No user token found")
58
- await check_user_token(ctx, token=user_token)
58
+ await check_user_token_with_client(user_client, token=user_token)
59
59
  except Exception:
60
60
  click.echo(FeedbackManager.error(message="This action requires authentication. Run 'tb login' first."))
61
61
  return
62
-
62
+ user_client.token = user_token
63
63
  llm = LLM(user_token=user_token, client=user_client)
64
64
  tb_client = await get_tinybird_local_client(os.path.abspath(folder))
65
65
  sql = await llm.generate_sql_sample_data(datasource_content, rows=rows, prompt=prompt)
@@ -223,6 +223,16 @@ async def test_run(name: Tuple[str, ...], folder: str) -> None:
223
223
  except Exception as e:
224
224
  click.echo(FeedbackManager.error(message=f"✗ {test_file_path.name} - {test['name']}"))
225
225
  click.echo(FeedbackManager.error(message=f"Output and expected output are different: \n{e}"))
226
+ return False
227
+ return True
226
228
 
229
+ tests_failed = False
227
230
  for test_file in file_list:
228
- await run_test(test_file)
231
+ if not await run_test(test_file):
232
+ tests_failed = True
233
+
234
+ if tests_failed:
235
+ click.echo(FeedbackManager.error(message="✗ Some tests failed"))
236
+ exit(1)
237
+ else:
238
+ click.echo(FeedbackManager.success(message="✓ All tests passed"))
@@ -0,0 +1,112 @@
1
+ import asyncio
2
+ import os
3
+ import time
4
+ from typing import Any, Callable, List, Optional, Union
5
+
6
+ import click
7
+ from watchdog.events import DirMovedEvent, FileMovedEvent, FileSystemEventHandler
8
+ from watchdog.observers import Observer
9
+
10
+ from tinybird.tb.modules.feedback_manager import FeedbackManager
11
+ from tinybird.tb.modules.shell import Shell
12
+
13
+
14
+ class FileChangeHandler(FileSystemEventHandler):
15
+ def __init__(self, filenames: List[str], process: Callable[[List[str]], None], build_ok: bool):
16
+ self.unprocessed_filenames = [os.path.abspath(f) for f in filenames]
17
+ self.process = process
18
+ self.build_ok = build_ok
19
+
20
+ @property
21
+ def filenames(self) -> List[str]:
22
+ return [f for f in self.unprocessed_filenames if os.path.exists(f)]
23
+
24
+ def should_process(self, event: Any) -> Optional[str]:
25
+ if event.is_directory:
26
+ return False
27
+
28
+ def should_process_path(path: str) -> bool:
29
+ if not os.path.exists(path):
30
+ return False
31
+ is_vendor = "vendor/" in path
32
+ if is_vendor:
33
+ return False
34
+ return any(path.endswith(ext) for ext in [".datasource", ".pipe", ".ndjson"])
35
+
36
+ if should_process_path(event.src_path):
37
+ return event.src_path
38
+
39
+ if should_process_path(event.dest_path):
40
+ return event.dest_path
41
+
42
+ return None
43
+
44
+ def on_modified(self, event: Any) -> None:
45
+ if path := self.should_process(event):
46
+ filename = path.split("/")[-1]
47
+ click.echo(FeedbackManager.highlight(message=f"\n\n⟲ Changes detected in {filename}\n"))
48
+ try:
49
+ to_process = [path] if self.build_ok else self.filenames
50
+ self.process(to_process)
51
+ self.build_ok = True
52
+ except Exception as e:
53
+ click.echo(FeedbackManager.error_exception(error=e))
54
+
55
+ def on_moved(self, event: Union[DirMovedEvent, FileMovedEvent]) -> None:
56
+ if path := self.should_process(event):
57
+ is_new_file = False
58
+ if path not in self.unprocessed_filenames:
59
+ is_new_file = True
60
+ self.unprocessed_filenames.append(path)
61
+
62
+ filename = path.split("/")[-1]
63
+ if is_new_file:
64
+ click.echo(FeedbackManager.highlight(message=f"\n\n⟲ New file detected: {filename}\n"))
65
+ else:
66
+ click.echo(FeedbackManager.highlight(message=f"\n\n⟲ Changes detected in {filename}\n"))
67
+ try:
68
+ should_rebuild_all = is_new_file or not self.build_ok
69
+ to_process = self.filenames if should_rebuild_all else [path]
70
+ self.process(to_process)
71
+ self.build_ok = True
72
+ except Exception as e:
73
+ click.echo(FeedbackManager.error_exception(error=e))
74
+
75
+
76
+ def watch_files(
77
+ filenames: List[str],
78
+ process: Callable,
79
+ shell: Shell,
80
+ folder: str,
81
+ build_ok: bool,
82
+ ) -> None:
83
+ # Handle both sync and async process functions
84
+ async def process_wrapper(files: List[str]) -> None:
85
+ click.echo("⚡ Rebuilding...")
86
+ time_start = time.time()
87
+ if asyncio.iscoroutinefunction(process):
88
+ await process(files, watch=True)
89
+ else:
90
+ process(files, watch=True)
91
+ time_end = time.time()
92
+ elapsed_time = time_end - time_start
93
+ click.echo(
94
+ FeedbackManager.success(message="\n✓ ")
95
+ + FeedbackManager.gray(message=f"Rebuild completed in {elapsed_time:.1f}s")
96
+ )
97
+ shell.reprint_prompt()
98
+
99
+ event_handler = FileChangeHandler(filenames, lambda f: asyncio.run(process_wrapper(f)), build_ok)
100
+ observer = Observer()
101
+
102
+ observer.schedule(event_handler, path=folder, recursive=True)
103
+
104
+ observer.start()
105
+
106
+ try:
107
+ while True:
108
+ time.sleep(1)
109
+ except KeyboardInterrupt:
110
+ observer.stop()
111
+
112
+ observer.join()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tinybird
3
- Version: 0.0.1.dev22
3
+ Version: 0.0.1.dev23
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/cli/introduction.html
6
6
  Author: Tinybird
@@ -1,72 +0,0 @@
1
- import asyncio
2
- import time
3
- from typing import Any, Callable, List
4
-
5
- import click
6
- from watchdog.events import FileSystemEventHandler
7
- from watchdog.observers import Observer
8
-
9
- from tinybird.tb.modules.feedback_manager import FeedbackManager
10
- from tinybird.tb.modules.shell import Shell
11
-
12
-
13
- class FileChangeHandler(FileSystemEventHandler):
14
- def __init__(self, filenames: List[str], process: Callable[[List[str]], None], build_ok: bool):
15
- self.filenames = filenames
16
- self.process = process
17
- self.build_ok = build_ok
18
-
19
- def on_modified(self, event: Any) -> None:
20
- is_not_vendor = "vendor/" not in event.src_path
21
- if (
22
- is_not_vendor
23
- and not event.is_directory
24
- and any(event.src_path.endswith(ext) for ext in [".datasource", ".pipe", ".ndjson"])
25
- ):
26
- filename = event.src_path.split("/")[-1]
27
- click.echo(FeedbackManager.highlight(message=f"\n\n⟲ Changes detected in {filename}\n"))
28
- try:
29
- to_process = [event.src_path] if self.build_ok else self.filenames
30
- self.process(to_process)
31
- self.build_ok = True
32
- except Exception as e:
33
- click.echo(FeedbackManager.error_exception(error=e))
34
-
35
-
36
- def watch_files(
37
- filenames: List[str],
38
- process: Callable,
39
- shell: Shell,
40
- folder: str,
41
- build_ok: bool,
42
- ) -> None:
43
- # Handle both sync and async process functions
44
- async def process_wrapper(files: List[str]) -> None:
45
- click.echo("⚡ Rebuilding...")
46
- time_start = time.time()
47
- if asyncio.iscoroutinefunction(process):
48
- await process(files, watch=True)
49
- else:
50
- process(files, watch=True)
51
- time_end = time.time()
52
- elapsed_time = time_end - time_start
53
- click.echo(
54
- FeedbackManager.success(message="\n✓ ")
55
- + FeedbackManager.gray(message=f"Rebuild completed in {elapsed_time:.1f}s")
56
- )
57
- shell.reprint_prompt()
58
-
59
- event_handler = FileChangeHandler(filenames, lambda f: asyncio.run(process_wrapper(f)), build_ok)
60
- observer = Observer()
61
-
62
- observer.schedule(event_handler, path=folder, recursive=True)
63
-
64
- observer.start()
65
-
66
- try:
67
- while True:
68
- time.sleep(1)
69
- except KeyboardInterrupt:
70
- observer.stop()
71
-
72
- observer.join()
File without changes