snowflake-cli 3.6.0__py3-none-any.whl → 3.7.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 -0
- snowflake/cli/_app/loggers.py +2 -2
- snowflake/cli/_app/snow_connector.py +2 -2
- snowflake/cli/_plugins/connection/commands.py +2 -1
- snowflake/cli/_plugins/helpers/commands.py +25 -1
- snowflake/cli/_plugins/helpers/snowsl_vars_reader.py +133 -0
- snowflake/cli/_plugins/init/commands.py +9 -6
- snowflake/cli/_plugins/logs/__init__.py +0 -0
- snowflake/cli/_plugins/logs/commands.py +105 -0
- snowflake/cli/_plugins/logs/manager.py +107 -0
- snowflake/cli/_plugins/logs/plugin_spec.py +16 -0
- snowflake/cli/_plugins/logs/utils.py +60 -0
- snowflake/cli/_plugins/notebook/commands.py +3 -0
- snowflake/cli/_plugins/notebook/notebook_entity.py +16 -27
- snowflake/cli/_plugins/project/commands.py +73 -48
- snowflake/cli/_plugins/project/manager.py +57 -23
- snowflake/cli/_plugins/project/project_entity_model.py +22 -3
- snowflake/cli/_plugins/snowpark/commands.py +15 -2
- snowflake/cli/_plugins/spcs/image_registry/manager.py +15 -6
- snowflake/cli/_plugins/sql/manager.py +4 -4
- snowflake/cli/_plugins/stage/manager.py +17 -10
- snowflake/cli/_plugins/streamlit/commands.py +3 -0
- snowflake/cli/_plugins/streamlit/manager.py +19 -15
- snowflake/cli/api/artifacts/upload.py +30 -34
- snowflake/cli/api/artifacts/utils.py +8 -6
- snowflake/cli/api/cli_global_context.py +7 -2
- snowflake/cli/api/commands/decorators.py +11 -2
- snowflake/cli/api/commands/flags.py +23 -2
- snowflake/cli/api/commands/snow_typer.py +20 -2
- snowflake/cli/api/config.py +5 -3
- snowflake/cli/api/entities/utils.py +29 -16
- snowflake/cli/api/exceptions.py +69 -28
- snowflake/cli/api/identifiers.py +2 -0
- snowflake/cli/api/plugins/plugin_config.py +2 -2
- snowflake/cli/api/project/schemas/template.py +3 -3
- snowflake/cli/api/rendering/project_templates.py +3 -3
- snowflake/cli/api/rendering/sql_templates.py +2 -2
- snowflake/cli/api/sql_execution.py +1 -1
- snowflake/cli/api/utils/definition_rendering.py +14 -8
- snowflake/cli/api/utils/templating_functions.py +4 -4
- {snowflake_cli-3.6.0.dist-info → snowflake_cli-3.7.1.dist-info}/METADATA +9 -8
- {snowflake_cli-3.6.0.dist-info → snowflake_cli-3.7.1.dist-info}/RECORD +46 -40
- {snowflake_cli-3.6.0.dist-info → snowflake_cli-3.7.1.dist-info}/WHEEL +0 -0
- {snowflake_cli-3.6.0.dist-info → snowflake_cli-3.7.1.dist-info}/entry_points.txt +0 -0
- {snowflake_cli-3.6.0.dist-info → snowflake_cli-3.7.1.dist-info}/licenses/LICENSE +0 -0
snowflake/cli/api/exceptions.py
CHANGED
|
@@ -22,46 +22,87 @@ from snowflake.cli.api.constants import ObjectType
|
|
|
22
22
|
from snowflake.connector.compat import IS_WINDOWS
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
class
|
|
25
|
+
class BaseCliError(ClickException):
|
|
26
|
+
"""Base Cli Exception.
|
|
27
|
+
|
|
28
|
+
0 Everything ran smoothly.
|
|
29
|
+
1 Something went wrong with the client.
|
|
30
|
+
2 Something went wrong with command line arguments.
|
|
31
|
+
3 Cli could not connect to server.
|
|
32
|
+
4 Cli could not communicate properly with server.
|
|
33
|
+
5 The enhanced_exit_codes parameter was set and Cli exited because of error.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, *args, **kwargs):
|
|
37
|
+
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
38
|
+
|
|
39
|
+
if not get_cli_context().enhanced_exit_codes:
|
|
40
|
+
self.exit_code = kwargs.pop("exit_code", 1)
|
|
41
|
+
super().__init__(*args, **kwargs)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class CliError(BaseCliError):
|
|
45
|
+
"""Generic Cli Error - to be used in favour of ClickException."""
|
|
46
|
+
|
|
47
|
+
exit_code = 1
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class CliArgumentError(BaseCliError):
|
|
51
|
+
exit_code = 2
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class CliConnectionError(BaseCliError):
|
|
55
|
+
exit_code = 3
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class CliCommunicationError(BaseCliError):
|
|
59
|
+
exit_code = 4
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class CliSqlError(BaseCliError):
|
|
63
|
+
exit_code = 5
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class EnvironmentVariableNotFoundError(CliError):
|
|
26
67
|
def __init__(self, env_variable_name: str):
|
|
27
68
|
super().__init__(f"Environment variable {env_variable_name} not found")
|
|
28
69
|
|
|
29
70
|
|
|
30
|
-
class
|
|
71
|
+
class MissingConfigurationError(CliError):
|
|
31
72
|
pass
|
|
32
73
|
|
|
33
74
|
|
|
34
|
-
class CycleDetectedError(
|
|
75
|
+
class CycleDetectedError(CliError):
|
|
35
76
|
pass
|
|
36
77
|
|
|
37
78
|
|
|
38
|
-
class
|
|
79
|
+
class InvalidTemplateError(CliError):
|
|
39
80
|
pass
|
|
40
81
|
|
|
41
82
|
|
|
42
|
-
class
|
|
83
|
+
class InvalidConnectionConfigurationError(CliError):
|
|
43
84
|
def format_message(self):
|
|
44
85
|
return f"Invalid connection configuration. {self.message}"
|
|
45
86
|
|
|
46
87
|
|
|
47
|
-
class
|
|
88
|
+
class InvalidLogsConfigurationError(CliError):
|
|
48
89
|
def format_message(self):
|
|
49
90
|
return f"Invalid logs configuration. {self.message}"
|
|
50
91
|
|
|
51
92
|
|
|
52
|
-
class
|
|
93
|
+
class InvalidPluginConfigurationError(CliError):
|
|
53
94
|
def format_message(self):
|
|
54
95
|
return f"Invalid plugin configuration. {self.message}"
|
|
55
96
|
|
|
56
97
|
|
|
57
|
-
class PluginNotInstalledError(
|
|
98
|
+
class PluginNotInstalledError(CliError):
|
|
58
99
|
def __init__(self, plugin_name, installed_plugins: List[str]):
|
|
59
100
|
super().__init__(
|
|
60
101
|
f"Plugin {plugin_name} is not installed. Available plugins: {', '.join(installed_plugins)}."
|
|
61
102
|
)
|
|
62
103
|
|
|
63
104
|
|
|
64
|
-
class SnowflakeConnectionError(
|
|
105
|
+
class SnowflakeConnectionError(CliError):
|
|
65
106
|
def __init__(self, snowflake_err: Exception):
|
|
66
107
|
super().__init__(f"Could not connect to Snowflake. Reason: {snowflake_err}")
|
|
67
108
|
|
|
@@ -71,17 +112,17 @@ class UnsupportedConfigSectionTypeError(Exception):
|
|
|
71
112
|
super().__init__(f"Unsupported configuration section type {section_type}")
|
|
72
113
|
|
|
73
114
|
|
|
74
|
-
class OutputDataTypeError(
|
|
115
|
+
class OutputDataTypeError(CliError):
|
|
75
116
|
def __init__(self, got_type: type, expected_type: type):
|
|
76
117
|
super().__init__(f"Got {got_type} type but expected {expected_type}")
|
|
77
118
|
|
|
78
119
|
|
|
79
|
-
class CommandReturnTypeError(
|
|
120
|
+
class CommandReturnTypeError(CliError):
|
|
80
121
|
def __init__(self, got_type: type):
|
|
81
122
|
super().__init__(f"Commands have to return OutputData type, but got {got_type}")
|
|
82
123
|
|
|
83
124
|
|
|
84
|
-
class SnowflakeSQLExecutionError(
|
|
125
|
+
class SnowflakeSQLExecutionError(CliError):
|
|
85
126
|
"""
|
|
86
127
|
Could not successfully execute the Snowflake SQL statements.
|
|
87
128
|
"""
|
|
@@ -95,7 +136,7 @@ class SnowflakeSQLExecutionError(ClickException):
|
|
|
95
136
|
)
|
|
96
137
|
|
|
97
138
|
|
|
98
|
-
class ObjectAlreadyExistsError(
|
|
139
|
+
class ObjectAlreadyExistsError(CliError):
|
|
99
140
|
def __init__(
|
|
100
141
|
self,
|
|
101
142
|
object_type: ObjectType,
|
|
@@ -108,45 +149,45 @@ class ObjectAlreadyExistsError(ClickException):
|
|
|
108
149
|
super().__init__(msg)
|
|
109
150
|
|
|
110
151
|
|
|
111
|
-
class NoProjectDefinitionError(
|
|
152
|
+
class NoProjectDefinitionError(CliError):
|
|
112
153
|
def __init__(self, project_type: str, project_root: str | Path):
|
|
113
154
|
super().__init__(
|
|
114
155
|
f"No {project_type} project definition found in {project_root}"
|
|
115
156
|
)
|
|
116
157
|
|
|
117
158
|
|
|
118
|
-
class InvalidProjectDefinitionVersionError(
|
|
159
|
+
class InvalidProjectDefinitionVersionError(CliError):
|
|
119
160
|
def __init__(self, expected_version: str, actual_version: str):
|
|
120
161
|
super().__init__(
|
|
121
162
|
f"This command only supports definition version {expected_version}, got {actual_version}."
|
|
122
163
|
)
|
|
123
164
|
|
|
124
165
|
|
|
125
|
-
class InvalidSchemaError(
|
|
166
|
+
class InvalidSchemaError(CliError):
|
|
126
167
|
def __init__(self, schema: str):
|
|
127
168
|
super().__init__(f"Invalid schema {schema}")
|
|
128
169
|
|
|
129
170
|
|
|
130
|
-
class SecretsWithoutExternalAccessIntegrationError(
|
|
171
|
+
class SecretsWithoutExternalAccessIntegrationError(CliError):
|
|
131
172
|
def __init__(self, object_name: str):
|
|
132
173
|
super().__init__(
|
|
133
174
|
f"{object_name} defined with secrets but without external integration."
|
|
134
175
|
)
|
|
135
176
|
|
|
136
177
|
|
|
137
|
-
class FileTooLargeError(
|
|
178
|
+
class FileTooLargeError(CliError):
|
|
138
179
|
def __init__(self, path: Path, size_limit_in_kb: int):
|
|
139
180
|
super().__init__(
|
|
140
181
|
f"File {path} is too large (size limit: {size_limit_in_kb} KB)"
|
|
141
182
|
)
|
|
142
183
|
|
|
143
184
|
|
|
144
|
-
class DirectoryIsNotEmptyError(
|
|
185
|
+
class DirectoryIsNotEmptyError(CliError):
|
|
145
186
|
def __init__(self, path: Path):
|
|
146
187
|
super().__init__(f"Directory '{path}' is not empty")
|
|
147
188
|
|
|
148
189
|
|
|
149
|
-
class ConfigFileTooWidePermissionsError(
|
|
190
|
+
class ConfigFileTooWidePermissionsError(CliError):
|
|
150
191
|
def __init__(self, path: Path):
|
|
151
192
|
change_permissons_command = (
|
|
152
193
|
f'icacls "{path}" /deny <USER_ID>:F'
|
|
@@ -162,26 +203,26 @@ class ConfigFileTooWidePermissionsError(ClickException):
|
|
|
162
203
|
super().__init__(msg)
|
|
163
204
|
|
|
164
205
|
|
|
165
|
-
class DatabaseNotProvidedError(
|
|
206
|
+
class DatabaseNotProvidedError(CliError):
|
|
166
207
|
def __init__(self):
|
|
167
208
|
super().__init__(
|
|
168
209
|
"Database not specified. Please update connection to add `database` parameter, or re-run command using `--database` option. Use `snow connection list` to list existing connections."
|
|
169
210
|
)
|
|
170
211
|
|
|
171
212
|
|
|
172
|
-
class SchemaNotProvidedError(
|
|
213
|
+
class SchemaNotProvidedError(CliError):
|
|
173
214
|
def __init__(self):
|
|
174
215
|
super().__init__(
|
|
175
216
|
"Schema not specified. Please update connection to add `schema` parameter, or re-run command using `--schema` option. Use `snow connection list` to list existing connections."
|
|
176
217
|
)
|
|
177
218
|
|
|
178
219
|
|
|
179
|
-
class FQNNameError(
|
|
220
|
+
class FQNNameError(CliError):
|
|
180
221
|
def __init__(self, name: str):
|
|
181
222
|
super().__init__(f"Specified name '{name}' is not valid name.")
|
|
182
223
|
|
|
183
224
|
|
|
184
|
-
class FQNInconsistencyError(
|
|
225
|
+
class FQNInconsistencyError(CliError):
|
|
185
226
|
def __init__(self, part: str, name: str):
|
|
186
227
|
super().__init__(
|
|
187
228
|
f"{part.capitalize()} provided but name '{name}' is fully qualified name."
|
|
@@ -206,7 +247,7 @@ class UnmetParametersError(UsageError):
|
|
|
206
247
|
)
|
|
207
248
|
|
|
208
249
|
|
|
209
|
-
class NoWarehouseSelectedInSessionError(
|
|
250
|
+
class NoWarehouseSelectedInSessionError(CliError):
|
|
210
251
|
def __init__(self, msg: str):
|
|
211
252
|
super().__init__(
|
|
212
253
|
"Received the following error message while executing SQL statement:\n"
|
|
@@ -215,7 +256,7 @@ class NoWarehouseSelectedInSessionError(ClickException):
|
|
|
215
256
|
)
|
|
216
257
|
|
|
217
258
|
|
|
218
|
-
class DoesNotExistOrUnauthorizedError(
|
|
259
|
+
class DoesNotExistOrUnauthorizedError(CliError):
|
|
219
260
|
def __init__(self, msg: str):
|
|
220
261
|
super().__init__(
|
|
221
262
|
"Received the following error message while executing SQL statement:\n"
|
|
@@ -224,7 +265,7 @@ class DoesNotExistOrUnauthorizedError(ClickException):
|
|
|
224
265
|
)
|
|
225
266
|
|
|
226
267
|
|
|
227
|
-
class CouldNotUseObjectError(
|
|
268
|
+
class CouldNotUseObjectError(CliError):
|
|
228
269
|
def __init__(self, object_type: ObjectType, name: str):
|
|
229
270
|
super().__init__(
|
|
230
271
|
f"Could not use {object_type} {name}. Object does not exist, or operation cannot be performed."
|
|
@@ -238,7 +279,7 @@ class ShowSpecificObjectMultipleRowsError(RuntimeError):
|
|
|
238
279
|
)
|
|
239
280
|
|
|
240
281
|
|
|
241
|
-
class CouldNotSetKeyPairError(
|
|
282
|
+
class CouldNotSetKeyPairError(CliError):
|
|
242
283
|
def __init__(self):
|
|
243
284
|
super().__init__(
|
|
244
285
|
"The public key is set already. Use the rotate command instead."
|
snowflake/cli/api/identifiers.py
CHANGED
|
@@ -25,7 +25,7 @@ from snowflake.cli.api.config import (
|
|
|
25
25
|
get_config_value,
|
|
26
26
|
get_plugins_config,
|
|
27
27
|
)
|
|
28
|
-
from snowflake.cli.api.exceptions import
|
|
28
|
+
from snowflake.cli.api.exceptions import InvalidPluginConfigurationError
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
@dataclass
|
|
@@ -66,6 +66,6 @@ class PluginConfigProvider:
|
|
|
66
66
|
|
|
67
67
|
def _assert_value_is_bool(value, *, value_name: str, plugin_name: str) -> None:
|
|
68
68
|
if type(value) is not bool:
|
|
69
|
-
raise
|
|
69
|
+
raise InvalidPluginConfigurationError(
|
|
70
70
|
f'[{plugin_name}]: "{value_name}" must be a boolean'
|
|
71
71
|
)
|
|
@@ -19,7 +19,7 @@ from typing import Any, List, Literal, Optional, Union
|
|
|
19
19
|
import typer
|
|
20
20
|
from click import ClickException
|
|
21
21
|
from pydantic import BaseModel, Field
|
|
22
|
-
from snowflake.cli.api.exceptions import
|
|
22
|
+
from snowflake.cli.api.exceptions import InvalidTemplateError
|
|
23
23
|
from snowflake.cli.api.secure_path import SecurePath
|
|
24
24
|
|
|
25
25
|
|
|
@@ -68,10 +68,10 @@ class Template(BaseModel):
|
|
|
68
68
|
for path_in_template in self.files_to_render:
|
|
69
69
|
full_path = template_root / path_in_template
|
|
70
70
|
if not full_path.exists():
|
|
71
|
-
raise
|
|
71
|
+
raise InvalidTemplateError(
|
|
72
72
|
f"[files_to_render] contains not-existing file: {path_in_template}"
|
|
73
73
|
)
|
|
74
74
|
if full_path.is_dir():
|
|
75
|
-
raise
|
|
75
|
+
raise InvalidTemplateError(
|
|
76
76
|
f"[files_to_render] contains a dictionary: {path_in_template}"
|
|
77
77
|
)
|
|
@@ -24,7 +24,7 @@ from jinja2 import (
|
|
|
24
24
|
UndefinedError,
|
|
25
25
|
loaders,
|
|
26
26
|
)
|
|
27
|
-
from snowflake.cli.api.exceptions import
|
|
27
|
+
from snowflake.cli.api.exceptions import InvalidTemplateError
|
|
28
28
|
from snowflake.cli.api.rendering.jinja import IgnoreAttrEnvironment, env_bootstrap
|
|
29
29
|
from snowflake.cli.api.secure_path import SecurePath
|
|
30
30
|
|
|
@@ -90,9 +90,9 @@ def render_template_files(
|
|
|
90
90
|
full_path = template_root / path
|
|
91
91
|
full_path.write_text(rendered_result)
|
|
92
92
|
except TemplateSyntaxError as err:
|
|
93
|
-
raise
|
|
93
|
+
raise InvalidTemplateError(
|
|
94
94
|
f"Invalid template syntax in line {err.lineno} of file {path}:\n"
|
|
95
95
|
f"{err.message}"
|
|
96
96
|
)
|
|
97
97
|
except UndefinedError as err:
|
|
98
|
-
raise
|
|
98
|
+
raise InvalidTemplateError(err.message)
|
|
@@ -20,7 +20,7 @@ from click import ClickException
|
|
|
20
20
|
from jinja2 import Environment, StrictUndefined, loaders, meta
|
|
21
21
|
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
22
22
|
from snowflake.cli.api.console.console import cli_console
|
|
23
|
-
from snowflake.cli.api.exceptions import
|
|
23
|
+
from snowflake.cli.api.exceptions import InvalidTemplateError
|
|
24
24
|
from snowflake.cli.api.metrics import CLICounterField
|
|
25
25
|
from snowflake.cli.api.rendering.jinja import (
|
|
26
26
|
CONTEXT_KEY,
|
|
@@ -72,7 +72,7 @@ def choose_sql_jinja_env_based_on_template_syntax(
|
|
|
72
72
|
has_new_syntax = _does_template_have_env_syntax(new_syntax_env, template_content)
|
|
73
73
|
reference_name_str = f" in {reference_name}" if reference_name else ""
|
|
74
74
|
if has_old_syntax and has_new_syntax:
|
|
75
|
-
raise
|
|
75
|
+
raise InvalidTemplateError(
|
|
76
76
|
f"The SQL query{reference_name_str} mixes {_OLD_SQL_TEMPLATE_START} ... {_OLD_SQL_TEMPLATE_END} syntax"
|
|
77
77
|
f" and {_SQL_TEMPLATE_START} ... {_SQL_TEMPLATE_END} syntax."
|
|
78
78
|
)
|
|
@@ -89,7 +89,7 @@ class BaseSqlExecutor:
|
|
|
89
89
|
"""Executes a single SQL query and returns the results"""
|
|
90
90
|
return self._execute_string(query, **kwargs)
|
|
91
91
|
|
|
92
|
-
def execute_query(self, query: str, **kwargs):
|
|
92
|
+
def execute_query(self, query: str, **kwargs) -> SnowflakeCursor:
|
|
93
93
|
"""Executes a single SQL query and returns the last result"""
|
|
94
94
|
*_, last_result = list(self.execute_string(dedent(query), **kwargs))
|
|
95
95
|
return last_result
|
|
@@ -21,7 +21,7 @@ from jinja2 import Environment, TemplateSyntaxError, nodes
|
|
|
21
21
|
from packaging.version import Version
|
|
22
22
|
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
23
23
|
from snowflake.cli.api.console import cli_console as cc
|
|
24
|
-
from snowflake.cli.api.exceptions import CycleDetectedError,
|
|
24
|
+
from snowflake.cli.api.exceptions import CycleDetectedError, InvalidTemplateError
|
|
25
25
|
from snowflake.cli.api.metrics import CLICounterField
|
|
26
26
|
from snowflake.cli.api.project.schemas.project_definition import (
|
|
27
27
|
ProjectProperties,
|
|
@@ -60,7 +60,7 @@ class TemplatedEnvironment:
|
|
|
60
60
|
try:
|
|
61
61
|
ast = self._jinja_env.parse(template_str)
|
|
62
62
|
except TemplateSyntaxError as e:
|
|
63
|
-
raise
|
|
63
|
+
raise InvalidTemplateError(
|
|
64
64
|
f"Error parsing template from project definition file. Value: '{template_str}'. Error: {e}"
|
|
65
65
|
) from e
|
|
66
66
|
|
|
@@ -98,7 +98,9 @@ class TemplatedEnvironment:
|
|
|
98
98
|
)
|
|
99
99
|
or current_attr_chain is not None
|
|
100
100
|
):
|
|
101
|
-
raise
|
|
101
|
+
raise InvalidTemplateError(
|
|
102
|
+
f"Unexpected template syntax in {template_value}"
|
|
103
|
+
)
|
|
102
104
|
|
|
103
105
|
for child_node in ast_node.iter_child_nodes():
|
|
104
106
|
all_referenced_vars.update(
|
|
@@ -182,16 +184,20 @@ class TemplateVar:
|
|
|
182
184
|
not isinstance(current_dict_level, dict)
|
|
183
185
|
or key not in current_dict_level
|
|
184
186
|
):
|
|
185
|
-
raise
|
|
187
|
+
raise InvalidTemplateError(
|
|
188
|
+
f"Could not find template variable {self.key}"
|
|
189
|
+
)
|
|
186
190
|
current_dict_level = current_dict_level[key]
|
|
187
191
|
|
|
188
192
|
value = current_dict_level
|
|
189
193
|
|
|
190
194
|
if value is None:
|
|
191
|
-
raise
|
|
195
|
+
raise InvalidTemplateError(
|
|
196
|
+
f"Template variable {self.key} does not have a value"
|
|
197
|
+
)
|
|
192
198
|
|
|
193
199
|
if isinstance(value, (dict, list)):
|
|
194
|
-
raise
|
|
200
|
+
raise InvalidTemplateError(
|
|
195
201
|
f"Template variable {self.key} does not have a scalar value"
|
|
196
202
|
)
|
|
197
203
|
|
|
@@ -245,12 +251,12 @@ def _render_graph_node(env: TemplatedEnvironment, node: Node[TemplateVar]) -> No
|
|
|
245
251
|
|
|
246
252
|
def _validate_env_section(env_section: dict):
|
|
247
253
|
if not isinstance(env_section, dict):
|
|
248
|
-
raise
|
|
254
|
+
raise InvalidTemplateError(
|
|
249
255
|
"env section in project definition file should be a mapping"
|
|
250
256
|
)
|
|
251
257
|
for variable, value in env_section.items():
|
|
252
258
|
if value is None or isinstance(value, (dict, list)):
|
|
253
|
-
raise
|
|
259
|
+
raise InvalidTemplateError(
|
|
254
260
|
f"Variable {variable} in env section of project definition file should be a scalar"
|
|
255
261
|
)
|
|
256
262
|
|
|
@@ -16,7 +16,7 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
from typing import Any, List, Optional
|
|
18
18
|
|
|
19
|
-
from snowflake.cli.api.exceptions import
|
|
19
|
+
from snowflake.cli.api.exceptions import InvalidTemplateError
|
|
20
20
|
from snowflake.cli.api.project.util import (
|
|
21
21
|
concat_identifiers,
|
|
22
22
|
get_env_username,
|
|
@@ -41,18 +41,18 @@ class TemplatingFunctions:
|
|
|
41
41
|
max_count: Optional[int] = None,
|
|
42
42
|
):
|
|
43
43
|
if min_count is not None and len(args) < min_count:
|
|
44
|
-
raise
|
|
44
|
+
raise InvalidTemplateError(
|
|
45
45
|
f"{func_name} requires at least {min_count} argument(s)"
|
|
46
46
|
)
|
|
47
47
|
|
|
48
48
|
if max_count is not None and len(args) > max_count:
|
|
49
|
-
raise
|
|
49
|
+
raise InvalidTemplateError(
|
|
50
50
|
f"{func_name} supports at most {max_count} argument(s)"
|
|
51
51
|
)
|
|
52
52
|
|
|
53
53
|
for arg in args:
|
|
54
54
|
if not isinstance(arg, str):
|
|
55
|
-
raise
|
|
55
|
+
raise InvalidTemplateError(f"{func_name} only accepts String values")
|
|
56
56
|
|
|
57
57
|
@staticmethod
|
|
58
58
|
def concat_ids(*args):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snowflake-cli
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.7.1
|
|
4
4
|
Summary: Snowflake CLI
|
|
5
5
|
Project-URL: Source code, https://github.com/snowflakedb/snowflake-cli
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/snowflakedb/snowflake-cli/issues
|
|
@@ -217,32 +217,33 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
217
217
|
Classifier: Programming Language :: SQL
|
|
218
218
|
Classifier: Topic :: Database
|
|
219
219
|
Requires-Python: >=3.10
|
|
220
|
+
Requires-Dist: certifi==2025.1.31
|
|
220
221
|
Requires-Dist: gitpython==3.1.44
|
|
221
222
|
Requires-Dist: jinja2==3.1.6
|
|
222
223
|
Requires-Dist: packaging
|
|
223
224
|
Requires-Dist: pip
|
|
224
225
|
Requires-Dist: pluggy==1.5.0
|
|
225
|
-
Requires-Dist: pydantic==2.
|
|
226
|
+
Requires-Dist: pydantic==2.11.2
|
|
226
227
|
Requires-Dist: pyyaml==6.0.2
|
|
227
228
|
Requires-Dist: requests==2.32.3
|
|
228
229
|
Requires-Dist: requirements-parser==0.11.0
|
|
229
|
-
Requires-Dist: rich==
|
|
230
|
-
Requires-Dist: setuptools==
|
|
230
|
+
Requires-Dist: rich==14.0.0
|
|
231
|
+
Requires-Dist: setuptools==78.1.0
|
|
231
232
|
Requires-Dist: snowflake-connector-python[secure-local-storage]==3.14.0
|
|
232
|
-
Requires-Dist: snowflake-core==1.0
|
|
233
|
+
Requires-Dist: snowflake-core==1.2.0; python_version < '3.12'
|
|
233
234
|
Requires-Dist: snowflake-snowpark-python<1.26.0,>=1.15.0; python_version < '3.12'
|
|
234
235
|
Requires-Dist: tomlkit==0.13.2
|
|
235
236
|
Requires-Dist: typer==0.15.2
|
|
236
237
|
Requires-Dist: urllib3<2.4,>=1.24.3
|
|
237
238
|
Provides-Extra: development
|
|
238
|
-
Requires-Dist: coverage==7.
|
|
239
|
+
Requires-Dist: coverage==7.8.0; extra == 'development'
|
|
239
240
|
Requires-Dist: factory-boy==3.3.3; extra == 'development'
|
|
240
|
-
Requires-Dist: faker==37.
|
|
241
|
+
Requires-Dist: faker==37.1.0; extra == 'development'
|
|
241
242
|
Requires-Dist: pre-commit>=3.5.0; extra == 'development'
|
|
242
243
|
Requires-Dist: pytest-httpserver==1.1.2; extra == 'development'
|
|
243
244
|
Requires-Dist: pytest-randomly==3.16.0; extra == 'development'
|
|
244
245
|
Requires-Dist: pytest==8.3.5; extra == 'development'
|
|
245
|
-
Requires-Dist: syrupy==4.9.
|
|
246
|
+
Requires-Dist: syrupy==4.9.1; extra == 'development'
|
|
246
247
|
Provides-Extra: packaging
|
|
247
248
|
Description-Content-Type: text/markdown
|
|
248
249
|
|