snowflake-cli 3.9.1__py3-none-any.whl → 3.10.1__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.
- snowflake/cli/__about__.py +1 -1
- snowflake/cli/_app/commands_registration/builtin_plugins.py +2 -2
- snowflake/cli/_app/printing.py +53 -13
- snowflake/cli/_app/snow_connector.py +1 -0
- snowflake/cli/_app/telemetry.py +2 -0
- snowflake/cli/_app/version_check.py +73 -6
- snowflake/cli/_plugins/cortex/commands.py +8 -3
- snowflake/cli/_plugins/cortex/manager.py +24 -20
- snowflake/cli/_plugins/dbt/commands.py +5 -2
- snowflake/cli/_plugins/dbt/manager.py +9 -7
- snowflake/cli/_plugins/{project → dcm}/commands.py +95 -48
- snowflake/cli/_plugins/{project/project_entity_model.py → dcm/dcm_project_entity_model.py} +5 -5
- snowflake/cli/_plugins/{project → dcm}/manager.py +35 -14
- snowflake/cli/_plugins/{project → dcm}/plugin_spec.py +1 -1
- snowflake/cli/_plugins/git/manager.py +1 -11
- snowflake/cli/_plugins/nativeapp/codegen/snowpark/python_processor.py +4 -0
- snowflake/cli/_plugins/nativeapp/commands.py +3 -4
- snowflake/cli/_plugins/nativeapp/entities/application_package.py +1 -1
- snowflake/cli/_plugins/nativeapp/release_channel/commands.py +1 -2
- snowflake/cli/_plugins/nativeapp/version/commands.py +1 -2
- snowflake/cli/_plugins/snowpark/common.py +23 -11
- snowflake/cli/_plugins/snowpark/snowpark_entity.py +13 -5
- snowflake/cli/_plugins/snowpark/snowpark_entity_model.py +10 -2
- snowflake/cli/_plugins/sql/commands.py +49 -1
- snowflake/cli/_plugins/sql/manager.py +14 -4
- snowflake/cli/_plugins/sql/repl.py +4 -0
- snowflake/cli/_plugins/stage/commands.py +30 -11
- snowflake/cli/_plugins/stage/diff.py +2 -0
- snowflake/cli/_plugins/stage/manager.py +79 -55
- snowflake/cli/_plugins/streamlit/streamlit_entity.py +17 -30
- snowflake/cli/api/artifacts/upload.py +1 -1
- snowflake/cli/api/cli_global_context.py +5 -14
- snowflake/cli/api/commands/decorators.py +7 -0
- snowflake/cli/api/commands/flags.py +12 -0
- snowflake/cli/api/commands/snow_typer.py +23 -2
- snowflake/cli/api/config.py +9 -5
- snowflake/cli/api/connections.py +1 -0
- snowflake/cli/api/constants.py +2 -2
- snowflake/cli/api/entities/common.py +16 -13
- snowflake/cli/api/entities/utils.py +15 -9
- snowflake/cli/api/feature_flags.py +2 -5
- snowflake/cli/api/output/formats.py +6 -0
- snowflake/cli/api/output/types.py +48 -2
- snowflake/cli/api/project/schemas/entities/entities.py +6 -6
- snowflake/cli/api/rendering/sql_templates.py +67 -11
- snowflake/cli/api/rest_api.py +1 -0
- snowflake/cli/api/stage_path.py +41 -5
- {snowflake_cli-3.9.1.dist-info → snowflake_cli-3.10.1.dist-info}/METADATA +46 -13
- {snowflake_cli-3.9.1.dist-info → snowflake_cli-3.10.1.dist-info}/RECORD +53 -54
- snowflake/cli/_plugins/project/feature_flags.py +0 -22
- /snowflake/cli/_plugins/{project → dcm}/__init__.py +0 -0
- {snowflake_cli-3.9.1.dist-info → snowflake_cli-3.10.1.dist-info}/WHEEL +0 -0
- {snowflake_cli-3.9.1.dist-info → snowflake_cli-3.10.1.dist-info}/entry_points.txt +0 -0
- {snowflake_cli-3.9.1.dist-info → snowflake_cli-3.10.1.dist-info}/licenses/LICENSE +0 -0
snowflake/cli/__about__.py
CHANGED
|
@@ -16,6 +16,7 @@ from snowflake.cli._plugins.auth.keypair import plugin_spec as auth_plugin_spec
|
|
|
16
16
|
from snowflake.cli._plugins.connection import plugin_spec as connection_plugin_spec
|
|
17
17
|
from snowflake.cli._plugins.cortex import plugin_spec as cortex_plugin_spec
|
|
18
18
|
from snowflake.cli._plugins.dbt import plugin_spec as dbt_plugin_spec
|
|
19
|
+
from snowflake.cli._plugins.dcm import plugin_spec as dcm_project_plugin_spec
|
|
19
20
|
from snowflake.cli._plugins.git import plugin_spec as git_plugin_spec
|
|
20
21
|
from snowflake.cli._plugins.helpers import plugin_spec as migrate_plugin_spec
|
|
21
22
|
from snowflake.cli._plugins.init import plugin_spec as init_plugin_spec
|
|
@@ -24,7 +25,6 @@ from snowflake.cli._plugins.nativeapp import plugin_spec as nativeapp_plugin_spe
|
|
|
24
25
|
from snowflake.cli._plugins.notebook import plugin_spec as notebook_plugin_spec
|
|
25
26
|
from snowflake.cli._plugins.object import plugin_spec as object_plugin_spec
|
|
26
27
|
from snowflake.cli._plugins.plugin import plugin_spec as plugin_plugin_spec
|
|
27
|
-
from snowflake.cli._plugins.project import plugin_spec as project_plugin_spec
|
|
28
28
|
from snowflake.cli._plugins.snowpark import plugin_spec as snowpark_plugin_spec
|
|
29
29
|
from snowflake.cli._plugins.spcs import plugin_spec as spcs_plugin_spec
|
|
30
30
|
from snowflake.cli._plugins.sql import plugin_spec as sql_plugin_spec
|
|
@@ -42,7 +42,7 @@ def get_builtin_plugin_name_to_plugin_spec():
|
|
|
42
42
|
"spcs": spcs_plugin_spec,
|
|
43
43
|
"app": nativeapp_plugin_spec,
|
|
44
44
|
"object": object_plugin_spec,
|
|
45
|
-
"
|
|
45
|
+
"dcm": dcm_project_plugin_spec,
|
|
46
46
|
"snowpark": snowpark_plugin_spec,
|
|
47
47
|
"stage": stage_plugin_spec,
|
|
48
48
|
"sql": sql_plugin_spec,
|
snowflake/cli/_app/printing.py
CHANGED
|
@@ -14,9 +14,11 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
+
import csv
|
|
17
18
|
import json
|
|
18
19
|
import sys
|
|
19
|
-
from datetime import date, datetime
|
|
20
|
+
from datetime import date, datetime, time
|
|
21
|
+
from decimal import Decimal
|
|
20
22
|
from json import JSONEncoder
|
|
21
23
|
from pathlib import Path
|
|
22
24
|
from textwrap import indent
|
|
@@ -57,10 +59,12 @@ class CustomJSONEncoder(JSONEncoder):
|
|
|
57
59
|
return o.result
|
|
58
60
|
if isinstance(o, (CollectionResult, MultipleResults)):
|
|
59
61
|
return list(o.result)
|
|
60
|
-
if isinstance(o, (date, datetime)):
|
|
62
|
+
if isinstance(o, (date, datetime, time)):
|
|
61
63
|
return o.isoformat()
|
|
62
|
-
if isinstance(o, Path):
|
|
64
|
+
if isinstance(o, (Path, Decimal)):
|
|
63
65
|
return str(o)
|
|
66
|
+
if isinstance(o, bytearray):
|
|
67
|
+
return o.hex()
|
|
64
68
|
return super().default(o)
|
|
65
69
|
|
|
66
70
|
|
|
@@ -86,36 +90,72 @@ def _print_multiple_table_results(obj: CollectionResult):
|
|
|
86
90
|
for column in first_item.keys():
|
|
87
91
|
table.add_column(column, overflow="fold")
|
|
88
92
|
with Live(table, refresh_per_second=4):
|
|
89
|
-
table.add_row(*[
|
|
93
|
+
table.add_row(*[__to_str(i) for i in first_item.values()])
|
|
90
94
|
for item in items:
|
|
91
|
-
table.add_row(*[
|
|
95
|
+
table.add_row(*[__to_str(i) for i in item.values()])
|
|
92
96
|
# Add separator between tables
|
|
93
97
|
rich_print(flush=True)
|
|
94
98
|
|
|
95
99
|
|
|
100
|
+
def __to_str(val):
|
|
101
|
+
if isinstance(val, bytearray):
|
|
102
|
+
return val.hex()
|
|
103
|
+
return str(val)
|
|
104
|
+
|
|
105
|
+
|
|
96
106
|
def is_structured_format(output_format):
|
|
97
|
-
return output_format == OutputFormat.
|
|
107
|
+
return output_format.is_json or output_format == OutputFormat.CSV
|
|
98
108
|
|
|
99
109
|
|
|
100
|
-
def print_structured(
|
|
110
|
+
def print_structured(
|
|
111
|
+
result: CommandResult, output_format: OutputFormat = OutputFormat.JSON
|
|
112
|
+
):
|
|
101
113
|
"""Handles outputs like json, yml and other structured and parsable formats."""
|
|
102
114
|
printed_end_line = False
|
|
103
115
|
if isinstance(result, MultipleResults):
|
|
104
|
-
|
|
116
|
+
if output_format == OutputFormat.CSV:
|
|
117
|
+
for command_result in result.result:
|
|
118
|
+
_print_csv_result(command_result)
|
|
119
|
+
print(flush=True)
|
|
120
|
+
printed_end_line = True
|
|
121
|
+
else:
|
|
122
|
+
_stream_json(result)
|
|
105
123
|
elif isinstance(result, StreamResult):
|
|
106
124
|
# A StreamResult prints each value onto its own line
|
|
107
|
-
# instead of joining all the values into a JSON array
|
|
125
|
+
# instead of joining all the values into a JSON array or CSV entry set
|
|
108
126
|
for r in result.result:
|
|
109
|
-
|
|
127
|
+
if output_format == OutputFormat.CSV:
|
|
128
|
+
_print_csv_result(r.result)
|
|
129
|
+
else:
|
|
130
|
+
json.dump(r, sys.stdout, cls=CustomJSONEncoder)
|
|
110
131
|
print(flush=True)
|
|
111
132
|
printed_end_line = True
|
|
112
133
|
else:
|
|
113
|
-
|
|
134
|
+
if output_format == OutputFormat.CSV:
|
|
135
|
+
_print_csv_result(result)
|
|
136
|
+
printed_end_line = True
|
|
137
|
+
else:
|
|
138
|
+
json.dump(result, sys.stdout, cls=CustomJSONEncoder, indent=4)
|
|
114
139
|
# Adds empty line at the end
|
|
115
140
|
if not printed_end_line:
|
|
116
141
|
print(flush=True)
|
|
117
142
|
|
|
118
143
|
|
|
144
|
+
def _print_csv_result(result: CommandResult):
|
|
145
|
+
data = json.loads(json.dumps(result, cls=CustomJSONEncoder))
|
|
146
|
+
if isinstance(data, dict):
|
|
147
|
+
writer = csv.DictWriter(sys.stdout, [*data], lineterminator="\n")
|
|
148
|
+
writer.writeheader()
|
|
149
|
+
writer.writerow(data)
|
|
150
|
+
elif isinstance(data, list):
|
|
151
|
+
if not data:
|
|
152
|
+
return
|
|
153
|
+
writer = csv.DictWriter(sys.stdout, [*data[0]], lineterminator="\n")
|
|
154
|
+
writer.writeheader()
|
|
155
|
+
for entry in data:
|
|
156
|
+
writer.writerow(entry)
|
|
157
|
+
|
|
158
|
+
|
|
119
159
|
def _stream_json(result):
|
|
120
160
|
"""Simple helper for streaming multiple results as a JSON."""
|
|
121
161
|
indent_size = 2
|
|
@@ -160,7 +200,7 @@ def _print_single_table(obj):
|
|
|
160
200
|
table.add_column("value", overflow="fold")
|
|
161
201
|
for key, value in obj.result.items():
|
|
162
202
|
table.add_row(
|
|
163
|
-
sanitize_for_terminal(str(key)), sanitize_for_terminal(
|
|
203
|
+
sanitize_for_terminal(str(key)), sanitize_for_terminal(__to_str(value))
|
|
164
204
|
)
|
|
165
205
|
rich_print(table, flush=True)
|
|
166
206
|
|
|
@@ -168,7 +208,7 @@ def _print_single_table(obj):
|
|
|
168
208
|
def print_result(cmd_result: CommandResult, output_format: OutputFormat | None = None):
|
|
169
209
|
output_format = output_format or _get_format_type()
|
|
170
210
|
if is_structured_format(output_format):
|
|
171
|
-
print_structured(cmd_result)
|
|
211
|
+
print_structured(cmd_result, output_format)
|
|
172
212
|
elif isinstance(cmd_result, (MultipleResults, StreamResult)):
|
|
173
213
|
for res in cmd_result.result:
|
|
174
214
|
print_result(res)
|
snowflake/cli/_app/telemetry.py
CHANGED
|
@@ -178,6 +178,8 @@ def _get_definition_version() -> str | None:
|
|
|
178
178
|
|
|
179
179
|
|
|
180
180
|
def _get_ci_environment_type() -> str:
|
|
181
|
+
if "SF_GITHUB_ACTION" in os.environ:
|
|
182
|
+
return "SF_GITHUB_ACTION"
|
|
181
183
|
if "GITHUB_ACTIONS" in os.environ:
|
|
182
184
|
return "GITHUB_ACTIONS"
|
|
183
185
|
if "GITLAB_CI" in os.environ:
|
|
@@ -6,18 +6,54 @@ import requests
|
|
|
6
6
|
from packaging.version import Version
|
|
7
7
|
from snowflake.cli.__about__ import VERSION
|
|
8
8
|
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
9
|
+
from snowflake.cli.api.config import (
|
|
10
|
+
CLI_SECTION,
|
|
11
|
+
IGNORE_NEW_VERSION_WARNING_KEY,
|
|
12
|
+
get_config_bool_value,
|
|
13
|
+
)
|
|
9
14
|
from snowflake.cli.api.secure_path import SecurePath
|
|
10
15
|
from snowflake.connector.config_manager import CONFIG_MANAGER
|
|
11
16
|
|
|
12
17
|
REPOSITORY_URL_PIP = "https://pypi.org/pypi/snowflake-cli/json"
|
|
13
18
|
REPOSITORY_URL_BREW = "https://formulae.brew.sh/api/formula/snowflake-cli.json"
|
|
14
19
|
|
|
20
|
+
# How often to refresh the version cache (seconds)
|
|
21
|
+
VERSION_CACHE_REFRESH_INTERVAL = 60 * 60 # 1 hour
|
|
22
|
+
# How often to show the new version message (seconds)
|
|
23
|
+
NEW_VERSION_MESSAGE_INTERVAL = 60 * 60 * 24 * 7 # 1 week
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def should_ignore_new_version_warning() -> bool:
|
|
27
|
+
return get_config_bool_value(
|
|
28
|
+
CLI_SECTION, key=IGNORE_NEW_VERSION_WARNING_KEY, default=False
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def was_warning_shown_recently(last_time_shown: float | int | None) -> bool:
|
|
33
|
+
"""
|
|
34
|
+
Returns True if the new version warning was shown recently (within the interval),
|
|
35
|
+
meaning we should NOT show the warning again yet.
|
|
36
|
+
"""
|
|
37
|
+
if not last_time_shown:
|
|
38
|
+
return False
|
|
39
|
+
now = time.time()
|
|
40
|
+
return last_time_shown >= now - NEW_VERSION_MESSAGE_INTERVAL
|
|
41
|
+
|
|
15
42
|
|
|
16
43
|
def get_new_version_msg() -> str | None:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
44
|
+
if should_ignore_new_version_warning():
|
|
45
|
+
return None
|
|
46
|
+
cache = _VersionCache()
|
|
47
|
+
last_version = cache.get_last_version()
|
|
48
|
+
last_time_shown = cache.get_last_time_shown()
|
|
49
|
+
current_version = Version(VERSION)
|
|
50
|
+
if (
|
|
51
|
+
last_version
|
|
52
|
+
and last_version > current_version
|
|
53
|
+
and not was_warning_shown_recently(last_time_shown)
|
|
54
|
+
):
|
|
55
|
+
cache.update_last_time_shown()
|
|
56
|
+
return f"\nNew version of Snowflake CLI available. Newest: {last_version}, current: {VERSION}\n"
|
|
21
57
|
return None
|
|
22
58
|
|
|
23
59
|
|
|
@@ -32,6 +68,7 @@ def show_new_version_banner_callback(msg):
|
|
|
32
68
|
class _VersionCache:
|
|
33
69
|
_last_time = "last_time_check"
|
|
34
70
|
_version = "version"
|
|
71
|
+
_last_time_shown = "last_time_shown"
|
|
35
72
|
_version_cache_file = SecurePath(
|
|
36
73
|
CONFIG_MANAGER.file_path.parent / ".cli_version.cache"
|
|
37
74
|
)
|
|
@@ -44,6 +81,28 @@ class _VersionCache:
|
|
|
44
81
|
_VersionCache._last_time: time.time(),
|
|
45
82
|
_VersionCache._version: str(version),
|
|
46
83
|
}
|
|
84
|
+
if self._cache_file.exists():
|
|
85
|
+
try:
|
|
86
|
+
old_data = json.loads(self._cache_file.read_text(file_size_limit_mb=1))
|
|
87
|
+
if _VersionCache._last_time_shown in old_data:
|
|
88
|
+
data[_VersionCache._last_time_shown] = old_data[
|
|
89
|
+
_VersionCache._last_time_shown
|
|
90
|
+
]
|
|
91
|
+
except Exception:
|
|
92
|
+
pass
|
|
93
|
+
self._cache_file.parent.mkdir(parents=True, exist_ok=True)
|
|
94
|
+
self._cache_file.write_text(json.dumps(data))
|
|
95
|
+
|
|
96
|
+
def update_last_time_shown(self):
|
|
97
|
+
if self._cache_file.exists():
|
|
98
|
+
try:
|
|
99
|
+
data = json.loads(self._cache_file.read_text(file_size_limit_mb=1))
|
|
100
|
+
except Exception:
|
|
101
|
+
data = {}
|
|
102
|
+
else:
|
|
103
|
+
data = {}
|
|
104
|
+
data[_VersionCache._last_time_shown] = time.time()
|
|
105
|
+
self._cache_file.parent.mkdir(parents=True, exist_ok=True)
|
|
47
106
|
self._cache_file.write_text(json.dumps(data))
|
|
48
107
|
|
|
49
108
|
@staticmethod
|
|
@@ -73,9 +132,8 @@ class _VersionCache:
|
|
|
73
132
|
if self._cache_file.exists():
|
|
74
133
|
data = json.loads(self._cache_file.read_text(file_size_limit_mb=1))
|
|
75
134
|
now = time.time()
|
|
76
|
-
if data[_VersionCache._last_time] > now -
|
|
135
|
+
if data[_VersionCache._last_time] > now - VERSION_CACHE_REFRESH_INTERVAL:
|
|
77
136
|
return Version(data[_VersionCache._version])
|
|
78
|
-
|
|
79
137
|
return self._update_latest_version()
|
|
80
138
|
|
|
81
139
|
def get_last_version(self) -> Version | None:
|
|
@@ -83,3 +141,12 @@ class _VersionCache:
|
|
|
83
141
|
return self._read_latest_version()
|
|
84
142
|
except: # anything, this it not crucial feature
|
|
85
143
|
return None
|
|
144
|
+
|
|
145
|
+
def get_last_time_shown(self) -> float | int | None:
|
|
146
|
+
if self._cache_file.exists():
|
|
147
|
+
try:
|
|
148
|
+
data = json.loads(self._cache_file.read_text(file_size_limit_mb=1))
|
|
149
|
+
return data.get(_VersionCache._last_time_shown, 0)
|
|
150
|
+
except Exception:
|
|
151
|
+
return None
|
|
152
|
+
return None
|
|
@@ -41,6 +41,7 @@ from snowflake.cli.api.commands.overrideable_parameter import (
|
|
|
41
41
|
)
|
|
42
42
|
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
43
43
|
from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB, PYTHON_3_12
|
|
44
|
+
from snowflake.cli.api.exceptions import CliError
|
|
44
45
|
from snowflake.cli.api.output.types import (
|
|
45
46
|
CollectionResult,
|
|
46
47
|
CommandResult,
|
|
@@ -94,6 +95,7 @@ def search(
|
|
|
94
95
|
"""
|
|
95
96
|
Performs query search using Cortex Search Services.
|
|
96
97
|
"""
|
|
98
|
+
from snowflake.core import Root
|
|
97
99
|
|
|
98
100
|
if not SEARCH_COMMAND_ENABLED:
|
|
99
101
|
raise click.ClickException(
|
|
@@ -104,7 +106,12 @@ def search(
|
|
|
104
106
|
columns = []
|
|
105
107
|
|
|
106
108
|
conn = get_cli_context().connection
|
|
107
|
-
|
|
109
|
+
if conn:
|
|
110
|
+
root = Root(conn)
|
|
111
|
+
else:
|
|
112
|
+
raise CliError(
|
|
113
|
+
"Cortex Search requires a connection to be established. Please connect to a Snowflake account first."
|
|
114
|
+
)
|
|
108
115
|
|
|
109
116
|
search_service = (
|
|
110
117
|
root.databases[conn.database]
|
|
@@ -173,11 +180,9 @@ def complete(
|
|
|
173
180
|
is_file_input=is_file_input,
|
|
174
181
|
)
|
|
175
182
|
elif backend == Backend.REST:
|
|
176
|
-
root = get_cli_context().snow_api_root
|
|
177
183
|
result_text = manager.rest_complete(
|
|
178
184
|
text=Text(prompt),
|
|
179
185
|
model=Model(model),
|
|
180
|
-
root=root,
|
|
181
186
|
)
|
|
182
187
|
else:
|
|
183
188
|
raise UsageError("--backend option should be either rest or sql.")
|
|
@@ -26,18 +26,13 @@ from snowflake.cli._plugins.cortex.types import (
|
|
|
26
26
|
SourceDocument,
|
|
27
27
|
Text,
|
|
28
28
|
)
|
|
29
|
+
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
29
30
|
from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB
|
|
30
|
-
from snowflake.cli.api.exceptions import SnowflakeSQLExecutionError
|
|
31
|
+
from snowflake.cli.api.exceptions import CliError, SnowflakeSQLExecutionError
|
|
31
32
|
from snowflake.cli.api.secure_path import SecurePath
|
|
32
33
|
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
33
34
|
from snowflake.connector import ProgrammingError
|
|
34
35
|
from snowflake.connector.cursor import DictCursor
|
|
35
|
-
from snowflake.core._root import Root
|
|
36
|
-
from snowflake.core.cortex.inference_service import CortexInferenceService
|
|
37
|
-
from snowflake.core.cortex.inference_service._generated.models import CompleteRequest
|
|
38
|
-
from snowflake.core.cortex.inference_service._generated.models.complete_request_messages_inner import (
|
|
39
|
-
CompleteRequestMessagesInner,
|
|
40
|
-
)
|
|
41
36
|
|
|
42
37
|
log = logging.getLogger(__name__)
|
|
43
38
|
|
|
@@ -89,24 +84,33 @@ class CortexManager(SqlExecutionMixin):
|
|
|
89
84
|
lambda: json_result["choices"][0]["messages"]
|
|
90
85
|
)
|
|
91
86
|
|
|
92
|
-
def make_rest_complete_request(
|
|
93
|
-
self,
|
|
94
|
-
model: Model,
|
|
95
|
-
prompt: Text,
|
|
96
|
-
) -> CompleteRequest:
|
|
97
|
-
return CompleteRequest(
|
|
98
|
-
model=str(model),
|
|
99
|
-
messages=[CompleteRequestMessagesInner(content=str(prompt))],
|
|
100
|
-
stream=True,
|
|
101
|
-
)
|
|
102
|
-
|
|
103
87
|
def rest_complete(
|
|
104
88
|
self,
|
|
105
89
|
text: Text,
|
|
106
90
|
model: Model,
|
|
107
|
-
root: "Root",
|
|
108
91
|
) -> str:
|
|
109
|
-
|
|
92
|
+
from snowflake.core import Root
|
|
93
|
+
from snowflake.core.cortex.inference_service import CortexInferenceService
|
|
94
|
+
from snowflake.core.cortex.inference_service._generated.models import (
|
|
95
|
+
CompleteRequest,
|
|
96
|
+
)
|
|
97
|
+
from snowflake.core.cortex.inference_service._generated.models.complete_request_messages_inner import (
|
|
98
|
+
CompleteRequestMessagesInner,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
cli_context = get_cli_context()
|
|
102
|
+
if cli_context.connection:
|
|
103
|
+
root = Root(cli_context.connection)
|
|
104
|
+
else:
|
|
105
|
+
raise CliError(
|
|
106
|
+
"Cortex Search requires a connection to be established. Please connect to a Snowflake account first."
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
complete_request = CompleteRequest(
|
|
110
|
+
model=str(model),
|
|
111
|
+
messages=[CompleteRequestMessagesInner(content=str(text))],
|
|
112
|
+
stream=True,
|
|
113
|
+
)
|
|
110
114
|
cortex_inference_service = CortexInferenceService(root=root)
|
|
111
115
|
try:
|
|
112
116
|
raw_resp = cortex_inference_service.complete(
|
|
@@ -45,8 +45,9 @@ from snowflake.cli.api.secure_path import SecurePath
|
|
|
45
45
|
|
|
46
46
|
app = SnowTyperFactory(
|
|
47
47
|
name="dbt",
|
|
48
|
-
help="Manages dbt on Snowflake projects",
|
|
48
|
+
help="Manages dbt on Snowflake projects.",
|
|
49
49
|
is_hidden=FeatureFlag.ENABLE_DBT.is_disabled,
|
|
50
|
+
preview=True,
|
|
50
51
|
)
|
|
51
52
|
log = logging.getLogger(__name__)
|
|
52
53
|
|
|
@@ -64,7 +65,7 @@ add_object_command_aliases(
|
|
|
64
65
|
object_type=ObjectType.DBT_PROJECT,
|
|
65
66
|
name_argument=DBTNameArgument,
|
|
66
67
|
like_option=like_option(
|
|
67
|
-
help_example='`list --like "my%"` lists all dbt projects that begin with
|
|
68
|
+
help_example='`list --like "my%"` lists all dbt projects that begin with "my"'
|
|
68
69
|
),
|
|
69
70
|
scope_option=scope_option(help_example="`list --in database my_db`"),
|
|
70
71
|
ommit_commands=["drop", "create", "describe"],
|
|
@@ -115,6 +116,7 @@ dbt_execute_app = SnowTyperFactory(
|
|
|
115
116
|
help="Execute a dbt command on Snowflake. Subcommand name and all "
|
|
116
117
|
"parameters following it will be passed over to dbt.",
|
|
117
118
|
subcommand_metavar="DBT_COMMAND",
|
|
119
|
+
preview=True,
|
|
118
120
|
)
|
|
119
121
|
app.add_typer(dbt_execute_app)
|
|
120
122
|
|
|
@@ -141,6 +143,7 @@ for cmd in DBT_COMMANDS:
|
|
|
141
143
|
context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
|
|
142
144
|
help=f"Execute {cmd} command on Snowflake. Command name and all parameters following it will be passed over to dbt.",
|
|
143
145
|
add_help_option=False,
|
|
146
|
+
preview=True,
|
|
144
147
|
)
|
|
145
148
|
def _dbt_execute(
|
|
146
149
|
ctx: typer.Context,
|
|
@@ -26,6 +26,7 @@ from snowflake.cli.api.console import cli_console
|
|
|
26
26
|
from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB, ObjectType
|
|
27
27
|
from snowflake.cli.api.exceptions import CliError
|
|
28
28
|
from snowflake.cli.api.identifiers import FQN
|
|
29
|
+
from snowflake.cli.api.project.util import unquote_identifier
|
|
29
30
|
from snowflake.cli.api.secure_path import SecurePath
|
|
30
31
|
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
31
32
|
from snowflake.connector.cursor import SnowflakeCursor
|
|
@@ -44,7 +45,7 @@ class DBTManager(SqlExecutionMixin):
|
|
|
44
45
|
|
|
45
46
|
def deploy(
|
|
46
47
|
self,
|
|
47
|
-
|
|
48
|
+
fqn: FQN,
|
|
48
49
|
path: SecurePath,
|
|
49
50
|
profiles_path: SecurePath,
|
|
50
51
|
force: bool,
|
|
@@ -66,7 +67,8 @@ class DBTManager(SqlExecutionMixin):
|
|
|
66
67
|
|
|
67
68
|
with cli_console.phase("Creating temporary stage"):
|
|
68
69
|
stage_manager = StageManager()
|
|
69
|
-
|
|
70
|
+
unquoted_name = unquote_identifier(fqn.name)
|
|
71
|
+
stage_fqn = FQN.from_string(f"DBT_{unquoted_name}_STAGE").using_context()
|
|
70
72
|
stage_name = stage_manager.get_standard_stage_prefix(stage_fqn)
|
|
71
73
|
stage_manager.create(stage_fqn, temporary=True)
|
|
72
74
|
|
|
@@ -86,11 +88,11 @@ class DBTManager(SqlExecutionMixin):
|
|
|
86
88
|
|
|
87
89
|
with cli_console.phase("Creating DBT project"):
|
|
88
90
|
if force is True:
|
|
89
|
-
query = f"CREATE OR REPLACE DBT PROJECT {
|
|
90
|
-
elif self.exists(name=
|
|
91
|
-
query = f"ALTER DBT PROJECT {
|
|
91
|
+
query = f"CREATE OR REPLACE DBT PROJECT {fqn}"
|
|
92
|
+
elif self.exists(name=fqn):
|
|
93
|
+
query = f"ALTER DBT PROJECT {fqn} ADD VERSION"
|
|
92
94
|
else:
|
|
93
|
-
query = f"CREATE DBT PROJECT {
|
|
95
|
+
query = f"CREATE DBT PROJECT {fqn}"
|
|
94
96
|
query += f"\nFROM {stage_name}"
|
|
95
97
|
return self.execute_query(query)
|
|
96
98
|
|
|
@@ -174,7 +176,7 @@ class DBTManager(SqlExecutionMixin):
|
|
|
174
176
|
yaml.safe_dump(yaml.safe_load(sfd), tfd)
|
|
175
177
|
|
|
176
178
|
def execute(
|
|
177
|
-
self, dbt_command: str, name:
|
|
179
|
+
self, dbt_command: str, name: FQN, run_async: bool, *dbt_cli_args
|
|
178
180
|
) -> SnowflakeCursor:
|
|
179
181
|
if dbt_cli_args:
|
|
180
182
|
dbt_command = " ".join([dbt_command, *dbt_cli_args]).strip()
|