sqlframe 3.22.0__py3-none-any.whl → 3.23.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.
sqlframe/_version.py CHANGED
@@ -1,8 +1,13 @@
1
- # file generated by setuptools_scm
1
+ # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
+
4
+ __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
5
+
3
6
  TYPE_CHECKING = False
4
7
  if TYPE_CHECKING:
5
- from typing import Tuple, Union
8
+ from typing import Tuple
9
+ from typing import Union
10
+
6
11
  VERSION_TUPLE = Tuple[Union[int, str], ...]
7
12
  else:
8
13
  VERSION_TUPLE = object
@@ -12,5 +17,5 @@ __version__: str
12
17
  __version_tuple__: VERSION_TUPLE
13
18
  version_tuple: VERSION_TUPLE
14
19
 
15
- __version__ = version = '3.22.0'
16
- __version_tuple__ = version_tuple = (3, 22, 0)
20
+ __version__ = version = '3.23.0'
21
+ __version_tuple__ = version_tuple = (3, 23, 0)
sqlframe/base/catalog.py CHANGED
@@ -70,13 +70,16 @@ class _BaseCatalog(t.Generic[SESSION, DF]):
70
70
  }
71
71
 
72
72
  def add_table(
73
- self, table: exp.Table | str, column_mapping: t.Optional[ColumnMapping] = None
73
+ self,
74
+ table: exp.Table | str,
75
+ column_mapping: t.Optional[ColumnMapping] = None,
76
+ **kwargs: t.Any,
74
77
  ) -> None:
75
78
  # TODO: Making this an update or add
76
79
  table = self.ensure_table(table)
77
80
  if self._schema.find(table):
78
81
  return
79
- if not column_mapping:
82
+ if column_mapping is None:
80
83
  try:
81
84
  column_mapping = {
82
85
  normalize_string(
@@ -100,7 +103,7 @@ class _BaseCatalog(t.Generic[SESSION, DF]):
100
103
  if column.this.quoted:
101
104
  self._quoted_columns[table].append(column.this.name)
102
105
 
103
- self._schema.add_table(table, column_mapping, dialect=self.session.input_dialect)
106
+ self._schema.add_table(table, column_mapping, dialect=self.session.input_dialect, **kwargs)
104
107
 
105
108
  def getDatabase(self, dbName: str) -> Database:
106
109
  """Get the database with the specified name.
@@ -856,15 +856,21 @@ def expr(str: str) -> Column:
856
856
 
857
857
  @meta(unsupported_engines=["postgres"])
858
858
  def struct(col: t.Union[ColumnOrName, t.Iterable[ColumnOrName]], *cols: ColumnOrName) -> Column:
859
- from sqlframe.base.function_alternatives import struct_with_eq
860
-
861
859
  session = _get_session()
862
-
863
- if session._is_snowflake:
864
- return struct_with_eq(col, *cols)
865
-
866
- columns = ensure_list(col) + list(cols)
867
- return Column.invoke_expression_over_column(None, expression.Struct, expressions=columns)
860
+ col_func = get_func_from_session("col")
861
+
862
+ columns = [col_func(x) for x in ensure_list(col) + list(cols)]
863
+ expressions = []
864
+ for column in columns:
865
+ expressions.append(
866
+ expression.PropertyEQ(
867
+ this=expression.parse_identifier(
868
+ column.alias_or_name, dialect=session.input_dialect
869
+ ),
870
+ expression=column.column_expression,
871
+ )
872
+ )
873
+ return Column(expression.Struct(expressions=expressions))
868
874
 
869
875
 
870
876
  @meta(unsupported_engines=["bigquery", "duckdb", "postgres", "snowflake"])
sqlframe/base/util.py CHANGED
@@ -279,15 +279,6 @@ def verify_openai_installed():
279
279
  )
280
280
 
281
281
 
282
- def verify_numpy_installed():
283
- try:
284
- import numpy # noqa
285
- except ImportError:
286
- raise ImportError(
287
- """Numpy is required for this functionality. `pip install "sqlframe[pandas]"` (also include your engine if needed) to install pandas/numpy."""
288
- )
289
-
290
-
291
282
  def quote_preserving_alias_or_name(col: t.Union[exp.Column, exp.Alias]) -> str:
292
283
  from sqlframe.base.session import _BaseSession
293
284
 
sqlframe/base/window.py CHANGED
@@ -82,37 +82,26 @@ class WindowSpec:
82
82
  def _calc_start_end(
83
83
  self, start: int, end: int
84
84
  ) -> t.Dict[str, t.Optional[t.Union[str, exp.Expression]]]:
85
- kwargs: t.Dict[str, t.Optional[t.Union[str, exp.Expression]]] = {
86
- "start_side": None,
87
- "end_side": None,
85
+ def get_value_and_side(x: int) -> t.Tuple[t.Union[str, exp.Expression], t.Optional[str]]:
86
+ if x == Window.currentRow:
87
+ return "CURRENT ROW", None
88
+ if x < 0:
89
+ side = "PRECEDING"
90
+ value = "UNBOUNDED" if x <= Window.unboundedPreceding else F.lit(abs(x)).expression
91
+ return value, side
92
+ else:
93
+ side = "FOLLOWING"
94
+ value = "UNBOUNDED" if x >= Window.unboundedFollowing else F.lit(x).expression
95
+ return value, side
96
+
97
+ start, start_side = get_value_and_side(start) # type: ignore
98
+ end, end_side = get_value_and_side(end) # type: ignore
99
+ return {
100
+ "start": start, # type: ignore
101
+ "start_side": start_side,
102
+ "end": end, # type: ignore
103
+ "end_side": end_side,
88
104
  }
89
- if start == Window.currentRow:
90
- kwargs["start"] = "CURRENT ROW"
91
- else:
92
- kwargs = {
93
- **kwargs,
94
- **{
95
- "start_side": "PRECEDING",
96
- "start": (
97
- "UNBOUNDED"
98
- if start <= Window.unboundedPreceding
99
- else F.lit(start).expression
100
- ),
101
- },
102
- }
103
- if end == Window.currentRow:
104
- kwargs["end"] = "CURRENT ROW"
105
- else:
106
- kwargs = {
107
- **kwargs,
108
- **{
109
- "end_side": "FOLLOWING",
110
- "end": (
111
- "UNBOUNDED" if end >= Window.unboundedFollowing else F.lit(end).expression
112
- ),
113
- },
114
- }
115
- return kwargs
116
105
 
117
106
  def rowsBetween(self, start: int, end: int) -> WindowSpec:
118
107
  window_spec = self.copy()
@@ -4,7 +4,7 @@ import typing as t
4
4
  from functools import cached_property
5
5
 
6
6
  from sqlframe.base.session import _BaseSession
7
- from sqlframe.base.util import soundex, verify_numpy_installed
7
+ from sqlframe.base.util import soundex
8
8
  from sqlframe.duckdb.catalog import DuckDBCatalog
9
9
  from sqlframe.duckdb.dataframe import DuckDBDataFrame
10
10
  from sqlframe.duckdb.readwriter import (
@@ -46,8 +46,6 @@ class DuckDBSession(
46
46
  if not hasattr(self, "_conn"):
47
47
  conn = conn or duckdb.connect()
48
48
  try:
49
- # Creating a function requires numpy to be installed so if they don't have it, we'll just skip it
50
- verify_numpy_installed()
51
49
  conn.create_function("SOUNDEX", lambda x: soundex(x), return_type=VARCHAR)
52
50
  except ImportError:
53
51
  pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sqlframe
3
- Version: 3.22.0
3
+ Version: 3.23.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
@@ -17,7 +17,7 @@ Requires-Python: >=3.9
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
19
  Requires-Dist: prettytable <4
20
- Requires-Dist: sqlglot <26.7,>=24.0.0
20
+ Requires-Dist: sqlglot <26.9,>=24.0.0
21
21
  Requires-Dist: typing-extensions
22
22
  Provides-Extra: bigquery
23
23
  Requires-Dist: google-cloud-bigquery-storage <3,>=2 ; extra == 'bigquery'
@@ -25,7 +25,7 @@ Requires-Dist: google-cloud-bigquery[pandas] <4,>=3 ; extra == 'bigquery'
25
25
  Provides-Extra: databricks
26
26
  Requires-Dist: databricks-sql-connector <5,>=3.6 ; extra == 'databricks'
27
27
  Provides-Extra: dev
28
- Requires-Dist: duckdb <1.2,>=0.9 ; extra == 'dev'
28
+ Requires-Dist: duckdb <1.3,>=1.2 ; extra == 'dev'
29
29
  Requires-Dist: findspark <3,>=2 ; extra == 'dev'
30
30
  Requires-Dist: mypy <1.16,>=1.10.0 ; extra == 'dev'
31
31
  Requires-Dist: openai <2,>=1.30 ; extra == 'dev'
@@ -36,7 +36,7 @@ Requires-Dist: psycopg <4,>=3.1 ; extra == 'dev'
36
36
  Requires-Dist: pyarrow <20,>=10 ; extra == 'dev'
37
37
  Requires-Dist: pyspark <3.6,>=2 ; extra == 'dev'
38
38
  Requires-Dist: pytest-forked ; extra == 'dev'
39
- Requires-Dist: pytest-postgresql <7,>=6 ; extra == 'dev'
39
+ Requires-Dist: pytest-postgresql <8,>=6 ; extra == 'dev'
40
40
  Requires-Dist: pytest-xdist <3.7,>=3.6 ; extra == 'dev'
41
41
  Requires-Dist: pytest <8.4,>=8.2.0 ; extra == 'dev'
42
42
  Requires-Dist: ruff <0.10,>=0.4.4 ; extra == 'dev'
@@ -48,7 +48,7 @@ Requires-Dist: mkdocs-material ==9.0.5 ; extra == 'docs'
48
48
  Requires-Dist: mkdocs ==1.4.2 ; extra == 'docs'
49
49
  Requires-Dist: pymdown-extensions ; extra == 'docs'
50
50
  Provides-Extra: duckdb
51
- Requires-Dist: duckdb <1.2,>=0.9 ; extra == 'duckdb'
51
+ Requires-Dist: duckdb <1.3,>=1.2 ; extra == 'duckdb'
52
52
  Requires-Dist: pandas <3,>=2 ; extra == 'duckdb'
53
53
  Provides-Extra: openai
54
54
  Requires-Dist: openai <2,>=1.30 ; extra == 'openai'
@@ -59,7 +59,7 @@ Requires-Dist: psycopg2 <3,>=2.8 ; extra == 'postgres'
59
59
  Provides-Extra: redshift
60
60
  Requires-Dist: redshift-connector <2.2.0,>=2.1.1 ; extra == 'redshift'
61
61
  Provides-Extra: snowflake
62
- Requires-Dist: snowflake-connector-python[secure-local-storage] <3.14,>=3.10.0 ; extra == 'snowflake'
62
+ Requires-Dist: snowflake-connector-python[secure-local-storage] <3.15,>=3.10.0 ; extra == 'snowflake'
63
63
  Provides-Extra: spark
64
64
  Requires-Dist: pyspark <3.6,>=2 ; extra == 'spark'
65
65
 
@@ -1,14 +1,14 @@
1
1
  sqlframe/__init__.py,sha256=wfqm98eLoLid9oV_FzzpG5loKC6LxOhj2lXpfN7SARo,3138
2
- sqlframe/_version.py,sha256=z_95mpOa--N235aXeiPpCYjkuWuYr-3uQDssTEpMtnc,413
2
+ sqlframe/_version.py,sha256=LBEtYNWSnG3GH8sBUqzbBkvKuUnJ78uz2Pmt2SqvhMY,513
3
3
  sqlframe/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  sqlframe/base/_typing.py,sha256=b2clI5HI1zEZKB_3Msx3FeAJQyft44ubUifJwQRVXyQ,1298
5
- sqlframe/base/catalog.py,sha256=SzFQalTWdhWzxUY-4ut1f9TfOECp_JmJEgNPfrRKCe0,38457
5
+ sqlframe/base/catalog.py,sha256=D39Mn4AIkUyaVyLJiI5gcX0Bv_pChl89GAyYHrtOw5g,38513
6
6
  sqlframe/base/column.py,sha256=oHVwkSWABO3ZlAbgBShsxSSlgbI06BOup5XJrRhgqJI,18097
7
7
  sqlframe/base/dataframe.py,sha256=9wcN5I5bSiGKs6m-mSCwlDUSRfrZ_ymfRUtJa8hggd4,83990
8
8
  sqlframe/base/decorators.py,sha256=ms-CvDOIW3T8IVB9VqDmLwAiaEsqXLYRXEqVQaxktiM,1890
9
9
  sqlframe/base/exceptions.py,sha256=9Uwvqn2eAkDpqm4BrRgbL61qM-GMCbJEMAW8otxO46s,370
10
10
  sqlframe/base/function_alternatives.py,sha256=KFkEm0aIHzajvQmiPZnzTLh-Ud9wjeg4lJ4Rk0vk-YU,53674
11
- sqlframe/base/functions.py,sha256=0lLefa959J1z7Ea6QBnQrru06lKCLurEX1xFYxGJbTc,223082
11
+ sqlframe/base/functions.py,sha256=gWUxngV4cgbPvKqK7_N-2rYGycRyoKJnZqPfFyqIgbE,223305
12
12
  sqlframe/base/group.py,sha256=fsyG5990_Pd7gFPjTFrH9IEoAquL_wEkVpIlBAIkZJU,4091
13
13
  sqlframe/base/normalize.py,sha256=nXAJ5CwxVf4DV0GsH-q1w0p8gmjSMlv96k_ez1eVul8,3880
14
14
  sqlframe/base/operations.py,sha256=xSPw74e59wYvNd6U1AlwziNCTG6Aftrbl4SybN9u9VE,3450
@@ -18,8 +18,8 @@ sqlframe/base/table.py,sha256=rCeh1W5SWbtEVfkLAUiexzrZwNgmZeptLEmLcM1ABkE,6961
18
18
  sqlframe/base/transforms.py,sha256=y0j3SGDz3XCmNGrvassk1S-owllUWfkHyMgZlY6SFO4,467
19
19
  sqlframe/base/types.py,sha256=iBNk9bpFtb2NBIogYS8i7OlQZMRvpR6XxqzBebsjQDU,12280
20
20
  sqlframe/base/udf.py,sha256=O6hMhBUy9NVv-mhJRtfFhXTIa_-Z8Y_FkmmuOHu0l90,1117
21
- sqlframe/base/util.py,sha256=RmeAqsZEb1zlUEvlRXJnOcDEWJC7OOYEw229s3LzpFA,15805
22
- sqlframe/base/window.py,sha256=8hOv-ignPPIsZA9FzvYzcLE9J_glalVaYjIAUdRUX3o,4943
21
+ sqlframe/base/util.py,sha256=QktpGRlkYsapQRs_uhuc3T736qRry2PNE7kcPxjYefo,15519
22
+ sqlframe/base/window.py,sha256=vmQEUa3FnaDmdce2f3xzskOJe7XsZ7JhMyOIR4RdJuY,4806
23
23
  sqlframe/base/mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  sqlframe/base/mixins/catalog_mixins.py,sha256=9tn0mK8oPoqIIjNItystD5tdBMdK9YpkxTG7G9KQl8k,18619
25
25
  sqlframe/base/mixins/dataframe_mixins.py,sha256=9U556vWjhmAwnbqkQ4mDkKHxQRs-FkncwEEY9RWmm6U,1408
@@ -59,7 +59,7 @@ sqlframe/duckdb/functions.py,sha256=ix2efGGD4HLaY1rtCtEd3IrsicGEVGiBAeKOo5OD8rA,
59
59
  sqlframe/duckdb/functions.pyi,sha256=P0ky6k-J7LdCDrQ0OjfRC3ARIYNHPmAmmaB_jBEO5L0,12383
60
60
  sqlframe/duckdb/group.py,sha256=IkhbW42Ng1U5YT3FkIdiB4zBqRkW4QyTb-1detY1e_4,383
61
61
  sqlframe/duckdb/readwriter.py,sha256=-_Ama7evadIa3PYvynKDK6RcTMTDBHpHJzfANTine7g,4983
62
- sqlframe/duckdb/session.py,sha256=Uf7im6eBbBYRvIhVGV0VCTCF76FQ00A5FbKPCdNllzw,2898
62
+ sqlframe/duckdb/session.py,sha256=H1qjMYmhpwUHmf6jOPA6IhPIEIeX8rlvOl3MTIEijG0,2719
63
63
  sqlframe/duckdb/table.py,sha256=AmEKoH2TZo98loS5NbNaTuqv0eg76SY_OckVBMmQ6Co,410
64
64
  sqlframe/duckdb/types.py,sha256=KwNyuXIo-2xVVd4bZED3YrQOobKCtemlxGrJL7DrTC8,34
65
65
  sqlframe/duckdb/udf.py,sha256=Du9LnOtT1lJvB90D4HSR2tB7MXy179jZngDR-EjVjQk,656
@@ -129,8 +129,8 @@ sqlframe/standalone/udf.py,sha256=azmgtUjHNIPs0WMVNId05SHwiYn41MKVBhKXsQJ5dmY,27
129
129
  sqlframe/standalone/window.py,sha256=6GKPzuxeSapJakBaKBeT9VpED1ACdjggDv9JRILDyV0,35
130
130
  sqlframe/testing/__init__.py,sha256=VVCosQhitU74A3NnE52O4mNtGZONapuEXcc20QmSlnQ,132
131
131
  sqlframe/testing/utils.py,sha256=PFsGZpwNUE_4-g_f43_vstTqsK0AQ2lBneb5Eb6NkFo,13008
132
- sqlframe-3.22.0.dist-info/LICENSE,sha256=VZu79YgW780qxaFJMr0t5ZgbOYEh04xWoxaWOaqIGWk,1068
133
- sqlframe-3.22.0.dist-info/METADATA,sha256=uN5N8oTC6EkNmVWzBgxkT_Ri1eIgTN3XIaC7VH3_zL4,8970
134
- sqlframe-3.22.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
135
- sqlframe-3.22.0.dist-info/top_level.txt,sha256=T0_RpoygaZSF6heeWwIDQgaP0varUdSK1pzjeJZRjM8,9
136
- sqlframe-3.22.0.dist-info/RECORD,,
132
+ sqlframe-3.23.0.dist-info/LICENSE,sha256=VZu79YgW780qxaFJMr0t5ZgbOYEh04xWoxaWOaqIGWk,1068
133
+ sqlframe-3.23.0.dist-info/METADATA,sha256=li6TMha72t0_876a0_gTA6ckfhiYptkeNrTtZL4c4M0,8970
134
+ sqlframe-3.23.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
135
+ sqlframe-3.23.0.dist-info/top_level.txt,sha256=T0_RpoygaZSF6heeWwIDQgaP0varUdSK1pzjeJZRjM8,9
136
+ sqlframe-3.23.0.dist-info/RECORD,,