snowflake-cli 3.0.2__py3-none-any.whl → 3.2.0__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.
Files changed (84) hide show
  1. snowflake/cli/__about__.py +1 -1
  2. snowflake/cli/_app/cli_app.py +3 -0
  3. snowflake/cli/_app/dev/docs/templates/overview.rst.jinja2 +1 -1
  4. snowflake/cli/_app/dev/docs/templates/usage.rst.jinja2 +2 -2
  5. snowflake/cli/_app/telemetry.py +69 -4
  6. snowflake/cli/_plugins/connection/commands.py +152 -99
  7. snowflake/cli/_plugins/connection/util.py +54 -9
  8. snowflake/cli/_plugins/cortex/manager.py +1 -1
  9. snowflake/cli/_plugins/git/commands.py +6 -3
  10. snowflake/cli/_plugins/git/manager.py +9 -4
  11. snowflake/cli/_plugins/nativeapp/artifacts.py +77 -13
  12. snowflake/cli/_plugins/nativeapp/codegen/artifact_processor.py +1 -1
  13. snowflake/cli/_plugins/nativeapp/codegen/compiler.py +7 -0
  14. snowflake/cli/_plugins/nativeapp/codegen/sandbox.py +10 -10
  15. snowflake/cli/_plugins/nativeapp/codegen/setup/native_app_setup_processor.py +2 -2
  16. snowflake/cli/_plugins/nativeapp/codegen/snowpark/extension_function_utils.py +1 -1
  17. snowflake/cli/_plugins/nativeapp/codegen/snowpark/python_processor.py +8 -8
  18. snowflake/cli/_plugins/nativeapp/codegen/templates/templates_processor.py +5 -3
  19. snowflake/cli/_plugins/nativeapp/commands.py +144 -188
  20. snowflake/cli/_plugins/nativeapp/constants.py +1 -0
  21. snowflake/cli/_plugins/nativeapp/entities/application.py +564 -351
  22. snowflake/cli/_plugins/nativeapp/entities/application_package.py +583 -929
  23. snowflake/cli/_plugins/nativeapp/entities/models/event_sharing_telemetry.py +58 -0
  24. snowflake/cli/_plugins/nativeapp/exceptions.py +12 -0
  25. snowflake/cli/_plugins/nativeapp/same_account_install_method.py +0 -2
  26. snowflake/cli/_plugins/nativeapp/sf_facade.py +30 -0
  27. snowflake/cli/_plugins/nativeapp/sf_facade_constants.py +25 -0
  28. snowflake/cli/_plugins/nativeapp/sf_facade_exceptions.py +117 -0
  29. snowflake/cli/_plugins/nativeapp/sf_sql_facade.py +525 -0
  30. snowflake/cli/_plugins/nativeapp/v2_conversions/{v2_to_v1_decorator.py → compat.py} +88 -117
  31. snowflake/cli/_plugins/nativeapp/version/commands.py +36 -32
  32. snowflake/cli/_plugins/notebook/manager.py +2 -2
  33. snowflake/cli/_plugins/object/commands.py +10 -1
  34. snowflake/cli/_plugins/object/manager.py +13 -5
  35. snowflake/cli/_plugins/snowpark/common.py +63 -21
  36. snowflake/cli/_plugins/snowpark/package/anaconda_packages.py +3 -3
  37. snowflake/cli/_plugins/spcs/common.py +29 -0
  38. snowflake/cli/_plugins/spcs/compute_pool/manager.py +7 -9
  39. snowflake/cli/_plugins/spcs/image_registry/manager.py +2 -2
  40. snowflake/cli/_plugins/spcs/image_repository/commands.py +4 -37
  41. snowflake/cli/_plugins/spcs/image_repository/manager.py +4 -1
  42. snowflake/cli/_plugins/spcs/services/commands.py +100 -17
  43. snowflake/cli/_plugins/spcs/services/manager.py +108 -16
  44. snowflake/cli/_plugins/sql/commands.py +9 -1
  45. snowflake/cli/_plugins/sql/manager.py +9 -4
  46. snowflake/cli/_plugins/stage/commands.py +28 -19
  47. snowflake/cli/_plugins/stage/diff.py +17 -17
  48. snowflake/cli/_plugins/stage/manager.py +304 -84
  49. snowflake/cli/_plugins/stage/md5.py +1 -1
  50. snowflake/cli/_plugins/streamlit/manager.py +5 -5
  51. snowflake/cli/_plugins/workspace/commands.py +27 -4
  52. snowflake/cli/_plugins/workspace/context.py +38 -0
  53. snowflake/cli/_plugins/workspace/manager.py +23 -13
  54. snowflake/cli/api/cli_global_context.py +4 -3
  55. snowflake/cli/api/commands/flags.py +23 -7
  56. snowflake/cli/api/config.py +30 -9
  57. snowflake/cli/api/connections.py +12 -1
  58. snowflake/cli/api/console/console.py +4 -19
  59. snowflake/cli/api/entities/common.py +4 -2
  60. snowflake/cli/api/entities/utils.py +36 -69
  61. snowflake/cli/api/errno.py +2 -0
  62. snowflake/cli/api/exceptions.py +41 -0
  63. snowflake/cli/api/identifiers.py +8 -0
  64. snowflake/cli/api/metrics.py +223 -7
  65. snowflake/cli/api/output/types.py +1 -1
  66. snowflake/cli/api/project/definition_conversion.py +293 -77
  67. snowflake/cli/api/project/schemas/entities/common.py +11 -0
  68. snowflake/cli/api/project/schemas/project_definition.py +30 -25
  69. snowflake/cli/api/rest_api.py +26 -4
  70. snowflake/cli/api/secure_utils.py +1 -1
  71. snowflake/cli/api/sql_execution.py +40 -29
  72. snowflake/cli/api/stage_path.py +244 -0
  73. snowflake/cli/api/utils/definition_rendering.py +3 -5
  74. {snowflake_cli-3.0.2.dist-info → snowflake_cli-3.2.0.dist-info}/METADATA +14 -15
  75. {snowflake_cli-3.0.2.dist-info → snowflake_cli-3.2.0.dist-info}/RECORD +78 -77
  76. {snowflake_cli-3.0.2.dist-info → snowflake_cli-3.2.0.dist-info}/WHEEL +1 -1
  77. snowflake/cli/_plugins/nativeapp/manager.py +0 -415
  78. snowflake/cli/_plugins/nativeapp/project_model.py +0 -211
  79. snowflake/cli/_plugins/nativeapp/run_processor.py +0 -184
  80. snowflake/cli/_plugins/nativeapp/teardown_processor.py +0 -70
  81. snowflake/cli/_plugins/nativeapp/version/version_processor.py +0 -98
  82. snowflake/cli/_plugins/workspace/action_context.py +0 -18
  83. {snowflake_cli-3.0.2.dist-info → snowflake_cli-3.2.0.dist-info}/entry_points.txt +0 -0
  84. {snowflake_cli-3.0.2.dist-info → snowflake_cli-3.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -25,8 +25,10 @@ from snowflake.cli.api.cli_global_context import get_cli_context
25
25
  from snowflake.cli.api.console import cli_console
26
26
  from snowflake.cli.api.constants import ObjectType
27
27
  from snowflake.cli.api.exceptions import (
28
+ CouldNotUseObjectError,
28
29
  DatabaseNotProvidedError,
29
30
  SchemaNotProvidedError,
31
+ ShowSpecificObjectMultipleRowsError,
30
32
  SnowflakeSQLExecutionError,
31
33
  )
32
34
  from snowflake.cli.api.identifiers import FQN
@@ -40,19 +42,27 @@ from snowflake.connector.cursor import DictCursor, SnowflakeCursor
40
42
  from snowflake.connector.errors import ProgrammingError
41
43
 
42
44
 
43
- class SqlExecutor:
44
- def __init__(self, connection: SnowflakeConnection | None = None):
45
- self._snowpark_session = None
45
+ class BaseSqlExecutor:
46
+ """
47
+ Base class for executing SQL queries on a Snowflake connection.
48
+
49
+ This class provides methods to execute single or multiple SQL queries and handle the connection context.
50
+ It also includes logging capabilities.
51
+ """
52
+
53
+ def __init__(self, connection: SnowflakeConnection | None = None) -> None:
46
54
  self._connection = connection
47
55
 
48
56
  @property
49
57
  def _conn(self) -> SnowflakeConnection:
58
+ """Returns the current Snowflake connection, either from the instance or the global CLI context."""
50
59
  if self._connection:
51
60
  return self._connection
52
61
  return get_cli_context().connection
53
62
 
54
63
  @cached_property
55
64
  def _log(self):
65
+ """Returns a logger instance for logging debug information."""
56
66
  return logging.getLogger(__name__)
57
67
 
58
68
  def _execute_string(
@@ -75,30 +85,35 @@ class SqlExecutor:
75
85
  )
76
86
  return stream_generator if return_cursors else list()
77
87
 
78
- def _execute_query(self, query: str, **kwargs):
79
- *_, last_result = self._execute_queries(query, **kwargs)
88
+ def execute_query(self, query: str, **kwargs):
89
+ """Executes a single SQL query and returns the result"""
90
+ *_, last_result = list(self._execute_string(dedent(query), **kwargs))
80
91
  return last_result
81
92
 
82
- def _execute_queries(self, queries: str, **kwargs):
93
+ def execute_queries(self, queries: str, **kwargs):
94
+ """Executes multiple SQL queries (passed as one string) and returns the results as a list"""
83
95
  return list(self._execute_string(dedent(queries), **kwargs))
84
96
 
85
- def execute_query(self, query: str, **kwargs):
86
- return self._execute_query(query, **kwargs)
87
97
 
88
- def execute_queries(self, queries: str, **kwargs):
89
- return self._execute_queries(queries, **kwargs)
98
+ class SqlExecutor(BaseSqlExecutor):
99
+ """
100
+ SqlExecutor extends BaseSqlExecutor and provides additional methods to manage roles, warehouses,
101
+ and create specific objects like secrets and API integrations.
102
+ """
103
+
104
+ def __init__(self, connection: SnowflakeConnection | None = None):
105
+ super().__init__(connection)
106
+ self._snowpark_session = None
90
107
 
91
108
  def use(self, object_type: ObjectType, name: str):
92
109
  try:
93
- self._execute_query(f"use {object_type.value.sf_name} {name}")
94
- except ProgrammingError:
110
+ self.execute_query(f"use {object_type.value.sf_name} {name}")
111
+ except ProgrammingError as err:
95
112
  # Rewrite the error to make the message more useful.
96
- raise ProgrammingError(
97
- f"Could not use {object_type} {name}. Object does not exist, or operation cannot be performed."
98
- )
113
+ raise CouldNotUseObjectError(object_type=object_type, name=name) from err
99
114
 
100
115
  def current_role(self) -> str:
101
- return self._execute_query(f"select current_role()").fetchone()[0]
116
+ return self.execute_query(f"select current_role()").fetchone()[0]
102
117
 
103
118
  @contextmanager
104
119
  def use_role(self, new_role: str):
@@ -110,17 +125,15 @@ class SqlExecutor:
110
125
  is_different_role = new_role.lower() != prev_role.lower()
111
126
  if is_different_role:
112
127
  self._log.debug("Assuming different role: %s", new_role)
113
- self._execute_query(f"use role {new_role}")
128
+ self.execute_query(f"use role {new_role}")
114
129
  try:
115
130
  yield
116
131
  finally:
117
132
  if is_different_role:
118
- self._execute_query(f"use role {prev_role}")
133
+ self.execute_query(f"use role {prev_role}")
119
134
 
120
135
  def session_has_warehouse(self) -> bool:
121
- result = self._execute_query(
122
- "select current_warehouse() is not null"
123
- ).fetchone()
136
+ result = self.execute_query("select current_warehouse() is not null").fetchone()
124
137
  return bool(result[0])
125
138
 
126
139
  @contextmanager
@@ -131,7 +144,7 @@ class SqlExecutor:
131
144
  If there is no default warehouse in the account, it will throw an error.
132
145
  """
133
146
 
134
- wh_result = self._execute_query(f"select current_warehouse()").fetchone()
147
+ wh_result = self.execute_query(f"select current_warehouse()").fetchone()
135
148
  # If user has an assigned default warehouse, prev_wh will contain a value even if the warehouse is suspended.
136
149
  try:
137
150
  prev_wh = wh_result[0]
@@ -153,7 +166,7 @@ class SqlExecutor:
153
166
  def create_password_secret(
154
167
  self, name: FQN, username: str, password: str
155
168
  ) -> SnowflakeCursor:
156
- return self._execute_query(
169
+ return self.execute_query(
157
170
  f"""
158
171
  create secret {name.sql_identifier}
159
172
  type = password
@@ -165,7 +178,7 @@ class SqlExecutor:
165
178
  def create_api_integration(
166
179
  self, name: FQN, api_provider: str, allowed_prefix: str, secret: Optional[str]
167
180
  ) -> SnowflakeCursor:
168
- return self._execute_query(
181
+ return self.execute_query(
169
182
  f"""
170
183
  create api integration {name.sql_identifier}
171
184
  api_provider = {api_provider}
@@ -180,7 +193,7 @@ class SqlExecutor:
180
193
  Check that a database and schema are provided before executing the query. Useful for operating on schema level objects.
181
194
  """
182
195
  self.check_database_and_schema_provided(name)
183
- return self._execute_query(query, **kwargs)
196
+ return self.execute_query(query, **kwargs)
184
197
 
185
198
  def check_database_and_schema_provided(self, name: Optional[str] = None) -> None:
186
199
  """
@@ -240,16 +253,14 @@ class SqlExecutor:
240
253
  show_obj_query, name=name, cursor_class=DictCursor
241
254
  )
242
255
  else:
243
- show_obj_cursor = self._execute_query( # type: ignore
256
+ show_obj_cursor = self.execute_query( # type: ignore
244
257
  show_obj_query, cursor_class=DictCursor
245
258
  )
246
259
 
247
260
  if show_obj_cursor.rowcount is None:
248
261
  raise SnowflakeSQLExecutionError(show_obj_query)
249
262
  elif show_obj_cursor.rowcount > 1:
250
- raise ProgrammingError(
251
- f"Received multiple rows from result of SQL statement: {show_obj_query}. Usage of 'show_specific_object' may not be properly scoped."
252
- )
263
+ raise ShowSpecificObjectMultipleRowsError(show_obj_query=show_obj_query)
253
264
 
254
265
  show_obj_row = find_first_row(
255
266
  show_obj_cursor,
@@ -0,0 +1,244 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from pathlib import Path, PurePosixPath
5
+
6
+ from snowflake.cli.api.identifiers import FQN
7
+ from snowflake.cli.api.project.util import (
8
+ to_string_literal,
9
+ )
10
+
11
+ USER_STAGE_PREFIX = "~"
12
+
13
+
14
+ class StagePath:
15
+ def __init__(
16
+ self,
17
+ stage_name: str,
18
+ path: str | PurePosixPath | None = None,
19
+ git_ref: str | None = None,
20
+ trailing_slash: bool = False,
21
+ ):
22
+ self._stage_name = self.strip_stage_prefixes(stage_name)
23
+ self._path = PurePosixPath(path) if path else PurePosixPath(".")
24
+
25
+ self._trailing_slash = trailing_slash
26
+ # Check if user stage
27
+ self._is_user_stage = self._stage_name.startswith(USER_STAGE_PREFIX)
28
+
29
+ # Setup git information
30
+ self._git_ref = None
31
+ self._is_git_repo = False
32
+ if git_ref:
33
+ self._git_ref = git_ref
34
+ self._is_git_repo = True
35
+
36
+ @classmethod
37
+ def get_user_stage(cls) -> StagePath:
38
+ return cls.from_stage_str("~")
39
+
40
+ @property
41
+ def stage(self) -> str:
42
+ return self._stage_name
43
+
44
+ @property
45
+ def path(self) -> PurePosixPath:
46
+ return self._path
47
+
48
+ @property
49
+ def stage_with_at(self) -> str:
50
+ return self.add_at_prefix(self._stage_name)
51
+
52
+ def is_user_stage(self) -> bool:
53
+ return self._is_user_stage
54
+
55
+ def is_git_repo(self) -> bool:
56
+ return self._is_git_repo
57
+
58
+ @property
59
+ def git_ref(self) -> str | None:
60
+ return self._git_ref
61
+
62
+ @staticmethod
63
+ def add_at_prefix(text: str):
64
+ if not text.startswith("@"):
65
+ return "@" + text
66
+ return text
67
+
68
+ @staticmethod
69
+ def strip_at_prefix(text: str):
70
+ if text.startswith("@"):
71
+ return text[1:]
72
+ return text
73
+
74
+ @staticmethod
75
+ def strip_snow_prefix(text: str):
76
+ if text.startswith("snow://"):
77
+ return text[len("snow://") :]
78
+ return text
79
+
80
+ @classmethod
81
+ def strip_stage_prefixes(cls, text: str):
82
+ return cls.strip_at_prefix(cls.strip_snow_prefix(text))
83
+
84
+ @classmethod
85
+ def from_stage_str(cls, stage_str: str | FQN):
86
+ stage_str = cls.strip_stage_prefixes(str(stage_str))
87
+ parts = stage_str.split("/", maxsplit=1)
88
+ parts = [p for p in parts if p]
89
+ if len(parts) == 2:
90
+ stage_string, path = parts
91
+ else:
92
+ stage_string = parts[0]
93
+ path = None
94
+ return cls(
95
+ stage_name=stage_string, path=path, trailing_slash=stage_str.endswith("/")
96
+ )
97
+
98
+ @classmethod
99
+ def from_git_str(cls, git_str: str):
100
+ """
101
+ @configuration_repo / branches/main / scripts/setup.sql
102
+ @configuration_repo / branches/"foo/main" / scripts/setup.sql
103
+ """
104
+ repo_name, git_ref, path = cls._split_repo_path(
105
+ cls.strip_stage_prefixes(git_str)
106
+ )
107
+ return cls(
108
+ stage_name=repo_name,
109
+ path=path,
110
+ git_ref=git_ref,
111
+ trailing_slash=git_str.endswith("/"),
112
+ )
113
+
114
+ @staticmethod
115
+ def _split_repo_path(git_str: str) -> tuple[str, str, str]:
116
+ parts = []
117
+ slash_index = 0
118
+ skipping_mode = False
119
+ for current_idx, (char, next_char) in enumerate(zip(git_str[:-1], git_str[1:])):
120
+ if not skipping_mode:
121
+ if char != "/":
122
+ continue
123
+
124
+ # Normal split
125
+ parts.append(git_str[slash_index:current_idx])
126
+ slash_index = current_idx + 1
127
+
128
+ if next_char == '"':
129
+ skipping_mode = not skipping_mode
130
+ # Add last part
131
+ parts.append(git_str[slash_index:])
132
+ repo_name = parts[0]
133
+ ref = parts[1] + "/" + parts[2]
134
+ path = "/".join(parts[3:]) if len(parts) > 2 else ""
135
+ return repo_name, ref, path
136
+
137
+ def absolute_path(self, no_fqn=False, at_prefix=True) -> str:
138
+ stage_name = self._stage_name
139
+ if not self.is_user_stage() and no_fqn:
140
+ stage_name = FQN.from_string(self._stage_name).name
141
+
142
+ path = PurePosixPath(stage_name)
143
+ if self.git_ref:
144
+ path = path / self.git_ref
145
+ if not self.is_root():
146
+ path = path / self._path
147
+
148
+ str_path = str(path)
149
+ if at_prefix:
150
+ str_path = self.add_at_prefix(str_path)
151
+
152
+ if self._trailing_slash:
153
+ return str_path.rstrip("/") + "/"
154
+ return str_path
155
+
156
+ def joinpath(self, path: str | Path) -> StagePath:
157
+ if self.is_file():
158
+ raise ValueError("Cannot join path to a file")
159
+
160
+ return StagePath(
161
+ stage_name=self._stage_name,
162
+ path=PurePosixPath(self._path) / str(path).lstrip("/"),
163
+ git_ref=self._git_ref,
164
+ )
165
+
166
+ def __truediv__(self, path: str):
167
+ return self.joinpath(path)
168
+
169
+ def with_stage(self, stage_name: str) -> StagePath:
170
+ """Returns a new path with new stage name"""
171
+ return StagePath(
172
+ stage_name=stage_name,
173
+ path=self._path,
174
+ git_ref=self._git_ref,
175
+ )
176
+
177
+ @property
178
+ def parts(self) -> tuple[str, ...]:
179
+ return self._path.parts
180
+
181
+ @property
182
+ def name(self) -> str:
183
+ return self._path.name
184
+
185
+ def is_dir(self) -> bool:
186
+ return "." not in self.name
187
+
188
+ def is_file(self) -> bool:
189
+ return not self.is_dir()
190
+
191
+ @property
192
+ def suffix(self) -> str:
193
+ return self._path.suffix
194
+
195
+ @property
196
+ def stem(self) -> str:
197
+ return self._path.stem
198
+
199
+ @property
200
+ def parent(self) -> StagePath:
201
+ return StagePath(
202
+ stage_name=self._stage_name, path=self._path.parent, git_ref=self._git_ref
203
+ )
204
+
205
+ def is_root(self) -> bool:
206
+ return self._path == PurePosixPath(".")
207
+
208
+ def root_path(self) -> StagePath:
209
+ if self.is_git_repo():
210
+ return StagePath(stage_name=self._stage_name, git_ref=self._git_ref)
211
+ return StagePath(stage_name=self._stage_name)
212
+
213
+ def is_quoted(self) -> bool:
214
+ path = self.absolute_path()
215
+ return path.startswith("'") and path.endswith("'")
216
+
217
+ def path_for_sql(self) -> str:
218
+ path = self.absolute_path()
219
+ if not re.fullmatch(r"@([\w./$])+", path):
220
+ return to_string_literal(path)
221
+ return path
222
+
223
+ def quoted_absolute_path(self) -> str:
224
+ if self.is_quoted():
225
+ return self.absolute_path()
226
+ return to_string_literal(self.absolute_path())
227
+
228
+ def relative_to(self, stage_path: StagePath) -> PurePosixPath:
229
+ return self.path.relative_to(stage_path.path)
230
+
231
+ def get_local_target_path(self, target_dir: Path, stage_root: StagePath):
232
+ # Case for downloading @stage/aa/file.py with root @stage/aa
233
+ if self.relative_to(stage_root) == PurePosixPath("."):
234
+ return target_dir
235
+ return (target_dir / self.relative_to(stage_root)).parent
236
+
237
+ def __str__(self):
238
+ return self.absolute_path()
239
+
240
+ def __repr__(self):
241
+ return str(self)
242
+
243
+ def __eq__(self, other):
244
+ return self.absolute_path() == other.absolute_path()
@@ -285,9 +285,7 @@ def _add_defaults_to_definition(original_definition: Definition) -> Definition:
285
285
  with context({"skip_validation_on_templates": True}):
286
286
  # pass a flag to Pydantic to skip validation for templated scalars
287
287
  # populate the defaults
288
- project_definition = build_project_definition(
289
- **copy.deepcopy(original_definition)
290
- )
288
+ project_definition = build_project_definition(**original_definition)
291
289
 
292
290
  definition_with_defaults = project_definition.model_dump(
293
291
  exclude_none=True, warnings=False, by_alias=True
@@ -392,8 +390,8 @@ def render_definition_template(
392
390
  definition,
393
391
  update_action=lambda val: template_env.render(val, final_context),
394
392
  )
395
-
396
- project_definition = build_project_definition(**definition)
393
+ with context({"is_duplicated_run": True}):
394
+ project_definition = build_project_definition(**definition)
397
395
 
398
396
  # Use the values originally provided by the user as the template context
399
397
  # This intentionally doesn't reflect any field changes made by
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: snowflake-cli
3
- Version: 3.0.2
3
+ Version: 3.2.0
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
@@ -206,7 +206,6 @@ License: Apache License
206
206
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
207
207
  See the License for the specific language governing permissions and
208
208
  limitations under the License.
209
- License-File: LICENSE
210
209
  Classifier: Development Status :: 5 - Production/Stable
211
210
  Classifier: Environment :: Console
212
211
  Classifier: Intended Audience :: Developers
@@ -226,20 +225,22 @@ Requires-Dist: pydantic==2.9.2
226
225
  Requires-Dist: pyyaml==6.0.2
227
226
  Requires-Dist: requests==2.32.3
228
227
  Requires-Dist: requirements-parser==0.11.0
229
- Requires-Dist: rich==13.8.1
230
- Requires-Dist: setuptools==75.1.0
231
- Requires-Dist: snowflake-connector-python[secure-local-storage]==3.12.2
228
+ Requires-Dist: rich==13.9.4
229
+ Requires-Dist: setuptools==75.3.0
230
+ Requires-Dist: snowflake-connector-python[secure-local-storage]==3.12.3
232
231
  Requires-Dist: snowflake-core==0.12.1; python_version < '3.12'
233
232
  Requires-Dist: snowflake-snowpark-python>=1.15.0; python_version < '3.12'
234
233
  Requires-Dist: tomlkit==0.13.2
235
234
  Requires-Dist: typer==0.12.5
236
235
  Requires-Dist: urllib3<2.3,>=1.24.3
237
236
  Provides-Extra: development
238
- Requires-Dist: coverage==7.6.1; extra == 'development'
237
+ Requires-Dist: coverage==7.6.4; extra == 'development'
238
+ Requires-Dist: factory-boy==3.3.1; extra == 'development'
239
+ Requires-Dist: faker==30.8.2; extra == 'development'
239
240
  Requires-Dist: pre-commit>=3.5.0; extra == 'development'
240
- Requires-Dist: pytest-randomly==3.15.0; extra == 'development'
241
+ Requires-Dist: pytest-randomly==3.16.0; extra == 'development'
241
242
  Requires-Dist: pytest==8.3.3; extra == 'development'
242
- Requires-Dist: syrupy==4.7.1; extra == 'development'
243
+ Requires-Dist: syrupy==4.7.2; extra == 'development'
243
244
  Provides-Extra: packaging
244
245
  Requires-Dist: pyinstaller~=6.10; extra == 'packaging'
245
246
  Description-Content-Type: text/markdown
@@ -272,15 +273,13 @@ Snowflake CLI is an open-source command-line tool explicitly designed for develo
272
273
 
273
274
  With Snowflake CLI, developers can create, manage, update, and view apps running on Snowflake across workloads such as Streamlit in Snowflake, the Snowflake Native App Framework, Snowpark Container Services, and Snowpark. It supports a range of Snowflake features, including user-defined functions, stored procedures, Streamlit in Snowflake, and SQL execution.
274
275
 
275
-
276
276
  **Note**: Snowflake CLI is in Public Preview (PuPr).
277
277
 
278
- Docs: https://docs.snowflake.com/en/developer-guide/snowflake-cli-v2/index.
279
-
280
- Quick start: https://quickstarts.snowflake.com/guide/getting-started-with-snowflake-cli
278
+ Docs: <https://docs.snowflake.com/en/developer-guide/snowflake-cli-v2/index>.
281
279
 
282
- Cheatsheet: https://github.com/Snowflake-Labs/sf-cheatsheets/blob/main/snowflake-cli.md
280
+ Quick start: <https://quickstarts.snowflake.com/guide/getting-started-with-snowflake-cli>
283
281
 
282
+ Cheatsheet: <https://github.com/Snowflake-Labs/sf-cheatsheets/blob/main/snowflake-cli.md>
284
283
 
285
284
  ## Install Snowflake CLI
286
285
 
@@ -289,7 +288,7 @@ Cheatsheet: https://github.com/Snowflake-Labs/sf-cheatsheets/blob/main/snowflake
289
288
  We recommend installing Snowflake CLI in isolated environment using [pipx](https://pipx.pypa.io/stable/). Requires Python >= 3.10
290
289
 
291
290
  ```bash
292
- pipx install snowflake-cli-labs
291
+ pipx install snowflake-cli
293
292
  snow --help
294
293
  ```
295
294
 
@@ -322,4 +321,4 @@ You should now be able to run `snow` and get the CLI message.
322
321
  ## Get involved
323
322
 
324
323
  Have a feature idea? Running into a bug? Want to contribute? We'd love to hear from you!
325
- Please open or review issues, open pull requests, or reach out to us on developers@snowflake.com
324
+ Please open or review issues, open pull requests, or reach out to us on <developers@snowflake.com>