snowflake-cli-labs 3.0.0rc5__py3-none-any.whl → 3.0.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 (244) hide show
  1. README.md +21 -0
  2. {snowflake_cli_labs-3.0.0rc5.dist-info → snowflake_cli_labs-3.0.2.dist-info}/METADATA +6 -96
  3. snowflake_cli_labs-3.0.2.dist-info/RECORD +5 -0
  4. snowflake/cli/__about__.py +0 -17
  5. snowflake/cli/__init__.py +0 -13
  6. snowflake/cli/_app/__init__.py +0 -22
  7. snowflake/cli/_app/__main__.py +0 -31
  8. snowflake/cli/_app/api_impl/__init__.py +0 -13
  9. snowflake/cli/_app/api_impl/plugin/__init__.py +0 -13
  10. snowflake/cli/_app/api_impl/plugin/plugin_config_provider_impl.py +0 -66
  11. snowflake/cli/_app/cli_app.py +0 -252
  12. snowflake/cli/_app/commands_registration/__init__.py +0 -33
  13. snowflake/cli/_app/commands_registration/builtin_plugins.py +0 -50
  14. snowflake/cli/_app/commands_registration/command_plugins_loader.py +0 -169
  15. snowflake/cli/_app/commands_registration/commands_registration_with_callbacks.py +0 -105
  16. snowflake/cli/_app/commands_registration/exception_logging.py +0 -26
  17. snowflake/cli/_app/commands_registration/threadsafe.py +0 -48
  18. snowflake/cli/_app/commands_registration/typer_registration.py +0 -153
  19. snowflake/cli/_app/constants.py +0 -19
  20. snowflake/cli/_app/dev/__init__.py +0 -13
  21. snowflake/cli/_app/dev/commands_structure.py +0 -48
  22. snowflake/cli/_app/dev/docs/__init__.py +0 -13
  23. snowflake/cli/_app/dev/docs/commands_docs_generator.py +0 -118
  24. snowflake/cli/_app/dev/docs/generator.py +0 -35
  25. snowflake/cli/_app/dev/docs/project_definition_docs_generator.py +0 -58
  26. snowflake/cli/_app/dev/docs/project_definition_generate_json_schema.py +0 -227
  27. snowflake/cli/_app/dev/docs/template_utils.py +0 -23
  28. snowflake/cli/_app/dev/docs/templates/definition_description.rst.jinja2 +0 -38
  29. snowflake/cli/_app/dev/docs/templates/overview.rst.jinja2 +0 -9
  30. snowflake/cli/_app/dev/docs/templates/usage.rst.jinja2 +0 -67
  31. snowflake/cli/_app/dev/pycharm_remote_debug.py +0 -46
  32. snowflake/cli/_app/loggers.py +0 -199
  33. snowflake/cli/_app/main_typer.py +0 -62
  34. snowflake/cli/_app/printing.py +0 -181
  35. snowflake/cli/_app/secret.py +0 -9
  36. snowflake/cli/_app/snow_connector.py +0 -309
  37. snowflake/cli/_app/telemetry.py +0 -220
  38. snowflake/cli/_app/version_check.py +0 -74
  39. snowflake/cli/_plugins/__init__.py +0 -13
  40. snowflake/cli/_plugins/connection/__init__.py +0 -13
  41. snowflake/cli/_plugins/connection/commands.py +0 -353
  42. snowflake/cli/_plugins/connection/plugin_spec.py +0 -30
  43. snowflake/cli/_plugins/connection/util.py +0 -195
  44. snowflake/cli/_plugins/cortex/__init__.py +0 -13
  45. snowflake/cli/_plugins/cortex/commands.py +0 -332
  46. snowflake/cli/_plugins/cortex/constants.py +0 -17
  47. snowflake/cli/_plugins/cortex/manager.py +0 -189
  48. snowflake/cli/_plugins/cortex/plugin_spec.py +0 -30
  49. snowflake/cli/_plugins/cortex/types.py +0 -22
  50. snowflake/cli/_plugins/git/__init__.py +0 -13
  51. snowflake/cli/_plugins/git/commands.py +0 -358
  52. snowflake/cli/_plugins/git/manager.py +0 -151
  53. snowflake/cli/_plugins/git/plugin_spec.py +0 -30
  54. snowflake/cli/_plugins/helpers/__init__.py +0 -13
  55. snowflake/cli/_plugins/helpers/commands.py +0 -90
  56. snowflake/cli/_plugins/helpers/plugin_spec.py +0 -30
  57. snowflake/cli/_plugins/init/__init__.py +0 -13
  58. snowflake/cli/_plugins/init/commands.py +0 -248
  59. snowflake/cli/_plugins/init/plugin_spec.py +0 -30
  60. snowflake/cli/_plugins/nativeapp/__init__.py +0 -13
  61. snowflake/cli/_plugins/nativeapp/artifacts.py +0 -757
  62. snowflake/cli/_plugins/nativeapp/bundle_context.py +0 -31
  63. snowflake/cli/_plugins/nativeapp/codegen/__init__.py +0 -13
  64. snowflake/cli/_plugins/nativeapp/codegen/artifact_processor.py +0 -91
  65. snowflake/cli/_plugins/nativeapp/codegen/compiler.py +0 -149
  66. snowflake/cli/_plugins/nativeapp/codegen/sandbox.py +0 -306
  67. snowflake/cli/_plugins/nativeapp/codegen/setup/native_app_setup_processor.py +0 -249
  68. snowflake/cli/_plugins/nativeapp/codegen/setup/setup_driver.py.source +0 -59
  69. snowflake/cli/_plugins/nativeapp/codegen/snowpark/callback_source.py.jinja +0 -181
  70. snowflake/cli/_plugins/nativeapp/codegen/snowpark/extension_function_utils.py +0 -217
  71. snowflake/cli/_plugins/nativeapp/codegen/snowpark/models.py +0 -61
  72. snowflake/cli/_plugins/nativeapp/codegen/snowpark/python_processor.py +0 -523
  73. snowflake/cli/_plugins/nativeapp/codegen/templates/templates_processor.py +0 -114
  74. snowflake/cli/_plugins/nativeapp/commands.py +0 -559
  75. snowflake/cli/_plugins/nativeapp/common_flags.py +0 -44
  76. snowflake/cli/_plugins/nativeapp/constants.py +0 -27
  77. snowflake/cli/_plugins/nativeapp/entities/__init__.py +0 -0
  78. snowflake/cli/_plugins/nativeapp/entities/application.py +0 -878
  79. snowflake/cli/_plugins/nativeapp/entities/application_package.py +0 -1392
  80. snowflake/cli/_plugins/nativeapp/exceptions.py +0 -113
  81. snowflake/cli/_plugins/nativeapp/feature_flags.py +0 -24
  82. snowflake/cli/_plugins/nativeapp/manager.py +0 -415
  83. snowflake/cli/_plugins/nativeapp/plugin_spec.py +0 -30
  84. snowflake/cli/_plugins/nativeapp/policy.py +0 -53
  85. snowflake/cli/_plugins/nativeapp/project_model.py +0 -211
  86. snowflake/cli/_plugins/nativeapp/run_processor.py +0 -184
  87. snowflake/cli/_plugins/nativeapp/same_account_install_method.py +0 -70
  88. snowflake/cli/_plugins/nativeapp/teardown_processor.py +0 -70
  89. snowflake/cli/_plugins/nativeapp/utils.py +0 -98
  90. snowflake/cli/_plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +0 -262
  91. snowflake/cli/_plugins/nativeapp/version/__init__.py +0 -13
  92. snowflake/cli/_plugins/nativeapp/version/commands.py +0 -141
  93. snowflake/cli/_plugins/nativeapp/version/version_processor.py +0 -98
  94. snowflake/cli/_plugins/notebook/__init__.py +0 -13
  95. snowflake/cli/_plugins/notebook/commands.py +0 -86
  96. snowflake/cli/_plugins/notebook/exceptions.py +0 -20
  97. snowflake/cli/_plugins/notebook/manager.py +0 -71
  98. snowflake/cli/_plugins/notebook/plugin_spec.py +0 -30
  99. snowflake/cli/_plugins/notebook/types.py +0 -15
  100. snowflake/cli/_plugins/object/__init__.py +0 -13
  101. snowflake/cli/_plugins/object/command_aliases.py +0 -95
  102. snowflake/cli/_plugins/object/commands.py +0 -180
  103. snowflake/cli/_plugins/object/common.py +0 -85
  104. snowflake/cli/_plugins/object/manager.py +0 -118
  105. snowflake/cli/_plugins/object/plugin_spec.py +0 -30
  106. snowflake/cli/_plugins/snowpark/__init__.py +0 -13
  107. snowflake/cli/_plugins/snowpark/commands.py +0 -450
  108. snowflake/cli/_plugins/snowpark/common.py +0 -268
  109. snowflake/cli/_plugins/snowpark/models.py +0 -150
  110. snowflake/cli/_plugins/snowpark/package/__init__.py +0 -13
  111. snowflake/cli/_plugins/snowpark/package/anaconda_packages.py +0 -199
  112. snowflake/cli/_plugins/snowpark/package/commands.py +0 -195
  113. snowflake/cli/_plugins/snowpark/package/manager.py +0 -44
  114. snowflake/cli/_plugins/snowpark/package/utils.py +0 -26
  115. snowflake/cli/_plugins/snowpark/package_utils.py +0 -354
  116. snowflake/cli/_plugins/snowpark/plugin_spec.py +0 -30
  117. snowflake/cli/_plugins/snowpark/snowpark_entity.py +0 -29
  118. snowflake/cli/_plugins/snowpark/snowpark_entity_model.py +0 -173
  119. snowflake/cli/_plugins/snowpark/snowpark_project_paths.py +0 -109
  120. snowflake/cli/_plugins/snowpark/snowpark_shared.py +0 -59
  121. snowflake/cli/_plugins/snowpark/zipper.py +0 -89
  122. snowflake/cli/_plugins/spcs/__init__.py +0 -33
  123. snowflake/cli/_plugins/spcs/common.py +0 -99
  124. snowflake/cli/_plugins/spcs/compute_pool/__init__.py +0 -13
  125. snowflake/cli/_plugins/spcs/compute_pool/commands.py +0 -241
  126. snowflake/cli/_plugins/spcs/compute_pool/manager.py +0 -121
  127. snowflake/cli/_plugins/spcs/image_registry/__init__.py +0 -13
  128. snowflake/cli/_plugins/spcs/image_registry/commands.py +0 -65
  129. snowflake/cli/_plugins/spcs/image_registry/manager.py +0 -105
  130. snowflake/cli/_plugins/spcs/image_repository/__init__.py +0 -13
  131. snowflake/cli/_plugins/spcs/image_repository/commands.py +0 -202
  132. snowflake/cli/_plugins/spcs/image_repository/manager.py +0 -84
  133. snowflake/cli/_plugins/spcs/plugin_spec.py +0 -30
  134. snowflake/cli/_plugins/spcs/services/__init__.py +0 -13
  135. snowflake/cli/_plugins/spcs/services/commands.py +0 -345
  136. snowflake/cli/_plugins/spcs/services/manager.py +0 -208
  137. snowflake/cli/_plugins/sql/__init__.py +0 -13
  138. snowflake/cli/_plugins/sql/commands.py +0 -86
  139. snowflake/cli/_plugins/sql/manager.py +0 -92
  140. snowflake/cli/_plugins/sql/plugin_spec.py +0 -30
  141. snowflake/cli/_plugins/sql/snowsql_templating.py +0 -28
  142. snowflake/cli/_plugins/stage/__init__.py +0 -13
  143. snowflake/cli/_plugins/stage/commands.py +0 -264
  144. snowflake/cli/_plugins/stage/diff.py +0 -280
  145. snowflake/cli/_plugins/stage/manager.py +0 -582
  146. snowflake/cli/_plugins/stage/md5.py +0 -160
  147. snowflake/cli/_plugins/stage/plugin_spec.py +0 -30
  148. snowflake/cli/_plugins/stage/utils.py +0 -54
  149. snowflake/cli/_plugins/streamlit/__init__.py +0 -13
  150. snowflake/cli/_plugins/streamlit/commands.py +0 -195
  151. snowflake/cli/_plugins/streamlit/manager.py +0 -220
  152. snowflake/cli/_plugins/streamlit/plugin_spec.py +0 -30
  153. snowflake/cli/_plugins/streamlit/streamlit_entity.py +0 -12
  154. snowflake/cli/_plugins/streamlit/streamlit_entity_model.py +0 -66
  155. snowflake/cli/_plugins/workspace/__init__.py +0 -13
  156. snowflake/cli/_plugins/workspace/action_context.py +0 -18
  157. snowflake/cli/_plugins/workspace/commands.py +0 -306
  158. snowflake/cli/_plugins/workspace/manager.py +0 -74
  159. snowflake/cli/_plugins/workspace/plugin_spec.py +0 -30
  160. snowflake/cli/api/__init__.py +0 -48
  161. snowflake/cli/api/cli_global_context.py +0 -247
  162. snowflake/cli/api/commands/__init__.py +0 -13
  163. snowflake/cli/api/commands/alias.py +0 -23
  164. snowflake/cli/api/commands/common.py +0 -25
  165. snowflake/cli/api/commands/decorators.py +0 -369
  166. snowflake/cli/api/commands/execution_metadata.py +0 -40
  167. snowflake/cli/api/commands/experimental_behaviour.py +0 -18
  168. snowflake/cli/api/commands/flags.py +0 -561
  169. snowflake/cli/api/commands/overrideable_parameter.py +0 -143
  170. snowflake/cli/api/commands/snow_typer.py +0 -247
  171. snowflake/cli/api/commands/utils.py +0 -18
  172. snowflake/cli/api/config.py +0 -380
  173. snowflake/cli/api/connections.py +0 -216
  174. snowflake/cli/api/console/__init__.py +0 -17
  175. snowflake/cli/api/console/abc.py +0 -94
  176. snowflake/cli/api/console/console.py +0 -134
  177. snowflake/cli/api/console/enum.py +0 -17
  178. snowflake/cli/api/constants.py +0 -90
  179. snowflake/cli/api/entities/common.py +0 -56
  180. snowflake/cli/api/entities/utils.py +0 -370
  181. snowflake/cli/api/errno.py +0 -28
  182. snowflake/cli/api/exceptions.py +0 -190
  183. snowflake/cli/api/feature_flags.py +0 -54
  184. snowflake/cli/api/identifiers.py +0 -190
  185. snowflake/cli/api/metrics.py +0 -92
  186. snowflake/cli/api/output/__init__.py +0 -13
  187. snowflake/cli/api/output/formats.py +0 -20
  188. snowflake/cli/api/output/types.py +0 -118
  189. snowflake/cli/api/plugins/__init__.py +0 -13
  190. snowflake/cli/api/plugins/command/__init__.py +0 -72
  191. snowflake/cli/api/plugins/command/plugin_hook_specs.py +0 -21
  192. snowflake/cli/api/plugins/plugin_config.py +0 -32
  193. snowflake/cli/api/project/__init__.py +0 -13
  194. snowflake/cli/api/project/definition.py +0 -126
  195. snowflake/cli/api/project/definition_conversion.py +0 -400
  196. snowflake/cli/api/project/definition_manager.py +0 -145
  197. snowflake/cli/api/project/errors.py +0 -56
  198. snowflake/cli/api/project/project_verification.py +0 -23
  199. snowflake/cli/api/project/schemas/__init__.py +0 -13
  200. snowflake/cli/api/project/schemas/entities/__init__.py +0 -13
  201. snowflake/cli/api/project/schemas/entities/common.py +0 -153
  202. snowflake/cli/api/project/schemas/entities/entities.py +0 -61
  203. snowflake/cli/api/project/schemas/project_definition.py +0 -330
  204. snowflake/cli/api/project/schemas/template.py +0 -77
  205. snowflake/cli/api/project/schemas/updatable_model.py +0 -202
  206. snowflake/cli/api/project/schemas/v1/__init__.py +0 -0
  207. snowflake/cli/api/project/schemas/v1/identifier_model.py +0 -51
  208. snowflake/cli/api/project/schemas/v1/native_app/__init__.py +0 -0
  209. snowflake/cli/api/project/schemas/v1/native_app/application.py +0 -61
  210. snowflake/cli/api/project/schemas/v1/native_app/native_app.py +0 -93
  211. snowflake/cli/api/project/schemas/v1/native_app/package.py +0 -84
  212. snowflake/cli/api/project/schemas/v1/native_app/path_mapping.py +0 -65
  213. snowflake/cli/api/project/schemas/v1/snowpark/__init__.py +0 -0
  214. snowflake/cli/api/project/schemas/v1/snowpark/argument.py +0 -28
  215. snowflake/cli/api/project/schemas/v1/snowpark/callable.py +0 -69
  216. snowflake/cli/api/project/schemas/v1/snowpark/snowpark.py +0 -36
  217. snowflake/cli/api/project/schemas/v1/streamlit/__init__.py +0 -0
  218. snowflake/cli/api/project/schemas/v1/streamlit/streamlit.py +0 -47
  219. snowflake/cli/api/project/util.py +0 -278
  220. snowflake/cli/api/rendering/__init__.py +0 -13
  221. snowflake/cli/api/rendering/jinja.py +0 -118
  222. snowflake/cli/api/rendering/project_definition_templates.py +0 -43
  223. snowflake/cli/api/rendering/project_templates.py +0 -98
  224. snowflake/cli/api/rendering/sql_templates.py +0 -105
  225. snowflake/cli/api/rest_api.py +0 -178
  226. snowflake/cli/api/sanitizers.py +0 -43
  227. snowflake/cli/api/secure_path.py +0 -360
  228. snowflake/cli/api/secure_utils.py +0 -118
  229. snowflake/cli/api/sql_execution.py +0 -280
  230. snowflake/cli/api/utils/__init__.py +0 -13
  231. snowflake/cli/api/utils/cursor.py +0 -34
  232. snowflake/cli/api/utils/definition_rendering.py +0 -415
  233. snowflake/cli/api/utils/dict_utils.py +0 -73
  234. snowflake/cli/api/utils/error_handling.py +0 -23
  235. snowflake/cli/api/utils/graph.py +0 -97
  236. snowflake/cli/api/utils/models.py +0 -63
  237. snowflake/cli/api/utils/naming_utils.py +0 -13
  238. snowflake/cli/api/utils/path_utils.py +0 -36
  239. snowflake/cli/api/utils/templating_functions.py +0 -144
  240. snowflake/cli/api/utils/types.py +0 -35
  241. snowflake_cli_labs-3.0.0rc5.dist-info/RECORD +0 -242
  242. snowflake_cli_labs-3.0.0rc5.dist-info/entry_points.txt +0 -2
  243. {snowflake_cli_labs-3.0.0rc5.dist-info → snowflake_cli_labs-3.0.2.dist-info}/WHEEL +0 -0
  244. {snowflake_cli_labs-3.0.0rc5.dist-info → snowflake_cli_labs-3.0.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,195 +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 logging
18
- from pathlib import Path
19
- from textwrap import dedent
20
- from typing import Optional
21
-
22
- import typer
23
- from click import ClickException
24
- from snowflake.cli._plugins.snowpark.models import (
25
- Requirement,
26
- )
27
- from snowflake.cli._plugins.snowpark.package.anaconda_packages import (
28
- AnacondaPackages,
29
- AnacondaPackagesManager,
30
- )
31
- from snowflake.cli._plugins.snowpark.package.manager import upload
32
- from snowflake.cli._plugins.snowpark.package_utils import (
33
- detect_and_log_shared_libraries,
34
- download_unavailable_packages,
35
- get_package_name_from_pip_wheel,
36
- )
37
- from snowflake.cli._plugins.snowpark.snowpark_shared import (
38
- AllowSharedLibrariesOption,
39
- IgnoreAnacondaOption,
40
- IndexUrlOption,
41
- SkipVersionCheckOption,
42
- )
43
- from snowflake.cli._plugins.snowpark.zipper import zip_dir
44
- from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
45
- from snowflake.cli.api.output.types import CommandResult, MessageResult
46
- from snowflake.cli.api.secure_path import SecurePath
47
-
48
- app = SnowTyperFactory(
49
- name="package",
50
- help="Manages custom Python packages for Snowpark",
51
- )
52
- log = logging.getLogger(__name__)
53
-
54
-
55
- @app.command("lookup", requires_connection=True)
56
- def package_lookup(
57
- package_name: str = typer.Argument(
58
- ..., help="Name of the package.", show_default=False
59
- ),
60
- **options,
61
- ) -> CommandResult:
62
- """
63
- Checks if a package is available on the Snowflake Anaconda channel.
64
- """
65
- anaconda_packages_manager = AnacondaPackagesManager()
66
- anaconda_packages = (
67
- anaconda_packages_manager.find_packages_available_in_snowflake_anaconda()
68
- )
69
-
70
- package = Requirement.parse(package_name)
71
- if anaconda_packages.is_package_available(package=package):
72
- msg = f"Package `{package_name}` is available in Anaconda"
73
- if version := anaconda_packages.package_latest_version(package=package):
74
- msg += f". Latest available version: {version}."
75
- elif versions := anaconda_packages.package_versions(package=package):
76
- msg += f" in versions: {', '.join(versions)}."
77
- return MessageResult(msg)
78
-
79
- return MessageResult(
80
- dedent(
81
- f"""
82
- Package `{package_name}` is not available in Anaconda. To prepare Snowpark compatible package run:
83
- snow snowpark package create {package_name}
84
- """
85
- )
86
- )
87
-
88
-
89
- @app.command("upload", requires_connection=True)
90
- def package_upload(
91
- file: Path = typer.Option(
92
- ...,
93
- "--file",
94
- "-f",
95
- help="Path to the file to upload.",
96
- exists=False,
97
- show_default=False,
98
- ),
99
- stage: str = typer.Option(
100
- ...,
101
- "--stage",
102
- "-s",
103
- help="Name of the stage in which to upload the file, not including the @ symbol.",
104
- show_default=False,
105
- ),
106
- overwrite: bool = typer.Option(
107
- False,
108
- "--overwrite",
109
- "-o",
110
- help="Overwrites the file if it already exists.",
111
- ),
112
- **options,
113
- ) -> CommandResult:
114
- """
115
- Uploads a Python package zip file to a Snowflake stage so it can be referenced in the imports of a procedure or function.
116
- """
117
- return MessageResult(upload(file=file, stage=stage, overwrite=overwrite))
118
-
119
-
120
- @app.command("create", requires_connection=True)
121
- def package_create(
122
- name: str = typer.Argument(
123
- ...,
124
- help="Name of the package to create.",
125
- show_default=False,
126
- ),
127
- ignore_anaconda: bool = IgnoreAnacondaOption,
128
- index_url: Optional[str] = IndexUrlOption,
129
- skip_version_check: bool = SkipVersionCheckOption,
130
- allow_shared_libraries: bool = AllowSharedLibrariesOption,
131
- **options,
132
- ) -> CommandResult:
133
- """
134
- Creates a Python package as a zip file that can be uploaded to a stage and imported for a Snowpark Python app.
135
- """
136
- with SecurePath.temporary_directory() as packages_dir:
137
- package = Requirement.parse(name)
138
- anaconda_packages_manager = AnacondaPackagesManager()
139
- download_result = download_unavailable_packages(
140
- requirements=[package],
141
- target_dir=packages_dir,
142
- anaconda_packages=(
143
- AnacondaPackages.empty()
144
- if ignore_anaconda
145
- else anaconda_packages_manager.find_packages_available_in_snowflake_anaconda()
146
- ),
147
- skip_version_check=skip_version_check,
148
- pip_index_url=index_url,
149
- )
150
- if not download_result.succeeded:
151
- raise ClickException(download_result.error_message)
152
-
153
- # check if package was detected as available
154
- package_available_in_conda = any(
155
- p.line == package.line for p in download_result.anaconda_packages
156
- )
157
- if package_available_in_conda:
158
- return MessageResult(
159
- f"Package {name} is already available in Snowflake Anaconda Channel."
160
- )
161
-
162
- # The package is not in anaconda, so we have to pack it
163
- log.info("Checking to see if packages have shared (.so/.dll) libraries...")
164
- if detect_and_log_shared_libraries(download_result.downloaded_packages_details):
165
- if not allow_shared_libraries:
166
- raise ClickException(
167
- "Some packages contain shared (.so/.dll) libraries. "
168
- "Try again with --allow-shared-libraries."
169
- )
170
-
171
- # The package is not in anaconda, so we have to pack it
172
- # the package was downloaded once, pip wheel should use cache
173
- zip_file = f"{get_package_name_from_pip_wheel(name, index_url=index_url)}.zip"
174
- zip_dir(dest_zip=Path(zip_file), source=packages_dir.path)
175
- message = dedent(
176
- f"""
177
- Package {zip_file} created. You can now upload it to a stage using
178
- snow snowpark package upload -f {zip_file} -s <stage-name>`
179
- and reference it in your procedure or function.
180
- Remember to add it to imports in the procedure or function definition.
181
- """
182
- )
183
- if download_result.anaconda_packages:
184
- message += dedent(
185
- f"""
186
- The package {name} is successfully created, but depends on the following
187
- Anaconda libraries. They need to be included in project requirements,
188
- as their are not included in .zip.
189
- """
190
- )
191
- message += "\n".join(
192
- (req.line for req in download_result.anaconda_packages)
193
- )
194
-
195
- return MessageResult(message)
@@ -1,44 +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 logging
18
- from pathlib import Path
19
-
20
- from snowflake.cli._plugins.snowpark.package.utils import prepare_app_zip
21
- from snowflake.cli._plugins.stage.manager import StageManager
22
- from snowflake.cli.api.identifiers import FQN
23
- from snowflake.cli.api.secure_path import SecurePath
24
-
25
- log = logging.getLogger(__name__)
26
-
27
-
28
- def upload(file: Path, stage: str, overwrite: bool):
29
- log.info("Uploading %s to Snowflake @%s/%s...", file, stage, file)
30
- with SecurePath.temporary_directory() as temp_dir:
31
- temp_app_zip_path = prepare_app_zip(SecurePath(file), temp_dir)
32
- sm = StageManager()
33
-
34
- sm.create(FQN.from_string(sm.get_stage_from_path(stage)))
35
- put_response = sm.put(
36
- temp_app_zip_path.path, stage, overwrite=overwrite
37
- ).fetchone()
38
-
39
- message = f"Package {file} {put_response[6]} to Snowflake @{stage}/{file}."
40
-
41
- if put_response[6] == "SKIPPED":
42
- message = "Package already exists on stage. Consider using --overwrite to overwrite the file."
43
-
44
- return message
@@ -1,26 +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
- from snowflake.cli.api.secure_path import SecurePath
18
-
19
-
20
- def prepare_app_zip(file_path: SecurePath, temp_dir: SecurePath) -> SecurePath:
21
- # get filename from file path (e.g. app.zip from /path/to/app.zip)
22
- # TODO: think if no file exceptions are handled correctly
23
- file_name = file_path.path.name
24
- temp_path = temp_dir / file_name
25
- file_path.copy(temp_path.path)
26
- return temp_path
@@ -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._plugins.snowpark.models import (
29
- Requirement,
30
- RequirementWithFiles,
31
- RequirementWithWheel,
32
- WheelMetadata,
33
- )
34
- from snowflake.cli._plugins.snowpark.package.anaconda_packages import (
35
- AnacondaPackages,
36
- )
37
- from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB
38
- from snowflake.cli.api.secure_path import SecurePath
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(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._plugins.snowpark import commands
16
- from snowflake.cli.api.plugins.command import (
17
- SNOWCLI_ROOT_COMMAND_PATH,
18
- CommandSpec,
19
- CommandType,
20
- plugin_hook_impl,
21
- )
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,29 +0,0 @@
1
- from typing import Generic, TypeVar
2
-
3
- from snowflake.cli._plugins.snowpark.snowpark_entity_model import (
4
- FunctionEntityModel,
5
- ProcedureEntityModel,
6
- )
7
- from snowflake.cli.api.entities.common import EntityBase
8
-
9
- T = TypeVar("T")
10
-
11
-
12
- class SnowparkEntity(EntityBase[Generic[T]]):
13
- pass
14
-
15
-
16
- class FunctionEntity(SnowparkEntity[FunctionEntityModel]):
17
- """
18
- A single UDF
19
- """
20
-
21
- pass
22
-
23
-
24
- class ProcedureEntity(SnowparkEntity[ProcedureEntityModel]):
25
- """
26
- A stored procedure
27
- """
28
-
29
- pass