tinybird 0.0.1.dev6__py3-none-any.whl → 0.0.1.dev7__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/tb/modules/branch.py +0 -21
- tinybird/tb/modules/build.py +7 -18
- tinybird/tb/modules/cli.py +11 -131
- tinybird/tb/modules/common.py +14 -2
- tinybird/tb/modules/create.py +10 -14
- tinybird/tb/modules/datafile/build.py +2103 -0
- tinybird/tb/modules/datafile/build_common.py +118 -0
- tinybird/tb/modules/datafile/build_datasource.py +403 -0
- tinybird/tb/modules/datafile/build_pipe.py +648 -0
- tinybird/tb/modules/datafile/common.py +897 -0
- tinybird/tb/modules/datafile/diff.py +197 -0
- tinybird/tb/modules/datafile/exceptions.py +23 -0
- tinybird/tb/modules/datafile/format_common.py +66 -0
- tinybird/tb/modules/datafile/format_datasource.py +160 -0
- tinybird/tb/modules/datafile/format_pipe.py +195 -0
- tinybird/tb/modules/datafile/parse_datasource.py +41 -0
- tinybird/tb/modules/datafile/parse_pipe.py +69 -0
- tinybird/tb/modules/datafile/pipe_checker.py +560 -0
- tinybird/tb/modules/datafile/pull.py +157 -0
- tinybird/tb/modules/datasource.py +1 -1
- tinybird/tb/modules/fmt.py +4 -1
- tinybird/tb/modules/pipe.py +8 -2
- tinybird/tb/modules/prompts.py +1 -1
- tinybird/tb/modules/workspace.py +1 -1
- {tinybird-0.0.1.dev6.dist-info → tinybird-0.0.1.dev7.dist-info}/METADATA +1 -1
- {tinybird-0.0.1.dev6.dist-info → tinybird-0.0.1.dev7.dist-info}/RECORD +29 -16
- tinybird/tb/modules/datafile.py +0 -6122
- {tinybird-0.0.1.dev6.dist-info → tinybird-0.0.1.dev7.dist-info}/WHEEL +0 -0
- {tinybird-0.0.1.dev6.dist-info → tinybird-0.0.1.dev7.dist-info}/entry_points.txt +0 -0
- {tinybird-0.0.1.dev6.dist-info → tinybird-0.0.1.dev7.dist-info}/top_level.txt +0 -0
tinybird/tb/modules/branch.py
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
# - But please, **do not** interleave utility functions and command definitions.
|
|
5
5
|
|
|
6
6
|
import os
|
|
7
|
-
from os import getcwd
|
|
8
7
|
from typing import List, Optional, Tuple
|
|
9
8
|
|
|
10
9
|
import aiofiles
|
|
@@ -37,7 +36,6 @@ from tinybird.tb.modules.common import (
|
|
|
37
36
|
wait_job,
|
|
38
37
|
)
|
|
39
38
|
from tinybird.tb.modules.config import CLIConfig
|
|
40
|
-
from tinybird.tb.modules.datafile import create_release
|
|
41
39
|
from tinybird.tb.modules.exceptions import CLIBranchException, CLIException, CLIReleaseException
|
|
42
40
|
|
|
43
41
|
|
|
@@ -130,25 +128,6 @@ set -euxo pipefail
|
|
|
130
128
|
click.echo(FeedbackManager.info_release_generated(semver=semver))
|
|
131
129
|
|
|
132
130
|
|
|
133
|
-
@release.command(name="create", short_help="Create a new Release in deploying status")
|
|
134
|
-
@click.option(
|
|
135
|
-
"--semver",
|
|
136
|
-
is_flag=False,
|
|
137
|
-
required=True,
|
|
138
|
-
type=str,
|
|
139
|
-
help="Semver of the new Release. Example: 1.0.0",
|
|
140
|
-
)
|
|
141
|
-
@coro
|
|
142
|
-
async def release_create(semver: str) -> None:
|
|
143
|
-
click.echo(FeedbackManager.warning_deprecated_releases())
|
|
144
|
-
config = CLIConfig.get_project_config()
|
|
145
|
-
_ = await try_update_config_with_remote(config, only_if_needed=True)
|
|
146
|
-
|
|
147
|
-
client = config.get_client()
|
|
148
|
-
folder = getcwd()
|
|
149
|
-
await create_release(client, config, semver, folder)
|
|
150
|
-
|
|
151
|
-
|
|
152
131
|
@release.command(name="promote", short_help="Promotes to live status a preview Release")
|
|
153
132
|
@click.option(
|
|
154
133
|
"--semver", required=True, type=str, help="Semver of a preview Release to promote to live. Example: 1.0.0"
|
tinybird/tb/modules/build.py
CHANGED
|
@@ -3,7 +3,7 @@ import os
|
|
|
3
3
|
import random
|
|
4
4
|
import time
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import Any, Awaitable, Callable,
|
|
6
|
+
from typing import Any, Awaitable, Callable, List, Union
|
|
7
7
|
|
|
8
8
|
import click
|
|
9
9
|
import humanfriendly
|
|
@@ -18,17 +18,12 @@ from tinybird.tb.modules.cli import cli
|
|
|
18
18
|
from tinybird.tb.modules.common import (
|
|
19
19
|
coro,
|
|
20
20
|
)
|
|
21
|
-
from tinybird.tb.modules.datafile import
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
parse_pipe,
|
|
28
|
-
)
|
|
29
|
-
from tinybird.tb.modules.local import (
|
|
30
|
-
get_tinybird_local_client,
|
|
31
|
-
)
|
|
21
|
+
from tinybird.tb.modules.datafile.build import folder_build
|
|
22
|
+
from tinybird.tb.modules.datafile.common import get_project_filenames, has_internal_datafiles
|
|
23
|
+
from tinybird.tb.modules.datafile.exceptions import ParseException
|
|
24
|
+
from tinybird.tb.modules.datafile.parse_datasource import parse_datasource
|
|
25
|
+
from tinybird.tb.modules.datafile.parse_pipe import parse_pipe
|
|
26
|
+
from tinybird.tb.modules.local import get_tinybird_local_client
|
|
32
27
|
from tinybird.tb.modules.table import format_table
|
|
33
28
|
|
|
34
29
|
|
|
@@ -116,9 +111,6 @@ async def build(
|
|
|
116
111
|
context.disable_template_security_validation.set(True)
|
|
117
112
|
is_internal = has_internal_datafiles(folder)
|
|
118
113
|
tb_client = get_tinybird_local_client()
|
|
119
|
-
workspaces: List[Dict[str, Any]] = (await tb_client.user_workspaces_and_branches()).get("workspaces", [])
|
|
120
|
-
datasources: List[Dict[str, Any]] = await tb_client.datasources()
|
|
121
|
-
pipes: List[Dict[str, Any]] = await tb_client.pipes(dependencies=True)
|
|
122
114
|
|
|
123
115
|
def check_filenames(filenames: List[str]):
|
|
124
116
|
parser_matrix = {".pipe": parse_pipe, ".datasource": parse_datasource}
|
|
@@ -142,9 +134,6 @@ async def build(
|
|
|
142
134
|
check_filenames(filenames=filenames)
|
|
143
135
|
await folder_build(
|
|
144
136
|
tb_client,
|
|
145
|
-
workspaces,
|
|
146
|
-
datasources,
|
|
147
|
-
pipes,
|
|
148
137
|
filenames,
|
|
149
138
|
ignore_sql_errors=ignore_sql_errors,
|
|
150
139
|
is_internal=is_internal,
|
tinybird/tb/modules/cli.py
CHANGED
|
@@ -24,12 +24,10 @@ from tinybird.client import (
|
|
|
24
24
|
AuthException,
|
|
25
25
|
AuthNoTokenException,
|
|
26
26
|
DoesNotExistException,
|
|
27
|
-
OperationCanNotBePerformed,
|
|
28
27
|
TinyB,
|
|
29
28
|
)
|
|
30
29
|
from tinybird.config import CURRENT_VERSION, SUPPORTED_CONNECTORS, VERSION, FeatureFlags, get_config
|
|
31
30
|
from tinybird.feedback_manager import FeedbackManager
|
|
32
|
-
from tinybird.tb.modules.cicd import check_cicd_exists, init_cicd
|
|
33
31
|
from tinybird.tb.modules.common import (
|
|
34
32
|
OLDEST_ROLLBACK,
|
|
35
33
|
CatchAuthExceptions,
|
|
@@ -49,24 +47,21 @@ from tinybird.tb.modules.common import (
|
|
|
49
47
|
wait_job,
|
|
50
48
|
)
|
|
51
49
|
from tinybird.tb.modules.config import CLIConfig
|
|
52
|
-
from tinybird.tb.modules.datafile import
|
|
53
|
-
|
|
54
|
-
CLIGitRelease,
|
|
55
|
-
CLIGitReleaseException,
|
|
50
|
+
from tinybird.tb.modules.datafile.build import build_graph, folder_push
|
|
51
|
+
from tinybird.tb.modules.datafile.common import (
|
|
56
52
|
Datafile,
|
|
57
|
-
ParseException,
|
|
58
|
-
build_graph,
|
|
59
|
-
create_release,
|
|
60
|
-
diff_command,
|
|
61
|
-
folder_pull,
|
|
62
|
-
folder_push,
|
|
63
53
|
get_project_filenames,
|
|
64
54
|
get_resource_versions,
|
|
65
55
|
has_internal_datafiles,
|
|
66
|
-
parse_datasource,
|
|
67
|
-
parse_pipe,
|
|
68
|
-
parse_token,
|
|
69
56
|
)
|
|
57
|
+
from tinybird.tb.modules.datafile.diff import diff_command
|
|
58
|
+
from tinybird.tb.modules.datafile.exceptions import (
|
|
59
|
+
AlreadyExistsException,
|
|
60
|
+
ParseException,
|
|
61
|
+
)
|
|
62
|
+
from tinybird.tb.modules.datafile.parse_datasource import parse_datasource
|
|
63
|
+
from tinybird.tb.modules.datafile.parse_pipe import parse_pipe
|
|
64
|
+
from tinybird.tb.modules.datafile.pull import folder_pull
|
|
70
65
|
from tinybird.tb.modules.telemetry import add_telemetry_event
|
|
71
66
|
|
|
72
67
|
__old_click_echo = click.echo
|
|
@@ -323,118 +318,8 @@ async def init(
|
|
|
323
318
|
|
|
324
319
|
await folder_init(client, folder, generate_datasources, generate_releases=True, force=force)
|
|
325
320
|
|
|
326
|
-
if not (git or override_commit or cicd):
|
|
327
|
-
return
|
|
328
|
-
|
|
329
|
-
sync_git = git or override_commit
|
|
330
|
-
cli_git_release = None
|
|
331
321
|
error = False
|
|
332
322
|
final_response = None
|
|
333
|
-
try:
|
|
334
|
-
cli_git_release = CLIGitRelease(path=folder)
|
|
335
|
-
except CLIGitReleaseException:
|
|
336
|
-
raise CLIGitReleaseException(FeedbackManager.error_no_git_repo_for_init(repo_path=folder))
|
|
337
|
-
|
|
338
|
-
if sync_git:
|
|
339
|
-
if not cli_git_release.is_main_branch() and not override_commit:
|
|
340
|
-
raise CLIGitReleaseException(FeedbackManager.error_no_git_main_branch())
|
|
341
|
-
|
|
342
|
-
if not cli_git_release.is_dottinyb_ignored():
|
|
343
|
-
raise CLIGitReleaseException(
|
|
344
|
-
FeedbackManager.error_dottinyb_not_ignored(git_working_dir=f"{cli_git_release.working_dir()}/")
|
|
345
|
-
)
|
|
346
|
-
else:
|
|
347
|
-
click.echo(FeedbackManager.info_dottinyb_already_ignored())
|
|
348
|
-
|
|
349
|
-
if (
|
|
350
|
-
os.path.exists(f"{cli_git_release.working_dir()}/.diff_tmp")
|
|
351
|
-
and not cli_git_release.is_dotdifftemp_ignored()
|
|
352
|
-
):
|
|
353
|
-
raise CLIGitReleaseException(
|
|
354
|
-
FeedbackManager.error_dotdiff_not_ignored(git_working_dir=f"{cli_git_release.working_dir()}/")
|
|
355
|
-
)
|
|
356
|
-
else:
|
|
357
|
-
click.echo(FeedbackManager.info_dotdifftemp_already_ignored())
|
|
358
|
-
|
|
359
|
-
if "release" not in current_ws:
|
|
360
|
-
raise CLIGitReleaseException(FeedbackManager.error_no_correct_token_for_init())
|
|
361
|
-
|
|
362
|
-
# If we have a release and we are not overriding the commit, we check if we have a release already
|
|
363
|
-
elif current_ws.get("release") and not override_commit:
|
|
364
|
-
final_response = FeedbackManager.error_release_already_set(
|
|
365
|
-
workspace=current_ws["name"], commit=current_ws["release"]["commit"]
|
|
366
|
-
)
|
|
367
|
-
error = True
|
|
368
|
-
|
|
369
|
-
elif override_commit:
|
|
370
|
-
if click.confirm(
|
|
371
|
-
FeedbackManager.prompt_init_git_release_force(
|
|
372
|
-
current_commit=current_ws["release"]["commit"], new_commit=override_commit
|
|
373
|
-
)
|
|
374
|
-
):
|
|
375
|
-
try:
|
|
376
|
-
release = await cli_git_release.update_release(client, current_ws, override_commit)
|
|
377
|
-
except Exception as exc:
|
|
378
|
-
raise CLIGitReleaseException(FeedbackManager.error_exception(error=str(exc)))
|
|
379
|
-
|
|
380
|
-
final_response = FeedbackManager.success_init_git_release(
|
|
381
|
-
workspace_name=current_ws["name"], release_commit=release["commit"]
|
|
382
|
-
)
|
|
383
|
-
else:
|
|
384
|
-
return
|
|
385
|
-
|
|
386
|
-
else:
|
|
387
|
-
click.echo(FeedbackManager.info_no_git_release_yet(workspace=current_ws["name"]))
|
|
388
|
-
click.echo(FeedbackManager.info_diff_resources_for_git_init())
|
|
389
|
-
changed = await diff_command(
|
|
390
|
-
[], True, client, with_print=False, verbose=False, clean_up=True, progress_bar=True
|
|
391
|
-
)
|
|
392
|
-
changed = {
|
|
393
|
-
k: v
|
|
394
|
-
for k, v in changed.items()
|
|
395
|
-
if v is not None and (not ignore_remote or v not in ["remote", "shared"])
|
|
396
|
-
}
|
|
397
|
-
if changed:
|
|
398
|
-
tb_pull_command = "tb pull --force"
|
|
399
|
-
click.echo(FeedbackManager.warning_git_release_init_with_diffs())
|
|
400
|
-
if click.confirm(FeedbackManager.prompt_init_git_release_pull(pull_command=tb_pull_command)):
|
|
401
|
-
await folder_pull(client, folder, auto=True, match=None, force=True)
|
|
402
|
-
|
|
403
|
-
else:
|
|
404
|
-
raise CLIGitReleaseException(
|
|
405
|
-
FeedbackManager.error_diff_resources_for_git_init(
|
|
406
|
-
workspace=current_ws["name"], pull_command=tb_pull_command
|
|
407
|
-
)
|
|
408
|
-
)
|
|
409
|
-
else:
|
|
410
|
-
click.echo(FeedbackManager.info_git_release_init_without_diffs(workspace=current_ws["name"]))
|
|
411
|
-
if cli_git_release.is_dirty_to_init():
|
|
412
|
-
raise CLIGitReleaseException(
|
|
413
|
-
FeedbackManager.error_commit_changes_to_init_release(
|
|
414
|
-
path=cli_git_release.path, git_output=cli_git_release.status()
|
|
415
|
-
)
|
|
416
|
-
)
|
|
417
|
-
try:
|
|
418
|
-
release = await cli_git_release.update_release(client, current_ws)
|
|
419
|
-
except Exception as exc:
|
|
420
|
-
raise CLIGitReleaseException(FeedbackManager.error_exception(error=str(exc)))
|
|
421
|
-
|
|
422
|
-
final_response = FeedbackManager.success_init_git_release(
|
|
423
|
-
workspace_name=current_ws["name"], release_commit=release["commit"]
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
if not override_commit:
|
|
427
|
-
cicd_provider = await check_cicd_exists(cli_git_release.working_dir())
|
|
428
|
-
if not force and cicd_provider:
|
|
429
|
-
if cicd:
|
|
430
|
-
final_response = FeedbackManager.error_cicd_already_exists(provider=cicd_provider.name)
|
|
431
|
-
error = True
|
|
432
|
-
else:
|
|
433
|
-
click.echo(FeedbackManager.info_cicd_already_exists(provider=cicd_provider.name))
|
|
434
|
-
else:
|
|
435
|
-
if cicd:
|
|
436
|
-
data_project_dir = os.path.relpath(folder, cli_git_release.working_dir())
|
|
437
|
-
await init_cicd(client, path=cli_git_release.working_dir(), data_project_dir=data_project_dir)
|
|
438
323
|
|
|
439
324
|
if final_response:
|
|
440
325
|
if error:
|
|
@@ -452,7 +337,7 @@ def check(filenames: List[str], debug: bool) -> None:
|
|
|
452
337
|
filenames = get_project_filenames(".")
|
|
453
338
|
|
|
454
339
|
def process(filenames: Iterable):
|
|
455
|
-
parser_matrix = {".pipe": parse_pipe, ".datasource": parse_datasource
|
|
340
|
+
parser_matrix = {".pipe": parse_pipe, ".datasource": parse_datasource}
|
|
456
341
|
incl_suffix = ".incl"
|
|
457
342
|
try:
|
|
458
343
|
for filename in filenames:
|
|
@@ -1473,11 +1358,6 @@ async def deploy(
|
|
|
1473
1358
|
new_release = True
|
|
1474
1359
|
|
|
1475
1360
|
if new_release:
|
|
1476
|
-
if not dry_run:
|
|
1477
|
-
try:
|
|
1478
|
-
await create_release(client, config, semver)
|
|
1479
|
-
except OperationCanNotBePerformed as e:
|
|
1480
|
-
raise CLIException(FeedbackManager.error_exception(error=str(e)))
|
|
1481
1361
|
release_created = True
|
|
1482
1362
|
fork_downstream = True
|
|
1483
1363
|
# allows TB_CHECK_BACKFILL_REQUIRED=0 so it is not checked
|
tinybird/tb/modules/common.py
CHANGED
|
@@ -27,6 +27,7 @@ import click.formatting
|
|
|
27
27
|
import humanfriendly
|
|
28
28
|
import humanfriendly.tables
|
|
29
29
|
import pyperclip
|
|
30
|
+
import requests
|
|
30
31
|
from click import Context
|
|
31
32
|
from click._termui_impl import ProgressBar
|
|
32
33
|
from humanfriendly.tables import format_pretty_table
|
|
@@ -60,7 +61,7 @@ if TYPE_CHECKING:
|
|
|
60
61
|
|
|
61
62
|
from tinybird.feedback_manager import FeedbackManager, warning_message
|
|
62
63
|
from tinybird.git_settings import DEFAULT_TINYENV_FILE
|
|
63
|
-
from tinybird.syncasync import async_to_sync
|
|
64
|
+
from tinybird.syncasync import async_to_sync, sync_to_async
|
|
64
65
|
from tinybird.tb.modules.cicd import APPEND_FIXTURES_SH, DEFAULT_REQUIREMENTS_FILE, EXEC_TEST_SH
|
|
65
66
|
from tinybird.tb.modules.config import CLIConfig
|
|
66
67
|
from tinybird.tb.modules.exceptions import (
|
|
@@ -160,10 +161,17 @@ def normalize_datasource_name(s: str) -> str:
|
|
|
160
161
|
|
|
161
162
|
|
|
162
163
|
def generate_datafile(
|
|
163
|
-
datafile: str,
|
|
164
|
+
datafile: str,
|
|
165
|
+
filename: str,
|
|
166
|
+
data: Optional[bytes],
|
|
167
|
+
force: Optional[bool] = False,
|
|
168
|
+
_format: Optional[str] = "csv",
|
|
169
|
+
parent_dir: Optional[str] = None,
|
|
164
170
|
):
|
|
165
171
|
p = Path(filename)
|
|
166
172
|
base = Path("datasources")
|
|
173
|
+
if parent_dir:
|
|
174
|
+
base = Path(parent_dir) / base
|
|
167
175
|
datasource_name = normalize_datasource_name(p.stem)
|
|
168
176
|
if not base.exists():
|
|
169
177
|
base = Path()
|
|
@@ -2096,3 +2104,7 @@ def get_ca_pem_content(ca_pem: Optional[str], filename: Optional[str] = None) ->
|
|
|
2096
2104
|
raise CLIConnectionException(FeedbackManager.error_connection_invalid_ca_pem())
|
|
2097
2105
|
|
|
2098
2106
|
return ca_pem_content
|
|
2107
|
+
|
|
2108
|
+
|
|
2109
|
+
requests_get = sync_to_async(requests.get, thread_sensitive=False)
|
|
2110
|
+
requests_delete = sync_to_async(requests.delete, thread_sensitive=False)
|
tinybird/tb/modules/create.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from os import getcwd
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Optional
|
|
5
5
|
|
|
6
6
|
import click
|
|
7
7
|
from click import Context
|
|
@@ -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, coro, generate_datafile, push_data
|
|
14
14
|
from tinybird.tb.modules.config import CLIConfig
|
|
15
|
-
from tinybird.tb.modules.datafile import folder_build
|
|
15
|
+
from tinybird.tb.modules.datafile.build import folder_build
|
|
16
16
|
from tinybird.tb.modules.exceptions import CLIDatasourceException
|
|
17
17
|
from tinybird.tb.modules.llm import LLM
|
|
18
18
|
from tinybird.tb.modules.local import (
|
|
@@ -55,15 +55,7 @@ async def create(
|
|
|
55
55
|
click.echo(FeedbackManager.gray(message="Creating new project structure..."))
|
|
56
56
|
await project_create(tb_client, data, prompt, folder)
|
|
57
57
|
click.echo(FeedbackManager.success(message="✓ Scaffolding completed!\n"))
|
|
58
|
-
|
|
59
|
-
datasources = await tb_client.datasources()
|
|
60
|
-
pipes = await tb_client.pipes(dependencies=True)
|
|
61
|
-
await folder_build(
|
|
62
|
-
tb_client,
|
|
63
|
-
workspaces,
|
|
64
|
-
datasources,
|
|
65
|
-
pipes,
|
|
66
|
-
)
|
|
58
|
+
await folder_build(tb_client, folder=folder)
|
|
67
59
|
|
|
68
60
|
await init_cicd(data_project_dir=os.path.relpath(folder))
|
|
69
61
|
|
|
@@ -102,8 +94,10 @@ async def project_create(
|
|
|
102
94
|
except FileExistsError:
|
|
103
95
|
click.echo(FeedbackManager.info_path_created(path=x))
|
|
104
96
|
|
|
105
|
-
def generate_pipe_file(name: str, content: str):
|
|
97
|
+
def generate_pipe_file(name: str, content: str, parent_dir: Optional[str] = None):
|
|
106
98
|
base = Path("endpoints")
|
|
99
|
+
if parent_dir:
|
|
100
|
+
base = Path(parent_dir) / base
|
|
107
101
|
if not base.exists():
|
|
108
102
|
base = Path()
|
|
109
103
|
f = base / (f"{name}.pipe")
|
|
@@ -168,8 +162,10 @@ SQL >
|
|
|
168
162
|
LIMIT 5
|
|
169
163
|
TYPE ENDPOINT
|
|
170
164
|
"""
|
|
171
|
-
generate_datafile(
|
|
172
|
-
|
|
165
|
+
generate_datafile(
|
|
166
|
+
events_ds, filename="events.datasource", data=None, _format="ndjson", force=force, parent_dir=folder
|
|
167
|
+
)
|
|
168
|
+
generate_pipe_file("top_airlines", top_airlines, parent_dir=folder)
|
|
173
169
|
|
|
174
170
|
|
|
175
171
|
async def append_datasource(
|