tinybird 0.0.1.dev246__py3-none-any.whl → 0.0.1.dev248__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.
- tinybird/ch_utils/constants.py +2 -0
- tinybird/prompts.py +2 -0
- tinybird/tb/__cli__.py +2 -2
- tinybird/tb/modules/agent/agent.py +107 -18
- tinybird/tb/modules/agent/models.py +6 -0
- tinybird/tb/modules/agent/prompts.py +57 -29
- tinybird/tb/modules/agent/tools/append.py +55 -0
- tinybird/tb/modules/agent/tools/build.py +1 -0
- tinybird/tb/modules/agent/tools/create_datafile.py +8 -3
- tinybird/tb/modules/agent/tools/deploy.py +1 -1
- tinybird/tb/modules/agent/tools/mock.py +59 -0
- tinybird/tb/modules/agent/tools/plan.py +1 -1
- tinybird/tb/modules/agent/tools/read_fixture_data.py +28 -0
- tinybird/tb/modules/agent/utils.py +296 -3
- tinybird/tb/modules/build.py +4 -1
- tinybird/tb/modules/build_common.py +2 -3
- tinybird/tb/modules/cli.py +9 -1
- tinybird/tb/modules/create.py +1 -1
- tinybird/tb/modules/feedback_manager.py +1 -0
- tinybird/tb/modules/llm.py +1 -1
- tinybird/tb/modules/login.py +6 -301
- tinybird/tb/modules/login_common.py +310 -0
- tinybird/tb/modules/mock.py +3 -69
- tinybird/tb/modules/mock_common.py +71 -0
- tinybird/tb/modules/project.py +9 -0
- {tinybird-0.0.1.dev246.dist-info → tinybird-0.0.1.dev248.dist-info}/METADATA +1 -1
- {tinybird-0.0.1.dev246.dist-info → tinybird-0.0.1.dev248.dist-info}/RECORD +30 -25
- {tinybird-0.0.1.dev246.dist-info → tinybird-0.0.1.dev248.dist-info}/WHEEL +0 -0
- {tinybird-0.0.1.dev246.dist-info → tinybird-0.0.1.dev248.dist-info}/entry_points.txt +0 -0
- {tinybird-0.0.1.dev246.dist-info → tinybird-0.0.1.dev248.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import difflib
|
|
1
2
|
import os
|
|
2
3
|
from contextlib import contextmanager
|
|
3
|
-
from typing import Any, Callable, List, Optional
|
|
4
|
+
from typing import Any, Callable, List, Optional, Tuple
|
|
4
5
|
|
|
5
6
|
import click
|
|
6
7
|
from prompt_toolkit.application import Application, get_app
|
|
@@ -13,9 +14,17 @@ from prompt_toolkit.layout.dimension import LayoutDimension as D
|
|
|
13
14
|
from prompt_toolkit.mouse_events import MouseEventType
|
|
14
15
|
from prompt_toolkit.patch_stdout import patch_stdout as pt_patch_stdout
|
|
15
16
|
from prompt_toolkit.shortcuts import PromptSession
|
|
16
|
-
from prompt_toolkit.styles import Style
|
|
17
|
+
from prompt_toolkit.styles import Style as PromptStyle
|
|
17
18
|
from pydantic import BaseModel, Field
|
|
18
19
|
|
|
20
|
+
try:
|
|
21
|
+
from colorama import Back, Fore, Style, init
|
|
22
|
+
|
|
23
|
+
init(autoreset=True)
|
|
24
|
+
COLORAMA_AVAILABLE = True
|
|
25
|
+
except ImportError:
|
|
26
|
+
COLORAMA_AVAILABLE = False
|
|
27
|
+
|
|
19
28
|
|
|
20
29
|
class TinybirdAgentContext(BaseModel):
|
|
21
30
|
folder: str
|
|
@@ -26,9 +35,13 @@ class TinybirdAgentContext(BaseModel):
|
|
|
26
35
|
build_project: Callable[..., None]
|
|
27
36
|
deploy_project: Callable[[], None]
|
|
28
37
|
deploy_check_project: Callable[[], None]
|
|
38
|
+
mock_data: Callable[..., list[dict[str, Any]]]
|
|
39
|
+
append_data: Callable[..., None]
|
|
40
|
+
analyze_fixture: Callable[..., dict[str, Any]]
|
|
41
|
+
dangerously_skip_permissions: bool
|
|
29
42
|
|
|
30
43
|
|
|
31
|
-
default_style =
|
|
44
|
+
default_style = PromptStyle.from_dict(
|
|
32
45
|
{
|
|
33
46
|
"separator": "#6C6C6C",
|
|
34
47
|
"questionmark": "#FF9D00 bold",
|
|
@@ -384,3 +397,283 @@ class Datafile(BaseModel):
|
|
|
384
397
|
description: str
|
|
385
398
|
pathname: str
|
|
386
399
|
dependencies: List[str] = Field(default_factory=list)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def create_terminal_box(content: str, new_content: Optional[str] = None, title: Optional[str] = None) -> str:
|
|
403
|
+
"""
|
|
404
|
+
Create a formatted box with automatic line numbers that fills the terminal width.
|
|
405
|
+
Optionally shows a diff between content and new_content.
|
|
406
|
+
|
|
407
|
+
Args:
|
|
408
|
+
content: The original text content to display in the box (without line numbers)
|
|
409
|
+
new_content: Optional new content to show as a diff against the original
|
|
410
|
+
title: Optional title to display as header, if not provided will use first line of content
|
|
411
|
+
|
|
412
|
+
Returns:
|
|
413
|
+
A string containing the formatted box with line numbers added
|
|
414
|
+
"""
|
|
415
|
+
# Get terminal width, default to 80 if can't determine
|
|
416
|
+
try:
|
|
417
|
+
terminal_width = os.get_terminal_size().columns
|
|
418
|
+
except:
|
|
419
|
+
terminal_width = 80
|
|
420
|
+
|
|
421
|
+
# Box characters
|
|
422
|
+
top_left = "╭"
|
|
423
|
+
top_right = "╮"
|
|
424
|
+
bottom_left = "╰"
|
|
425
|
+
bottom_right = "╯"
|
|
426
|
+
horizontal = "─"
|
|
427
|
+
vertical = "│"
|
|
428
|
+
|
|
429
|
+
# Calculate available width for content (terminal_width - 2 borders - 2 spaces padding)
|
|
430
|
+
available_width = terminal_width - 4
|
|
431
|
+
|
|
432
|
+
# Split content into lines
|
|
433
|
+
lines = content.strip().split("\n")
|
|
434
|
+
new_lines = new_content.strip().split("\n") if new_content else []
|
|
435
|
+
|
|
436
|
+
# Check if we have a title parameter or should use first line as header
|
|
437
|
+
header = title
|
|
438
|
+
content_lines = lines
|
|
439
|
+
new_content_lines = new_lines
|
|
440
|
+
|
|
441
|
+
if header is None and lines:
|
|
442
|
+
# Use first line as header if no title provided
|
|
443
|
+
header = lines[0]
|
|
444
|
+
content_lines = lines[1:] if len(lines) > 1 else []
|
|
445
|
+
if new_lines:
|
|
446
|
+
# Skip header in new content too
|
|
447
|
+
new_content_lines = new_lines[1:] if len(new_lines) > 1 else []
|
|
448
|
+
elif header is not None:
|
|
449
|
+
# Title provided, use all content lines as-is
|
|
450
|
+
content_lines = lines
|
|
451
|
+
new_content_lines = new_lines
|
|
452
|
+
|
|
453
|
+
# Process content lines
|
|
454
|
+
processed_lines = []
|
|
455
|
+
|
|
456
|
+
if new_content is None:
|
|
457
|
+
# No diff, just add line numbers
|
|
458
|
+
line_number = 1
|
|
459
|
+
for line in content_lines:
|
|
460
|
+
processed_lines.extend(_process_line(line, line_number, available_width, None))
|
|
461
|
+
line_number += 1
|
|
462
|
+
else:
|
|
463
|
+
# Create diff and process it properly
|
|
464
|
+
diff = list(
|
|
465
|
+
difflib.unified_diff(
|
|
466
|
+
content_lines,
|
|
467
|
+
new_content_lines,
|
|
468
|
+
lineterm="",
|
|
469
|
+
n=3, # Add some context lines
|
|
470
|
+
)
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
# Process the unified diff output
|
|
474
|
+
old_line_num = 1
|
|
475
|
+
new_line_num = 1
|
|
476
|
+
old_index = 0
|
|
477
|
+
new_index = 0
|
|
478
|
+
|
|
479
|
+
# Parse the diff output
|
|
480
|
+
i = 0
|
|
481
|
+
while i < len(diff):
|
|
482
|
+
line = diff[i]
|
|
483
|
+
if line.startswith("@@"):
|
|
484
|
+
# Parse hunk header to get line numbers
|
|
485
|
+
import re
|
|
486
|
+
|
|
487
|
+
match = re.match(r"@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@", line)
|
|
488
|
+
if match:
|
|
489
|
+
old_line_num = int(match.group(1))
|
|
490
|
+
new_line_num = int(match.group(2))
|
|
491
|
+
old_index = old_line_num - 1
|
|
492
|
+
new_index = new_line_num - 1
|
|
493
|
+
elif line.startswith("---") or line.startswith("+++"):
|
|
494
|
+
# Skip file headers
|
|
495
|
+
pass
|
|
496
|
+
elif line.startswith(" "):
|
|
497
|
+
# Context line (unchanged)
|
|
498
|
+
content = line[1:] # Remove the leading space
|
|
499
|
+
if old_index < len(content_lines) and content_lines[old_index] == content:
|
|
500
|
+
processed_lines.extend(_process_line(content, old_line_num, available_width, None))
|
|
501
|
+
old_line_num += 1
|
|
502
|
+
new_line_num += 1
|
|
503
|
+
old_index += 1
|
|
504
|
+
new_index += 1
|
|
505
|
+
elif line.startswith("-"):
|
|
506
|
+
# Removed line
|
|
507
|
+
content = line[1:] # Remove the leading minus
|
|
508
|
+
processed_lines.extend(_process_line(content, old_line_num, available_width, "-"))
|
|
509
|
+
old_line_num += 1
|
|
510
|
+
old_index += 1
|
|
511
|
+
elif line.startswith("+"):
|
|
512
|
+
# Added line
|
|
513
|
+
content = line[1:] # Remove the leading plus
|
|
514
|
+
processed_lines.extend(_process_line(content, new_line_num, available_width, "+"))
|
|
515
|
+
new_line_num += 1
|
|
516
|
+
new_index += 1
|
|
517
|
+
i += 1
|
|
518
|
+
|
|
519
|
+
# Add any remaining unchanged lines that weren't in the diff
|
|
520
|
+
while old_index < len(content_lines) and new_index < len(new_content_lines):
|
|
521
|
+
if content_lines[old_index] == new_content_lines[new_index]:
|
|
522
|
+
processed_lines.extend(_process_line(content_lines[old_index], old_line_num, available_width, None))
|
|
523
|
+
old_line_num += 1
|
|
524
|
+
new_line_num += 1
|
|
525
|
+
old_index += 1
|
|
526
|
+
new_index += 1
|
|
527
|
+
else:
|
|
528
|
+
break
|
|
529
|
+
|
|
530
|
+
# Build the box
|
|
531
|
+
result = []
|
|
532
|
+
|
|
533
|
+
# Top border
|
|
534
|
+
result.append(top_left + horizontal * (terminal_width - 2) + top_right)
|
|
535
|
+
|
|
536
|
+
# Add header if exists
|
|
537
|
+
if header:
|
|
538
|
+
# Center the header
|
|
539
|
+
header_padding = (available_width - len(header)) // 2
|
|
540
|
+
header_line = (
|
|
541
|
+
vertical
|
|
542
|
+
+ " "
|
|
543
|
+
+ " " * header_padding
|
|
544
|
+
+ header
|
|
545
|
+
+ " " * (available_width - len(header) - header_padding)
|
|
546
|
+
+ " "
|
|
547
|
+
+ vertical
|
|
548
|
+
)
|
|
549
|
+
result.append(header_line)
|
|
550
|
+
# Empty line after header
|
|
551
|
+
result.append(vertical + " " * (terminal_width - 2) + vertical)
|
|
552
|
+
|
|
553
|
+
# Content lines
|
|
554
|
+
for line_num, content, diff_marker in processed_lines:
|
|
555
|
+
if line_num is not None:
|
|
556
|
+
# Line with number
|
|
557
|
+
if COLORAMA_AVAILABLE:
|
|
558
|
+
line_num_str = f"{Fore.LIGHTBLACK_EX}{line_num:>4}{Style.RESET_ALL}"
|
|
559
|
+
else:
|
|
560
|
+
line_num_str = f"{line_num:>4}"
|
|
561
|
+
|
|
562
|
+
if diff_marker:
|
|
563
|
+
if COLORAMA_AVAILABLE:
|
|
564
|
+
if diff_marker == "-":
|
|
565
|
+
# Fill the entire content area with red background
|
|
566
|
+
content_with_bg = f"{Back.RED}{diff_marker} {content}{Style.RESET_ALL}"
|
|
567
|
+
# Calculate padding needed for the content area
|
|
568
|
+
content_area_width = available_width - 9 # 9 is reduced prefix length
|
|
569
|
+
content_padding = content_area_width - len(f"{diff_marker} {content}")
|
|
570
|
+
if content_padding > 0:
|
|
571
|
+
content_with_bg = (
|
|
572
|
+
f"{Back.RED}{diff_marker} {content}{' ' * content_padding}{Style.RESET_ALL}"
|
|
573
|
+
)
|
|
574
|
+
line = f"{vertical} {line_num_str} {content_with_bg}"
|
|
575
|
+
elif diff_marker == "+":
|
|
576
|
+
# Fill the entire content area with green background
|
|
577
|
+
content_with_bg = f"{Back.GREEN}{diff_marker} {content}{Style.RESET_ALL}"
|
|
578
|
+
# Calculate padding needed for the content area
|
|
579
|
+
content_area_width = available_width - 9 # 9 is reduced prefix length
|
|
580
|
+
content_padding = content_area_width - len(f"{diff_marker} {content}")
|
|
581
|
+
if content_padding > 0:
|
|
582
|
+
content_with_bg = (
|
|
583
|
+
f"{Back.GREEN}{diff_marker} {content}{' ' * content_padding}{Style.RESET_ALL}"
|
|
584
|
+
)
|
|
585
|
+
line = f"{vertical} {line_num_str} {content_with_bg}"
|
|
586
|
+
else:
|
|
587
|
+
line = f"{vertical} {line_num:>4} {diff_marker} {content}"
|
|
588
|
+
else:
|
|
589
|
+
line = f"{vertical} {line_num_str} {content}"
|
|
590
|
+
else:
|
|
591
|
+
# Continuation line without number - fill background starting from where symbol would be
|
|
592
|
+
if diff_marker and COLORAMA_AVAILABLE:
|
|
593
|
+
if diff_marker == "-":
|
|
594
|
+
# Calculate how much space we need to fill with background
|
|
595
|
+
content_area_width = available_width - 9 # 9 is reduced prefix length
|
|
596
|
+
content_padding = content_area_width - len(
|
|
597
|
+
content
|
|
598
|
+
) # Don't subtract spaces, they're in the background
|
|
599
|
+
if content_padding > 0:
|
|
600
|
+
line = f"{vertical} {Back.RED} {content}{' ' * content_padding}{Style.RESET_ALL}"
|
|
601
|
+
else:
|
|
602
|
+
line = f"{vertical} {Back.RED} {content}{Style.RESET_ALL}"
|
|
603
|
+
elif diff_marker == "+":
|
|
604
|
+
# Calculate how much space we need to fill with background
|
|
605
|
+
content_area_width = available_width - 9 # 9 is reduced prefix length
|
|
606
|
+
content_padding = content_area_width - len(
|
|
607
|
+
content
|
|
608
|
+
) # Don't subtract spaces, they're in the background
|
|
609
|
+
if content_padding > 0:
|
|
610
|
+
line = f"{vertical} {Back.GREEN} {content}{' ' * content_padding}{Style.RESET_ALL}"
|
|
611
|
+
else:
|
|
612
|
+
line = f"{vertical} {Back.GREEN} {content}{Style.RESET_ALL}"
|
|
613
|
+
else:
|
|
614
|
+
line = f"{vertical} {content}"
|
|
615
|
+
|
|
616
|
+
# Pad to terminal width
|
|
617
|
+
# Need to account for ANSI escape sequences not taking visual space
|
|
618
|
+
if COLORAMA_AVAILABLE:
|
|
619
|
+
# Calculate visible length (excluding ANSI codes)
|
|
620
|
+
visible_line = line
|
|
621
|
+
# Remove all ANSI escape sequences for length calculation
|
|
622
|
+
import re
|
|
623
|
+
|
|
624
|
+
ansi_escape = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
|
|
625
|
+
visible_line = ansi_escape.sub("", visible_line)
|
|
626
|
+
padding_needed = terminal_width - len(visible_line) - 1
|
|
627
|
+
else:
|
|
628
|
+
padding_needed = terminal_width - len(line) - 1
|
|
629
|
+
|
|
630
|
+
line += " " * padding_needed + vertical
|
|
631
|
+
result.append(line)
|
|
632
|
+
|
|
633
|
+
# Empty line before bottom (only if we have content)
|
|
634
|
+
if processed_lines:
|
|
635
|
+
result.append(vertical + " " * (terminal_width - 2) + vertical)
|
|
636
|
+
|
|
637
|
+
# Bottom border
|
|
638
|
+
result.append(bottom_left + horizontal * (terminal_width - 2) + bottom_right)
|
|
639
|
+
|
|
640
|
+
return "\n".join(result)
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
def _process_line(
|
|
644
|
+
line: str, line_number: int, available_width: int, diff_marker: Optional[str]
|
|
645
|
+
) -> List[Tuple[Optional[int], str, Optional[str]]]:
|
|
646
|
+
"""
|
|
647
|
+
Process a single line, handling wrapping if necessary.
|
|
648
|
+
|
|
649
|
+
Returns a list of tuples (line_number, content, diff_marker)
|
|
650
|
+
"""
|
|
651
|
+
# Calculate space needed for line number and spacing
|
|
652
|
+
# " 9999 " for normal lines or " 9999 + " for diff lines
|
|
653
|
+
prefix_length = 9 # Reduced from 13 to 9
|
|
654
|
+
|
|
655
|
+
# Available width for actual content
|
|
656
|
+
content_width = available_width - prefix_length
|
|
657
|
+
|
|
658
|
+
processed: List[Tuple[Optional[int], str, Optional[str]]] = []
|
|
659
|
+
|
|
660
|
+
if len(line) <= content_width:
|
|
661
|
+
# Line fits, add it as is
|
|
662
|
+
processed.append((line_number, line, diff_marker))
|
|
663
|
+
else:
|
|
664
|
+
# Line needs wrapping
|
|
665
|
+
# First line with line number
|
|
666
|
+
first_part = line[:content_width]
|
|
667
|
+
processed.append((line_number, first_part, diff_marker))
|
|
668
|
+
|
|
669
|
+
# Remaining wrapped lines without line numbers
|
|
670
|
+
remaining = line[content_width:]
|
|
671
|
+
while remaining:
|
|
672
|
+
if len(remaining) <= content_width:
|
|
673
|
+
processed.append((None, remaining, diff_marker))
|
|
674
|
+
break
|
|
675
|
+
else:
|
|
676
|
+
processed.append((None, remaining[:content_width], diff_marker))
|
|
677
|
+
remaining = remaining[content_width:]
|
|
678
|
+
|
|
679
|
+
return processed
|
tinybird/tb/modules/build.py
CHANGED
|
@@ -3,7 +3,7 @@ import time
|
|
|
3
3
|
from copy import deepcopy
|
|
4
4
|
from functools import partial
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import Callable, List
|
|
6
|
+
from typing import Any, Callable, Dict, List
|
|
7
7
|
from urllib.parse import urlencode
|
|
8
8
|
|
|
9
9
|
import click
|
|
@@ -32,8 +32,11 @@ def build(ctx: click.Context, watch: bool) -> None:
|
|
|
32
32
|
"""
|
|
33
33
|
Validate and build the project server side.
|
|
34
34
|
"""
|
|
35
|
+
obj: Dict[str, Any] = ctx.ensure_object(dict)
|
|
35
36
|
project: Project = ctx.ensure_object(dict)["project"]
|
|
36
37
|
tb_client: TinyB = ctx.ensure_object(dict)["client"]
|
|
38
|
+
if obj["env"] == "cloud":
|
|
39
|
+
raise click.ClickException(FeedbackManager.error_build_only_supported_in_local())
|
|
37
40
|
|
|
38
41
|
if project.has_deeper_level():
|
|
39
42
|
click.echo(
|
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
import time
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import Optional
|
|
6
|
-
from urllib.parse import urlencode
|
|
6
|
+
from urllib.parse import urlencode, urljoin
|
|
7
7
|
|
|
8
8
|
import click
|
|
9
9
|
import requests
|
|
@@ -25,7 +25,6 @@ def process(
|
|
|
25
25
|
file_changed: Optional[str] = None,
|
|
26
26
|
diff: Optional[str] = None,
|
|
27
27
|
silent: bool = False,
|
|
28
|
-
error: bool = False,
|
|
29
28
|
build_status: Optional[BuildStatus] = None,
|
|
30
29
|
exit_on_error: bool = True,
|
|
31
30
|
) -> Optional[str]:
|
|
@@ -190,7 +189,7 @@ def build_project(project: Project, tb_client: TinyB, silent: bool = False) -> O
|
|
|
190
189
|
".pipe": "text/plain",
|
|
191
190
|
".connection": "text/plain",
|
|
192
191
|
}
|
|
193
|
-
TINYBIRD_API_URL = tb_client.host
|
|
192
|
+
TINYBIRD_API_URL = urljoin(tb_client.host, "/v1/build")
|
|
194
193
|
logging.debug(TINYBIRD_API_URL)
|
|
195
194
|
TINYBIRD_API_KEY = tb_client.token
|
|
196
195
|
error: Optional[str] = None
|
tinybird/tb/modules/cli.py
CHANGED
|
@@ -79,6 +79,13 @@ agent_mode_flag = os.environ.get("TB_AGENT_MODE", "false") == "true"
|
|
|
79
79
|
"--output", type=click.Choice(["human", "json", "csv"], case_sensitive=False), default="human", help="Output format"
|
|
80
80
|
)
|
|
81
81
|
@click.option("--max-depth", type=int, default=3, help="Maximum depth of the project files.")
|
|
82
|
+
@click.option(
|
|
83
|
+
"--dangerously-skip-permissions",
|
|
84
|
+
is_flag=True,
|
|
85
|
+
default=False,
|
|
86
|
+
help="Skip permissions check in agent mode.",
|
|
87
|
+
hidden=True,
|
|
88
|
+
)
|
|
82
89
|
@click.version_option(version=VERSION)
|
|
83
90
|
@click.pass_context
|
|
84
91
|
def cli(
|
|
@@ -93,6 +100,7 @@ def cli(
|
|
|
93
100
|
staging: bool,
|
|
94
101
|
output: str,
|
|
95
102
|
max_depth: int,
|
|
103
|
+
dangerously_skip_permissions: bool,
|
|
96
104
|
) -> None:
|
|
97
105
|
"""
|
|
98
106
|
Use `OBFUSCATE_REGEX_PATTERN` and `OBFUSCATE_PATTERN_SEPARATOR` environment variables to define a regex pattern and a separator (in case of a single string with multiple regex) to obfuscate secrets in the CLI output.
|
|
@@ -196,7 +204,7 @@ def cli(
|
|
|
196
204
|
is_agent_mode = agent_mode_flag and ctx.invoked_subcommand is None
|
|
197
205
|
|
|
198
206
|
if is_agent_mode:
|
|
199
|
-
run_agent(config, project)
|
|
207
|
+
run_agent(config, project, dangerously_skip_permissions)
|
|
200
208
|
|
|
201
209
|
|
|
202
210
|
@cli.command(hidden=True)
|
tinybird/tb/modules/create.py
CHANGED
|
@@ -21,7 +21,7 @@ from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
|
21
21
|
from tinybird.tb.modules.llm import LLM
|
|
22
22
|
from tinybird.tb.modules.llm_utils import extract_xml, parse_xml
|
|
23
23
|
from tinybird.tb.modules.local_common import get_tinybird_local_client
|
|
24
|
-
from tinybird.tb.modules.
|
|
24
|
+
from tinybird.tb.modules.mock_common import create_mock_data
|
|
25
25
|
from tinybird.tb.modules.project import Project
|
|
26
26
|
|
|
27
27
|
|
|
@@ -444,6 +444,7 @@ class FeedbackManager:
|
|
|
444
444
|
error_invalid_output_format = error_message(
|
|
445
445
|
"Invalid output format for this command. Supported formats are: {formats}"
|
|
446
446
|
)
|
|
447
|
+
error_build_only_supported_in_local = error_message("Builds are only supported in Tinybird Local")
|
|
447
448
|
|
|
448
449
|
info_incl_relative_path = info_message("** Relative path {path} does not exist, skipping.")
|
|
449
450
|
info_ignoring_incl_file = info_message(
|