sqlframe 2.0.0__tar.gz → 2.1.0__tar.gz

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 (224) hide show
  1. {sqlframe-2.0.0 → sqlframe-2.1.0}/PKG-INFO +1 -1
  2. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/duckdb.md +1 -0
  3. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/snowflake.md +1 -0
  4. {sqlframe-2.0.0 → sqlframe-2.1.0}/setup.py +3 -3
  5. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/_version.py +2 -2
  6. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/_typing.py +1 -0
  7. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/functions.py +10 -5
  8. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/session.py +11 -64
  9. sqlframe-2.1.0/sqlframe/base/udf.py +36 -0
  10. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/bigquery/session.py +3 -0
  11. sqlframe-2.1.0/sqlframe/bigquery/udf.py +11 -0
  12. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/duckdb/session.py +3 -0
  13. sqlframe-2.1.0/sqlframe/duckdb/udf.py +19 -0
  14. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/postgres/session.py +3 -0
  15. sqlframe-2.1.0/sqlframe/postgres/udf.py +11 -0
  16. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/redshift/session.py +3 -0
  17. sqlframe-2.1.0/sqlframe/redshift/udf.py +11 -0
  18. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/snowflake/session.py +4 -0
  19. sqlframe-2.1.0/sqlframe/snowflake/udf.py +11 -0
  20. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/spark/session.py +3 -0
  21. sqlframe-2.1.0/sqlframe/spark/udf.py +34 -0
  22. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/standalone/session.py +3 -0
  23. sqlframe-2.1.0/sqlframe/standalone/udf.py +11 -0
  24. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe.egg-info/PKG-INFO +1 -1
  25. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe.egg-info/SOURCES.txt +9 -0
  26. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe.egg-info/requires.txt +3 -3
  27. sqlframe-2.1.0/tests/integration/engines/duck/test_duckdb_udf.py +12 -0
  28. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/test_int_functions.py +10 -1
  29. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/unit/standalone/test_functions.py +12 -3
  30. {sqlframe-2.0.0 → sqlframe-2.1.0}/.github/CODEOWNERS +0 -0
  31. {sqlframe-2.0.0 → sqlframe-2.1.0}/.github/workflows/main.workflow.yaml +0 -0
  32. {sqlframe-2.0.0 → sqlframe-2.1.0}/.github/workflows/publish.workflow.yaml +0 -0
  33. {sqlframe-2.0.0 → sqlframe-2.1.0}/.gitignore +0 -0
  34. {sqlframe-2.0.0 → sqlframe-2.1.0}/.pre-commit-config.yaml +0 -0
  35. {sqlframe-2.0.0 → sqlframe-2.1.0}/.readthedocs.yaml +0 -0
  36. {sqlframe-2.0.0 → sqlframe-2.1.0}/LICENSE +0 -0
  37. {sqlframe-2.0.0 → sqlframe-2.1.0}/Makefile +0 -0
  38. {sqlframe-2.0.0 → sqlframe-2.1.0}/README.md +0 -0
  39. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/add_chatgpt_support.md +0 -0
  40. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/images/add_chatgpt_support/adding_ai_to_meal.jpeg +0 -0
  41. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/images/add_chatgpt_support/hype_train.gif +0 -0
  42. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/images/add_chatgpt_support/marvin_paranoid_robot.gif +0 -0
  43. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/images/add_chatgpt_support/nonsense_sql.png +0 -0
  44. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/images/add_chatgpt_support/openai_full_rewrite.png +0 -0
  45. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/images/add_chatgpt_support/openai_replacing_cte_names.png +0 -0
  46. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/images/add_chatgpt_support/sqlglot_optimized_code.png +0 -0
  47. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/images/add_chatgpt_support/sunny_shake_head_no.gif +0 -0
  48. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/images/but_wait_theres_more.gif +0 -0
  49. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/images/cake.gif +0 -0
  50. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/images/you_get_pyspark_api.gif +0 -0
  51. {sqlframe-2.0.0 → sqlframe-2.1.0}/blogs/sqlframe_universal_dataframe_api.md +0 -0
  52. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/bigquery.md +0 -0
  53. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/configuration.md +0 -0
  54. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/docs/bigquery.md +0 -0
  55. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/docs/duckdb.md +0 -0
  56. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/docs/images/SF.png +0 -0
  57. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/docs/images/favicon.png +0 -0
  58. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/docs/images/favicon_old.png +0 -0
  59. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/docs/images/sqlframe_diagram.png +0 -0
  60. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/docs/images/sqlframe_logo.png +0 -0
  61. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/docs/postgres.md +0 -0
  62. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/images/SF.png +0 -0
  63. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/images/favicon.png +0 -0
  64. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/images/favicon_old.png +0 -0
  65. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/images/sqlframe_diagram.png +0 -0
  66. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/images/sqlframe_logo.png +0 -0
  67. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/index.md +0 -0
  68. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/postgres.md +0 -0
  69. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/requirements.txt +0 -0
  70. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/spark.md +0 -0
  71. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/standalone.md +0 -0
  72. {sqlframe-2.0.0 → sqlframe-2.1.0}/docs/stylesheets/extra.css +0 -0
  73. {sqlframe-2.0.0 → sqlframe-2.1.0}/mkdocs.yml +0 -0
  74. {sqlframe-2.0.0 → sqlframe-2.1.0}/pytest.ini +0 -0
  75. {sqlframe-2.0.0 → sqlframe-2.1.0}/renovate.json +0 -0
  76. {sqlframe-2.0.0 → sqlframe-2.1.0}/setup.cfg +0 -0
  77. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/LICENSE +0 -0
  78. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/__init__.py +0 -0
  79. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/__init__.py +0 -0
  80. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/catalog.py +0 -0
  81. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/column.py +0 -0
  82. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/dataframe.py +0 -0
  83. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/decorators.py +0 -0
  84. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/exceptions.py +0 -0
  85. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/function_alternatives.py +0 -0
  86. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/group.py +0 -0
  87. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/mixins/__init__.py +0 -0
  88. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/mixins/catalog_mixins.py +0 -0
  89. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/mixins/dataframe_mixins.py +0 -0
  90. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/mixins/readwriter_mixins.py +0 -0
  91. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/normalize.py +0 -0
  92. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/operations.py +0 -0
  93. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/readerwriter.py +0 -0
  94. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/transforms.py +0 -0
  95. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/types.py +0 -0
  96. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/util.py +0 -0
  97. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/base/window.py +0 -0
  98. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/bigquery/__init__.py +0 -0
  99. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/bigquery/catalog.py +0 -0
  100. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/bigquery/column.py +0 -0
  101. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/bigquery/dataframe.py +0 -0
  102. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/bigquery/functions.py +0 -0
  103. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/bigquery/functions.pyi +0 -0
  104. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/bigquery/group.py +0 -0
  105. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/bigquery/readwriter.py +0 -0
  106. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/bigquery/types.py +0 -0
  107. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/bigquery/window.py +0 -0
  108. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/duckdb/__init__.py +0 -0
  109. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/duckdb/catalog.py +0 -0
  110. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/duckdb/column.py +0 -0
  111. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/duckdb/dataframe.py +0 -0
  112. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/duckdb/functions.py +0 -0
  113. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/duckdb/functions.pyi +0 -0
  114. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/duckdb/group.py +0 -0
  115. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/duckdb/readwriter.py +0 -0
  116. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/duckdb/types.py +0 -0
  117. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/duckdb/window.py +0 -0
  118. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/postgres/__init__.py +0 -0
  119. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/postgres/catalog.py +0 -0
  120. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/postgres/column.py +0 -0
  121. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/postgres/dataframe.py +0 -0
  122. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/postgres/functions.py +0 -0
  123. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/postgres/functions.pyi +0 -0
  124. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/postgres/group.py +0 -0
  125. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/postgres/readwriter.py +0 -0
  126. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/postgres/types.py +0 -0
  127. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/postgres/window.py +0 -0
  128. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/redshift/__init__.py +0 -0
  129. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/redshift/catalog.py +0 -0
  130. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/redshift/column.py +0 -0
  131. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/redshift/dataframe.py +0 -0
  132. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/redshift/functions.py +0 -0
  133. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/redshift/group.py +0 -0
  134. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/redshift/readwriter.py +0 -0
  135. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/redshift/types.py +0 -0
  136. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/redshift/window.py +0 -0
  137. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/snowflake/__init__.py +0 -0
  138. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/snowflake/catalog.py +0 -0
  139. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/snowflake/column.py +0 -0
  140. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/snowflake/dataframe.py +0 -0
  141. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/snowflake/functions.py +0 -0
  142. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/snowflake/functions.pyi +0 -0
  143. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/snowflake/group.py +0 -0
  144. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/snowflake/readwriter.py +0 -0
  145. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/snowflake/types.py +0 -0
  146. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/snowflake/window.py +0 -0
  147. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/spark/__init__.py +0 -0
  148. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/spark/catalog.py +0 -0
  149. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/spark/column.py +0 -0
  150. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/spark/dataframe.py +0 -0
  151. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/spark/functions.py +0 -0
  152. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/spark/functions.pyi +0 -0
  153. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/spark/group.py +0 -0
  154. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/spark/readwriter.py +0 -0
  155. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/spark/types.py +0 -0
  156. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/spark/window.py +0 -0
  157. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/standalone/__init__.py +0 -0
  158. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/standalone/catalog.py +0 -0
  159. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/standalone/column.py +0 -0
  160. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/standalone/dataframe.py +0 -0
  161. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/standalone/functions.py +0 -0
  162. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/standalone/group.py +0 -0
  163. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/standalone/readwriter.py +0 -0
  164. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/standalone/types.py +0 -0
  165. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/standalone/window.py +0 -0
  166. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/testing/__init__.py +0 -0
  167. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe/testing/utils.py +0 -0
  168. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe.egg-info/dependency_links.txt +0 -0
  169. {sqlframe-2.0.0 → sqlframe-2.1.0}/sqlframe.egg-info/top_level.txt +0 -0
  170. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/__init__.py +0 -0
  171. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/common_fixtures.py +0 -0
  172. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/conftest.py +0 -0
  173. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/fixtures/employee.csv +0 -0
  174. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/fixtures/employee.json +0 -0
  175. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/fixtures/employee.parquet +0 -0
  176. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/fixtures/employee_extra_line.csv +0 -0
  177. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/__init__.py +0 -0
  178. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/__init__.py +0 -0
  179. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/bigquery/__init__.py +0 -0
  180. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/bigquery/test_bigquery_catalog.py +0 -0
  181. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/bigquery/test_bigquery_dataframe.py +0 -0
  182. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/bigquery/test_bigquery_session.py +0 -0
  183. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/duck/__init__.py +0 -0
  184. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/duck/test_duckdb_catalog.py +0 -0
  185. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/duck/test_duckdb_dataframe.py +0 -0
  186. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/duck/test_duckdb_reader.py +0 -0
  187. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/duck/test_duckdb_session.py +0 -0
  188. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/postgres/__init__.py +0 -0
  189. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/postgres/test_postgres_catalog.py +0 -0
  190. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/postgres/test_postgres_dataframe.py +0 -0
  191. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/postgres/test_postgres_session.py +0 -0
  192. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/redshift/__init__.py +0 -0
  193. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/redshift/test_redshift_catalog.py +0 -0
  194. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/redshift/test_redshift_session.py +0 -0
  195. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/snowflake/__init__.py +0 -0
  196. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/snowflake/test_snowflake_catalog.py +0 -0
  197. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/snowflake/test_snowflake_dataframe.py +0 -0
  198. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/snowflake/test_snowflake_session.py +0 -0
  199. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/spark/__init__.py +0 -0
  200. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/spark/test_spark_catalog.py +0 -0
  201. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/spark/test_spark_dataframe.py +0 -0
  202. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/test_engine_column.py +0 -0
  203. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/test_engine_dataframe.py +0 -0
  204. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/test_engine_reader.py +0 -0
  205. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/test_engine_session.py +0 -0
  206. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/test_engine_writer.py +0 -0
  207. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/engines/test_int_testing.py +0 -0
  208. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/fixtures.py +0 -0
  209. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/test_int_dataframe.py +0 -0
  210. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/test_int_dataframe_stats.py +0 -0
  211. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/test_int_grouped_data.py +0 -0
  212. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/integration/test_int_session.py +0 -0
  213. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/types.py +0 -0
  214. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/unit/__init__.py +0 -0
  215. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/unit/standalone/__init__.py +0 -0
  216. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/unit/standalone/fixtures.py +0 -0
  217. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/unit/standalone/test_column.py +0 -0
  218. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/unit/standalone/test_dataframe.py +0 -0
  219. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/unit/standalone/test_dataframe_writer.py +0 -0
  220. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/unit/standalone/test_session.py +0 -0
  221. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/unit/standalone/test_session_case_sensitivity.py +0 -0
  222. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/unit/standalone/test_types.py +0 -0
  223. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/unit/standalone/test_window.py +0 -0
  224. {sqlframe-2.0.0 → sqlframe-2.1.0}/tests/unit/test_util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sqlframe
3
- Version: 2.0.0
3
+ Version: 2.1.0
4
4
  Summary: Turning PySpark Into a Universal DataFrame API
5
5
  Home-page: https://github.com/eakmanrq/sqlframe
6
6
  Author: Ryan Eakman
@@ -258,6 +258,7 @@ See something that you would like to see supported? [Open an issue](https://gith
258
258
  * [concat](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.concat.html)
259
259
  * Only works on strings (does not work on arrays)
260
260
  * [concat_ws](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.concat_ws.html)
261
+ * [convert_timezone](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.convert_timezone.html)
261
262
  * [corr](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.corr.html)
262
263
  * [cos](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.cos.html)
263
264
  * [cot](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.cot.html)
@@ -286,6 +286,7 @@ See something that you would like to see supported? [Open an issue](https://gith
286
286
  * [concat](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.concat.html)
287
287
  * Can only concat strings not arrays
288
288
  * [concat_ws](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.concat_ws.html)
289
+ * [convert_timezone](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.convert_timezone.html)
289
290
  * [corr](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.corr.html)
290
291
  * [cos](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.cos.html)
291
292
  * [cosh](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.cosh.html)
@@ -20,7 +20,7 @@ setup(
20
20
  python_requires=">=3.8",
21
21
  install_requires=[
22
22
  "prettytable<3.11.0",
23
- "sqlglot>=24.0.0,<25.9",
23
+ "sqlglot>=24.0.0,<25.11",
24
24
  "typing_extensions>=4.8,<5",
25
25
  ],
26
26
  extras_require={
@@ -31,7 +31,7 @@ setup(
31
31
  "dev": [
32
32
  "duckdb>=0.9,<1.1",
33
33
  "mypy>=1.10.0,<1.12",
34
- "openai>=1.30,<1.38",
34
+ "openai>=1.30,<1.41",
35
35
  "pandas>=2,<3",
36
36
  "pandas-stubs>=2,<3",
37
37
  "psycopg>=3.1,<4",
@@ -57,7 +57,7 @@ setup(
57
57
  "pandas>=2,<3",
58
58
  ],
59
59
  "openai": [
60
- "openai>=1.30,<1.38",
60
+ "openai>=1.30,<1.41",
61
61
  ],
62
62
  "pandas": [
63
63
  "pandas>=2,<3",
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '2.0.0'
16
- __version_tuple__ = version_tuple = (2, 0, 0)
15
+ __version__ = version = '2.1.0'
16
+ __version_tuple__ = version_tuple = (2, 1, 0)
@@ -24,6 +24,7 @@ OutputExpressionContainer = t.Union[exp.Select, exp.Create, exp.Insert]
24
24
  StorageLevel = str
25
25
  PathOrPaths = t.Union[str, t.List[str]]
26
26
  OptionalPrimitiveType = t.Optional[PrimitiveType]
27
+ DataTypeOrString = t.Union[DataType, str]
27
28
 
28
29
 
29
30
  class UserDefinedFunctionLike(t.Protocol):
@@ -2070,14 +2070,19 @@ def contains(left: ColumnOrName, right: ColumnOrName) -> Column:
2070
2070
  return Column.invoke_anonymous_function(left, "contains", right)
2071
2071
 
2072
2072
 
2073
- @meta(unsupported_engines="*")
2073
+ @meta(unsupported_engines=["bigquery", "postgres"])
2074
2074
  def convert_timezone(
2075
2075
  sourceTz: t.Optional[Column], targetTz: Column, sourceTs: ColumnOrName
2076
2076
  ) -> Column:
2077
- if sourceTz is None:
2078
- return Column.invoke_anonymous_function(targetTz, "convert_timezone", sourceTs)
2079
- else:
2080
- return Column.invoke_anonymous_function(sourceTz, "convert_timezone", targetTz, sourceTs)
2077
+ to_timestamp = get_func_from_session("to_timestamp")
2078
+
2079
+ return Column(
2080
+ expression.ConvertTimezone(
2081
+ timestamp=to_timestamp(Column.ensure_col(sourceTs)).expression,
2082
+ source_tz=sourceTz.expression if sourceTz else None,
2083
+ target_tz=Column.ensure_col(targetTz).expression,
2084
+ )
2085
+ )
2081
2086
 
2082
2087
 
2083
2088
  @meta(unsupported_engines="postgres")
@@ -27,6 +27,7 @@ from sqlframe.base.catalog import _BaseCatalog
27
27
  from sqlframe.base.dataframe import _BaseDataFrame
28
28
  from sqlframe.base.normalize import normalize_dict
29
29
  from sqlframe.base.readerwriter import _BaseDataFrameReader, _BaseDataFrameWriter
30
+ from sqlframe.base.udf import _BaseUDFRegistration
30
31
  from sqlframe.base.util import (
31
32
  get_column_mapping_from_schema_input,
32
33
  normalize_string,
@@ -64,16 +65,18 @@ CATALOG = t.TypeVar("CATALOG", bound=_BaseCatalog)
64
65
  READER = t.TypeVar("READER", bound=_BaseDataFrameReader)
65
66
  WRITER = t.TypeVar("WRITER", bound=_BaseDataFrameWriter)
66
67
  DF = t.TypeVar("DF", bound=_BaseDataFrame)
68
+ UDF_REGISTRATION = t.TypeVar("UDF_REGISTRATION", bound=_BaseUDFRegistration)
67
69
 
68
70
  _MISSING = "MISSING"
69
71
 
70
72
 
71
- class _BaseSession(t.Generic[CATALOG, READER, WRITER, DF, CONN]):
73
+ class _BaseSession(t.Generic[CATALOG, READER, WRITER, DF, CONN, UDF_REGISTRATION]):
72
74
  _instance = None
73
75
  _reader: t.Type[READER]
74
76
  _writer: t.Type[WRITER]
75
77
  _catalog: t.Type[CATALOG]
76
78
  _df: t.Type[DF]
79
+ _udf_registration: t.Type[UDF_REGISTRATION]
77
80
 
78
81
  SANITIZE_COLUMN_NAMES = False
79
82
 
@@ -81,7 +84,6 @@ class _BaseSession(t.Generic[CATALOG, READER, WRITER, DF, CONN]):
81
84
  self,
82
85
  conn: t.Optional[CONN] = None,
83
86
  schema: t.Optional[MappingSchema] = None,
84
- case_sensitive: bool = False,
85
87
  *args,
86
88
  **kwargs,
87
89
  ):
@@ -91,11 +93,6 @@ class _BaseSession(t.Generic[CATALOG, READER, WRITER, DF, CONN]):
91
93
  self.execution_dialect: Dialect = Dialect.get_or_raise(
92
94
  self.builder.DEFAULT_EXECUTION_DIALECT
93
95
  )
94
- self.case_sensitive: bool = case_sensitive
95
- if self.case_sensitive:
96
- self.input_dialect.NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_SENSITIVE
97
- self.output_dialect.NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_SENSITIVE
98
- self.execution_dialect.NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_SENSITIVE
99
96
  self.known_ids: t.Set[str] = set()
100
97
  self.known_branch_ids: t.Set[str] = set()
101
98
  self.known_sequence_ids: t.Set[str] = set()
@@ -176,6 +173,13 @@ class _BaseSession(t.Generic[CATALOG, READER, WRITER, DF, CONN]):
176
173
  def _has_connection(self) -> bool:
177
174
  return hasattr(self, "_connection") and bool(self._connection)
178
175
 
176
+ @property
177
+ def udf(self) -> UDF_REGISTRATION:
178
+ return self._udf_registration(self)
179
+
180
+ def getActiveSession(self) -> Self:
181
+ return self
182
+
179
183
  def range(self, *args):
180
184
  start = 0
181
185
  step = 1
@@ -573,53 +577,10 @@ class _BaseSession(t.Generic[CATALOG, READER, WRITER, DF, CONN]):
573
577
  converted_values.append(cls._to_value(value))
574
578
  return _create_row(columns, converted_values)
575
579
 
576
- @property
577
- def _is_standalone(self) -> bool:
578
- from sqlframe.standalone.session import StandaloneSession
579
-
580
- return isinstance(self, StandaloneSession)
581
-
582
- @property
583
- def _is_duckdb(self) -> bool:
584
- from sqlframe.duckdb.session import DuckDBSession
585
-
586
- return isinstance(self, DuckDBSession)
587
-
588
- @property
589
- def _is_postgres(self) -> bool:
590
- from sqlframe.postgres.session import PostgresSession
591
-
592
- return isinstance(self, PostgresSession)
593
-
594
- @property
595
- def _is_spark(self) -> bool:
596
- from sqlframe.spark.session import SparkSession
597
-
598
- return isinstance(self, SparkSession)
599
-
600
- @property
601
- def _is_bigquery(self) -> bool:
602
- from sqlframe.bigquery.session import BigQuerySession
603
-
604
- return isinstance(self, BigQuerySession)
605
-
606
- @property
607
- def _is_redshift(self) -> bool:
608
- from sqlframe.redshift.session import RedshiftSession
609
-
610
- return isinstance(self, RedshiftSession)
611
-
612
- @property
613
- def _is_snowflake(self) -> bool:
614
- from sqlframe.snowflake.session import SnowflakeSession
615
-
616
- return isinstance(self, SnowflakeSession)
617
-
618
580
  class Builder:
619
581
  SQLFRAME_INPUT_DIALECT_KEY = "sqlframe.input.dialect"
620
582
  SQLFRAME_OUTPUT_DIALECT_KEY = "sqlframe.output.dialect"
621
583
  SQLFRAME_EXECUTION_DIALECT_KEY = "sqlframe.execution.dialect"
622
- SQLFRAME_CASE_SENSITIVE_KEY = "spark.sql.caseSensitive"
623
584
  SQLFRAME_CONN_KEY = "sqlframe.conn"
624
585
  SQLFRAME_SCHEMA_KEY = "sqlframe.schema"
625
586
  DEFAULT_INPUT_DIALECT = "spark"
@@ -665,8 +626,6 @@ class _BaseSession(t.Generic[CATALOG, READER, WRITER, DF, CONN]):
665
626
  self._session_kwargs["conn"] = value
666
627
  elif key == self.SQLFRAME_SCHEMA_KEY:
667
628
  self._session_kwargs["schema"] = value
668
- elif key == self.SQLFRAME_CASE_SENSITIVE_KEY:
669
- self._session_kwargs["case_sensitive"] = value
670
629
  else:
671
630
  self._session_kwargs[key] = value
672
631
  if map:
@@ -676,8 +635,6 @@ class _BaseSession(t.Generic[CATALOG, READER, WRITER, DF, CONN]):
676
635
  self.output_dialect = map[self.SQLFRAME_OUTPUT_DIALECT_KEY]
677
636
  if self.SQLFRAME_EXECUTION_DIALECT_KEY in map:
678
637
  self.execution_dialect = map[self.SQLFRAME_EXECUTION_DIALECT_KEY]
679
- if self.SQLFRAME_CASE_SENSITIVE_KEY in map:
680
- self._session_kwargs["case_sensitive"] = map[self.SQLFRAME_CASE_SENSITIVE_KEY]
681
638
  if self.SQLFRAME_CONN_KEY in map:
682
639
  self._session_kwargs["conn"] = map[self.SQLFRAME_CONN_KEY]
683
640
  if self.SQLFRAME_SCHEMA_KEY in map:
@@ -700,15 +657,5 @@ class _BaseSession(t.Generic[CATALOG, READER, WRITER, DF, CONN]):
700
657
  self.session.execution_dialect = Dialect.get_or_raise(self.execution_dialect)
701
658
  if hasattr(self.session, "_connection") and not self.session._connection:
702
659
  self.session._connection = self._conn
703
- if self.session.case_sensitive:
704
- self.session.input_dialect.NORMALIZATION_STRATEGY = (
705
- NormalizationStrategy.CASE_SENSITIVE
706
- )
707
- self.session.output_dialect.NORMALIZATION_STRATEGY = (
708
- NormalizationStrategy.CASE_SENSITIVE
709
- )
710
- self.session.execution_dialect.NORMALIZATION_STRATEGY = (
711
- NormalizationStrategy.CASE_SENSITIVE
712
- )
713
660
 
714
661
  builder = Builder()
@@ -0,0 +1,36 @@
1
+ # This code is based on code from Apache Spark under the license found in the LICENSE file located in the 'sqlframe' folder.
2
+ from __future__ import annotations
3
+
4
+ import typing as t
5
+
6
+ if t.TYPE_CHECKING:
7
+ from sqlframe.base._typing import DataTypeOrString, UserDefinedFunctionLike
8
+ from sqlframe.base.session import _BaseSession
9
+
10
+ SESSION = t.TypeVar("SESSION", bound=_BaseSession)
11
+ else:
12
+ SESSION = t.TypeVar("SESSION")
13
+
14
+
15
+ class _BaseUDFRegistration(t.Generic[SESSION]):
16
+ def __init__(self, sparkSession: SESSION):
17
+ self.sparkSession = sparkSession
18
+
19
+ def register(
20
+ self,
21
+ name: str,
22
+ f: t.Union[t.Callable[..., t.Any], UserDefinedFunctionLike],
23
+ returnType: t.Optional[DataTypeOrString] = None,
24
+ ) -> UserDefinedFunctionLike:
25
+ raise NotImplementedError
26
+
27
+ def registerJavaFunction(
28
+ self,
29
+ name: str,
30
+ javaClassName: str,
31
+ returnType: t.Optional[DataTypeOrString] = None,
32
+ ) -> None:
33
+ raise NotImplementedError
34
+
35
+ def registerJavaUDAF(self, name: str, javaClassName: str) -> None:
36
+ raise NotImplementedError
@@ -9,6 +9,7 @@ from sqlframe.bigquery.readwriter import (
9
9
  BigQueryDataFrameReader,
10
10
  BigQueryDataFrameWriter,
11
11
  )
12
+ from sqlframe.bigquery.udf import BigQueryUDFRegistration
12
13
 
13
14
  if t.TYPE_CHECKING:
14
15
  from google.cloud.bigquery.client import Client as BigQueryClient
@@ -25,12 +26,14 @@ class BigQuerySession(
25
26
  BigQueryDataFrameWriter,
26
27
  BigQueryDataFrame,
27
28
  BigQueryConnection,
29
+ BigQueryUDFRegistration,
28
30
  ],
29
31
  ):
30
32
  _catalog = BigQueryCatalog
31
33
  _reader = BigQueryDataFrameReader
32
34
  _writer = BigQueryDataFrameWriter
33
35
  _df = BigQueryDataFrame
36
+ _udf_registration = BigQueryUDFRegistration
34
37
 
35
38
  QUALIFY_INFO_SCHEMA_WITH_DATABASE = True
36
39
  SANITIZE_COLUMN_NAMES = True
@@ -0,0 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from sqlframe.base.udf import _BaseUDFRegistration
6
+
7
+ if t.TYPE_CHECKING:
8
+ from sqlframe.bigquery.session import BigQuerySession
9
+
10
+
11
+ class BigQueryUDFRegistration(_BaseUDFRegistration["BigQuerySession"]): ...
@@ -11,6 +11,7 @@ from sqlframe.duckdb.readwriter import (
11
11
  DuckDBDataFrameReader,
12
12
  DuckDBDataFrameWriter,
13
13
  )
14
+ from sqlframe.duckdb.udf import DuckDBUDFRegistration
14
15
 
15
16
  if t.TYPE_CHECKING:
16
17
  from duckdb import DuckDBPyConnection
@@ -26,12 +27,14 @@ class DuckDBSession(
26
27
  DuckDBDataFrameWriter,
27
28
  DuckDBDataFrame,
28
29
  DuckDBPyConnection,
30
+ DuckDBUDFRegistration,
29
31
  ]
30
32
  ):
31
33
  _catalog = DuckDBCatalog
32
34
  _reader = DuckDBDataFrameReader
33
35
  _writer = DuckDBDataFrameWriter
34
36
  _df = DuckDBDataFrame
37
+ _udf_registration = DuckDBUDFRegistration
35
38
 
36
39
  def __init__(self, conn: t.Optional[DuckDBPyConnection] = None, *args, **kwargs):
37
40
  import duckdb
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from sqlframe.base.udf import _BaseUDFRegistration
6
+
7
+ if t.TYPE_CHECKING:
8
+ from sqlframe.base._typing import DataTypeOrString, UserDefinedFunctionLike
9
+ from sqlframe.duckdb.session import DuckDBSession
10
+
11
+
12
+ class DuckDBUDFRegistration(_BaseUDFRegistration["DuckDBSession"]):
13
+ def register( # type: ignore
14
+ self,
15
+ name: str,
16
+ f: t.Union[t.Callable[..., t.Any], UserDefinedFunctionLike],
17
+ returnType: t.Optional[DataTypeOrString] = None,
18
+ ) -> UserDefinedFunctionLike:
19
+ self.sparkSession._conn.create_function(name, f, return_type=returnType) # type: ignore
@@ -11,6 +11,7 @@ from sqlframe.postgres.readwriter import (
11
11
  PostgresDataFrameReader,
12
12
  PostgresDataFrameWriter,
13
13
  )
14
+ from sqlframe.postgres.udf import PostgresUDFRegistration
14
15
 
15
16
  if t.TYPE_CHECKING:
16
17
  from psycopg2.extensions import connection as psycopg2_connection
@@ -27,12 +28,14 @@ class PostgresSession(
27
28
  PostgresDataFrameWriter,
28
29
  PostgresDataFrame,
29
30
  psycopg2_connection,
31
+ PostgresUDFRegistration,
30
32
  ],
31
33
  ):
32
34
  _catalog = PostgresCatalog
33
35
  _reader = PostgresDataFrameReader
34
36
  _writer = PostgresDataFrameWriter
35
37
  _df = PostgresDataFrame
38
+ _udf_registration = PostgresUDFRegistration
36
39
 
37
40
  def __init__(self, conn: t.Optional[psycopg2_connection] = None):
38
41
  if not hasattr(self, "_conn"):
@@ -0,0 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from sqlframe.base.udf import _BaseUDFRegistration
6
+
7
+ if t.TYPE_CHECKING:
8
+ from sqlframe.postgres.session import PostgresSession
9
+
10
+
11
+ class PostgresUDFRegistration(_BaseUDFRegistration["PostgresSession"]): ...
@@ -10,6 +10,7 @@ from sqlframe.redshift.readwriter import (
10
10
  RedshiftDataFrameReader,
11
11
  RedshiftDataFrameWriter,
12
12
  )
13
+ from sqlframe.redshift.udf import RedshiftUDFRegistration
13
14
 
14
15
  if t.TYPE_CHECKING:
15
16
  from redshift_connector.core import Connection as RedshiftConnection
@@ -24,12 +25,14 @@ class RedshiftSession(
24
25
  RedshiftDataFrameWriter,
25
26
  RedshiftDataFrame,
26
27
  RedshiftConnection,
28
+ RedshiftUDFRegistration,
27
29
  ],
28
30
  ):
29
31
  _catalog = RedshiftCatalog
30
32
  _reader = RedshiftDataFrameReader
31
33
  _writer = RedshiftDataFrameWriter
32
34
  _df = RedshiftDataFrame
35
+ _udf_registration = RedshiftUDFRegistration
33
36
 
34
37
  def __init__(self, conn: t.Optional[RedshiftConnection] = None):
35
38
  warnings.warn(
@@ -0,0 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from sqlframe.base.udf import _BaseUDFRegistration
6
+
7
+ if t.TYPE_CHECKING:
8
+ from sqlframe.redshift.session import RedshiftSession
9
+
10
+
11
+ class RedshiftUDFRegistration(_BaseUDFRegistration["RedshiftSession"]): ...
@@ -4,6 +4,8 @@ import json
4
4
  import typing as t
5
5
  import warnings
6
6
 
7
+ from sqlframe.snowflake.udf import SnowflakeUDFRegistration
8
+
7
9
  try:
8
10
  from snowflake.connector.converter import SnowflakeConverter
9
11
  except ImportError:
@@ -50,12 +52,14 @@ class SnowflakeSession(
50
52
  SnowflakeDataFrameWriter,
51
53
  SnowflakeDataFrame,
52
54
  SnowflakeConnection,
55
+ SnowflakeUDFRegistration,
53
56
  ],
54
57
  ):
55
58
  _catalog = SnowflakeCatalog
56
59
  _reader = SnowflakeDataFrameReader
57
60
  _writer = SnowflakeDataFrameWriter
58
61
  _df = SnowflakeDataFrame
62
+ _udf_registration = SnowflakeUDFRegistration
59
63
 
60
64
  def __init__(self, conn: t.Optional[SnowflakeConnection] = None):
61
65
  import snowflake
@@ -0,0 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from sqlframe.base.udf import _BaseUDFRegistration
6
+
7
+ if t.TYPE_CHECKING:
8
+ from sqlframe.snowflake.session import SnowflakeSession
9
+
10
+
11
+ class SnowflakeUDFRegistration(_BaseUDFRegistration["SnowflakeSession"]): ...
@@ -14,6 +14,7 @@ from sqlframe.spark.readwriter import (
14
14
  SparkDataFrameWriter,
15
15
  )
16
16
  from sqlframe.spark.types import Row
17
+ from sqlframe.spark.udf import SparkUDFRegistration
17
18
 
18
19
  if t.TYPE_CHECKING:
19
20
  import pandas as pd
@@ -32,12 +33,14 @@ class SparkSession(
32
33
  SparkDataFrameWriter,
33
34
  SparkDataFrame,
34
35
  PySparkSession,
36
+ SparkUDFRegistration,
35
37
  ],
36
38
  ):
37
39
  _catalog = SparkCatalog
38
40
  _reader = SparkDataFrameReader
39
41
  _writer = SparkDataFrameWriter
40
42
  _df = SparkDataFrame
43
+ _udf_registration = SparkUDFRegistration
41
44
 
42
45
  def __init__(self, conn: t.Optional[PySparkSession] = None, *args, **kwargs):
43
46
  from pyspark.sql.session import DataFrame, SparkSession
@@ -0,0 +1,34 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from sqlframe.base.udf import _BaseUDFRegistration
6
+
7
+ if t.TYPE_CHECKING:
8
+ from sqlframe.base._typing import DataTypeOrString, UserDefinedFunctionLike
9
+ from sqlframe.spark.session import SparkSession # type: ignore
10
+
11
+
12
+ class SparkUDFRegistration(_BaseUDFRegistration["SparkSession"]):
13
+ def register(
14
+ self,
15
+ name: str,
16
+ f: t.Union[t.Callable[..., t.Any], UserDefinedFunctionLike],
17
+ returnType: t.Optional[DataTypeOrString] = None,
18
+ ) -> UserDefinedFunctionLike:
19
+ return self.sparkSession.spark_session.udf.register(name, f, returnType=returnType) # type: ignore
20
+
21
+ def registerJavaFunction(
22
+ self,
23
+ name: str,
24
+ javaClassName: str,
25
+ returnType: t.Optional[DataTypeOrString] = None,
26
+ ) -> None:
27
+ self.sparkSession.spark_session.udf.registerJavaFunction(
28
+ name,
29
+ javaClassName,
30
+ returnType=returnType, # type: ignore
31
+ )
32
+
33
+ def registerJavaUDAF(self, name: str, javaClassName: str) -> None:
34
+ self.sparkSession.spark_session.udf.registerJavaUDAF(name, javaClassName)
@@ -9,6 +9,7 @@ from sqlframe.standalone.readwriter import (
9
9
  StandaloneDataFrameReader,
10
10
  StandaloneDataFrameWriter,
11
11
  )
12
+ from sqlframe.standalone.udf import StandaloneUDFRegistration
12
13
 
13
14
 
14
15
  class StandaloneSession(
@@ -18,12 +19,14 @@ class StandaloneSession(
18
19
  StandaloneDataFrameWriter,
19
20
  StandaloneDataFrame,
20
21
  object,
22
+ StandaloneUDFRegistration,
21
23
  ]
22
24
  ): # type: ignore
23
25
  _catalog = StandaloneCatalog
24
26
  _reader = StandaloneDataFrameReader
25
27
  _writer = StandaloneDataFrameWriter
26
28
  _df = StandaloneDataFrame
29
+ _udf_registration = StandaloneUDFRegistration
27
30
 
28
31
  class Builder(_BaseSession.Builder):
29
32
  DEFAULT_INPUT_DIALECT = "spark"
@@ -0,0 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from sqlframe.base.udf import _BaseUDFRegistration
6
+
7
+ if t.TYPE_CHECKING:
8
+ from sqlframe.standalone.session import StandaloneSession
9
+
10
+
11
+ class StandaloneUDFRegistration(_BaseUDFRegistration["StandaloneSession"]): ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sqlframe
3
- Version: 2.0.0
3
+ Version: 2.1.0
4
4
  Summary: Turning PySpark Into a Universal DataFrame API
5
5
  Home-page: https://github.com/eakmanrq/sqlframe
6
6
  Author: Ryan Eakman
@@ -72,6 +72,7 @@ sqlframe/base/readerwriter.py
72
72
  sqlframe/base/session.py
73
73
  sqlframe/base/transforms.py
74
74
  sqlframe/base/types.py
75
+ sqlframe/base/udf.py
75
76
  sqlframe/base/util.py
76
77
  sqlframe/base/window.py
77
78
  sqlframe/base/mixins/__init__.py
@@ -88,6 +89,7 @@ sqlframe/bigquery/group.py
88
89
  sqlframe/bigquery/readwriter.py
89
90
  sqlframe/bigquery/session.py
90
91
  sqlframe/bigquery/types.py
92
+ sqlframe/bigquery/udf.py
91
93
  sqlframe/bigquery/window.py
92
94
  sqlframe/duckdb/__init__.py
93
95
  sqlframe/duckdb/catalog.py
@@ -99,6 +101,7 @@ sqlframe/duckdb/group.py
99
101
  sqlframe/duckdb/readwriter.py
100
102
  sqlframe/duckdb/session.py
101
103
  sqlframe/duckdb/types.py
104
+ sqlframe/duckdb/udf.py
102
105
  sqlframe/duckdb/window.py
103
106
  sqlframe/postgres/__init__.py
104
107
  sqlframe/postgres/catalog.py
@@ -110,6 +113,7 @@ sqlframe/postgres/group.py
110
113
  sqlframe/postgres/readwriter.py
111
114
  sqlframe/postgres/session.py
112
115
  sqlframe/postgres/types.py
116
+ sqlframe/postgres/udf.py
113
117
  sqlframe/postgres/window.py
114
118
  sqlframe/redshift/__init__.py
115
119
  sqlframe/redshift/catalog.py
@@ -120,6 +124,7 @@ sqlframe/redshift/group.py
120
124
  sqlframe/redshift/readwriter.py
121
125
  sqlframe/redshift/session.py
122
126
  sqlframe/redshift/types.py
127
+ sqlframe/redshift/udf.py
123
128
  sqlframe/redshift/window.py
124
129
  sqlframe/snowflake/__init__.py
125
130
  sqlframe/snowflake/catalog.py
@@ -131,6 +136,7 @@ sqlframe/snowflake/group.py
131
136
  sqlframe/snowflake/readwriter.py
132
137
  sqlframe/snowflake/session.py
133
138
  sqlframe/snowflake/types.py
139
+ sqlframe/snowflake/udf.py
134
140
  sqlframe/snowflake/window.py
135
141
  sqlframe/spark/__init__.py
136
142
  sqlframe/spark/catalog.py
@@ -142,6 +148,7 @@ sqlframe/spark/group.py
142
148
  sqlframe/spark/readwriter.py
143
149
  sqlframe/spark/session.py
144
150
  sqlframe/spark/types.py
151
+ sqlframe/spark/udf.py
145
152
  sqlframe/spark/window.py
146
153
  sqlframe/standalone/__init__.py
147
154
  sqlframe/standalone/catalog.py
@@ -152,6 +159,7 @@ sqlframe/standalone/group.py
152
159
  sqlframe/standalone/readwriter.py
153
160
  sqlframe/standalone/session.py
154
161
  sqlframe/standalone/types.py
162
+ sqlframe/standalone/udf.py
155
163
  sqlframe/standalone/window.py
156
164
  sqlframe/testing/__init__.py
157
165
  sqlframe/testing/utils.py
@@ -186,6 +194,7 @@ tests/integration/engines/duck/test_duckdb_catalog.py
186
194
  tests/integration/engines/duck/test_duckdb_dataframe.py
187
195
  tests/integration/engines/duck/test_duckdb_reader.py
188
196
  tests/integration/engines/duck/test_duckdb_session.py
197
+ tests/integration/engines/duck/test_duckdb_udf.py
189
198
  tests/integration/engines/postgres/__init__.py
190
199
  tests/integration/engines/postgres/test_postgres_catalog.py
191
200
  tests/integration/engines/postgres/test_postgres_dataframe.py
@@ -1,5 +1,5 @@
1
1
  prettytable<3.11.0
2
- sqlglot<25.9,>=24.0.0
2
+ sqlglot<25.11,>=24.0.0
3
3
  typing_extensions<5,>=4.8
4
4
 
5
5
  [bigquery]
@@ -9,7 +9,7 @@ google-cloud-bigquery[pandas]<4,>=3
9
9
  [dev]
10
10
  duckdb<1.1,>=0.9
11
11
  mypy<1.12,>=1.10.0
12
- openai<1.38,>=1.30
12
+ openai<1.41,>=1.30
13
13
  pandas-stubs<3,>=2
14
14
  pandas<3,>=2
15
15
  psycopg<4,>=3.1
@@ -39,7 +39,7 @@ duckdb<1.1,>=0.9
39
39
  pandas<3,>=2
40
40
 
41
41
  [openai]
42
- openai<1.38,>=1.30
42
+ openai<1.41,>=1.30
43
43
 
44
44
  [pandas]
45
45
  pandas<3,>=2