interloper-sql 0.113.0__tar.gz → 0.116.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: interloper-sql
3
- Version: 0.113.0
3
+ Version: 0.116.0
4
4
  Summary: Interloper SQL integration: portable views over SQL warehouses, and a SQLAlchemy-backed destination for PostgreSQL and other SQL databases
5
5
  Author: Guillaume Onfroy
6
6
  Author-email: Guillaume Onfroy <guillaume@digitlcloud.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "interloper-sql"
3
- version = "0.113.0"
3
+ version = "0.116.0"
4
4
  description = "Interloper SQL integration: portable views over SQL warehouses, and a SQLAlchemy-backed destination for PostgreSQL and other SQL databases"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -3,7 +3,7 @@
3
3
  # ###############
4
4
  [project]
5
5
  name = "interloper-sql"
6
- version = "0.113.0"
6
+ version = "0.116.0"
7
7
  description = "Interloper SQL integration: portable views over SQL warehouses, and a SQLAlchemy-backed destination for PostgreSQL and other SQL databases"
8
8
  readme = "README.md"
9
9
  authors = [{ name = "Guillaume Onfroy", email = "guillaume@digitlcloud.com" }]
@@ -1,6 +1,6 @@
1
1
  """Interloper SQL integration: portable views, and a SQLAlchemy-backed destination behind the postgres extra."""
2
2
 
3
- from interloper_sql.view import IbisView, ibis_view, union
3
+ from interloper_sql.view import IbisView, ibis_view, latest, union
4
4
 
5
5
  try:
6
6
  from interloper_sql.connection import SQLConnection
@@ -12,6 +12,7 @@ except ModuleNotFoundError as error:
12
12
  __all__ = [
13
13
  "IbisView",
14
14
  "ibis_view",
15
+ "latest",
15
16
  "union",
16
17
  ]
17
18
  else:
@@ -20,5 +21,6 @@ else:
20
21
  "SQLConnection",
21
22
  "SQLDestination",
22
23
  "ibis_view",
24
+ "latest",
23
25
  "union",
24
26
  ]
@@ -1,7 +1,7 @@
1
1
  """Portable views: Ibis expressions over typed upstream tables, compiled per warehouse dialect."""
2
2
 
3
- from interloper_sql.view.base import IbisDefinition, IbisView, union
3
+ from interloper_sql.view.base import IbisDefinition, IbisView, latest, union
4
4
  from interloper_sql.view.decorator import ibis_view
5
5
  from interloper_sql.view.types import IBIS_DIALECTS, ibis_schema
6
6
 
7
- __all__ = ["IBIS_DIALECTS", "IbisDefinition", "IbisView", "ibis_schema", "ibis_view", "union"]
7
+ __all__ = ["IBIS_DIALECTS", "IbisDefinition", "IbisView", "ibis_schema", "ibis_view", "latest", "union"]
@@ -152,3 +152,19 @@ def union(upstreams: Sequence[Upstream], *columns: str, **stamps: Callable[[Upst
152
152
  values[name] = ibis.literal(stamped, type="int64") if is_integer else ibis.literal(stamped)
153
153
  tables.append(table.mutate(**values))
154
154
  return ibis.union(*tables, distinct=False).select(*names, *stamps)
155
+
156
+
157
+ def latest(rows: ibis.Table, key: str, *order: ibis.Expr) -> ibis.Table:
158
+ """One row per *key*, the first in *order*: the dimension pattern over candidate rows.
159
+
160
+ Args:
161
+ rows: Candidate rows, several per key.
162
+ key: The column one row is kept per value of.
163
+ *order: The sort that puts the row to keep first, such as a source
164
+ tier then the latest date.
165
+
166
+ Returns:
167
+ The kept rows, without the ranking column.
168
+ """
169
+ ranked = rows.mutate(rank=ibis.row_number().over(group_by=key, order_by=list(order)))
170
+ return ranked.filter(ranked["rank"] == 0).drop("rank")
@@ -15,7 +15,7 @@ IBIS_TYPES: dict[Any, str] = {
15
15
  float: "float64",
16
16
  bool: "boolean",
17
17
  dt.date: "date",
18
- dt.datetime: "timestamp",
18
+ dt.datetime: "timestamp('UTC')",
19
19
  Decimal: "decimal",
20
20
  bytes: "binary",
21
21
  }