snowflake-cli-labs 2.6.0.dev0__py3-none-any.whl → 2.6.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.
@@ -14,4 +14,4 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- VERSION = "2.6.0.dev0"
17
+ VERSION = "2.6.1"
@@ -114,6 +114,8 @@ def config_init(config_file: Optional[Path]):
114
114
  Initializes the app configuration. Config provided via cli flag takes precedence.
115
115
  If config file does not exist we create an empty one.
116
116
  """
117
+ from snowflake.cli.app.loggers import create_initial_loggers
118
+
117
119
  if config_file:
118
120
  CONFIG_MANAGER.file_path = config_file
119
121
  else:
@@ -121,6 +123,7 @@ def config_init(config_file: Optional[Path]):
121
123
  if not CONFIG_MANAGER.file_path.exists():
122
124
  _initialise_config(CONFIG_MANAGER.file_path)
123
125
  _read_config_file()
126
+ create_initial_loggers()
124
127
 
125
128
 
126
129
  def add_connection(name: str, connection_config: ConnectionConfig):
@@ -16,16 +16,27 @@ from __future__ import annotations
16
16
 
17
17
  import json
18
18
  import logging
19
- from typing import Any, Dict, List, Optional
19
+ from typing import Any, Dict, Optional
20
20
 
21
+ from click import ClickException
21
22
  from snowflake.cli.api.constants import SF_REST_API_URL_PREFIX
22
23
  from snowflake.connector.connection import SnowflakeConnection
23
- from snowflake.connector.errors import InterfaceError
24
+ from snowflake.connector.errors import BadRequest, InterfaceError
24
25
  from snowflake.connector.network import SnowflakeRestful
25
26
 
26
27
  log = logging.getLogger(__name__)
27
28
 
28
29
 
30
+ def _pluralize_object_type(object_type: str) -> str:
31
+ """
32
+ Pluralize object type without depending on OBJECT_TO_NAMES.
33
+ """
34
+ if object_type.endswith("y"):
35
+ return object_type[:-1].lower() + "ies"
36
+ else:
37
+ return object_type.lower() + "s"
38
+
39
+
29
40
  class RestApi:
30
41
  def __init__(self, connection: SnowflakeConnection):
31
42
  self.conn = connection
@@ -43,6 +54,13 @@ class RestApi:
43
54
  return False
44
55
  raise err
45
56
 
57
+ def _fetch_endpoint_exists(self, url: str) -> bool:
58
+ try:
59
+ result = self.send_rest_request(url, method="get")
60
+ return bool(result)
61
+ except BadRequest:
62
+ return False
63
+
46
64
  def send_rest_request(
47
65
  self, url: str, method: str, data: Optional[Dict[str, Any]] = None
48
66
  ):
@@ -75,12 +93,18 @@ class RestApi:
75
93
  no_retry=True,
76
94
  )
77
95
 
78
- def determine_url_for_create_query(
79
- self, *, plural_object_type: str
80
- ) -> Optional[str]:
96
+ def _database_exists(self, db_name: str) -> bool:
97
+ url = f"{SF_REST_API_URL_PREFIX}/databases/{db_name}"
98
+ return self._fetch_endpoint_exists(url)
99
+
100
+ def _schema_exists(self, db_name: str, schema_name: str) -> bool:
101
+ url = f"{SF_REST_API_URL_PREFIX}/databases/{db_name}/schemas/{schema_name}"
102
+ return self._fetch_endpoint_exists(url)
103
+
104
+ def determine_url_for_create_query(self, object_type: str) -> str:
81
105
  """
82
106
  Determine an url for creating an object of given type via REST API.
83
- The function returns None if URL cannot be determined.
107
+ If URL cannot be determined, the function throws CannotDetermineCreateURLException exception.
84
108
 
85
109
  URLs we check:
86
110
  * /api/v2/<type>/
@@ -92,22 +116,57 @@ class RestApi:
92
116
  To check whether an URL exists, we send read-only GET request (LIST endpoint,
93
117
  which should imply CREATE endpoint).
94
118
  """
95
- urls_to_be_checked: List[Optional[str]] = [
96
- f"{SF_REST_API_URL_PREFIX}/{plural_object_type}/",
97
- (
98
- f"{SF_REST_API_URL_PREFIX}/databases/{self.conn.database}/{plural_object_type}/"
99
- if self.conn.database
100
- else None
101
- ),
102
- (
103
- f"{SF_REST_API_URL_PREFIX}/databases/{self.conn.database}/schemas/{self.conn.schema}/{plural_object_type}/"
104
- if self.conn.database and self.conn.schema
105
- else None
106
- ),
107
- ]
108
-
109
- for url in urls_to_be_checked:
110
- if url and self.get_endpoint_exists(url):
111
- return url
112
-
113
- return None
119
+ plural_object_type = _pluralize_object_type(object_type)
120
+
121
+ if self.get_endpoint_exists(
122
+ url := f"{SF_REST_API_URL_PREFIX}/{plural_object_type}/"
123
+ ):
124
+ return url
125
+
126
+ db = self.conn.database
127
+ if not db:
128
+ raise DatabaseNotDefinedException(
129
+ "Database not defined in connection. Please try again with `--database` flag."
130
+ )
131
+ if not self._database_exists(db):
132
+ raise DatabaseNotExistsException(f"Database '{db}' does not exist.")
133
+ if self.get_endpoint_exists(
134
+ url := f"{SF_REST_API_URL_PREFIX}/databases/{db}/{plural_object_type}/"
135
+ ):
136
+ return url
137
+
138
+ schema = self.conn.schema
139
+ if not schema:
140
+ raise SchemaNotDefinedException(
141
+ "Schema not defined in connection. Please try again with `--schema` flag."
142
+ )
143
+ if not self._schema_exists(db_name=db, schema_name=schema):
144
+ raise SchemaNotExistsException(f"Schema '{schema}' does not exist.")
145
+ if self.get_endpoint_exists(
146
+ url := f"{SF_REST_API_URL_PREFIX}/databases/{self.conn.database}/schemas/{self.conn.schema}/{plural_object_type}/"
147
+ ):
148
+ return url
149
+
150
+ raise CannotDetermineCreateURLException(
151
+ f"Create operation for type {object_type} is not supported. Try using `sql -q 'CREATE ...'` command."
152
+ )
153
+
154
+
155
+ class DatabaseNotDefinedException(ClickException):
156
+ pass
157
+
158
+
159
+ class SchemaNotDefinedException(ClickException):
160
+ pass
161
+
162
+
163
+ class DatabaseNotExistsException(ClickException):
164
+ pass
165
+
166
+
167
+ class SchemaNotExistsException(ClickException):
168
+ pass
169
+
170
+
171
+ class CannotDetermineCreateURLException(ClickException):
172
+ pass
@@ -30,7 +30,6 @@ from snowflake.cli.api.config import config_init
30
30
  from snowflake.cli.api.output.formats import OutputFormat
31
31
  from snowflake.cli.api.output.types import CollectionResult
32
32
  from snowflake.cli.api.secure_path import SecurePath
33
- from snowflake.cli.app import loggers
34
33
  from snowflake.cli.app.api_impl.plugin.plugin_config_provider_impl import (
35
34
  PluginConfigProviderImpl,
36
35
  )
@@ -89,7 +88,6 @@ def _commands_registration_callback(value: bool):
89
88
  @_commands_registration.before
90
89
  def _config_init_callback(configuration_file: Optional[Path]):
91
90
  config_init(configuration_file)
92
- loggers.create_initial_loggers()
93
91
 
94
92
 
95
93
  @_commands_registration.before
@@ -20,9 +20,6 @@ from dataclasses import asdict, dataclass, field
20
20
  from typing import Any, Dict, List
21
21
 
22
22
  import typer
23
- from snowflake.cli.api.config import (
24
- get_logs_config,
25
- )
26
23
  from snowflake.cli.api.exceptions import InvalidLogsConfiguration
27
24
  from snowflake.cli.api.secure_path import SecurePath
28
25
  from snowflake.connector.errors import ConfigSourceError
@@ -103,6 +100,10 @@ def _remove_underscore_prefixes_from_keys(d: Dict[str, Any]) -> None:
103
100
 
104
101
  class FileLogsConfig:
105
102
  def __init__(self, debug: bool) -> None:
103
+ from snowflake.cli.api.config import (
104
+ get_logs_config,
105
+ )
106
+
106
107
  config = get_logs_config()
107
108
 
108
109
  self.path: SecurePath = SecurePath(config["path"])
@@ -142,8 +143,9 @@ def create_initial_loggers():
142
143
  config = InitialLoggingConfig()
143
144
  try:
144
145
  file_logs_config = FileLogsConfig(debug=False)
145
- config.handlers["file"]["filename"] = file_logs_config.filename
146
- _configurate_logging(config)
146
+ if file_logs_config.save_logs:
147
+ config.handlers["file"]["filename"] = file_logs_config.filename
148
+ _configurate_logging(config)
147
149
  except ConfigSourceError:
148
150
  pass
149
151
 
@@ -33,7 +33,7 @@ app = SnowTyperFactory(
33
33
 
34
34
  NameArgument = typer.Argument(help="Name of the object")
35
35
  ObjectArgument = typer.Argument(
36
- help="Type of object. For example table, procedure, streamlit.",
36
+ help="Type of object. For example table, database, compute-pool.",
37
37
  case_sensitive=False,
38
38
  show_default=False,
39
39
  )
@@ -36,16 +36,6 @@ def _get_object_names(object_type: str) -> ObjectNames:
36
36
  return OBJECT_TO_NAMES[object_type]
37
37
 
38
38
 
39
- def _pluralize_object_type(object_type: str) -> str:
40
- """
41
- Pluralize object type without depending on OBJECT_TO_NAMES.
42
- """
43
- if object_type.endswith("y"):
44
- return object_type[:-1].lower() + "ies"
45
- else:
46
- return object_type.lower() + "s"
47
-
48
-
49
39
  class ObjectManager(SqlExecutionMixin):
50
40
  def show(
51
41
  self,
@@ -85,11 +75,8 @@ class ObjectManager(SqlExecutionMixin):
85
75
 
86
76
  def create(self, object_type: str, object_data: Dict[str, Any]) -> str:
87
77
  rest = RestApi(self._conn)
88
- url = rest.determine_url_for_create_query(
89
- plural_object_type=_pluralize_object_type(object_type)
90
- )
91
- if not url:
92
- return f"Create operation for type {object_type} is not supported. Try using `sql -q 'CREATE ...'` command"
78
+ url = rest.determine_url_for_create_query(object_type=object_type)
79
+
93
80
  try:
94
81
  response = rest.send_rest_request(url=url, method="post", data=object_data)
95
82
  # workaround as SnowflakeRestful class ignores some errors, dropping their info and returns {} instead.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: snowflake-cli-labs
3
- Version: 2.6.0.dev0
3
+ Version: 2.6.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
@@ -1,13 +1,13 @@
1
- snowflake/cli/__about__.py,sha256=2PqF8ZNCimt_Kp8RtMfYKYXUGCq8g_c3tB4T4_qD7XE,638
1
+ snowflake/cli/__about__.py,sha256=hHAuylb0wGYbADN1G-eyVMxlkwOx6WgGwIIu5v9ZVV4,633
2
2
  snowflake/cli/__init__.py,sha256=uGA_QRGW3iGwaegpFsLgOhup0zBliBSXh9ou8J439uU,578
3
3
  snowflake/cli/api/__init__.py,sha256=kD6lYv5et7QJvW7vzvLN9p2ibfD7pjh9KRWsp2QoYqo,1330
4
4
  snowflake/cli/api/cli_global_context.py,sha256=pelnxYpGV6Hg_lTpUC860Xt1c8VFXDS55LL0ockmphc,11410
5
- snowflake/cli/api/config.py,sha256=15i7iYmYc4Z6E65MPjWtkGchZT7Fd54Sa-zpfqBw7X8,10856
5
+ snowflake/cli/api/config.py,sha256=_dCeNdKhkeF5QQbpBg5s32Xhu2Xa490ixjn9rmCRcxU,10951
6
6
  snowflake/cli/api/constants.py,sha256=nVcX-NNZBFUIDX3Gbgm_YKjzv8tgcd1JdYvicV-nL_A,2964
7
7
  snowflake/cli/api/exceptions.py,sha256=syNz7HdRVs3hAVC2NUaQINlSo-Ge-WEceuFvLoau2eQ,5118
8
8
  snowflake/cli/api/feature_flags.py,sha256=1bBlILOtTn7wSqk0jY3CdwOSCV5lMZF6FxT3HuoYvAI,1418
9
9
  snowflake/cli/api/identifiers.py,sha256=_Q53mRIkXCow2mqnXgF7LdMpp-DXvTN8FrKb0rnq8nA,5036
10
- snowflake/cli/api/rest_api.py,sha256=fYGr9GwMbpR2Y75OqH3nf4czp9G9_MXiRTjav_HshFk,4137
10
+ snowflake/cli/api/rest_api.py,sha256=X2hYq-J2mZJmVIEeCUvdk8ccTiV86ltVlj9ac5ZmIak,6070
11
11
  snowflake/cli/api/sanitizers.py,sha256=7EKqVQ3KOob0IFFoc_GmXPYpRhgnmIqhnJSvHPgxM5I,1211
12
12
  snowflake/cli/api/secure_path.py,sha256=-H2UD1ERc31cCoXyKVQDT0EzjRRLunuOBTfVA49-wc8,13058
13
13
  snowflake/cli/api/secure_utils.py,sha256=7fBLtlckmKMPaPRgXfb9XN66tXLX5GdnWw8dL2ZmNKw,1102
@@ -64,9 +64,9 @@ snowflake/cli/api/utils/rendering.py,sha256=g5Sqc5OsjaRABtU6igFInNbnvpts5PTp4SM4
64
64
  snowflake/cli/api/utils/types.py,sha256=fVKuls8axKSsBzPqWwrkwkwoXXmedqxNJKqfXrrGyBM,1190
65
65
  snowflake/cli/app/__init__.py,sha256=CR_uTgoqHnU1XdyRhm5iQsS86yWXGVx5Ht7aGSDNFmc,765
66
66
  snowflake/cli/app/__main__.py,sha256=KrWQBN5trQZUBqC9nQLeQDq134JLkFC0AfmDxRD3U38,833
67
- snowflake/cli/app/cli_app.py,sha256=ekEU6IAjkANK3xrHVgh82QhH7FFTXxNvTmud4gKuKDE,8224
67
+ snowflake/cli/app/cli_app.py,sha256=culZ_65q5eFKR35ScLRNh1z-TbPtJ0-CMVjPjd_ChLs,8149
68
68
  snowflake/cli/app/constants.py,sha256=WCqViioXdOt0Cykf-KK42cBLfqHKTfYobMJJ-AC7kSs,698
69
- snowflake/cli/app/loggers.py,sha256=5DnwA2ot7WXERyEQ-Z_RnwDgrouFkZG7TdvzTXlJ5UI,6494
69
+ snowflake/cli/app/loggers.py,sha256=tHf5OT-Hj3_LjsZhSphheRwKVc9-pUXuv_BA_6EII8w,6566
70
70
  snowflake/cli/app/main_typer.py,sha256=4VQqUCxTGHrc21I2nt-Lel6_T_NS8uwkuAntHjrkx3w,2101
71
71
  snowflake/cli/app/printing.py,sha256=H6yclrM5lD55jQ5DXueVBz2bsNyY8UVXwuQ0Aw6ykiA,5322
72
72
  snowflake/cli/app/snow_connector.py,sha256=4ZOa7TufXOpnRH5_AKpx6pDcZU8ioz4wo3oE6i3uZhs,8453
@@ -143,9 +143,9 @@ snowflake/cli/plugins/notebook/plugin_spec.py,sha256=dzmt9GvlDfcFXmM8plhmoQoOtxG
143
143
  snowflake/cli/plugins/notebook/types.py,sha256=dWXZAsDEzH8iEQPws_w-XTYASynouA1hrHz62zocduw,622
144
144
  snowflake/cli/plugins/object/__init__.py,sha256=uGA_QRGW3iGwaegpFsLgOhup0zBliBSXh9ou8J439uU,578
145
145
  snowflake/cli/plugins/object/command_aliases.py,sha256=AhInra53zxJDamKWwdWAmJcjH1C6o41CEcvk6QqiPV8,3111
146
- snowflake/cli/plugins/object/commands.py,sha256=TpRo2Bf8svW9EBEhDmfyOXVcix3EHxWYm2WsOnriWDs,5767
146
+ snowflake/cli/plugins/object/commands.py,sha256=ok3UIhckd_14b2QaZfKAO-qLjlTbPqFmnQPNFn72H8Y,5769
147
147
  snowflake/cli/plugins/object/common.py,sha256=x1V8fiVnh7ohHHq0_NaGFtUvTz0soVRSGm-oCIuhJHs,2608
148
- snowflake/cli/plugins/object/manager.py,sha256=Wd-x71vDnlqPsZy5N0e-dTyTo3bO3rXLxFyWMLYK1ik,4331
148
+ snowflake/cli/plugins/object/manager.py,sha256=Mb_oW85YvyG-EUIPB9sbmNNBE8FAuLnGG-PjBLGwWH0,3871
149
149
  snowflake/cli/plugins/object/plugin_spec.py,sha256=nqOiA-qCm2mBGSow4mDvf4A6TKQVwIz5YTGZSxQpr2Q,994
150
150
  snowflake/cli/plugins/object_stage_deprecated/__init__.py,sha256=RLQpA97914b74tTgiUft4JM_LvM8zVLWGgDy3Cq2sc8,608
151
151
  snowflake/cli/plugins/object_stage_deprecated/commands.py,sha256=_lsUcmu1mYj9HurpLLBpoJspwiEtWbnglXPPTCqGcVk,3835
@@ -210,8 +210,8 @@ snowflake/cli/templates/default_streamlit/snowflake.yml,sha256=yWFU-vqJ7Z17K3loU
210
210
  snowflake/cli/templates/default_streamlit/streamlit_app.py,sha256=BtWuwdkgcMiYt21ghyi6Y1b_ITcIunN13ulUknvQbgI,688
211
211
  snowflake/cli/templates/default_streamlit/common/hello.py,sha256=3kZSJggAWSYgi06NuI_5USV06mcCOBEzzz2DYeNGpc0,617
212
212
  snowflake/cli/templates/default_streamlit/pages/my_page.py,sha256=wj2nMJmpAH_e9hOHoAUxyG4q17vyeVdnBtaXv_5KG24,628
213
- snowflake_cli_labs-2.6.0.dev0.dist-info/METADATA,sha256=b8UJVWvK-fTm2LaecrrcUbDJ7e9epeAq8b4SJC0f2-8,17732
214
- snowflake_cli_labs-2.6.0.dev0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
215
- snowflake_cli_labs-2.6.0.dev0.dist-info/entry_points.txt,sha256=_qdnT44fYFbH78kb6Em5jr2_26amIg3UIAvSdmqT6TY,57
216
- snowflake_cli_labs-2.6.0.dev0.dist-info/licenses/LICENSE,sha256=mJMA3Uz2AbjU_kVggo1CAx01XhBsI7BSi2H7ggUg_-c,11344
217
- snowflake_cli_labs-2.6.0.dev0.dist-info/RECORD,,
213
+ snowflake_cli_labs-2.6.1.dist-info/METADATA,sha256=X8DfxpBbg5VTbXdDNDkQ7jwU8QR9MbQHRq1x2wmc7iU,17727
214
+ snowflake_cli_labs-2.6.1.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
215
+ snowflake_cli_labs-2.6.1.dist-info/entry_points.txt,sha256=_qdnT44fYFbH78kb6Em5jr2_26amIg3UIAvSdmqT6TY,57
216
+ snowflake_cli_labs-2.6.1.dist-info/licenses/LICENSE,sha256=mJMA3Uz2AbjU_kVggo1CAx01XhBsI7BSi2H7ggUg_-c,11344
217
+ snowflake_cli_labs-2.6.1.dist-info/RECORD,,