snowflake-cli-labs 2.8.0rc1__py3-none-any.whl → 2.8.2__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 (242) hide show
  1. README.md +21 -0
  2. {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-2.8.2.dist-info}/METADATA +7 -95
  3. snowflake_cli_labs-2.8.2.dist-info/RECORD +5 -0
  4. snowflake/cli/__about__.py +0 -17
  5. snowflake/cli/__init__.py +0 -13
  6. snowflake/cli/api/__init__.py +0 -48
  7. snowflake/cli/api/cli_global_context.py +0 -390
  8. snowflake/cli/api/commands/__init__.py +0 -13
  9. snowflake/cli/api/commands/alias.py +0 -23
  10. snowflake/cli/api/commands/decorators.py +0 -354
  11. snowflake/cli/api/commands/execution_metadata.py +0 -40
  12. snowflake/cli/api/commands/experimental_behaviour.py +0 -19
  13. snowflake/cli/api/commands/flags.py +0 -640
  14. snowflake/cli/api/commands/project_initialisation.py +0 -65
  15. snowflake/cli/api/commands/snow_typer.py +0 -237
  16. snowflake/cli/api/commands/typer_pre_execute.py +0 -26
  17. snowflake/cli/api/config.py +0 -348
  18. snowflake/cli/api/console/__init__.py +0 -17
  19. snowflake/cli/api/console/abc.py +0 -89
  20. snowflake/cli/api/console/console.py +0 -134
  21. snowflake/cli/api/console/enum.py +0 -17
  22. snowflake/cli/api/constants.py +0 -79
  23. snowflake/cli/api/errno.py +0 -27
  24. snowflake/cli/api/exceptions.py +0 -164
  25. snowflake/cli/api/feature_flags.py +0 -55
  26. snowflake/cli/api/identifiers.py +0 -154
  27. snowflake/cli/api/output/__init__.py +0 -13
  28. snowflake/cli/api/output/formats.py +0 -20
  29. snowflake/cli/api/output/types.py +0 -118
  30. snowflake/cli/api/plugins/__init__.py +0 -13
  31. snowflake/cli/api/plugins/command/__init__.py +0 -72
  32. snowflake/cli/api/plugins/command/plugin_hook_specs.py +0 -21
  33. snowflake/cli/api/plugins/plugin_config.py +0 -32
  34. snowflake/cli/api/project/__init__.py +0 -13
  35. snowflake/cli/api/project/definition.py +0 -84
  36. snowflake/cli/api/project/definition_manager.py +0 -134
  37. snowflake/cli/api/project/errors.py +0 -56
  38. snowflake/cli/api/project/project_verification.py +0 -23
  39. snowflake/cli/api/project/schemas/__init__.py +0 -13
  40. snowflake/cli/api/project/schemas/entities/application_entity.py +0 -44
  41. snowflake/cli/api/project/schemas/entities/application_package_entity.py +0 -66
  42. snowflake/cli/api/project/schemas/entities/common.py +0 -78
  43. snowflake/cli/api/project/schemas/entities/entities.py +0 -30
  44. snowflake/cli/api/project/schemas/identifier_model.py +0 -49
  45. snowflake/cli/api/project/schemas/native_app/__init__.py +0 -13
  46. snowflake/cli/api/project/schemas/native_app/application.py +0 -62
  47. snowflake/cli/api/project/schemas/native_app/native_app.py +0 -93
  48. snowflake/cli/api/project/schemas/native_app/package.py +0 -78
  49. snowflake/cli/api/project/schemas/native_app/path_mapping.py +0 -65
  50. snowflake/cli/api/project/schemas/project_definition.py +0 -199
  51. snowflake/cli/api/project/schemas/snowpark/__init__.py +0 -13
  52. snowflake/cli/api/project/schemas/snowpark/argument.py +0 -28
  53. snowflake/cli/api/project/schemas/snowpark/callable.py +0 -69
  54. snowflake/cli/api/project/schemas/snowpark/snowpark.py +0 -36
  55. snowflake/cli/api/project/schemas/streamlit/__init__.py +0 -13
  56. snowflake/cli/api/project/schemas/streamlit/streamlit.py +0 -46
  57. snowflake/cli/api/project/schemas/template.py +0 -77
  58. snowflake/cli/api/project/schemas/updatable_model.py +0 -194
  59. snowflake/cli/api/project/util.py +0 -261
  60. snowflake/cli/api/rendering/__init__.py +0 -13
  61. snowflake/cli/api/rendering/jinja.py +0 -112
  62. snowflake/cli/api/rendering/project_definition_templates.py +0 -39
  63. snowflake/cli/api/rendering/project_templates.py +0 -98
  64. snowflake/cli/api/rendering/sql_templates.py +0 -60
  65. snowflake/cli/api/rest_api.py +0 -172
  66. snowflake/cli/api/sanitizers.py +0 -43
  67. snowflake/cli/api/secure_path.py +0 -362
  68. snowflake/cli/api/secure_utils.py +0 -29
  69. snowflake/cli/api/sql_execution.py +0 -260
  70. snowflake/cli/api/utils/__init__.py +0 -13
  71. snowflake/cli/api/utils/cursor.py +0 -34
  72. snowflake/cli/api/utils/definition_rendering.py +0 -383
  73. snowflake/cli/api/utils/dict_utils.py +0 -73
  74. snowflake/cli/api/utils/error_handling.py +0 -23
  75. snowflake/cli/api/utils/graph.py +0 -97
  76. snowflake/cli/api/utils/models.py +0 -63
  77. snowflake/cli/api/utils/naming_utils.py +0 -13
  78. snowflake/cli/api/utils/path_utils.py +0 -36
  79. snowflake/cli/api/utils/templating_functions.py +0 -144
  80. snowflake/cli/api/utils/types.py +0 -35
  81. snowflake/cli/app/__init__.py +0 -22
  82. snowflake/cli/app/__main__.py +0 -31
  83. snowflake/cli/app/api_impl/__init__.py +0 -13
  84. snowflake/cli/app/api_impl/plugin/__init__.py +0 -13
  85. snowflake/cli/app/api_impl/plugin/plugin_config_provider_impl.py +0 -66
  86. snowflake/cli/app/build_and_push.sh +0 -8
  87. snowflake/cli/app/cli_app.py +0 -243
  88. snowflake/cli/app/commands_registration/__init__.py +0 -33
  89. snowflake/cli/app/commands_registration/builtin_plugins.py +0 -54
  90. snowflake/cli/app/commands_registration/command_plugins_loader.py +0 -169
  91. snowflake/cli/app/commands_registration/commands_registration_with_callbacks.py +0 -105
  92. snowflake/cli/app/commands_registration/exception_logging.py +0 -26
  93. snowflake/cli/app/commands_registration/threadsafe.py +0 -48
  94. snowflake/cli/app/commands_registration/typer_registration.py +0 -153
  95. snowflake/cli/app/constants.py +0 -19
  96. snowflake/cli/app/dev/__init__.py +0 -13
  97. snowflake/cli/app/dev/commands_structure.py +0 -48
  98. snowflake/cli/app/dev/docs/__init__.py +0 -13
  99. snowflake/cli/app/dev/docs/commands_docs_generator.py +0 -100
  100. snowflake/cli/app/dev/docs/generator.py +0 -35
  101. snowflake/cli/app/dev/docs/project_definition_docs_generator.py +0 -58
  102. snowflake/cli/app/dev/docs/project_definition_generate_json_schema.py +0 -227
  103. snowflake/cli/app/dev/docs/template_utils.py +0 -23
  104. snowflake/cli/app/dev/docs/templates/definition_description.rst.jinja2 +0 -38
  105. snowflake/cli/app/dev/docs/templates/overview.rst.jinja2 +0 -9
  106. snowflake/cli/app/dev/docs/templates/usage.rst.jinja2 +0 -57
  107. snowflake/cli/app/dev/pycharm_remote_debug.py +0 -46
  108. snowflake/cli/app/loggers.py +0 -199
  109. snowflake/cli/app/main_typer.py +0 -62
  110. snowflake/cli/app/printing.py +0 -181
  111. snowflake/cli/app/snow_connector.py +0 -243
  112. snowflake/cli/app/telemetry.py +0 -189
  113. snowflake/cli/plugins/__init__.py +0 -13
  114. snowflake/cli/plugins/connection/__init__.py +0 -13
  115. snowflake/cli/plugins/connection/commands.py +0 -330
  116. snowflake/cli/plugins/connection/plugin_spec.py +0 -30
  117. snowflake/cli/plugins/connection/util.py +0 -179
  118. snowflake/cli/plugins/cortex/__init__.py +0 -13
  119. snowflake/cli/plugins/cortex/commands.py +0 -327
  120. snowflake/cli/plugins/cortex/constants.py +0 -17
  121. snowflake/cli/plugins/cortex/manager.py +0 -189
  122. snowflake/cli/plugins/cortex/plugin_spec.py +0 -30
  123. snowflake/cli/plugins/cortex/types.py +0 -22
  124. snowflake/cli/plugins/git/__init__.py +0 -13
  125. snowflake/cli/plugins/git/commands.py +0 -305
  126. snowflake/cli/plugins/git/manager.py +0 -96
  127. snowflake/cli/plugins/git/plugin_spec.py +0 -30
  128. snowflake/cli/plugins/init/__init__.py +0 -13
  129. snowflake/cli/plugins/init/commands.py +0 -244
  130. snowflake/cli/plugins/init/plugin_spec.py +0 -30
  131. snowflake/cli/plugins/nativeapp/__init__.py +0 -13
  132. snowflake/cli/plugins/nativeapp/artifacts.py +0 -742
  133. snowflake/cli/plugins/nativeapp/codegen/__init__.py +0 -13
  134. snowflake/cli/plugins/nativeapp/codegen/artifact_processor.py +0 -91
  135. snowflake/cli/plugins/nativeapp/codegen/compiler.py +0 -130
  136. snowflake/cli/plugins/nativeapp/codegen/sandbox.py +0 -306
  137. snowflake/cli/plugins/nativeapp/codegen/setup/native_app_setup_processor.py +0 -172
  138. snowflake/cli/plugins/nativeapp/codegen/setup/setup_driver.py.source +0 -56
  139. snowflake/cli/plugins/nativeapp/codegen/snowpark/callback_source.py.jinja +0 -181
  140. snowflake/cli/plugins/nativeapp/codegen/snowpark/extension_function_utils.py +0 -217
  141. snowflake/cli/plugins/nativeapp/codegen/snowpark/models.py +0 -61
  142. snowflake/cli/plugins/nativeapp/codegen/snowpark/python_processor.py +0 -528
  143. snowflake/cli/plugins/nativeapp/commands.py +0 -439
  144. snowflake/cli/plugins/nativeapp/common_flags.py +0 -44
  145. snowflake/cli/plugins/nativeapp/constants.py +0 -27
  146. snowflake/cli/plugins/nativeapp/exceptions.py +0 -122
  147. snowflake/cli/plugins/nativeapp/feature_flags.py +0 -24
  148. snowflake/cli/plugins/nativeapp/init.py +0 -345
  149. snowflake/cli/plugins/nativeapp/manager.py +0 -823
  150. snowflake/cli/plugins/nativeapp/plugin_spec.py +0 -30
  151. snowflake/cli/plugins/nativeapp/policy.py +0 -50
  152. snowflake/cli/plugins/nativeapp/project_model.py +0 -195
  153. snowflake/cli/plugins/nativeapp/run_processor.py +0 -389
  154. snowflake/cli/plugins/nativeapp/teardown_processor.py +0 -301
  155. snowflake/cli/plugins/nativeapp/utils.py +0 -98
  156. snowflake/cli/plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +0 -135
  157. snowflake/cli/plugins/nativeapp/version/__init__.py +0 -13
  158. snowflake/cli/plugins/nativeapp/version/commands.py +0 -170
  159. snowflake/cli/plugins/nativeapp/version/version_processor.py +0 -362
  160. snowflake/cli/plugins/notebook/__init__.py +0 -13
  161. snowflake/cli/plugins/notebook/commands.py +0 -84
  162. snowflake/cli/plugins/notebook/exceptions.py +0 -20
  163. snowflake/cli/plugins/notebook/manager.py +0 -71
  164. snowflake/cli/plugins/notebook/plugin_spec.py +0 -30
  165. snowflake/cli/plugins/notebook/types.py +0 -16
  166. snowflake/cli/plugins/object/__init__.py +0 -13
  167. snowflake/cli/plugins/object/command_aliases.py +0 -94
  168. snowflake/cli/plugins/object/commands.py +0 -174
  169. snowflake/cli/plugins/object/common.py +0 -85
  170. snowflake/cli/plugins/object/manager.py +0 -96
  171. snowflake/cli/plugins/object/plugin_spec.py +0 -30
  172. snowflake/cli/plugins/object_stage_deprecated/__init__.py +0 -15
  173. snowflake/cli/plugins/object_stage_deprecated/commands.py +0 -122
  174. snowflake/cli/plugins/object_stage_deprecated/plugin_spec.py +0 -32
  175. snowflake/cli/plugins/snowpark/__init__.py +0 -13
  176. snowflake/cli/plugins/snowpark/commands.py +0 -548
  177. snowflake/cli/plugins/snowpark/common.py +0 -307
  178. snowflake/cli/plugins/snowpark/manager.py +0 -109
  179. snowflake/cli/plugins/snowpark/models.py +0 -156
  180. snowflake/cli/plugins/snowpark/package/__init__.py +0 -13
  181. snowflake/cli/plugins/snowpark/package/anaconda_packages.py +0 -233
  182. snowflake/cli/plugins/snowpark/package/commands.py +0 -256
  183. snowflake/cli/plugins/snowpark/package/manager.py +0 -43
  184. snowflake/cli/plugins/snowpark/package/utils.py +0 -26
  185. snowflake/cli/plugins/snowpark/package_utils.py +0 -354
  186. snowflake/cli/plugins/snowpark/plugin_spec.py +0 -30
  187. snowflake/cli/plugins/snowpark/snowpark_package_paths.py +0 -65
  188. snowflake/cli/plugins/snowpark/snowpark_shared.py +0 -95
  189. snowflake/cli/plugins/snowpark/zipper.py +0 -81
  190. snowflake/cli/plugins/spcs/__init__.py +0 -35
  191. snowflake/cli/plugins/spcs/common.py +0 -99
  192. snowflake/cli/plugins/spcs/compute_pool/__init__.py +0 -13
  193. snowflake/cli/plugins/spcs/compute_pool/commands.py +0 -240
  194. snowflake/cli/plugins/spcs/compute_pool/manager.py +0 -121
  195. snowflake/cli/plugins/spcs/image_registry/__init__.py +0 -13
  196. snowflake/cli/plugins/spcs/image_registry/commands.py +0 -65
  197. snowflake/cli/plugins/spcs/image_registry/manager.py +0 -105
  198. snowflake/cli/plugins/spcs/image_repository/__init__.py +0 -13
  199. snowflake/cli/plugins/spcs/image_repository/commands.py +0 -196
  200. snowflake/cli/plugins/spcs/image_repository/manager.py +0 -84
  201. snowflake/cli/plugins/spcs/jobs/__init__.py +0 -13
  202. snowflake/cli/plugins/spcs/jobs/commands.py +0 -78
  203. snowflake/cli/plugins/spcs/jobs/manager.py +0 -53
  204. snowflake/cli/plugins/spcs/plugin_spec.py +0 -30
  205. snowflake/cli/plugins/spcs/services/__init__.py +0 -13
  206. snowflake/cli/plugins/spcs/services/commands.py +0 -311
  207. snowflake/cli/plugins/spcs/services/manager.py +0 -170
  208. snowflake/cli/plugins/sql/__init__.py +0 -13
  209. snowflake/cli/plugins/sql/commands.py +0 -83
  210. snowflake/cli/plugins/sql/manager.py +0 -92
  211. snowflake/cli/plugins/sql/plugin_spec.py +0 -30
  212. snowflake/cli/plugins/sql/snowsql_templating.py +0 -28
  213. snowflake/cli/plugins/stage/__init__.py +0 -13
  214. snowflake/cli/plugins/stage/commands.py +0 -261
  215. snowflake/cli/plugins/stage/diff.py +0 -326
  216. snowflake/cli/plugins/stage/manager.py +0 -544
  217. snowflake/cli/plugins/stage/md5.py +0 -160
  218. snowflake/cli/plugins/stage/plugin_spec.py +0 -30
  219. snowflake/cli/plugins/streamlit/__init__.py +0 -13
  220. snowflake/cli/plugins/streamlit/commands.py +0 -186
  221. snowflake/cli/plugins/streamlit/manager.py +0 -222
  222. snowflake/cli/plugins/streamlit/plugin_spec.py +0 -30
  223. snowflake/cli/plugins/workspace/__init__.py +0 -13
  224. snowflake/cli/plugins/workspace/commands.py +0 -35
  225. snowflake/cli/plugins/workspace/plugin_spec.py +0 -30
  226. snowflake/cli/templates/default_snowpark/.gitignore +0 -4
  227. snowflake/cli/templates/default_snowpark/app/__init__.py +0 -0
  228. snowflake/cli/templates/default_snowpark/app/common.py +0 -2
  229. snowflake/cli/templates/default_snowpark/app/functions.py +0 -15
  230. snowflake/cli/templates/default_snowpark/app/procedures.py +0 -22
  231. snowflake/cli/templates/default_snowpark/requirements.txt +0 -1
  232. snowflake/cli/templates/default_snowpark/snowflake.yml +0 -23
  233. snowflake/cli/templates/default_streamlit/.gitignore +0 -4
  234. snowflake/cli/templates/default_streamlit/common/hello.py +0 -2
  235. snowflake/cli/templates/default_streamlit/environment.yml +0 -6
  236. snowflake/cli/templates/default_streamlit/pages/my_page.py +0 -3
  237. snowflake/cli/templates/default_streamlit/snowflake.yml +0 -10
  238. snowflake/cli/templates/default_streamlit/streamlit_app.py +0 -4
  239. snowflake_cli_labs-2.8.0rc1.dist-info/RECORD +0 -240
  240. snowflake_cli_labs-2.8.0rc1.dist-info/entry_points.txt +0 -2
  241. {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-2.8.2.dist-info}/WHEEL +0 -0
  242. {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-2.8.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,354 +0,0 @@
1
- # Copyright (c) 2024 Snowflake Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from __future__ import annotations
16
-
17
- import dataclasses
18
- import locale
19
- import logging
20
- import os
21
- import re
22
- import subprocess
23
- from pathlib import Path
24
- from textwrap import dedent
25
- from typing import Dict, List, Optional
26
-
27
- from click import ClickException
28
- from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB
29
- from snowflake.cli.api.secure_path import SecurePath
30
- from snowflake.cli.plugins.snowpark.models import (
31
- Requirement,
32
- RequirementWithFiles,
33
- RequirementWithWheel,
34
- WheelMetadata,
35
- )
36
- from snowflake.cli.plugins.snowpark.package.anaconda_packages import (
37
- AnacondaPackages,
38
- )
39
-
40
- log = logging.getLogger(__name__)
41
-
42
- PIP_PATH = os.environ.get("SNOWCLI_PIP_PATH", "pip")
43
-
44
-
45
- def parse_requirements(
46
- requirements_file: SecurePath = SecurePath("requirements.txt"),
47
- ) -> List[Requirement]:
48
- """Reads and parses a Python requirements.txt file.
49
-
50
- Args:
51
- requirements_file (str, optional): The name of the file.
52
- Defaults to 'requirements.txt'.
53
-
54
- Returns:
55
- list[Requirement]: A flat list of necessary packages
56
- """
57
- reqs = []
58
- if requirements_file.exists():
59
- for line in requirements_file.read_text(
60
- file_size_limit_mb=DEFAULT_SIZE_LIMIT_MB
61
- ).splitlines():
62
- line = re.sub(r"\s*#.*", "", line).strip()
63
- if line:
64
- reqs.append(Requirement.parse(line))
65
- return reqs
66
-
67
-
68
- def generate_deploy_stage_name(identifier: str) -> str:
69
- return (
70
- identifier.replace("()", "")
71
- .replace(
72
- "(",
73
- "_",
74
- )
75
- .replace(
76
- ")",
77
- "",
78
- )
79
- .replace(
80
- " ",
81
- "_",
82
- )
83
- .replace(
84
- ",",
85
- "",
86
- )
87
- )
88
-
89
-
90
- def get_package_name_from_pip_wheel(package: str, index_url: str | None = None) -> str:
91
- """Downloads the package using pip and returns the package name.
92
- If the package name cannot be determined, it returns the [package]."""
93
- with SecurePath.temporary_directory() as tmp_dir:
94
- pip_result = pip_wheel(
95
- package_name=package,
96
- requirements_file=None,
97
- download_dir=tmp_dir.path,
98
- index_url=index_url,
99
- dependencies=False,
100
- )
101
- file_list = [
102
- f.path.name for f in tmp_dir.iterdir() if f.path.name.endswith(".whl")
103
- ]
104
-
105
- if pip_result != 0 or len(file_list) != 1:
106
- # cannot determine package name
107
- return package
108
- return WheelMetadata.from_wheel((tmp_dir / file_list[0]).path).name
109
-
110
-
111
- def _write_requirements_file(file_path: SecurePath, requirements: List[Requirement]):
112
- log.info("Writing %s file", file_path.path)
113
- with file_path.open("w", encoding="utf-8") as f:
114
- for req in requirements:
115
- f.write(f"{req.line}\n")
116
-
117
-
118
- @dataclasses.dataclass
119
- class DownloadUnavailablePackagesResult:
120
- succeeded: bool
121
- error_message: str | None = None
122
- anaconda_packages: List[Requirement] = dataclasses.field(default_factory=list)
123
- downloaded_packages_details: List[RequirementWithFiles] = dataclasses.field(
124
- default_factory=list
125
- )
126
-
127
-
128
- def download_unavailable_packages(
129
- requirements: List[Requirement],
130
- target_dir: SecurePath,
131
- # available packages lookup specs
132
- anaconda_packages: AnacondaPackages,
133
- skip_version_check: bool = False,
134
- # pip lookup specs
135
- pip_index_url: str | None = None,
136
- ) -> DownloadUnavailablePackagesResult:
137
- """Download packages unavailable on Snowflake Anaconda Channel to target directory.
138
-
139
- Returns an object with fields:
140
- - download_successful - whether packages were successfully downloaded
141
- - error_message - error message if download was not successful
142
- - anaconda_packages - list of omitted packages
143
- - downloaded_packages - list of downloaded packages details
144
- """
145
- # pre-check of available packages to avoid potentially heavy downloads
146
- split_requirements = anaconda_packages.filter_available_packages(
147
- requirements, skip_version_check=skip_version_check
148
- )
149
- packages_in_snowflake = split_requirements.in_snowflake
150
- requirements = split_requirements.unavailable
151
- if not requirements:
152
- # all packages are available in Snowflake
153
- return DownloadUnavailablePackagesResult(
154
- succeeded=True,
155
- anaconda_packages=packages_in_snowflake,
156
- )
157
-
158
- # download all packages with their dependencies
159
- with SecurePath.temporary_directory() as downloads_dir:
160
- # This is a Windows workaround where use TemporaryDirectory instead of NamedTemporaryFile
161
- requirements_file = downloads_dir / "requirements.txt"
162
- _write_requirements_file(requirements_file, requirements) # type: ignore
163
- pip_wheel_result = pip_wheel(
164
- package_name=None,
165
- requirements_file=requirements_file.path, # type: ignore
166
- download_dir=downloads_dir.path,
167
- index_url=pip_index_url,
168
- dependencies=True,
169
- )
170
- if pip_wheel_result != 0:
171
- log.info(_pip_failed_log_msg(pip_wheel_result))
172
- return DownloadUnavailablePackagesResult(
173
- succeeded=False,
174
- error_message=_pip_failed_log_msg(pip_wheel_result),
175
- )
176
-
177
- # scan all downloaded packages and filter out ones available on Anaconda
178
- dependencies = split_downloaded_dependencies(
179
- requirements_file,
180
- downloads_dir=downloads_dir.path,
181
- anaconda_packages=anaconda_packages,
182
- skip_version_check=skip_version_check,
183
- )
184
- log.info(
185
- "Downloaded packages: %s",
186
- ", ".join(
187
- dep.requirement.name
188
- for dep in dependencies.unavailable_dependencies_wheels
189
- ),
190
- )
191
- _log_dependencies_found_in_conda(dependencies.snowflake_dependencies)
192
- packages_in_snowflake += dependencies.snowflake_dependencies
193
-
194
- # move filtered packages to target directory
195
- target_dir.mkdir(exist_ok=True)
196
- for package in dependencies.unavailable_dependencies_wheels:
197
- package.extract_files(target_dir.path)
198
- return DownloadUnavailablePackagesResult(
199
- succeeded=True,
200
- anaconda_packages=packages_in_snowflake,
201
- downloaded_packages_details=[
202
- RequirementWithFiles(requirement=dep.requirement, files=dep.namelist())
203
- for dep in dependencies.unavailable_dependencies_wheels
204
- ],
205
- )
206
-
207
-
208
- def pip_wheel(
209
- requirements_file: Optional[str],
210
- package_name: Optional[str],
211
- download_dir: Path,
212
- index_url: Optional[str],
213
- dependencies: bool = True,
214
- ):
215
- command = ["-m", "pip", "wheel", "-w", str(download_dir)]
216
- if package_name:
217
- command.append(package_name)
218
- if requirements_file:
219
- command.extend(["-r", str(requirements_file)])
220
- if index_url:
221
- command.extend(["-i", index_url])
222
- if not dependencies:
223
- command.append("--no-deps")
224
-
225
- try:
226
- log.info(
227
- "Running pip wheel with command: %s",
228
- " ".join([str(com) for com in command]),
229
- )
230
- process = subprocess.run(
231
- ["python", *command],
232
- capture_output=True,
233
- text=True,
234
- encoding=locale.getpreferredencoding(),
235
- )
236
- except subprocess.CalledProcessError as e:
237
- log.error("Encountered error %s", e.stderr)
238
- raise ClickException(f"Encountered error while running pip wheel.")
239
-
240
- log.info("Pip wheel command executed successfully")
241
- return process.returncode
242
-
243
-
244
- @dataclasses.dataclass
245
- class SplitDownloadedDependenciesResult:
246
- snowflake_dependencies: List[Requirement] = dataclasses.field(default_factory=list)
247
- unavailable_dependencies_wheels: List[RequirementWithWheel] = dataclasses.field(
248
- default_factory=list
249
- )
250
-
251
-
252
- def split_downloaded_dependencies(
253
- requirements_file: SecurePath,
254
- downloads_dir: Path,
255
- anaconda_packages: AnacondaPackages,
256
- skip_version_check: bool,
257
- ) -> SplitDownloadedDependenciesResult:
258
- packages_metadata: Dict[str, WheelMetadata] = {
259
- meta.name: meta
260
- for meta in (
261
- WheelMetadata.from_wheel(wheel_path)
262
- for wheel_path in downloads_dir.glob("*.whl")
263
- )
264
- if meta is not None
265
- }
266
- available_in_snowflake_dependencies: Dict = {}
267
- unavailable_dependencies: Dict = {}
268
-
269
- def _get_dependencies(package: Requirement):
270
- if (
271
- package.name not in available_in_snowflake_dependencies
272
- and package.name not in unavailable_dependencies
273
- ):
274
- if anaconda_packages.is_package_available(
275
- package, skip_version_check=skip_version_check
276
- ):
277
- available_in_snowflake_dependencies[package.name] = package
278
- else:
279
- meta = packages_metadata.get(
280
- WheelMetadata.to_wheel_name_format(package.name)
281
- )
282
- wheel_path = meta.wheel_path if meta else None
283
- requires = meta.dependencies if meta else []
284
- unavailable_dependencies[package.name] = RequirementWithWheel(
285
- requirement=package,
286
- wheel_path=wheel_path,
287
- )
288
-
289
- log.debug(
290
- "Checking package %s, with dependencies: %s", package.name, requires
291
- )
292
-
293
- for package in requires:
294
- _get_dependencies(Requirement.parse_line(package))
295
-
296
- with requirements_file.open("r", read_file_limit_mb=512) as req_file:
297
- for line in req_file:
298
- _get_dependencies(Requirement.parse_line(line))
299
-
300
- return SplitDownloadedDependenciesResult(
301
- snowflake_dependencies=list(available_in_snowflake_dependencies.values()),
302
- unavailable_dependencies_wheels=list(unavailable_dependencies.values()),
303
- )
304
-
305
-
306
- def detect_and_log_shared_libraries(dependencies: List[RequirementWithFiles]):
307
- shared_libraries = [
308
- dependency.requirement.name
309
- for dependency in dependencies
310
- if any(
311
- file.endswith(".so") or file.endswith(".dll") for file in dependency.files
312
- )
313
- ]
314
- if shared_libraries:
315
- _log_shared_libraries(shared_libraries)
316
- return True
317
- else:
318
- log.info("Unsupported native libraries not found in packages (Good news!)...")
319
- return False
320
-
321
-
322
- def _log_shared_libraries(
323
- shared_libraries: List[str],
324
- ) -> None:
325
- log.error(
326
- "Following dependencies utilise shared libraries, not supported by Conda:"
327
- )
328
- log.error("\n".join(set(shared_libraries)))
329
- log.error(
330
- "You may still try to create your package with --allow-shared-libraries, but the might not work."
331
- )
332
- log.error("You may also request adding the package to Snowflake Conda channel")
333
- log.error("at https://support.anaconda.com/")
334
-
335
-
336
- def _log_dependencies_found_in_conda(available_dependencies: List[Requirement]) -> None:
337
- if len(available_dependencies) > 0:
338
- log.info(
339
- "Good news! Packages available in Anaconda and excluded from the zip archive: %s",
340
- format(", ".join(dep.name for dep in available_dependencies)),
341
- )
342
- else:
343
- log.info("None of the package dependencies were found on Anaconda")
344
-
345
-
346
- def _pip_failed_log_msg(return_code: int) -> str:
347
- return dedent(
348
- f"""
349
- pip failed with return code {return_code}. Most likely reasons:
350
- * incorrect package name or version
351
- * package isn't compatible with host architecture (most probably due to .so libraries)
352
- * pip is not installed correctly
353
- """
354
- )
@@ -1,30 +0,0 @@
1
- # Copyright (c) 2024 Snowflake Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from snowflake.cli.api.plugins.command import (
16
- SNOWCLI_ROOT_COMMAND_PATH,
17
- CommandSpec,
18
- CommandType,
19
- plugin_hook_impl,
20
- )
21
- from snowflake.cli.plugins.snowpark import commands
22
-
23
-
24
- @plugin_hook_impl
25
- def command_spec():
26
- return CommandSpec(
27
- parent_command_path=SNOWCLI_ROOT_COMMAND_PATH,
28
- command_type=CommandType.COMMAND_GROUP,
29
- typer_instance=commands.app.create_instance(),
30
- )
@@ -1,65 +0,0 @@
1
- # Copyright (c) 2024 Snowflake Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from dataclasses import dataclass
16
-
17
- from snowflake.cli.api.project.schemas.snowpark.snowpark import Snowpark
18
- from snowflake.cli.api.secure_path import SecurePath
19
-
20
- _DEFINED_REQUIREMENTS = "requirements.txt"
21
- _REQUIREMENTS_SNOWFLAKE = "requirements.snowflake.txt"
22
-
23
-
24
- @dataclass
25
- class SnowparkPackagePaths:
26
- source: SecurePath
27
- artifact_file: SecurePath
28
- defined_requirements_file: SecurePath = SecurePath(_DEFINED_REQUIREMENTS)
29
- snowflake_requirements_file: SecurePath = SecurePath(_REQUIREMENTS_SNOWFLAKE)
30
-
31
- @classmethod
32
- def for_snowpark_project(
33
- cls, project_root: SecurePath, snowpark_project_definition: Snowpark
34
- ) -> "SnowparkPackagePaths":
35
- defined_source_path = SecurePath(snowpark_project_definition.src)
36
- return cls(
37
- source=cls._get_snowpark_project_source_absolute_path(
38
- project_root=project_root,
39
- defined_source_path=defined_source_path,
40
- ),
41
- artifact_file=cls._get_snowpark_project_artifact_absolute_path(
42
- project_root=project_root,
43
- defined_source_path=defined_source_path,
44
- ),
45
- defined_requirements_file=project_root / _DEFINED_REQUIREMENTS,
46
- snowflake_requirements_file=project_root / _REQUIREMENTS_SNOWFLAKE,
47
- )
48
-
49
- @classmethod
50
- def _get_snowpark_project_source_absolute_path(
51
- cls, project_root: SecurePath, defined_source_path: SecurePath
52
- ) -> SecurePath:
53
- if defined_source_path.path.is_absolute():
54
- return defined_source_path
55
- return SecurePath((project_root / defined_source_path.path).path.resolve())
56
-
57
- @classmethod
58
- def _get_snowpark_project_artifact_absolute_path(
59
- cls, project_root: SecurePath, defined_source_path: SecurePath
60
- ) -> SecurePath:
61
- source_path = cls._get_snowpark_project_source_absolute_path(
62
- project_root=project_root, defined_source_path=defined_source_path
63
- )
64
- artifact_file = project_root / (source_path.path.name + ".zip")
65
- return artifact_file
@@ -1,95 +0,0 @@
1
- # Copyright (c) 2024 Snowflake Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from __future__ import annotations
16
-
17
- import click
18
- import typer
19
- from snowflake.cli.api.commands.flags import (
20
- deprecated_flag_callback,
21
- deprecated_flag_callback_enum,
22
- )
23
- from snowflake.cli.plugins.snowpark.models import YesNoAsk
24
-
25
-
26
- def deprecated_allow_native_libraries_option(old_flag_name: str):
27
- return typer.Option(
28
- YesNoAsk.NO.value,
29
- old_flag_name,
30
- help="Allows native libraries, when using packages installed through PIP",
31
- hidden=True,
32
- callback=deprecated_flag_callback_enum(
33
- f"{old_flag_name} flag is deprecated. Use --allow-shared-libraries flag instead."
34
- ),
35
- )
36
-
37
-
38
- def resolve_allow_shared_libraries_yes_no_ask(allow_shared_libraries: YesNoAsk) -> bool:
39
- if allow_shared_libraries == YesNoAsk.ASK:
40
- return click.confirm("Continue with package installation?", default=False)
41
- else:
42
- return allow_shared_libraries == YesNoAsk.YES
43
-
44
-
45
- AllowSharedLibrariesOption: bool = typer.Option(
46
- False,
47
- "--allow-shared-libraries",
48
- help="Allows shared (.so) libraries, when using packages installed through PIP.",
49
- )
50
-
51
- DeprecatedCheckAnacondaForPyPiDependencies: bool = typer.Option(
52
- True,
53
- "--check-anaconda-for-pypi-deps/--no-check-anaconda-for-pypi-deps",
54
- "-a",
55
- help="""Checks if any of missing Anaconda packages dependencies can be imported directly from Anaconda. Valid values include: `true`, `false`, Default: `true`.""",
56
- hidden=True,
57
- callback=deprecated_flag_callback(
58
- "--check-anaconda-for-pypi-deps flag is deprecated. Use --ignore-anaconda flag instead."
59
- ),
60
- )
61
-
62
- IgnoreAnacondaOption: bool = typer.Option(
63
- False,
64
- "--ignore-anaconda",
65
- help="Does not lookup packages on Snowflake Anaconda channel.",
66
- )
67
-
68
- SkipVersionCheckOption: bool = typer.Option(
69
- False,
70
- "--skip-version-check",
71
- help="Skip comparing versions of dependencies between requirements and Anaconda.",
72
- )
73
-
74
- IndexUrlOption: str | None = typer.Option(
75
- None,
76
- "--index-url",
77
- help="Base URL of the Python Package Index to use for package lookup. This should point to "
78
- " a repository compliant with PEP 503 (the simple repository API) or a local directory laid"
79
- " out in the same format.",
80
- show_default=False,
81
- )
82
-
83
- ReturnsOption: str = typer.Option(
84
- ...,
85
- "--returns",
86
- "-r",
87
- help="Data type for the procedure to return.",
88
- )
89
-
90
- OverwriteOption: bool = typer.Option(
91
- False,
92
- "--overwrite",
93
- "-o",
94
- help="Replaces an existing procedure with this one.",
95
- )
@@ -1,81 +0,0 @@
1
- # Copyright (c) 2024 Snowflake Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from __future__ import annotations
16
-
17
- import fnmatch
18
- import logging
19
- from pathlib import Path
20
- from typing import Iterator, Literal
21
- from zipfile import ZIP_DEFLATED, ZipFile
22
-
23
- log = logging.getLogger(__name__)
24
-
25
- IGNORED_FILES = [
26
- "**/.DS_Store",
27
- "**/.git",
28
- "**/.git/*",
29
- "**/.gitignore",
30
- "**/.env",
31
- "**/.env/*",
32
- "**/.venv",
33
- "**/.venv/*",
34
- "**/__pycache__",
35
- "**/*.zip",
36
- "**/*.pyc",
37
- "**/env",
38
- "**/env/*",
39
- "**/ENV",
40
- "**/ENV/*",
41
- "**/venv",
42
- "**/venv/*",
43
- "**/requirements.txt",
44
- "**/requirements.snowflake.txt",
45
- "**/requirements.other.txt",
46
- "**/snowflake.yml",
47
- ]
48
-
49
-
50
- def add_file_to_existing_zip(zip_file: str, file: str):
51
- """Adds another file to an existing zip file
52
-
53
- Args:
54
- zip_file (str): The existing zip file
55
- file (str): The new file to add
56
- """
57
- with ZipFile(zip_file, mode="a") as myzip:
58
- myzip.write(file, Path(file).name)
59
-
60
-
61
- def zip_dir(
62
- source: Path, dest_zip: Path, mode: Literal["r", "w", "x", "a"] = "w"
63
- ) -> None:
64
- files_to_pack: Iterator[Path] = filter(
65
- _to_be_zipped, map(lambda f: f.absolute(), source.glob("**/*"))
66
- )
67
-
68
- with ZipFile(dest_zip, mode, ZIP_DEFLATED, allowZip64=True) as package_zip:
69
- for file in files_to_pack:
70
- log.debug("Adding %s to %s", file, dest_zip)
71
- package_zip.write(file, arcname=file.relative_to(source.absolute()))
72
-
73
-
74
- def _to_be_zipped(file: Path) -> bool:
75
- for pattern in IGNORED_FILES:
76
- # This has to be a string because of fnmatch
77
- file_as_str = str(file)
78
- if file_as_str == pattern or fnmatch.fnmatch(file_as_str, pattern):
79
- return False
80
-
81
- return True
@@ -1,35 +0,0 @@
1
- # Copyright (c) 2024 Snowflake Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
16
- from snowflake.cli.plugins.spcs.compute_pool.commands import (
17
- app as compute_pools_app,
18
- )
19
- from snowflake.cli.plugins.spcs.image_registry.commands import app as registry_app
20
- from snowflake.cli.plugins.spcs.image_repository.commands import (
21
- app as image_repository_app,
22
- )
23
- from snowflake.cli.plugins.spcs.jobs.commands import app as jobs_app
24
- from snowflake.cli.plugins.spcs.services.commands import app as services_app
25
-
26
- app = SnowTyperFactory(
27
- name="spcs",
28
- help="Manages Snowpark Container Services compute pools, services, image registries, and image repositories.",
29
- )
30
-
31
- app.add_typer(compute_pools_app)
32
- app.add_typer(services_app)
33
- app.add_typer(jobs_app)
34
- app.add_typer(registry_app)
35
- app.add_typer(image_repository_app)