duckdb 1.5.0.dev37__cp314-cp314-win_amd64.whl → 1.5.0.dev94__cp314-cp314-win_amd64.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.

Potentially problematic release.


This version of duckdb might be problematic. Click here for more details.

Files changed (56) hide show
  1. _duckdb-stubs/__init__.pyi +1443 -0
  2. _duckdb-stubs/_func.pyi +46 -0
  3. _duckdb-stubs/_sqltypes.pyi +75 -0
  4. _duckdb.cp314-win_amd64.pyd +0 -0
  5. adbc_driver_duckdb/__init__.py +49 -0
  6. adbc_driver_duckdb/dbapi.py +115 -0
  7. duckdb/__init__.py +341 -435
  8. duckdb/_dbapi_type_object.py +231 -0
  9. duckdb/_version.py +22 -0
  10. duckdb/bytes_io_wrapper.py +12 -9
  11. duckdb/experimental/__init__.py +2 -1
  12. duckdb/experimental/spark/__init__.py +3 -4
  13. duckdb/experimental/spark/_globals.py +8 -8
  14. duckdb/experimental/spark/_typing.py +7 -9
  15. duckdb/experimental/spark/conf.py +16 -15
  16. duckdb/experimental/spark/context.py +60 -44
  17. duckdb/experimental/spark/errors/__init__.py +33 -35
  18. duckdb/experimental/spark/errors/error_classes.py +1 -1
  19. duckdb/experimental/spark/errors/exceptions/__init__.py +1 -1
  20. duckdb/experimental/spark/errors/exceptions/base.py +39 -88
  21. duckdb/experimental/spark/errors/utils.py +11 -16
  22. duckdb/experimental/spark/exception.py +9 -6
  23. duckdb/experimental/spark/sql/__init__.py +5 -5
  24. duckdb/experimental/spark/sql/_typing.py +8 -15
  25. duckdb/experimental/spark/sql/catalog.py +21 -20
  26. duckdb/experimental/spark/sql/column.py +48 -55
  27. duckdb/experimental/spark/sql/conf.py +9 -8
  28. duckdb/experimental/spark/sql/dataframe.py +185 -233
  29. duckdb/experimental/spark/sql/functions.py +1222 -1248
  30. duckdb/experimental/spark/sql/group.py +56 -52
  31. duckdb/experimental/spark/sql/readwriter.py +80 -94
  32. duckdb/experimental/spark/sql/session.py +64 -59
  33. duckdb/experimental/spark/sql/streaming.py +9 -10
  34. duckdb/experimental/spark/sql/type_utils.py +67 -65
  35. duckdb/experimental/spark/sql/types.py +309 -345
  36. duckdb/experimental/spark/sql/udf.py +6 -6
  37. duckdb/filesystem.py +26 -16
  38. duckdb/func/__init__.py +3 -0
  39. duckdb/functional/__init__.py +12 -16
  40. duckdb/polars_io.py +130 -83
  41. duckdb/query_graph/__main__.py +91 -96
  42. duckdb/sqltypes/__init__.py +63 -0
  43. duckdb/typing/__init__.py +18 -8
  44. duckdb/udf.py +10 -5
  45. duckdb/value/__init__.py +1 -0
  46. duckdb/value/constant/__init__.py +62 -60
  47. {duckdb-1.5.0.dev37.dist-info → duckdb-1.5.0.dev94.dist-info}/METADATA +12 -4
  48. duckdb-1.5.0.dev94.dist-info/RECORD +52 -0
  49. duckdb/__init__.pyi +0 -713
  50. duckdb/functional/__init__.pyi +0 -31
  51. duckdb/typing/__init__.pyi +0 -36
  52. duckdb/value/constant/__init__.pyi +0 -115
  53. duckdb-1.5.0.dev37.dist-info/RECORD +0 -47
  54. /duckdb/{value/__init__.pyi → py.typed} +0 -0
  55. {duckdb-1.5.0.dev37.dist-info → duckdb-1.5.0.dev94.dist-info}/WHEEL +0 -0
  56. {duckdb-1.5.0.dev37.dist-info → duckdb-1.5.0.dev94.dist-info}/licenses/LICENSE +0 -0
@@ -1,10 +1,9 @@
1
+ import argparse # noqa: D100
1
2
  import json
2
- import os
3
- import sys
4
3
  import re
5
4
  import webbrowser
6
5
  from functools import reduce
7
- import argparse
6
+ from pathlib import Path
8
7
 
9
8
  qgraph_css = """
10
9
  .styled-table {
@@ -57,7 +56,7 @@ qgraph_css = """
57
56
  text-align: center;
58
57
  padding: 0px;
59
58
  border-radius: 1px;
60
-
59
+
61
60
  /* Positioning */
62
61
  position: absolute;
63
62
  z-index: 1;
@@ -65,7 +64,7 @@ qgraph_css = """
65
64
  left: 50%;
66
65
  transform: translateX(-50%);
67
66
  margin-bottom: 8px;
68
-
67
+
69
68
  /* Tooltip Arrow */
70
69
  width: 400px;
71
70
  }
@@ -76,124 +75,128 @@ qgraph_css = """
76
75
  """
77
76
 
78
77
 
79
- class NodeTiming:
80
-
81
- def __init__(self, phase: str, time: float) -> object:
78
+ class NodeTiming: # noqa: D101
79
+ def __init__(self, phase: str, time: float) -> None: # noqa: D107
82
80
  self.phase = phase
83
81
  self.time = time
84
82
  # percentage is determined later.
85
83
  self.percentage = 0
86
84
 
87
- def calculate_percentage(self, total_time: float) -> None:
85
+ def calculate_percentage(self, total_time: float) -> None: # noqa: D102
88
86
  self.percentage = self.time / total_time
89
87
 
90
- def combine_timing(l: object, r: object) -> object:
91
- # TODO: can only add timings for same-phase nodes
92
- total_time = l.time + r.time
93
- return NodeTiming(l.phase, total_time)
88
+ def combine_timing(self, r: "NodeTiming") -> "NodeTiming": # noqa: D102
89
+ # TODO: can only add timings for same-phase nodes # noqa: TD002, TD003
90
+ total_time = self.time + r.time
91
+ return NodeTiming(self.phase, total_time)
94
92
 
95
93
 
96
- class AllTimings:
97
-
98
- def __init__(self):
94
+ class AllTimings: # noqa: D101
95
+ def __init__(self) -> None: # noqa: D107
99
96
  self.phase_to_timings = {}
100
97
 
101
- def add_node_timing(self, node_timing: NodeTiming):
98
+ def add_node_timing(self, node_timing: NodeTiming) -> None: # noqa: D102
102
99
  if node_timing.phase in self.phase_to_timings:
103
100
  self.phase_to_timings[node_timing.phase].append(node_timing)
104
- return
105
- self.phase_to_timings[node_timing.phase] = [node_timing]
101
+ else:
102
+ self.phase_to_timings[node_timing.phase] = [node_timing]
106
103
 
107
- def get_phase_timings(self, phase: str):
104
+ def get_phase_timings(self, phase: str) -> list[NodeTiming]: # noqa: D102
108
105
  return self.phase_to_timings[phase]
109
106
 
110
- def get_summary_phase_timings(self, phase: str):
107
+ def get_summary_phase_timings(self, phase: str) -> NodeTiming: # noqa: D102
111
108
  return reduce(NodeTiming.combine_timing, self.phase_to_timings[phase])
112
109
 
113
- def get_phases(self):
110
+ def get_phases(self) -> list[NodeTiming]: # noqa: D102
114
111
  phases = list(self.phase_to_timings.keys())
115
112
  phases.sort(key=lambda x: (self.get_summary_phase_timings(x)).time)
116
113
  phases.reverse()
117
114
  return phases
118
115
 
119
- def get_sum_of_all_timings(self):
116
+ def get_sum_of_all_timings(self) -> float: # noqa: D102
120
117
  total_timing_sum = 0
121
- for phase in self.phase_to_timings.keys():
118
+ for phase in self.phase_to_timings:
122
119
  total_timing_sum += self.get_summary_phase_timings(phase).time
123
120
  return total_timing_sum
124
121
 
125
122
 
126
- def open_utf8(fpath: str, flags: str) -> object:
127
- return open(fpath, flags, encoding="utf8")
123
+ def open_utf8(fpath: str, flags: str) -> object: # noqa: D103
124
+ return Path(fpath).open(mode=flags, encoding="utf8")
128
125
 
129
126
 
130
- def get_child_timings(top_node: object, query_timings: object) -> str:
131
- node_timing = NodeTiming(top_node['operator_type'], float(top_node['operator_timing']))
127
+ def get_child_timings(top_node: object, query_timings: object) -> str: # noqa: D103
128
+ node_timing = NodeTiming(top_node["operator_type"], float(top_node["operator_timing"]))
132
129
  query_timings.add_node_timing(node_timing)
133
- for child in top_node['children']:
130
+ for child in top_node["children"]:
134
131
  get_child_timings(child, query_timings)
135
132
 
136
133
 
137
- def get_pink_shade_hex(fraction: float):
134
+ def get_pink_shade_hex(fraction: float) -> str: # noqa: D103
138
135
  fraction = max(0, min(1, fraction))
139
-
136
+
140
137
  # Define the RGB values for very light pink (almost white) and dark pink
141
138
  light_pink = (255, 250, 250) # Very light pink
142
- dark_pink = (255, 20, 147) # Dark pink
143
-
139
+ dark_pink = (255, 20, 147) # Dark pink
140
+
144
141
  # Calculate the RGB values for the given fraction
145
142
  r = int(light_pink[0] + (dark_pink[0] - light_pink[0]) * fraction)
146
143
  g = int(light_pink[1] + (dark_pink[1] - light_pink[1]) * fraction)
147
144
  b = int(light_pink[2] + (dark_pink[2] - light_pink[2]) * fraction)
148
-
145
+
149
146
  # Return as hexadecimal color code
150
147
  return f"#{r:02x}{g:02x}{b:02x}"
151
148
 
152
- def get_node_body(name: str, result: str, cpu_time: float, card: int, est: int, width: int, extra_info: str) -> str:
153
- node_style = f"background-color: {get_pink_shade_hex(float(result)/cpu_time)};"
154
149
 
155
- body = f"<span class=\"tf-nc custom-tooltip\" style=\"{node_style}\">"
156
- body += "<div class=\"node-body\">"
150
+ def get_node_body(name: str, result: str, cpu_time: float, card: int, est: int, width: int, extra_info: str) -> str: # noqa: D103
151
+ node_style = f"background-color: {get_pink_shade_hex(float(result) / cpu_time)};"
152
+
153
+ body = f'<span class="tf-nc custom-tooltip" style="{node_style}">'
154
+ body += '<div class="node-body">'
157
155
  new_name = "BRIDGE" if (name == "INVALID") else name.replace("_", " ")
158
156
  formatted_num = f"{float(result):.4f}"
159
157
  body += f"<p><b>{new_name}</b> </p><p>time: {formatted_num} seconds</p>"
160
- body += f"<span class=\"tooltip-text\"> {extra_info} </span>"
161
- if (width > 0):
158
+ body += f'<span class="tooltip-text"> {extra_info} </span>'
159
+ if width > 0:
162
160
  body += f"<p>cardinality: {card}</p>"
163
161
  body += f"<p>estimate: {est}</p>"
164
162
  body += f"<p>width: {width} bytes</p>"
165
- # TODO: Expand on timing. Usually available from a detailed profiling
163
+ # TODO: Expand on timing. Usually available from a detailed profiling # noqa: TD002, TD003
166
164
  body += "</div>"
167
165
  body += "</span>"
168
166
  return body
169
167
 
170
168
 
171
- def generate_tree_recursive(json_graph: object, cpu_time: float) -> str:
169
+ def generate_tree_recursive(json_graph: object, cpu_time: float) -> str: # noqa: D103
172
170
  node_prefix_html = "<li>"
173
171
  node_suffix_html = "</li>"
174
172
 
175
173
  extra_info = ""
176
174
  estimate = 0
177
- for key in json_graph['extra_info']:
178
- value = json_graph['extra_info'][key]
179
- if (key == "Estimated Cardinality"):
175
+ for key in json_graph["extra_info"]:
176
+ value = json_graph["extra_info"][key]
177
+ if key == "Estimated Cardinality":
180
178
  estimate = int(value)
181
179
  else:
182
180
  extra_info += f"{key}: {value} <br>"
183
181
  cardinality = json_graph["operator_cardinality"]
184
- width = int(json_graph["result_set_size"]/max(1,cardinality))
182
+ width = int(json_graph["result_set_size"] / max(1, cardinality))
185
183
 
186
184
  # get rid of some typically long names
187
185
  extra_info = re.sub(r"__internal_\s*", "__", extra_info)
188
186
  extra_info = re.sub(r"compress_integral\s*", "compress", extra_info)
189
187
 
190
- node_body = get_node_body(json_graph["operator_type"],
191
- json_graph["operator_timing"],
192
- cpu_time, cardinality, estimate, width,
193
- re.sub(r",\s*", ", ", extra_info))
188
+ node_body = get_node_body(
189
+ json_graph["operator_type"],
190
+ json_graph["operator_timing"],
191
+ cpu_time,
192
+ cardinality,
193
+ estimate,
194
+ width,
195
+ re.sub(r",\s*", ", ", extra_info),
196
+ )
194
197
 
195
198
  children_html = ""
196
- if len(json_graph['children']) >= 1:
199
+ if len(json_graph["children"]) >= 1:
197
200
  children_html += "<ul>"
198
201
  for child in json_graph["children"]:
199
202
  children_html += generate_tree_recursive(child, cpu_time)
@@ -202,12 +205,12 @@ def generate_tree_recursive(json_graph: object, cpu_time: float) -> str:
202
205
 
203
206
 
204
207
  # For generating the table in the top left.
205
- def generate_timing_html(graph_json: object, query_timings: object) -> object:
208
+ def generate_timing_html(graph_json: object, query_timings: object) -> object: # noqa: D103
206
209
  json_graph = json.loads(graph_json)
207
210
  gather_timing_information(json_graph, query_timings)
208
- total_time = float(json_graph.get('operator_timing') or json_graph.get('latency'))
211
+ total_time = float(json_graph.get("operator_timing") or json_graph.get("latency"))
209
212
  table_head = """
210
- <table class=\"styled-table\">
213
+ <table class=\"styled-table\">
211
214
  <thead>
212
215
  <tr>
213
216
  <th>Phase</th>
@@ -224,7 +227,7 @@ def generate_timing_html(graph_json: object, query_timings: object) -> object:
224
227
  all_phases = query_timings.get_phases()
225
228
  query_timings.add_node_timing(NodeTiming("TOTAL TIME", total_time))
226
229
  query_timings.add_node_timing(NodeTiming("Execution Time", execution_time))
227
- all_phases = ["TOTAL TIME", "Execution Time"] + all_phases
230
+ all_phases = ["TOTAL TIME", "Execution Time", *all_phases]
228
231
  for phase in all_phases:
229
232
  summarized_phase = query_timings.get_summary_phase_timings(phase)
230
233
  summarized_phase.calculate_percentage(total_time)
@@ -240,55 +243,48 @@ def generate_timing_html(graph_json: object, query_timings: object) -> object:
240
243
  return table_head + table_body
241
244
 
242
245
 
243
- def generate_tree_html(graph_json: object) -> str:
246
+ def generate_tree_html(graph_json: object) -> str: # noqa: D103
244
247
  json_graph = json.loads(graph_json)
245
- cpu_time = float(json_graph['cpu_time'])
246
- tree_prefix = "<div class=\"tf-tree tf-gap-sm\"> \n <ul>"
248
+ cpu_time = float(json_graph["cpu_time"])
249
+ tree_prefix = '<div class="tf-tree tf-gap-sm"> \n <ul>'
247
250
  tree_suffix = "</ul> </div>"
248
251
  # first level of json is general overview
249
- # FIXME: make sure json output first level always has only 1 level
250
- tree_body = generate_tree_recursive(json_graph['children'][0], cpu_time)
252
+ # TODO: make sure json output first level always has only 1 level # noqa: TD002, TD003
253
+ tree_body = generate_tree_recursive(json_graph["children"][0], cpu_time)
251
254
  return tree_prefix + tree_body + tree_suffix
252
255
 
253
256
 
254
- def generate_ipython(json_input: str) -> str:
257
+ def generate_ipython(json_input: str) -> str: # noqa: D103
255
258
  from IPython.core.display import HTML
256
259
 
257
- html_output = generate_html(json_input, False)
260
+ html_output = generate_html(json_input, False) # noqa: F821
258
261
 
259
- return HTML(("\n"
260
- " ${CSS}\n"
261
- " ${LIBRARIES}\n"
262
- " <div class=\"chart\" id=\"query-profile\"></div>\n"
263
- " ${CHART_SCRIPT}\n"
264
- " ").replace("${CSS}", html_output['css']).replace('${CHART_SCRIPT}',
265
- html_output['chart_script']).replace(
266
- '${LIBRARIES}', html_output['libraries']))
262
+ return HTML(
263
+ ('\n ${CSS}\n ${LIBRARIES}\n <div class="chart" id="query-profile"></div>\n ${CHART_SCRIPT}\n ')
264
+ .replace("${CSS}", html_output["css"])
265
+ .replace("${CHART_SCRIPT}", html_output["chart_script"])
266
+ .replace("${LIBRARIES}", html_output["libraries"])
267
+ )
267
268
 
268
269
 
269
- def generate_style_html(graph_json: str, include_meta_info: bool) -> None:
270
- treeflex_css = "<link rel=\"stylesheet\" href=\"https://unpkg.com/treeflex/dist/css/treeflex.css\">\n"
270
+ def generate_style_html(graph_json: str, include_meta_info: bool) -> None: # noqa: D103, FBT001
271
+ treeflex_css = '<link rel="stylesheet" href="https://unpkg.com/treeflex/dist/css/treeflex.css">\n'
271
272
  css = "<style>\n"
272
273
  css += qgraph_css + "\n"
273
274
  css += "</style>\n"
274
- return {
275
- 'treeflex_css': treeflex_css,
276
- 'duckdb_css': css,
277
- 'libraries': '',
278
- 'chart_script': ''
279
- }
275
+ return {"treeflex_css": treeflex_css, "duckdb_css": css, "libraries": "", "chart_script": ""}
280
276
 
281
277
 
282
- def gather_timing_information(json: str, query_timings: object) -> None:
278
+ def gather_timing_information(json: str, query_timings: object) -> None: # noqa: D103
283
279
  # add up all of the times
284
280
  # measure each time as a percentage of the total time.
285
281
  # then you can return a list of [phase, time, percentage]
286
- get_child_timings(json['children'][0], query_timings)
282
+ get_child_timings(json["children"][0], query_timings)
287
283
 
288
284
 
289
- def translate_json_to_html(input_file: str, output_file: str) -> None:
285
+ def translate_json_to_html(input_file: str, output_file: str) -> None: # noqa: D103
290
286
  query_timings = AllTimings()
291
- with open_utf8(input_file, 'r') as f:
287
+ with open_utf8(input_file, "r") as f:
292
288
  text = f.read()
293
289
 
294
290
  html_output = generate_style_html(text, True)
@@ -317,23 +313,22 @@ def translate_json_to_html(input_file: str, output_file: str) -> None:
317
313
  </body>
318
314
  </html>
319
315
  """
320
- html = html.replace("${TREEFLEX_CSS}", html_output['treeflex_css'])
321
- html = html.replace("${DUCKDB_CSS}", html_output['duckdb_css'])
316
+ html = html.replace("${TREEFLEX_CSS}", html_output["treeflex_css"])
317
+ html = html.replace("${DUCKDB_CSS}", html_output["duckdb_css"])
322
318
  html = html.replace("${TIMING_TABLE}", timing_table)
323
- html = html.replace('${TREE}', tree_output)
319
+ html = html.replace("${TREE}", tree_output)
324
320
  f.write(html)
325
321
 
326
322
 
327
- def main() -> None:
328
- if sys.version_info[0] < 3:
329
- print("Please use python3")
330
- exit(1)
323
+ def main() -> None: # noqa: D103
331
324
  parser = argparse.ArgumentParser(
332
- prog='Query Graph Generator',
333
- description='Given a json profile output, generate a html file showing the query graph and timings of operators')
334
- parser.add_argument('profile_input', help='profile input in json')
335
- parser.add_argument('--out', required=False, default=False)
336
- parser.add_argument('--open', required=False, action='store_true', default=True)
325
+ prog="Query Graph Generator",
326
+ description="""Given a json profile output, generate a html file showing the query graph and
327
+ timings of operators""",
328
+ )
329
+ parser.add_argument("profile_input", help="profile input in json")
330
+ parser.add_argument("--out", required=False, default=False)
331
+ parser.add_argument("--open", required=False, action="store_true", default=True)
337
332
  args = parser.parse_args()
338
333
 
339
334
  input = args.profile_input
@@ -356,8 +351,8 @@ def main() -> None:
356
351
  translate_json_to_html(input, output)
357
352
 
358
353
  if open_output:
359
- webbrowser.open('file://' + os.path.abspath(output), new=2)
354
+ webbrowser.open(f"file://{Path(output).resolve()}", new=2)
360
355
 
361
356
 
362
- if __name__ == '__main__':
357
+ if __name__ == "__main__":
363
358
  main()
@@ -0,0 +1,63 @@
1
+ """DuckDB's SQL types."""
2
+
3
+ from _duckdb._sqltypes import (
4
+ BIGINT,
5
+ BIT,
6
+ BLOB,
7
+ BOOLEAN,
8
+ DATE,
9
+ DOUBLE,
10
+ FLOAT,
11
+ HUGEINT,
12
+ INTEGER,
13
+ INTERVAL,
14
+ SMALLINT,
15
+ SQLNULL,
16
+ TIME,
17
+ TIME_TZ,
18
+ TIMESTAMP,
19
+ TIMESTAMP_MS,
20
+ TIMESTAMP_NS,
21
+ TIMESTAMP_S,
22
+ TIMESTAMP_TZ,
23
+ TINYINT,
24
+ UBIGINT,
25
+ UHUGEINT,
26
+ UINTEGER,
27
+ USMALLINT,
28
+ UTINYINT,
29
+ UUID,
30
+ VARCHAR,
31
+ DuckDBPyType,
32
+ )
33
+
34
+ __all__ = [
35
+ "BIGINT",
36
+ "BIT",
37
+ "BLOB",
38
+ "BOOLEAN",
39
+ "DATE",
40
+ "DOUBLE",
41
+ "FLOAT",
42
+ "HUGEINT",
43
+ "INTEGER",
44
+ "INTERVAL",
45
+ "SMALLINT",
46
+ "SQLNULL",
47
+ "TIME",
48
+ "TIMESTAMP",
49
+ "TIMESTAMP_MS",
50
+ "TIMESTAMP_NS",
51
+ "TIMESTAMP_S",
52
+ "TIMESTAMP_TZ",
53
+ "TIME_TZ",
54
+ "TINYINT",
55
+ "UBIGINT",
56
+ "UHUGEINT",
57
+ "UINTEGER",
58
+ "USMALLINT",
59
+ "UTINYINT",
60
+ "UUID",
61
+ "VARCHAR",
62
+ "DuckDBPyType",
63
+ ]
duckdb/typing/__init__.py CHANGED
@@ -1,5 +1,8 @@
1
- from _duckdb.typing import (
2
- DuckDBPyType,
1
+ """DuckDB's SQL types. DEPRECATED. Please use `duckdb.sqltypes` instead."""
2
+
3
+ import warnings
4
+
5
+ from duckdb.sqltypes import (
3
6
  BIGINT,
4
7
  BIT,
5
8
  BLOB,
@@ -8,29 +11,29 @@ from _duckdb.typing import (
8
11
  DOUBLE,
9
12
  FLOAT,
10
13
  HUGEINT,
11
- UHUGEINT,
12
14
  INTEGER,
13
15
  INTERVAL,
14
16
  SMALLINT,
15
17
  SQLNULL,
16
18
  TIME,
19
+ TIME_TZ,
17
20
  TIMESTAMP,
18
21
  TIMESTAMP_MS,
19
22
  TIMESTAMP_NS,
20
23
  TIMESTAMP_S,
21
24
  TIMESTAMP_TZ,
22
- TIME_TZ,
23
25
  TINYINT,
24
26
  UBIGINT,
27
+ UHUGEINT,
25
28
  UINTEGER,
26
29
  USMALLINT,
27
30
  UTINYINT,
28
31
  UUID,
29
- VARCHAR
32
+ VARCHAR,
33
+ DuckDBPyType,
30
34
  )
31
35
 
32
36
  __all__ = [
33
- "DuckDBPyType",
34
37
  "BIGINT",
35
38
  "BIT",
36
39
  "BLOB",
@@ -39,7 +42,6 @@ __all__ = [
39
42
  "DOUBLE",
40
43
  "FLOAT",
41
44
  "HUGEINT",
42
- "UHUGEINT",
43
45
  "INTEGER",
44
46
  "INTERVAL",
45
47
  "SMALLINT",
@@ -53,9 +55,17 @@ __all__ = [
53
55
  "TIME_TZ",
54
56
  "TINYINT",
55
57
  "UBIGINT",
58
+ "UHUGEINT",
56
59
  "UINTEGER",
57
60
  "USMALLINT",
58
61
  "UTINYINT",
59
62
  "UUID",
60
- "VARCHAR"
63
+ "VARCHAR",
64
+ "DuckDBPyType",
61
65
  ]
66
+
67
+ warnings.warn(
68
+ "`duckdb.typing` is deprecated and will be removed in a future version. Please use `duckdb.sqltypes` instead.",
69
+ DeprecationWarning,
70
+ stacklevel=2,
71
+ )
duckdb/udf.py CHANGED
@@ -1,9 +1,15 @@
1
- def vectorized(func):
2
- """
3
- Decorate a function with annotated function parameters, so DuckDB can infer that the function should be provided with pyarrow arrays and should expect pyarrow array(s) as output
1
+ # ruff: noqa: D100
2
+ import typing
3
+
4
+
5
+ def vectorized(func: typing.Callable[..., typing.Any]) -> typing.Callable[..., typing.Any]:
6
+ """Decorate a function with annotated function parameters.
7
+
8
+ This allows DuckDB to infer that the function should be provided with pyarrow arrays and should expect
9
+ pyarrow array(s) as output.
4
10
  """
5
- from inspect import signature
6
11
  import types
12
+ from inspect import signature
7
13
 
8
14
  new_func = types.FunctionType(func.__code__, func.__globals__, func.__name__, func.__defaults__, func.__closure__)
9
15
  # Construct the annotations:
@@ -11,7 +17,6 @@ def vectorized(func):
11
17
 
12
18
  new_annotations = {}
13
19
  sig = signature(func)
14
- sig.parameters
15
20
  for param in sig.parameters:
16
21
  new_annotations[param] = pa.lib.ChunkedArray
17
22
 
duckdb/value/__init__.py CHANGED
@@ -0,0 +1 @@
1
+ # noqa: D104