snowflake-cli 3.2.2__py3-none-any.whl → 3.4.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/__main__.py +2 -2
- snowflake/cli/_app/cli_app.py +224 -192
- snowflake/cli/_app/commands_registration/commands_registration_with_callbacks.py +1 -27
- snowflake/cli/_app/constants.py +4 -0
- snowflake/cli/_app/snow_connector.py +12 -0
- snowflake/cli/_app/telemetry.py +10 -3
- snowflake/cli/_plugins/connection/util.py +12 -19
- snowflake/cli/_plugins/cortex/commands.py +2 -4
- snowflake/cli/_plugins/git/manager.py +1 -1
- snowflake/cli/_plugins/helpers/commands.py +207 -1
- snowflake/cli/_plugins/nativeapp/artifacts.py +16 -628
- snowflake/cli/_plugins/nativeapp/bundle_context.py +1 -1
- snowflake/cli/_plugins/nativeapp/codegen/artifact_processor.py +1 -1
- snowflake/cli/_plugins/nativeapp/codegen/compiler.py +42 -20
- snowflake/cli/_plugins/nativeapp/codegen/setup/native_app_setup_processor.py +9 -2
- snowflake/cli/_plugins/nativeapp/codegen/snowpark/python_processor.py +6 -3
- snowflake/cli/_plugins/nativeapp/codegen/templates/templates_processor.py +44 -34
- snowflake/cli/_plugins/nativeapp/commands.py +113 -21
- snowflake/cli/_plugins/nativeapp/constants.py +5 -0
- snowflake/cli/_plugins/nativeapp/entities/application.py +226 -296
- snowflake/cli/_plugins/nativeapp/entities/application_package.py +911 -141
- snowflake/cli/_plugins/nativeapp/entities/application_package_child_interface.py +43 -0
- snowflake/cli/_plugins/nativeapp/feature_flags.py +5 -1
- snowflake/cli/_plugins/nativeapp/release_channel/__init__.py +13 -0
- snowflake/cli/_plugins/nativeapp/release_channel/commands.py +246 -0
- snowflake/cli/_plugins/nativeapp/release_directive/__init__.py +13 -0
- snowflake/cli/_plugins/nativeapp/release_directive/commands.py +243 -0
- snowflake/cli/_plugins/nativeapp/same_account_install_method.py +9 -17
- snowflake/cli/_plugins/nativeapp/sf_facade_exceptions.py +80 -0
- snowflake/cli/_plugins/nativeapp/sf_sql_facade.py +1184 -80
- snowflake/cli/_plugins/nativeapp/utils.py +11 -0
- snowflake/cli/_plugins/nativeapp/v2_conversions/compat.py +7 -3
- snowflake/cli/_plugins/nativeapp/version/commands.py +32 -5
- snowflake/cli/_plugins/notebook/commands.py +55 -2
- snowflake/cli/_plugins/notebook/exceptions.py +1 -1
- snowflake/cli/_plugins/notebook/manager.py +7 -5
- snowflake/cli/_plugins/notebook/notebook_entity.py +120 -0
- snowflake/cli/_plugins/notebook/notebook_entity_model.py +42 -0
- snowflake/cli/_plugins/notebook/notebook_project_paths.py +15 -0
- snowflake/cli/_plugins/notebook/types.py +3 -0
- snowflake/cli/_plugins/snowpark/commands.py +48 -30
- snowflake/cli/_plugins/snowpark/common.py +47 -2
- snowflake/cli/_plugins/snowpark/snowpark_entity.py +247 -4
- snowflake/cli/_plugins/snowpark/snowpark_entity_model.py +18 -30
- snowflake/cli/_plugins/snowpark/snowpark_project_paths.py +156 -23
- snowflake/cli/_plugins/snowpark/zipper.py +33 -1
- snowflake/cli/_plugins/spcs/common.py +129 -0
- snowflake/cli/_plugins/spcs/services/commands.py +131 -14
- snowflake/cli/_plugins/spcs/services/manager.py +169 -1
- snowflake/cli/_plugins/stage/commands.py +2 -1
- snowflake/cli/_plugins/stage/diff.py +60 -39
- snowflake/cli/_plugins/stage/manager.py +34 -13
- snowflake/cli/_plugins/stage/utils.py +1 -1
- snowflake/cli/_plugins/streamlit/commands.py +10 -1
- snowflake/cli/_plugins/streamlit/manager.py +70 -22
- snowflake/cli/_plugins/streamlit/streamlit_entity.py +131 -1
- snowflake/cli/_plugins/streamlit/streamlit_entity_model.py +14 -24
- snowflake/cli/_plugins/streamlit/streamlit_project_paths.py +30 -0
- snowflake/cli/_plugins/workspace/commands.py +6 -5
- snowflake/cli/_plugins/workspace/manager.py +9 -5
- snowflake/cli/api/artifacts/__init__.py +13 -0
- snowflake/cli/api/artifacts/bundle_map.py +500 -0
- snowflake/cli/api/artifacts/common.py +78 -0
- snowflake/cli/api/artifacts/utils.py +82 -0
- snowflake/cli/api/cli_global_context.py +36 -2
- snowflake/cli/api/commands/flags.py +10 -4
- snowflake/cli/api/commands/utils.py +28 -2
- snowflake/cli/api/config.py +6 -2
- snowflake/cli/api/connections.py +12 -1
- snowflake/cli/api/constants.py +10 -1
- snowflake/cli/api/entities/common.py +81 -14
- snowflake/cli/api/entities/resolver.py +160 -0
- snowflake/cli/api/entities/utils.py +65 -23
- snowflake/cli/api/errno.py +63 -3
- snowflake/cli/api/feature_flags.py +19 -4
- snowflake/cli/api/metrics.py +21 -27
- snowflake/cli/api/project/definition_conversion.py +4 -4
- snowflake/cli/api/project/project_paths.py +28 -0
- snowflake/cli/api/project/schemas/entities/common.py +130 -1
- snowflake/cli/api/project/schemas/entities/entities.py +4 -0
- snowflake/cli/api/project/schemas/project_definition.py +54 -6
- snowflake/cli/api/project/schemas/updatable_model.py +2 -2
- snowflake/cli/api/project/schemas/v1/native_app/native_app.py +5 -7
- snowflake/cli/api/project/schemas/v1/streamlit/streamlit.py +1 -1
- snowflake/cli/api/project/util.py +45 -0
- snowflake/cli/api/secure_path.py +6 -0
- snowflake/cli/api/sql_execution.py +5 -1
- snowflake/cli/api/stage_path.py +7 -2
- snowflake/cli/api/utils/graph.py +3 -0
- snowflake/cli/api/utils/path_utils.py +24 -0
- {snowflake_cli-3.2.2.dist-info → snowflake_cli-3.4.1.dist-info}/METADATA +14 -15
- {snowflake_cli-3.2.2.dist-info → snowflake_cli-3.4.1.dist-info}/RECORD +96 -82
- {snowflake_cli-3.2.2.dist-info → snowflake_cli-3.4.1.dist-info}/WHEEL +1 -1
- snowflake/cli/api/project/schemas/v1/native_app/path_mapping.py +0 -65
- {snowflake_cli-3.2.2.dist-info → snowflake_cli-3.4.1.dist-info}/entry_points.txt +0 -0
- {snowflake_cli-3.2.2.dist-info → snowflake_cli-3.4.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -96,16 +96,14 @@ def search(
|
|
|
96
96
|
"Cortex Search uses Snowflake Python API that currently does not support your Python version"
|
|
97
97
|
)
|
|
98
98
|
|
|
99
|
-
from snowflake.core import Root
|
|
100
|
-
|
|
101
99
|
if not columns:
|
|
102
100
|
columns = []
|
|
103
101
|
|
|
104
102
|
conn = get_cli_context().connection
|
|
103
|
+
root = get_cli_context().snow_api_root
|
|
105
104
|
|
|
106
105
|
search_service = (
|
|
107
|
-
|
|
108
|
-
.databases[conn.database]
|
|
106
|
+
root.databases[conn.database]
|
|
109
107
|
.schemas[conn.schema]
|
|
110
108
|
.cortex_search_services[service]
|
|
111
109
|
)
|
|
@@ -116,7 +116,7 @@ class GitManager(StageManager):
|
|
|
116
116
|
return f"{'/'.join(path_parts[ONLY_STAGE])}/"
|
|
117
117
|
|
|
118
118
|
@staticmethod
|
|
119
|
-
def
|
|
119
|
+
def stage_path_parts_from_str(stage_path: str) -> StagePathParts:
|
|
120
120
|
stage_path = StageManager.get_standard_stage_prefix(stage_path)
|
|
121
121
|
if stage_path.startswith(USER_STAGE_PREFIX):
|
|
122
122
|
return UserStagePathParts(stage_path)
|
|
@@ -14,17 +14,30 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
+
import logging
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Any, List, Optional
|
|
20
|
+
|
|
17
21
|
import typer
|
|
18
22
|
import yaml
|
|
19
23
|
from click import ClickException
|
|
20
24
|
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
21
|
-
from snowflake.cli.api.
|
|
25
|
+
from snowflake.cli.api.config import (
|
|
26
|
+
ConnectionConfig,
|
|
27
|
+
add_connection_to_proper_file,
|
|
28
|
+
get_all_connections,
|
|
29
|
+
set_config_value,
|
|
30
|
+
)
|
|
31
|
+
from snowflake.cli.api.console import cli_console
|
|
32
|
+
from snowflake.cli.api.output.types import CommandResult, MessageResult
|
|
22
33
|
from snowflake.cli.api.project.definition_conversion import (
|
|
23
34
|
convert_project_definition_to_v2,
|
|
24
35
|
)
|
|
25
36
|
from snowflake.cli.api.project.definition_manager import DefinitionManager
|
|
26
37
|
from snowflake.cli.api.secure_path import SecurePath
|
|
27
38
|
|
|
39
|
+
log = logging.getLogger(__name__)
|
|
40
|
+
|
|
28
41
|
app = SnowTyperFactory(
|
|
29
42
|
name="helpers",
|
|
30
43
|
help="Helper commands.",
|
|
@@ -88,3 +101,196 @@ def v1_to_v2(
|
|
|
88
101
|
width=float("inf"), # Don't break lines
|
|
89
102
|
)
|
|
90
103
|
return MessageResult("Project definition migrated to version 2.")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@app.command(name="import-snowsql-connections", requires_connection=False)
|
|
107
|
+
def import_snowsql_connections(
|
|
108
|
+
custom_snowsql_config_files: Optional[List[Path]] = typer.Option(
|
|
109
|
+
None,
|
|
110
|
+
"--snowsql-config-file",
|
|
111
|
+
help="Specifies file paths to custom SnowSQL configuration. The option can be used multiple times to specify more than 1 file.",
|
|
112
|
+
dir_okay=False,
|
|
113
|
+
exists=True,
|
|
114
|
+
),
|
|
115
|
+
default_cli_connection_name: str = typer.Option(
|
|
116
|
+
"default",
|
|
117
|
+
"--default-connection-name",
|
|
118
|
+
help="Specifies the name which will be given in Snowflake CLI to the default connection imported from SnowSQL.",
|
|
119
|
+
),
|
|
120
|
+
**options,
|
|
121
|
+
) -> CommandResult:
|
|
122
|
+
"""Import your existing connections from your SnowSQL configuration."""
|
|
123
|
+
|
|
124
|
+
snowsql_config_files: list[Path] = custom_snowsql_config_files or [
|
|
125
|
+
Path("/etc/snowsql.cnf"),
|
|
126
|
+
Path("/etc/snowflake/snowsql.cnf"),
|
|
127
|
+
Path("/usr/local/etc/snowsql.cnf"),
|
|
128
|
+
Path.home() / Path(".snowsql.cnf"),
|
|
129
|
+
Path.home() / Path(".snowsql/config"),
|
|
130
|
+
]
|
|
131
|
+
snowsql_config_secure_paths: list[SecurePath] = [
|
|
132
|
+
SecurePath(p) for p in snowsql_config_files
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
all_imported_connections = _read_all_connections_from_snowsql(
|
|
136
|
+
default_cli_connection_name, snowsql_config_secure_paths
|
|
137
|
+
)
|
|
138
|
+
_validate_and_save_connections_imported_from_snowsql(
|
|
139
|
+
default_cli_connection_name, all_imported_connections
|
|
140
|
+
)
|
|
141
|
+
return MessageResult(
|
|
142
|
+
"Connections successfully imported from SnowSQL to Snowflake CLI."
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _read_all_connections_from_snowsql(
|
|
147
|
+
default_cli_connection_name: str, snowsql_config_files: List[SecurePath]
|
|
148
|
+
) -> dict[str, dict]:
|
|
149
|
+
import configparser
|
|
150
|
+
|
|
151
|
+
imported_default_connection: dict[str, Any] = {}
|
|
152
|
+
imported_named_connections: dict[str, dict] = {}
|
|
153
|
+
|
|
154
|
+
for file in snowsql_config_files:
|
|
155
|
+
if not file.exists():
|
|
156
|
+
cli_console.step(
|
|
157
|
+
f"SnowSQL config file [{str(file.path)}] does not exist. Skipping."
|
|
158
|
+
)
|
|
159
|
+
continue
|
|
160
|
+
|
|
161
|
+
cli_console.step(f"Trying to read connections from [{str(file.path)}].")
|
|
162
|
+
snowsql_config = configparser.ConfigParser()
|
|
163
|
+
snowsql_config.read(file.path)
|
|
164
|
+
|
|
165
|
+
if "connections" in snowsql_config and snowsql_config.items("connections"):
|
|
166
|
+
cli_console.step(
|
|
167
|
+
f"Reading SnowSQL's default connection configuration from [{str(file.path)}]"
|
|
168
|
+
)
|
|
169
|
+
snowsql_default_connection = snowsql_config.items("connections")
|
|
170
|
+
imported_default_connection.update(
|
|
171
|
+
_convert_connection_from_snowsql_config_section(
|
|
172
|
+
snowsql_default_connection
|
|
173
|
+
)
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
other_snowsql_connection_section_names = [
|
|
177
|
+
section_name
|
|
178
|
+
for section_name in snowsql_config.sections()
|
|
179
|
+
if section_name.startswith("connections.")
|
|
180
|
+
]
|
|
181
|
+
for snowsql_connection_section_name in other_snowsql_connection_section_names:
|
|
182
|
+
cli_console.step(
|
|
183
|
+
f"Reading SnowSQL's connection configuration [{snowsql_connection_section_name}] from [{str(file.path)}]"
|
|
184
|
+
)
|
|
185
|
+
snowsql_named_connection = snowsql_config.items(
|
|
186
|
+
snowsql_connection_section_name
|
|
187
|
+
)
|
|
188
|
+
if not snowsql_named_connection:
|
|
189
|
+
cli_console.step(
|
|
190
|
+
f"Empty connection configuration [{snowsql_connection_section_name}] in [{str(file.path)}]. Skipping."
|
|
191
|
+
)
|
|
192
|
+
continue
|
|
193
|
+
|
|
194
|
+
connection_name = snowsql_connection_section_name.removeprefix(
|
|
195
|
+
"connections."
|
|
196
|
+
)
|
|
197
|
+
imported_named_conenction = _convert_connection_from_snowsql_config_section(
|
|
198
|
+
snowsql_named_connection
|
|
199
|
+
)
|
|
200
|
+
if connection_name in imported_named_connections:
|
|
201
|
+
imported_named_connections[connection_name].update(
|
|
202
|
+
imported_named_conenction
|
|
203
|
+
)
|
|
204
|
+
else:
|
|
205
|
+
imported_named_connections[connection_name] = imported_named_conenction
|
|
206
|
+
|
|
207
|
+
def imported_default_connection_as_named_connection():
|
|
208
|
+
name = _validate_imported_default_connection_name(
|
|
209
|
+
default_cli_connection_name, imported_named_connections
|
|
210
|
+
)
|
|
211
|
+
return {name: imported_default_connection}
|
|
212
|
+
|
|
213
|
+
named_default_connection = (
|
|
214
|
+
imported_default_connection_as_named_connection()
|
|
215
|
+
if imported_default_connection
|
|
216
|
+
else {}
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
return imported_named_connections | named_default_connection
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _validate_imported_default_connection_name(
|
|
223
|
+
name_candidate: str, other_snowsql_connections: dict[str, dict]
|
|
224
|
+
) -> str:
|
|
225
|
+
if name_candidate in other_snowsql_connections:
|
|
226
|
+
new_name_candidate = typer.prompt(
|
|
227
|
+
f"Chosen default connection name '{name_candidate}' is already taken by other connection being imported from SnowSQL. Please choose a different name for your default connection"
|
|
228
|
+
)
|
|
229
|
+
return _validate_imported_default_connection_name(
|
|
230
|
+
new_name_candidate, other_snowsql_connections
|
|
231
|
+
)
|
|
232
|
+
else:
|
|
233
|
+
return name_candidate
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def _convert_connection_from_snowsql_config_section(
|
|
237
|
+
snowsql_connection: list[tuple[str, Any]]
|
|
238
|
+
) -> dict[str, Any]:
|
|
239
|
+
from ast import literal_eval
|
|
240
|
+
|
|
241
|
+
key_names_replacements = {
|
|
242
|
+
"accountname": "account",
|
|
243
|
+
"username": "user",
|
|
244
|
+
"databasename": "database",
|
|
245
|
+
"dbname": "database",
|
|
246
|
+
"schemaname": "schema",
|
|
247
|
+
"warehousename": "warehouse",
|
|
248
|
+
"rolename": "role",
|
|
249
|
+
"private_key_path": "private_key_file",
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
def parse_value(value: Any):
|
|
253
|
+
try:
|
|
254
|
+
parsed_value = literal_eval(value)
|
|
255
|
+
except Exception:
|
|
256
|
+
parsed_value = value
|
|
257
|
+
return parsed_value
|
|
258
|
+
|
|
259
|
+
cli_connection: dict[str, Any] = {}
|
|
260
|
+
for key, value in snowsql_connection:
|
|
261
|
+
cli_key = key_names_replacements.get(key, key)
|
|
262
|
+
cli_value = parse_value(value)
|
|
263
|
+
cli_connection[cli_key] = cli_value
|
|
264
|
+
return cli_connection
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _validate_and_save_connections_imported_from_snowsql(
|
|
268
|
+
default_cli_connection_name: str, all_imported_connections: dict[str, Any]
|
|
269
|
+
):
|
|
270
|
+
existing_cli_connection_names: set[str] = set(get_all_connections().keys())
|
|
271
|
+
imported_connections_to_save: dict[str, Any] = {}
|
|
272
|
+
for (
|
|
273
|
+
imported_connection_name,
|
|
274
|
+
imported_connection,
|
|
275
|
+
) in all_imported_connections.items():
|
|
276
|
+
if imported_connection_name in existing_cli_connection_names:
|
|
277
|
+
override_cli_connection = typer.confirm(
|
|
278
|
+
f"Connection '{imported_connection_name}' already exists in Snowflake CLI, do you want to use SnowSQL definition and override existing connection in Snowflake CLI?"
|
|
279
|
+
)
|
|
280
|
+
if not override_cli_connection:
|
|
281
|
+
continue
|
|
282
|
+
imported_connections_to_save[imported_connection_name] = imported_connection
|
|
283
|
+
|
|
284
|
+
for name, connection in imported_connections_to_save.items():
|
|
285
|
+
cli_console.step(f"Saving [{name}] connection in Snowflake CLI's config.")
|
|
286
|
+
add_connection_to_proper_file(name, ConnectionConfig.from_dict(connection))
|
|
287
|
+
|
|
288
|
+
if default_cli_connection_name in imported_connections_to_save:
|
|
289
|
+
cli_console.step(
|
|
290
|
+
f"Setting [{default_cli_connection_name}] connection as Snowflake CLI's default connection."
|
|
291
|
+
)
|
|
292
|
+
set_config_value(
|
|
293
|
+
section=None,
|
|
294
|
+
key="default_connection_name",
|
|
295
|
+
value=default_cli_connection_name,
|
|
296
|
+
)
|