snowpark-connect 0.27.0__py3-none-any.whl → 1.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. snowflake/snowpark_connect/__init__.py +1 -0
  2. snowflake/snowpark_connect/analyze_plan/map_tree_string.py +8 -4
  3. snowflake/snowpark_connect/client/__init__.py +15 -0
  4. snowflake/snowpark_connect/client/error_utils.py +30 -0
  5. snowflake/snowpark_connect/client/exceptions.py +36 -0
  6. snowflake/snowpark_connect/client/query_results.py +90 -0
  7. snowflake/snowpark_connect/client/server.py +717 -0
  8. snowflake/snowpark_connect/client/utils/__init__.py +10 -0
  9. snowflake/snowpark_connect/client/utils/session.py +85 -0
  10. snowflake/snowpark_connect/column_name_handler.py +404 -243
  11. snowflake/snowpark_connect/column_qualifier.py +43 -0
  12. snowflake/snowpark_connect/config.py +309 -26
  13. snowflake/snowpark_connect/constants.py +2 -0
  14. snowflake/snowpark_connect/dataframe_container.py +102 -8
  15. snowflake/snowpark_connect/date_time_format_mapping.py +71 -13
  16. snowflake/snowpark_connect/error/error_codes.py +50 -0
  17. snowflake/snowpark_connect/error/error_utils.py +172 -23
  18. snowflake/snowpark_connect/error/exceptions.py +13 -4
  19. snowflake/snowpark_connect/execute_plan/map_execution_command.py +15 -160
  20. snowflake/snowpark_connect/execute_plan/map_execution_root.py +26 -20
  21. snowflake/snowpark_connect/execute_plan/utils.py +5 -1
  22. snowflake/snowpark_connect/expression/error_utils.py +28 -0
  23. snowflake/snowpark_connect/expression/function_defaults.py +9 -2
  24. snowflake/snowpark_connect/expression/hybrid_column_map.py +53 -5
  25. snowflake/snowpark_connect/expression/integral_types_support.py +219 -0
  26. snowflake/snowpark_connect/expression/literal.py +37 -13
  27. snowflake/snowpark_connect/expression/map_cast.py +224 -15
  28. snowflake/snowpark_connect/expression/map_expression.py +80 -27
  29. snowflake/snowpark_connect/expression/map_extension.py +322 -12
  30. snowflake/snowpark_connect/expression/map_sql_expression.py +316 -81
  31. snowflake/snowpark_connect/expression/map_udf.py +86 -20
  32. snowflake/snowpark_connect/expression/map_unresolved_attribute.py +451 -173
  33. snowflake/snowpark_connect/expression/map_unresolved_function.py +2964 -829
  34. snowflake/snowpark_connect/expression/map_unresolved_star.py +87 -23
  35. snowflake/snowpark_connect/expression/map_update_fields.py +70 -18
  36. snowflake/snowpark_connect/expression/map_window_function.py +18 -3
  37. snowflake/snowpark_connect/includes/jars/json4s-ast_2.13-3.7.0-M11.jar +0 -0
  38. snowflake/snowpark_connect/includes/jars/{scala-library-2.12.18.jar → sas-scala-udf_2.12-0.2.0.jar} +0 -0
  39. snowflake/snowpark_connect/includes/jars/sas-scala-udf_2.13-0.2.0.jar +0 -0
  40. snowflake/snowpark_connect/includes/jars/scala-reflect-2.13.16.jar +0 -0
  41. snowflake/snowpark_connect/includes/jars/spark-common-utils_2.13-3.5.6.jar +0 -0
  42. snowflake/snowpark_connect/includes/jars/{spark-connect-client-jvm_2.12-3.5.6.jar → spark-connect-client-jvm_2.13-3.5.6.jar} +0 -0
  43. snowflake/snowpark_connect/includes/jars/{spark-sql_2.12-3.5.6.jar → spark-sql_2.13-3.5.6.jar} +0 -0
  44. snowflake/snowpark_connect/includes/python/pyspark/sql/connect/streaming/worker/foreach_batch_worker.py +1 -1
  45. snowflake/snowpark_connect/includes/python/pyspark/sql/connect/streaming/worker/listener_worker.py +1 -1
  46. snowflake/snowpark_connect/proto/snowflake_expression_ext_pb2.py +12 -10
  47. snowflake/snowpark_connect/proto/snowflake_expression_ext_pb2.pyi +14 -2
  48. snowflake/snowpark_connect/proto/snowflake_relation_ext_pb2.py +10 -8
  49. snowflake/snowpark_connect/proto/snowflake_relation_ext_pb2.pyi +13 -6
  50. snowflake/snowpark_connect/relation/catalogs/abstract_spark_catalog.py +65 -17
  51. snowflake/snowpark_connect/relation/catalogs/snowflake_catalog.py +297 -49
  52. snowflake/snowpark_connect/relation/catalogs/utils.py +12 -4
  53. snowflake/snowpark_connect/relation/io_utils.py +110 -10
  54. snowflake/snowpark_connect/relation/map_aggregate.py +239 -256
  55. snowflake/snowpark_connect/relation/map_catalog.py +5 -1
  56. snowflake/snowpark_connect/relation/map_column_ops.py +264 -96
  57. snowflake/snowpark_connect/relation/map_extension.py +263 -29
  58. snowflake/snowpark_connect/relation/map_join.py +683 -442
  59. snowflake/snowpark_connect/relation/map_local_relation.py +28 -1
  60. snowflake/snowpark_connect/relation/map_map_partitions.py +83 -8
  61. snowflake/snowpark_connect/relation/map_relation.py +48 -19
  62. snowflake/snowpark_connect/relation/map_row_ops.py +310 -91
  63. snowflake/snowpark_connect/relation/map_show_string.py +13 -6
  64. snowflake/snowpark_connect/relation/map_sql.py +1233 -222
  65. snowflake/snowpark_connect/relation/map_stats.py +48 -9
  66. snowflake/snowpark_connect/relation/map_subquery_alias.py +11 -2
  67. snowflake/snowpark_connect/relation/map_udtf.py +14 -4
  68. snowflake/snowpark_connect/relation/read/jdbc_read_dbapi.py +53 -14
  69. snowflake/snowpark_connect/relation/read/map_read.py +134 -43
  70. snowflake/snowpark_connect/relation/read/map_read_csv.py +326 -47
  71. snowflake/snowpark_connect/relation/read/map_read_jdbc.py +21 -6
  72. snowflake/snowpark_connect/relation/read/map_read_json.py +324 -86
  73. snowflake/snowpark_connect/relation/read/map_read_parquet.py +146 -28
  74. snowflake/snowpark_connect/relation/read/map_read_partitioned_parquet.py +142 -0
  75. snowflake/snowpark_connect/relation/read/map_read_socket.py +15 -3
  76. snowflake/snowpark_connect/relation/read/map_read_table.py +86 -6
  77. snowflake/snowpark_connect/relation/read/map_read_text.py +22 -4
  78. snowflake/snowpark_connect/relation/read/metadata_utils.py +170 -0
  79. snowflake/snowpark_connect/relation/read/reader_config.py +42 -3
  80. snowflake/snowpark_connect/relation/read/utils.py +50 -5
  81. snowflake/snowpark_connect/relation/stage_locator.py +91 -55
  82. snowflake/snowpark_connect/relation/utils.py +128 -5
  83. snowflake/snowpark_connect/relation/write/jdbc_write_dbapi.py +19 -3
  84. snowflake/snowpark_connect/relation/write/map_write.py +929 -319
  85. snowflake/snowpark_connect/relation/write/map_write_jdbc.py +8 -2
  86. snowflake/snowpark_connect/resources/java_udfs-1.0-SNAPSHOT.jar +0 -0
  87. snowflake/snowpark_connect/resources_initializer.py +171 -48
  88. snowflake/snowpark_connect/server.py +528 -473
  89. snowflake/snowpark_connect/server_common/__init__.py +503 -0
  90. snowflake/snowpark_connect/snowflake_session.py +65 -0
  91. snowflake/snowpark_connect/start_server.py +53 -5
  92. snowflake/snowpark_connect/type_mapping.py +349 -27
  93. snowflake/snowpark_connect/type_support.py +130 -0
  94. snowflake/snowpark_connect/typed_column.py +9 -7
  95. snowflake/snowpark_connect/utils/artifacts.py +9 -8
  96. snowflake/snowpark_connect/utils/cache.py +49 -27
  97. snowflake/snowpark_connect/utils/concurrent.py +36 -1
  98. snowflake/snowpark_connect/utils/context.py +195 -37
  99. snowflake/snowpark_connect/utils/describe_query_cache.py +68 -53
  100. snowflake/snowpark_connect/utils/env_utils.py +5 -1
  101. snowflake/snowpark_connect/utils/expression_transformer.py +172 -0
  102. snowflake/snowpark_connect/utils/identifiers.py +137 -3
  103. snowflake/snowpark_connect/utils/io_utils.py +57 -1
  104. snowflake/snowpark_connect/utils/java_stored_procedure.py +151 -0
  105. snowflake/snowpark_connect/utils/java_udaf_utils.py +321 -0
  106. snowflake/snowpark_connect/utils/java_udtf_utils.py +239 -0
  107. snowflake/snowpark_connect/utils/jvm_udf_utils.py +281 -0
  108. snowflake/snowpark_connect/utils/open_telemetry.py +516 -0
  109. snowflake/snowpark_connect/utils/pandas_udtf_utils.py +8 -4
  110. snowflake/snowpark_connect/utils/patch_spark_line_number.py +181 -0
  111. snowflake/snowpark_connect/utils/profiling.py +25 -8
  112. snowflake/snowpark_connect/utils/scala_udf_utils.py +185 -340
  113. snowflake/snowpark_connect/utils/sequence.py +21 -0
  114. snowflake/snowpark_connect/utils/session.py +64 -28
  115. snowflake/snowpark_connect/utils/snowpark_connect_logging.py +51 -9
  116. snowflake/snowpark_connect/utils/spcs_logger.py +290 -0
  117. snowflake/snowpark_connect/utils/telemetry.py +192 -40
  118. snowflake/snowpark_connect/utils/temporary_view_cache.py +67 -0
  119. snowflake/snowpark_connect/utils/temporary_view_helper.py +334 -0
  120. snowflake/snowpark_connect/utils/udf_cache.py +117 -41
  121. snowflake/snowpark_connect/utils/udf_helper.py +39 -37
  122. snowflake/snowpark_connect/utils/udf_utils.py +133 -14
  123. snowflake/snowpark_connect/utils/udtf_helper.py +8 -1
  124. snowflake/snowpark_connect/utils/udtf_utils.py +46 -31
  125. snowflake/snowpark_connect/utils/udxf_import_utils.py +9 -2
  126. snowflake/snowpark_connect/utils/upload_java_jar.py +57 -0
  127. snowflake/snowpark_connect/version.py +1 -1
  128. snowflake/snowpark_decoder/dp_session.py +6 -2
  129. snowflake/snowpark_decoder/spark_decoder.py +12 -0
  130. {snowpark_connect-0.27.0.data → snowpark_connect-1.7.0.data}/scripts/snowpark-submit +14 -4
  131. {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/METADATA +16 -7
  132. {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/RECORD +139 -168
  133. snowflake/snowpark_connect/hidden_column.py +0 -39
  134. snowflake/snowpark_connect/includes/jars/antlr4-runtime-4.9.3.jar +0 -0
  135. snowflake/snowpark_connect/includes/jars/commons-cli-1.5.0.jar +0 -0
  136. snowflake/snowpark_connect/includes/jars/commons-codec-1.16.1.jar +0 -0
  137. snowflake/snowpark_connect/includes/jars/commons-collections-3.2.2.jar +0 -0
  138. snowflake/snowpark_connect/includes/jars/commons-collections4-4.4.jar +0 -0
  139. snowflake/snowpark_connect/includes/jars/commons-compiler-3.1.9.jar +0 -0
  140. snowflake/snowpark_connect/includes/jars/commons-compress-1.26.0.jar +0 -0
  141. snowflake/snowpark_connect/includes/jars/commons-crypto-1.1.0.jar +0 -0
  142. snowflake/snowpark_connect/includes/jars/commons-dbcp-1.4.jar +0 -0
  143. snowflake/snowpark_connect/includes/jars/commons-io-2.16.1.jar +0 -0
  144. snowflake/snowpark_connect/includes/jars/commons-lang-2.6.jar +0 -0
  145. snowflake/snowpark_connect/includes/jars/commons-lang3-3.12.0.jar +0 -0
  146. snowflake/snowpark_connect/includes/jars/commons-logging-1.1.3.jar +0 -0
  147. snowflake/snowpark_connect/includes/jars/commons-math3-3.6.1.jar +0 -0
  148. snowflake/snowpark_connect/includes/jars/commons-pool-1.5.4.jar +0 -0
  149. snowflake/snowpark_connect/includes/jars/commons-text-1.10.0.jar +0 -0
  150. snowflake/snowpark_connect/includes/jars/hadoop-client-api-trimmed-3.3.4.jar +0 -0
  151. snowflake/snowpark_connect/includes/jars/jackson-annotations-2.15.2.jar +0 -0
  152. snowflake/snowpark_connect/includes/jars/jackson-core-2.15.2.jar +0 -0
  153. snowflake/snowpark_connect/includes/jars/jackson-core-asl-1.9.13.jar +0 -0
  154. snowflake/snowpark_connect/includes/jars/jackson-databind-2.15.2.jar +0 -0
  155. snowflake/snowpark_connect/includes/jars/jackson-dataformat-yaml-2.15.2.jar +0 -0
  156. snowflake/snowpark_connect/includes/jars/jackson-datatype-jsr310-2.15.2.jar +0 -0
  157. snowflake/snowpark_connect/includes/jars/jackson-module-scala_2.12-2.15.2.jar +0 -0
  158. snowflake/snowpark_connect/includes/jars/json4s-ast_2.12-3.7.0-M11.jar +0 -0
  159. snowflake/snowpark_connect/includes/jars/json4s-core_2.12-3.7.0-M11.jar +0 -0
  160. snowflake/snowpark_connect/includes/jars/json4s-jackson_2.12-3.7.0-M11.jar +0 -0
  161. snowflake/snowpark_connect/includes/jars/json4s-native_2.12-3.7.0-M11.jar +0 -0
  162. snowflake/snowpark_connect/includes/jars/json4s-scalap_2.12-3.7.0-M11.jar +0 -0
  163. snowflake/snowpark_connect/includes/jars/kryo-shaded-4.0.2.jar +0 -0
  164. snowflake/snowpark_connect/includes/jars/log4j-1.2-api-2.20.0.jar +0 -0
  165. snowflake/snowpark_connect/includes/jars/log4j-api-2.20.0.jar +0 -0
  166. snowflake/snowpark_connect/includes/jars/log4j-core-2.20.0.jar +0 -0
  167. snowflake/snowpark_connect/includes/jars/log4j-slf4j2-impl-2.20.0.jar +0 -0
  168. snowflake/snowpark_connect/includes/jars/paranamer-2.8.3.jar +0 -0
  169. snowflake/snowpark_connect/includes/jars/paranamer-2.8.jar +0 -0
  170. snowflake/snowpark_connect/includes/jars/sas-scala-udf_2.12-0.1.0.jar +0 -0
  171. snowflake/snowpark_connect/includes/jars/scala-collection-compat_2.12-2.7.0.jar +0 -0
  172. snowflake/snowpark_connect/includes/jars/scala-parser-combinators_2.12-2.3.0.jar +0 -0
  173. snowflake/snowpark_connect/includes/jars/scala-reflect-2.12.18.jar +0 -0
  174. snowflake/snowpark_connect/includes/jars/scala-xml_2.12-2.1.0.jar +0 -0
  175. snowflake/snowpark_connect/includes/jars/slf4j-api-2.0.7.jar +0 -0
  176. snowflake/snowpark_connect/includes/jars/spark-catalyst_2.12-3.5.6.jar +0 -0
  177. snowflake/snowpark_connect/includes/jars/spark-common-utils_2.12-3.5.6.jar +0 -0
  178. snowflake/snowpark_connect/includes/jars/spark-core_2.12-3.5.6.jar +0 -0
  179. snowflake/snowpark_connect/includes/jars/spark-graphx_2.12-3.5.6.jar +0 -0
  180. snowflake/snowpark_connect/includes/jars/spark-hive-thriftserver_2.12-3.5.6.jar +0 -0
  181. snowflake/snowpark_connect/includes/jars/spark-hive_2.12-3.5.6.jar +0 -0
  182. snowflake/snowpark_connect/includes/jars/spark-kvstore_2.12-3.5.6.jar +0 -0
  183. snowflake/snowpark_connect/includes/jars/spark-launcher_2.12-3.5.6.jar +0 -0
  184. snowflake/snowpark_connect/includes/jars/spark-mesos_2.12-3.5.6.jar +0 -0
  185. snowflake/snowpark_connect/includes/jars/spark-mllib-local_2.12-3.5.6.jar +0 -0
  186. snowflake/snowpark_connect/includes/jars/spark-network-common_2.12-3.5.6.jar +0 -0
  187. snowflake/snowpark_connect/includes/jars/spark-network-shuffle_2.12-3.5.6.jar +0 -0
  188. snowflake/snowpark_connect/includes/jars/spark-repl_2.12-3.5.6.jar +0 -0
  189. snowflake/snowpark_connect/includes/jars/spark-sketch_2.12-3.5.6.jar +0 -0
  190. snowflake/snowpark_connect/includes/jars/spark-sql-api_2.12-3.5.6.jar +0 -0
  191. snowflake/snowpark_connect/includes/jars/spark-tags_2.12-3.5.6.jar +0 -0
  192. snowflake/snowpark_connect/includes/jars/spark-unsafe_2.12-3.5.6.jar +0 -0
  193. snowflake/snowpark_connect/includes/jars/spark-yarn_2.12-3.5.6.jar +0 -0
  194. {snowpark_connect-0.27.0.data → snowpark_connect-1.7.0.data}/scripts/snowpark-connect +0 -0
  195. {snowpark_connect-0.27.0.data → snowpark_connect-1.7.0.data}/scripts/snowpark-session +0 -0
  196. {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/WHEEL +0 -0
  197. {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/licenses/LICENSE-binary +0 -0
  198. {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/licenses/LICENSE.txt +0 -0
  199. {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/licenses/NOTICE-binary +0 -0
  200. {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/top_level.txt +0 -0
@@ -4,6 +4,8 @@
4
4
 
5
5
  from snowflake import snowpark
6
6
  from snowflake.snowpark_connect.dataframe_container import DataFrameContainer
7
+ from snowflake.snowpark_connect.error.error_codes import ErrorCodes
8
+ from snowflake.snowpark_connect.error.error_utils import attach_custom_error_code
7
9
  from snowflake.snowpark_connect.relation.read.map_read_jdbc import (
8
10
  close_connection,
9
11
  create_connection,
@@ -35,7 +37,9 @@ def map_write_jdbc(
35
37
  dbtable = None
36
38
 
37
39
  if dbtable is None:
38
- raise ValueError("Include dbtable is required option")
40
+ exception = ValueError("Include dbtable is required option")
41
+ attach_custom_error_code(exception, ErrorCodes.INVALID_INPUT)
42
+ raise exception
39
43
 
40
44
  try:
41
45
  JdbcDataFrameWriter(session, jdbc_options).jdbc_write_dbapi(
@@ -46,4 +50,6 @@ def map_write_jdbc(
46
50
  write_mode=write_mode,
47
51
  )
48
52
  except Exception as e:
49
- raise Exception(f"Error accessing JDBC datasource for write: {e}")
53
+ exception = Exception(f"Error accessing JDBC datasource for write: {e}")
54
+ attach_custom_error_code(exception, ErrorCodes.INTERNAL_ERROR)
55
+ raise exception
@@ -1,18 +1,168 @@
1
1
  #
2
2
  # Copyright (c) 2012-2025 Snowflake Computing Inc. All rights reserved.
3
3
  #
4
- import pathlib
5
4
  import threading
6
5
  import time
6
+ from collections.abc import Callable
7
+ from pathlib import Path
7
8
 
9
+ from snowflake.snowpark_connect.client.error_utils import attach_custom_error_code
10
+ from snowflake.snowpark_connect.config import get_scala_version
11
+ from snowflake.snowpark_connect.error.error_codes import ErrorCodes
8
12
  from snowflake.snowpark_connect.utils.session import get_or_create_snowpark_session
9
13
  from snowflake.snowpark_connect.utils.snowpark_connect_logging import logger
10
14
 
11
- _resources_initialized = threading.Event()
12
- _initializer_lock = threading.Lock()
13
15
  SPARK_VERSION = "3.5.6"
14
16
  RESOURCE_PATH = "/snowflake/snowpark_connect/resources"
15
17
 
18
+ # On demand Scala UDF jar upload state - separate from general resource initialization
19
+ _scala_2_12_jars_uploaded = threading.Event()
20
+ _scala_2_12_jars_lock = threading.Lock()
21
+ _scala_2_13_jars_uploaded = threading.Event()
22
+ _scala_2_13_jars_lock = threading.Lock()
23
+
24
+ # Define Scala resource names
25
+ SPARK_SQL_JAR_212 = f"spark-sql_2.12-{SPARK_VERSION}.jar"
26
+ SPARK_CONNECT_CLIENT_JAR_212 = f"spark-connect-client-jvm_2.12-{SPARK_VERSION}.jar"
27
+ SPARK_COMMON_UTILS_JAR_212 = f"spark-common-utils_2.12-{SPARK_VERSION}.jar"
28
+ SAS_SCALA_UDF_JAR_212 = "sas-scala-udf_2.12-0.2.0.jar"
29
+ JSON_4S_JAR_212 = "json4s-ast_2.12-3.7.0-M11.jar"
30
+ SCALA_REFLECT_JAR_212 = "scala-reflect-2.12.18.jar"
31
+
32
+ # Static dependencies for Scala 2.13
33
+ SPARK_SQL_JAR_213 = f"spark-sql_2.13-{SPARK_VERSION}.jar"
34
+ SPARK_CONNECT_CLIENT_JAR_213 = f"spark-connect-client-jvm_2.13-{SPARK_VERSION}.jar"
35
+ SPARK_COMMON_UTILS_JAR_213 = f"spark-common-utils_2.13-{SPARK_VERSION}.jar"
36
+ SAS_SCALA_UDF_JAR_213 = "sas-scala-udf_2.13-0.2.0.jar"
37
+ JSON_4S_JAR_213 = "json4s-ast_2.13-3.7.0-M11.jar"
38
+ SCALA_REFLECT_JAR_213 = "scala-reflect-2.13.16.jar"
39
+
40
+
41
+ def _upload_scala_udf_jars(jar_files: list[str]) -> None:
42
+ """Upload Spark jar files required for creating Scala UDFs.
43
+ This is the internal implementation - use ensure_scala_udf_jars_uploaded() for thread-safe lazy loading."""
44
+
45
+ session = get_or_create_snowpark_session()
46
+ stage = session.get_session_stage()
47
+ resource_path = stage + RESOURCE_PATH
48
+ import snowpark_connect_deps_1
49
+ import snowpark_connect_deps_2
50
+
51
+ # Path to includes/jars directory
52
+ includes_jars_dir = Path(__file__).parent / "includes" / "jars"
53
+
54
+ for jar_name in jar_files:
55
+ jar_path = None
56
+
57
+ # First check includes/jars directory
58
+ includes_jar_path = includes_jars_dir / jar_name
59
+ if includes_jar_path.exists():
60
+ jar_path = includes_jar_path
61
+ logger.info(f"Found {jar_name} in includes/jars")
62
+ else:
63
+ # Try to find the JAR in package 1 first, then package 2
64
+ try:
65
+ jar_path = snowpark_connect_deps_1.get_jar_path(jar_name)
66
+ except FileNotFoundError:
67
+ try:
68
+ jar_path = snowpark_connect_deps_2.get_jar_path(jar_name)
69
+ except FileNotFoundError:
70
+ raise FileNotFoundError(
71
+ f"JAR {jar_name} not found in includes/jars or either package"
72
+ )
73
+
74
+ try:
75
+ session.file.put(
76
+ str(jar_path),
77
+ resource_path,
78
+ auto_compress=False,
79
+ overwrite=False,
80
+ source_compression="NONE",
81
+ )
82
+ except Exception as e:
83
+ raise RuntimeError(f"Failed to upload JAR {jar_name}: {e}")
84
+
85
+
86
+ def _upload_scala_2_12_jars() -> None:
87
+ scala_2_12_jars = [
88
+ SPARK_SQL_JAR_212,
89
+ SPARK_CONNECT_CLIENT_JAR_212,
90
+ SPARK_COMMON_UTILS_JAR_212,
91
+ SAS_SCALA_UDF_JAR_212,
92
+ JSON_4S_JAR_212,
93
+ SCALA_REFLECT_JAR_212, # Required for deserializing Scala lambdas
94
+ ]
95
+ _upload_scala_udf_jars(scala_2_12_jars)
96
+
97
+
98
+ def _upload_scala_2_13_jars() -> None:
99
+ scala_2_13_jars = [
100
+ SPARK_SQL_JAR_213,
101
+ SPARK_CONNECT_CLIENT_JAR_213,
102
+ SPARK_COMMON_UTILS_JAR_213,
103
+ SAS_SCALA_UDF_JAR_213,
104
+ JSON_4S_JAR_213,
105
+ SCALA_REFLECT_JAR_213,
106
+ ]
107
+ _upload_scala_udf_jars(scala_2_13_jars)
108
+
109
+
110
+ def _ensure_configured_scala_jars_uploaded(
111
+ jars_uploaded: threading.Event, lock: threading.Lock, upload_fn: Callable[[], None]
112
+ ) -> None:
113
+ """
114
+ Ensure Scala UDF jars are uploaded to Snowflake, uploading them lazily if not already done.
115
+ This function is thread-safe and will only upload once even if called from multiple threads.
116
+
117
+ Uses the given upload_fn to upload Scala jars if the jars_uploaded event is not set yet.
118
+ """
119
+ # Fast path: if already uploaded, return immediately without acquiring lock
120
+ if jars_uploaded.is_set():
121
+ return
122
+
123
+ # Slow path: need to upload, acquire lock to ensure only one thread does it
124
+ with lock:
125
+ # Double-check pattern: another thread might have uploaded while we waited for the lock
126
+ if jars_uploaded.is_set():
127
+ return
128
+
129
+ try:
130
+ start_time = time.time()
131
+ logger.info("Uploading Scala UDF jars on-demand...")
132
+ upload_fn()
133
+ jars_uploaded.set()
134
+ logger.info(f"Scala UDF jars uploaded in {time.time() - start_time:.2f}s")
135
+ except Exception as e:
136
+ logger.error(f"Failed to upload Scala UDF jars: {e}")
137
+ raise
138
+
139
+
140
+ def ensure_scala_udf_jars_uploaded() -> None:
141
+ """
142
+ Public function to make sure Scala jars are uploaded and available for imports.
143
+ """
144
+ scala_version = get_scala_version()
145
+
146
+ match scala_version:
147
+ case "2.12":
148
+ _ensure_configured_scala_jars_uploaded(
149
+ _scala_2_12_jars_uploaded,
150
+ _scala_2_12_jars_lock,
151
+ _upload_scala_2_12_jars,
152
+ )
153
+ case "2.13":
154
+ _ensure_configured_scala_jars_uploaded(
155
+ _scala_2_13_jars_uploaded,
156
+ _scala_2_13_jars_lock,
157
+ _upload_scala_2_13_jars,
158
+ )
159
+ case _:
160
+ exception = ValueError(
161
+ f"Unsupported Scala version: {scala_version}. Snowpark Connect supports Scala 2.12 and 2.13"
162
+ )
163
+ attach_custom_error_code(exception, ErrorCodes.INVALID_CONFIG_VALUE)
164
+ raise exception
165
+
16
166
 
17
167
  def initialize_resources() -> None:
18
168
  """Initialize all expensive resources. We should initialize what we can here, so that actual rpc calls like
@@ -44,34 +194,6 @@ def initialize_resources() -> None:
44
194
 
45
195
  session.sql("select 1 as sf_connection_warm_up").collect()
46
196
 
47
- def upload_scala_udf_jars() -> None:
48
- """Upload Spark jar files required for creating Scala UDFs."""
49
- stage = session.get_session_stage()
50
- resource_path = stage + RESOURCE_PATH
51
- import snowflake
52
-
53
- pyspark_jars = (
54
- pathlib.Path(snowflake.snowpark_connect.__file__).parent / "includes/jars"
55
- )
56
- jar_files = [
57
- f"spark-sql_2.12-{SPARK_VERSION}.jar",
58
- f"spark-connect-client-jvm_2.12-{SPARK_VERSION}.jar",
59
- f"spark-common-utils_2.12-{SPARK_VERSION}.jar",
60
- "json4s-ast_2.12-3.7.0-M11.jar",
61
- "json4s-native_2.12-3.7.0-M11.jar",
62
- "json4s-core_2.12-3.7.0-M11.jar",
63
- "paranamer-2.8.3.jar",
64
- ]
65
-
66
- for jar in jar_files:
67
- session.file.put(
68
- str(pyspark_jars) + "/" + jar,
69
- resource_path,
70
- auto_compress=False,
71
- overwrite=False,
72
- source_compression="NONE",
73
- )
74
-
75
197
  start_time = time.time()
76
198
 
77
199
  resources = [
@@ -80,7 +202,6 @@ def initialize_resources() -> None:
80
202
  ("Initialize Session Stage", initialize_session_stage), # Takes about 0.3s
81
203
  ("Initialize Session Catalog", initialize_catalog), # Takes about 1.2s
82
204
  ("Snowflake Connection Warm Up", warm_up_sf_connection), # Takes about 1s
83
- ("Upload Scala UDF Jars", upload_scala_udf_jars),
84
205
  ]
85
206
 
86
207
  for name, resource_func in resources:
@@ -94,23 +215,25 @@ def initialize_resources() -> None:
94
215
  if str(e).find("because the session has been closed") == -1:
95
216
  logger.error(f"Failed to initialize {name}: {e}")
96
217
 
97
- _resources_initialized.set()
98
218
  logger.info(f"All resources initialized in {time.time() - start_time:.2f}s")
99
219
 
100
220
 
101
- _resource_initializer = threading.Thread(
102
- target=initialize_resources, name="ResourceInitializer"
103
- )
104
-
105
-
106
- def initialize_resources_async() -> threading.Thread:
107
- """Start resource initialization in background."""
108
- with _initializer_lock:
109
- if not _resource_initializer.is_alive() and _resource_initializer.ident is None:
110
- _resource_initializer.start()
111
- return _resource_initializer
112
-
113
-
114
221
  def wait_for_resource_initialization() -> None:
115
- with _initializer_lock:
116
- _resource_initializer.join()
222
+ """No-op function retained for backward compatibility.
223
+
224
+ This function is kept to maintain backward compatibility with external client code that may call it.
225
+ Previously, this function waited for asynchronous resource initialization to complete.
226
+ Now that resource initialization is synchronous, this function does nothing.
227
+ External callers can safely call this function without any effect.
228
+ """
229
+ pass
230
+
231
+
232
+ def set_upload_jars(upload: bool) -> None:
233
+ """No-op function retained for backward compatibility.
234
+ This function is kept to maintain backward compatibility with external client code that may call it.
235
+ Previously, this function was used to set whether to upload jars required for Scala UDFs.
236
+ Now that Scala UDF jar upload has been moved to lazy on-demand loading via ensure_scala_udf_jars_uploaded(),
237
+ this function does nothing. External callers can safely call this function without any effect.
238
+ """
239
+ pass