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.
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/PKG-INFO +1 -1
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/__cli__.py +2 -2
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/build.py +22 -20
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/create.py +3 -9
- tinybird-0.0.1.dev57/tinybird/tb/modules/datafile/fixture.py +30 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/login.py +19 -12
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/mock.py +3 -4
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/token.py +2 -1
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/watch.py +4 -116
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird.egg-info/PKG-INFO +1 -1
- tinybird-0.0.1.dev55/tinybird/tb/modules/datafile/fixture.py +0 -57
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/setup.cfg +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/__cli__.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/check_pypi.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/client.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/config.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/connectors.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/context.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/datafile.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/datatypes.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/git_settings.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/prompts.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/sql.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/sql_template.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/sql_toolset.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/syncasync.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/cli.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/auth.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/cicd.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/cli.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/common.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/config.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/copy.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/build.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/common.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/diff.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/exceptions.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/parse_datasource.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/parse_pipe.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/pull.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datasource.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/deployment.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/job.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/local.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/materialization.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/project.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/shell.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/table.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/tag.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/test.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tornado_template.py +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird.egg-info/SOURCES.txt +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird.egg-info/top_level.txt +0 -0
|
@@ -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.
|
|
8
|
-
__revision__ = '
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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"{
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
|
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
|
-
|
|
103
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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,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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/build_datasource.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/format_datasource.py
RENAMED
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb/modules/datafile/parse_datasource.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-0.0.1.dev55 → tinybird-0.0.1.dev57}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|