duckdb 1.4.0.dev2778__cp313-cp313-win_amd64.whl → 1.5.0.dev32__cp313-cp313-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.

duckdb/__init__.py CHANGED
@@ -1,17 +1,68 @@
1
- _exported_symbols = []
2
-
3
1
  # Modules
4
2
  import duckdb.functional as functional
5
3
  import duckdb.typing as typing
6
- import functools
4
+ from _duckdb import __version__ as duckdb_version
5
+ from importlib.metadata import version
6
+
7
+ # duckdb.__version__ returns the version of the distribution package, i.e. the pypi version
8
+ __version__ = version("duckdb")
9
+
10
+ # version() is a more human friendly formatted version string of both the distribution package and the bundled duckdb
11
+ def version():
12
+ return f"{__version__} (with duckdb {duckdb_version})"
13
+
14
+ _exported_symbols = ['__version__', 'version']
7
15
 
8
16
  _exported_symbols.extend([
9
17
  "typing",
10
18
  "functional"
11
19
  ])
12
20
 
21
+ class DBAPITypeObject:
22
+ def __init__(self, types: list[typing.DuckDBPyType]) -> None:
23
+ self.types = types
24
+
25
+ def __eq__(self, other):
26
+ if isinstance(other, typing.DuckDBPyType):
27
+ return other in self.types
28
+ return False
29
+
30
+ def __repr__(self):
31
+ return f"<DBAPITypeObject [{','.join(str(x) for x in self.types)}]>"
32
+
33
+ # Define the standard DBAPI sentinels
34
+ STRING = DBAPITypeObject([typing.VARCHAR])
35
+ NUMBER = DBAPITypeObject([
36
+ typing.TINYINT,
37
+ typing.UTINYINT,
38
+ typing.SMALLINT,
39
+ typing.USMALLINT,
40
+ typing.INTEGER,
41
+ typing.UINTEGER,
42
+ typing.BIGINT,
43
+ typing.UBIGINT,
44
+ typing.HUGEINT,
45
+ typing.UHUGEINT,
46
+ typing.DuckDBPyType("BIGNUM"),
47
+ typing.DuckDBPyType("DECIMAL"),
48
+ typing.FLOAT,
49
+ typing.DOUBLE
50
+ ])
51
+ DATETIME = DBAPITypeObject([
52
+ typing.DATE,
53
+ typing.TIME,
54
+ typing.TIME_TZ,
55
+ typing.TIMESTAMP,
56
+ typing.TIMESTAMP_TZ,
57
+ typing.TIMESTAMP_NS,
58
+ typing.TIMESTAMP_MS,
59
+ typing.TIMESTAMP_S
60
+ ])
61
+ BINARY = DBAPITypeObject([typing.BLOB])
62
+ ROWID = None
63
+
13
64
  # Classes
14
- from .duckdb import (
65
+ from _duckdb import (
15
66
  DuckDBPyRelation,
16
67
  DuckDBPyConnection,
17
68
  Statement,
@@ -54,7 +105,7 @@ _exported_symbols.extend([
54
105
  'df',
55
106
  'arrow'
56
107
  ])
57
- from .duckdb import (
108
+ from _duckdb import (
58
109
  df,
59
110
  arrow
60
111
  )
@@ -64,7 +115,7 @@ from .duckdb import (
64
115
 
65
116
  # START OF CONNECTION WRAPPER
66
117
 
67
- from .duckdb import (
118
+ from _duckdb import (
68
119
  cursor,
69
120
  register_filesystem,
70
121
  unregister_filesystem,
@@ -100,8 +151,8 @@ from .duckdb import (
100
151
  fetch_df_chunk,
101
152
  pl,
102
153
  fetch_arrow_table,
103
- fetch_record_batch,
104
154
  arrow,
155
+ fetch_record_batch,
105
156
  torch,
106
157
  tf,
107
158
  begin,
@@ -180,8 +231,8 @@ _exported_symbols.extend([
180
231
  'fetch_df_chunk',
181
232
  'pl',
182
233
  'fetch_arrow_table',
183
- 'fetch_record_batch',
184
234
  'arrow',
235
+ 'fetch_record_batch',
185
236
  'torch',
186
237
  'tf',
187
238
  'begin',
@@ -227,7 +278,7 @@ _exported_symbols.extend([
227
278
  # END OF CONNECTION WRAPPER
228
279
 
229
280
  # Enums
230
- from .duckdb import (
281
+ from _duckdb import (
231
282
  ANALYZE,
232
283
  DEFAULT,
233
284
  RETURN_NULL,
@@ -244,12 +295,11 @@ _exported_symbols.extend([
244
295
 
245
296
 
246
297
  # read-only properties
247
- from .duckdb import (
298
+ from _duckdb import (
248
299
  __standard_vector_size__,
249
300
  __interactive__,
250
301
  __jupyter__,
251
302
  __formatted_python_version__,
252
- __version__,
253
303
  apilevel,
254
304
  comment,
255
305
  identifier,
@@ -267,7 +317,6 @@ _exported_symbols.extend([
267
317
  "__interactive__",
268
318
  "__jupyter__",
269
319
  "__formatted_python_version__",
270
- "__version__",
271
320
  "apilevel",
272
321
  "comment",
273
322
  "identifier",
@@ -282,7 +331,7 @@ _exported_symbols.extend([
282
331
  ])
283
332
 
284
333
 
285
- from .duckdb import (
334
+ from _duckdb import (
286
335
  connect,
287
336
  default_connection,
288
337
  set_default_connection,
@@ -295,7 +344,7 @@ _exported_symbols.extend([
295
344
  ])
296
345
 
297
346
  # Exceptions
298
- from .duckdb import (
347
+ from _duckdb import (
299
348
  Error,
300
349
  DataError,
301
350
  ConversionException,
@@ -361,7 +410,7 @@ _exported_symbols.extend([
361
410
  ])
362
411
 
363
412
  # Value
364
- from .value.constant import (
413
+ from duckdb.value.constant import (
365
414
  Value,
366
415
  NullValue,
367
416
  BooleanValue,
@@ -415,7 +415,7 @@ class DuckDBPyRelation:
415
415
  def variance(self, column: str, groups: str = ..., window_spec: str = ..., projected_columns: str = ...) -> DuckDBPyRelation: ...
416
416
  def list(self, column: str, groups: str = ..., window_spec: str = ..., projected_columns: str = ...) -> DuckDBPyRelation: ...
417
417
 
418
- def arrow(self, batch_size: int = ...) -> pyarrow.lib.Table: ...
418
+ def arrow(self, batch_size: int = ...) -> pyarrow.lib.RecordBatchReader: ...
419
419
  def __arrow_c_stream__(self, requested_schema: Optional[object] = None) -> object: ...
420
420
  def create(self, table_name: str) -> None: ...
421
421
  def create_view(self, view_name: str, replace: bool = ...) -> DuckDBPyRelation: ...
@@ -448,6 +448,7 @@ class DuckDBPyRelation:
448
448
  def pl(self, rows_per_batch: int = ..., connection: DuckDBPyConnection = ...) -> polars.DataFrame: ...
449
449
  def query(self, virtual_table_name: str, sql_query: str) -> DuckDBPyRelation: ...
450
450
  def record_batch(self, batch_size: int = ...) -> pyarrow.lib.RecordBatchReader: ...
451
+ def fetch_record_batch(self, rows_per_batch: int = 1000000, *, connection: DuckDBPyConnection = ...) -> pyarrow.lib.RecordBatchReader: ...
451
452
  def select_types(self, types: List[Union[str, DuckDBPyType]]) -> DuckDBPyRelation: ...
452
453
  def select_dtypes(self, types: List[Union[str, DuckDBPyType]]) -> DuckDBPyRelation: ...
453
454
  def set_alias(self, alias: str) -> DuckDBPyRelation: ...
@@ -75,7 +75,7 @@ class DataFrame:
75
75
  age: [[2,5]]
76
76
  name: [["Alice","Bob"]]
77
77
  """
78
- return self.relation.arrow()
78
+ return self.relation.to_arrow_table()
79
79
 
80
80
  def createOrReplaceTempView(self, name: str) -> None:
81
81
  """Creates or replaces a local temporary view with this :class:`DataFrame`.
@@ -1403,5 +1403,35 @@ class DataFrame:
1403
1403
  rows = [construct_row(x, columns) for x in result]
1404
1404
  return rows
1405
1405
 
1406
+ def cache(self) -> "DataFrame":
1407
+ """Persists the :class:`DataFrame` with the default storage level (`MEMORY_AND_DISK_DESER`).
1408
+
1409
+ .. versionadded:: 1.3.0
1410
+
1411
+ .. versionchanged:: 3.4.0
1412
+ Supports Spark Connect.
1413
+
1414
+ Notes
1415
+ -----
1416
+ The default storage level has changed to `MEMORY_AND_DISK_DESER` to match Scala in 3.0.
1417
+
1418
+ Returns
1419
+ -------
1420
+ :class:`DataFrame`
1421
+ Cached DataFrame.
1422
+
1423
+ Examples
1424
+ --------
1425
+ >>> df = spark.range(1)
1426
+ >>> df.cache()
1427
+ DataFrame[id: bigint]
1428
+
1429
+ >>> df.explain()
1430
+ == Physical Plan ==
1431
+ InMemoryTableScan ...
1432
+ """
1433
+ cached_relation = self.relation.execute()
1434
+ return DataFrame(cached_relation, self.session)
1435
+
1406
1436
 
1407
1437
  __all__ = ["DataFrame"]
@@ -1851,6 +1851,30 @@ def isnotnull(col: "ColumnOrName") -> Column:
1851
1851
  return Column(_to_column_expr(col).isnotnull())
1852
1852
 
1853
1853
 
1854
+ def equal_null(col1: "ColumnOrName", col2: "ColumnOrName") -> Column:
1855
+ """
1856
+ Returns same result as the EQUAL(=) operator for non-null operands,
1857
+ but returns true if both are null, false if one of the them is null.
1858
+ .. versionadded:: 3.5.0
1859
+ Parameters
1860
+ ----------
1861
+ col1 : :class:`~pyspark.sql.Column` or str
1862
+ col2 : :class:`~pyspark.sql.Column` or str
1863
+ Examples
1864
+ --------
1865
+ >>> df = spark.createDataFrame([(None, None,), (1, 9,)], ["a", "b"])
1866
+ >>> df.select(equal_null(df.a, df.b).alias('r')).collect()
1867
+ [Row(r=True), Row(r=False)]
1868
+ """
1869
+ if isinstance(col1, str):
1870
+ col1 = col(col1)
1871
+
1872
+ if isinstance(col2, str):
1873
+ col2 = col(col2)
1874
+
1875
+ return nvl((col1 == col2) | ((col1.isNull() & col2.isNull())), lit(False))
1876
+
1877
+
1854
1878
  def flatten(col: "ColumnOrName") -> Column:
1855
1879
  """
1856
1880
  Collection function: creates a single array from an array of arrays.
@@ -2157,6 +2181,33 @@ def e() -> Column:
2157
2181
  return lit(2.718281828459045)
2158
2182
 
2159
2183
 
2184
+ def negative(col: "ColumnOrName") -> Column:
2185
+ """
2186
+ Returns the negative value.
2187
+ .. versionadded:: 3.5.0
2188
+ Parameters
2189
+ ----------
2190
+ col : :class:`~pyspark.sql.Column` or str
2191
+ column to calculate negative value for.
2192
+ Returns
2193
+ -------
2194
+ :class:`~pyspark.sql.Column`
2195
+ negative value.
2196
+ Examples
2197
+ --------
2198
+ >>> import pyspark.sql.functions as sf
2199
+ >>> spark.range(3).select(sf.negative("id")).show()
2200
+ +------------+
2201
+ |negative(id)|
2202
+ +------------+
2203
+ | 0|
2204
+ | -1|
2205
+ | -2|
2206
+ +------------+
2207
+ """
2208
+ return abs(col) * -1
2209
+
2210
+
2160
2211
  def pi() -> Column:
2161
2212
  """Returns Pi.
2162
2213
 
@@ -3774,6 +3825,53 @@ def datepart(field: "ColumnOrName", source: "ColumnOrName") -> Column:
3774
3825
  return date_part(field, source)
3775
3826
 
3776
3827
 
3828
+ def date_diff(end: "ColumnOrName", start: "ColumnOrName") -> Column:
3829
+ """
3830
+ Returns the number of days from `start` to `end`.
3831
+
3832
+ .. versionadded:: 3.5.0
3833
+
3834
+ Parameters
3835
+ ----------
3836
+ end : :class:`~pyspark.sql.Column` or column name
3837
+ to date column to work on.
3838
+ start : :class:`~pyspark.sql.Column` or column name
3839
+ from date column to work on.
3840
+
3841
+ Returns
3842
+ -------
3843
+ :class:`~pyspark.sql.Column`
3844
+ difference in days between two dates.
3845
+
3846
+ See Also
3847
+ --------
3848
+ :meth:`pyspark.sql.functions.dateadd`
3849
+ :meth:`pyspark.sql.functions.date_add`
3850
+ :meth:`pyspark.sql.functions.date_sub`
3851
+ :meth:`pyspark.sql.functions.datediff`
3852
+ :meth:`pyspark.sql.functions.timestamp_diff`
3853
+
3854
+ Examples
3855
+ --------
3856
+ >>> import pyspark.sql.functions as sf
3857
+ >>> df = spark.createDataFrame([('2015-04-08','2015-05-10')], ['d1', 'd2'])
3858
+ >>> df.select('*', sf.date_diff(sf.col('d1').cast('DATE'), sf.col('d2').cast('DATE'))).show()
3859
+ +----------+----------+-----------------+
3860
+ | d1| d2|date_diff(d1, d2)|
3861
+ +----------+----------+-----------------+
3862
+ |2015-04-08|2015-05-10| -32|
3863
+ +----------+----------+-----------------+
3864
+
3865
+ >>> df.select('*', sf.date_diff(sf.col('d1').cast('DATE'), sf.col('d2').cast('DATE'))).show()
3866
+ +----------+----------+-----------------+
3867
+ | d1| d2|date_diff(d2, d1)|
3868
+ +----------+----------+-----------------+
3869
+ |2015-04-08|2015-05-10| 32|
3870
+ +----------+----------+-----------------+
3871
+ """
3872
+ return _invoke_function_over_columns("date_diff", lit("day"), end, start)
3873
+
3874
+
3777
3875
  def year(col: "ColumnOrName") -> Column:
3778
3876
  """
3779
3877
  Extract the year of a given date/timestamp as integer.
@@ -5685,6 +5783,31 @@ def to_timestamp_ntz(
5685
5783
  return _to_date_or_timestamp(timestamp, _types.TimestampNTZType(), format)
5686
5784
 
5687
5785
 
5786
+ def try_to_timestamp(col: "ColumnOrName", format: Optional["ColumnOrName"] = None) -> Column:
5787
+ """
5788
+ Parses the `col` with the `format` to a timestamp. The function always
5789
+ returns null on an invalid input with/without ANSI SQL mode enabled. The result data type is
5790
+ consistent with the value of configuration `spark.sql.timestampType`.
5791
+ .. versionadded:: 3.5.0
5792
+ Parameters
5793
+ ----------
5794
+ col : :class:`~pyspark.sql.Column` or str
5795
+ column values to convert.
5796
+ format: str, optional
5797
+ format to use to convert timestamp values.
5798
+ Examples
5799
+ --------
5800
+ >>> df = spark.createDataFrame([('1997-02-28 10:30:00',)], ['t'])
5801
+ >>> df.select(try_to_timestamp(df.t).alias('dt')).collect()
5802
+ [Row(dt=datetime.datetime(1997, 2, 28, 10, 30))]
5803
+ >>> df.select(try_to_timestamp(df.t, lit('yyyy-MM-dd HH:mm:ss')).alias('dt')).collect()
5804
+ [Row(dt=datetime.datetime(1997, 2, 28, 10, 30))]
5805
+ """
5806
+ if format is None:
5807
+ format = lit(['%Y-%m-%d', '%Y-%m-%d %H:%M:%S'])
5808
+
5809
+ return _invoke_function_over_columns("try_strptime", col, format)
5810
+
5688
5811
  def substr(
5689
5812
  str: "ColumnOrName", pos: "ColumnOrName", len: Optional["ColumnOrName"] = None
5690
5813
  ) -> Column:
@@ -1,4 +1,4 @@
1
- from duckdb.duckdb.functional import (
1
+ from _duckdb.functional import (
2
2
  FunctionNullHandling,
3
3
  PythonUDFType,
4
4
  SPECIAL,
@@ -1,5 +1,3 @@
1
- from .. import DuckDBPyConnection
2
-
3
1
  from typing import Dict
4
2
 
5
3
  SPECIAL: FunctionNullHandling
duckdb/polars_io.py CHANGED
@@ -58,6 +58,18 @@ def _pl_operation_to_sql(op: str) -> str:
58
58
  raise NotImplementedError(op)
59
59
 
60
60
 
61
+ def _escape_sql_identifier(identifier: str) -> str:
62
+ """
63
+ Escape SQL identifiers by doubling any double quotes and wrapping in double quotes.
64
+
65
+ Example:
66
+ >>> _escape_sql_identifier('column"name')
67
+ '"column""name"'
68
+ """
69
+ escaped = identifier.replace('"', '""')
70
+ return f'"{escaped}"'
71
+
72
+
61
73
  def _pl_tree_to_sql(tree: dict) -> str:
62
74
  """
63
75
  Recursively convert a Polars expression tree (as JSON) to a SQL string.
@@ -95,7 +107,8 @@ def _pl_tree_to_sql(tree: dict) -> str:
95
107
  )
96
108
  if node_type == "Column":
97
109
  # A reference to a column name
98
- return subtree
110
+ # Wrap in quotes to handle special characters
111
+ return _escape_sql_identifier(subtree)
99
112
 
100
113
  if node_type in ("Literal", "Dyn"):
101
114
  # Recursively process dynamic or literal values
@@ -196,7 +209,7 @@ def duckdb_source(relation: duckdb.DuckDBPyRelation, schema: pl.schema.Schema) -
196
209
  duck_predicate = None
197
210
  relation_final = relation
198
211
  if with_columns is not None:
199
- cols = ",".join(with_columns)
212
+ cols = ",".join(map(_escape_sql_identifier, with_columns))
200
213
  relation_final = relation_final.project(cols)
201
214
  if n_rows is not None:
202
215
  relation_final = relation_final.limit(n_rows)
@@ -213,7 +226,6 @@ def duckdb_source(relation: duckdb.DuckDBPyRelation, schema: pl.schema.Schema) -
213
226
  while True:
214
227
  try:
215
228
  record_batch = results.read_next_batch()
216
- df = pl.from_arrow(record_batch)
217
229
  if predicate is not None and duck_predicate is None:
218
230
  # We have a predicate, but did not manage to push it down, we fallback here
219
231
  yield pl.from_arrow(record_batch).filter(predicate)
duckdb/typing/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- from duckdb.duckdb.typing import (
1
+ from _duckdb.typing import (
2
2
  DuckDBPyType,
3
3
  BIGINT,
4
4
  BIT,
@@ -1,5 +1,4 @@
1
- from .. import DuckDBPyConnection
2
- from typing import List
1
+ from duckdb import DuckDBPyConnection
3
2
 
4
3
  SQLNULL: DuckDBPyType
5
4
  BOOLEAN: DuckDBPyType
File without changes
@@ -1,5 +1,4 @@
1
- from ... import DuckDBPyConnection
2
- from ...typing import DuckDBPyType
1
+ from duckdb.typing import DuckDBPyType
3
2
  from typing import Any
4
3
 
5
4
  class NullValue(Value):
@@ -0,0 +1,326 @@
1
+ Metadata-Version: 2.1
2
+ Name: duckdb
3
+ Version: 1.5.0.dev32
4
+ Summary: DuckDB in-process database
5
+ Keywords: DuckDB,Database,SQL,OLAP
6
+ Author: DuckDB Foundation
7
+ Maintainer: DuckDB Foundation
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Topic :: Database
12
+ Classifier: Topic :: Database :: Database Engines/Servers
13
+ Classifier: Topic :: Scientific/Engineering
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Education
16
+ Classifier: Intended Audience :: Information Technology
17
+ Classifier: Intended Audience :: Science/Research
18
+ Classifier: Programming Language :: Python
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3 :: Only
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Programming Language :: C++
27
+ Project-URL: Documentation, https://duckdb.org/docs/stable/clients/python/overview
28
+ Project-URL: Source, https://github.com/duckdb/duckdb-python
29
+ Project-URL: Issues, https://github.com/duckdb/duckdb-python/issues
30
+ Project-URL: Changelog, https://github.com/duckdb/duckdb/releases
31
+ Requires-Python: >=3.9.0
32
+ Provides-Extra: all
33
+ Requires-Dist: ipython; extra == "all"
34
+ Requires-Dist: fsspec; extra == "all"
35
+ Requires-Dist: numpy; extra == "all"
36
+ Requires-Dist: pandas; python_version < "3.14" and extra == "all"
37
+ Requires-Dist: pyarrow; python_version < "3.14" and extra == "all"
38
+ Requires-Dist: adbc_driver_manager; python_version < "3.14" and extra == "all"
39
+ Description-Content-Type: text/markdown
40
+
41
+ <div align="center">
42
+ <picture>
43
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/duckdb/duckdb/refs/heads/main/logo/DuckDB_Logo-horizontal.svg">
44
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/duckdb/duckdb/refs/heads/main/logo/DuckDB_Logo-horizontal-dark-mode.svg">
45
+ <img alt="DuckDB logo" src="https://raw.githubusercontent.com/duckdb/duckdb/refs/heads/main/logo/DuckDB_Logo-horizontal.svg" height="100">
46
+ </picture>
47
+ </div>
48
+ <br />
49
+ <p align="center">
50
+ <a href="https://discord.gg/tcvwpjfnZx"><img src="https://shields.io/discord/909674491309850675" alt="Discord" /></a>
51
+ <a href="https://pypi.org/project/duckdb/"><img src="https://img.shields.io/pypi/v/duckdb.svg" alt="PyPI Latest Release"/></a>
52
+ </p>
53
+ <br />
54
+ <p align="center">
55
+ <a href="https://duckdb.org">DuckDB.org</a>
56
+ |
57
+ <a href="https://duckdb.org/docs/stable/guides/python/install">User Guide (Python)</a>
58
+ -
59
+ <a href="https://duckdb.org/docs/stable/clients/python/overview">API Docs (Python)</a>
60
+ </p>
61
+
62
+ # DuckDB: A Fast, In-Process, Portable, Open Source, Analytical Database System
63
+
64
+ * **Simple**: DuckDB is easy to install and deploy. It has zero external dependencies and runs in-process in its host application or as a single binary.
65
+ * **Portable**: DuckDB runs on Linux, macOS, Windows, Android, iOS and all popular hardware architectures. It has idiomatic client APIs for major programming languages.
66
+ * **Feature-rich**: DuckDB offers a rich SQL dialect. It can read and write file formats such as CSV, Parquet, and JSON, to and from the local file system and remote endpoints such as S3 buckets.
67
+ * **Fast**: DuckDB runs analytical queries at blazing speed thanks to its columnar engine, which supports parallel execution and can process larger-than-memory workloads.
68
+ * **Extensible**: DuckDB is extensible by third-party features such as new data types, functions, file formats and new SQL syntax. User contributions are available as community extensions.
69
+ * **Free**: DuckDB and its core extensions are open-source under the permissive MIT License. The intellectual property of the project is held by the DuckDB Foundation.
70
+
71
+ ## Installation
72
+
73
+ Install the latest release of DuckDB directly from [PyPI](https://pypi.org/project/duckdb/):
74
+
75
+ ```bash
76
+ pip install duckdb
77
+ ```
78
+
79
+ Install with all optional dependencies:
80
+
81
+ ```bash
82
+ pip install 'duckdb[all]'
83
+ ```
84
+
85
+ ## Development
86
+
87
+ Start by <a href="https://github.com/duckdb/duckdb-python/fork"><svg height="16" viewBox="0 0 16 16" version="1.1" width="16">
88
+ <path fill-rule="evenodd" d="M5 3.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm0 2.122a2.25 2.25 0 10-1.5 0v.878A2.25 2.25 0 005.75 8.5h1.5v2.128a2.251 2.251 0 101.5 0V8.5h1.5a2.25 2.25 0 002.25-2.25v-.878a2.25 2.25 0 10-1.5 0v.878a.75.75 0 01-.75.75h-4.5A.75.75 0 015 6.25v-.878z"></path>
89
+ </svg>forking duckdb-python</a>.
90
+
91
+ ### Cloning
92
+
93
+ After forking the duckdb-python repo we recommend you clone your fork as follows:
94
+ ```shell
95
+ git clone --recurse-submodules $REPO_URL
96
+ git remote add upstream https://github.com/duckdb/duckdb-python.git
97
+ git fetch --all
98
+ ```
99
+
100
+ ... or, if you have already cloned your fork:
101
+ ```shell
102
+ git submodule update --init --recursive
103
+ git remote add upstream https://github.com/duckdb/duckdb-python.git
104
+ git fetch --all
105
+ ```
106
+
107
+ ### Submodule update hook
108
+
109
+ If you'll be switching between branches that are have the submodule set to different refs, then make your life
110
+ easier and add the git hooks in the .githooks directory to your local config:
111
+ ```shell
112
+ git config --local core.hooksPath .githooks/
113
+ ```
114
+
115
+
116
+ ### Editable installs (general)
117
+
118
+ It's good to be aware of the following when performing an editable install:
119
+ - `uv sync` or `uv run [tool]` perform an editable install by default. We have
120
+ configured the project so that scikit-build-core will use a persistent build-dir, but since the build itself
121
+ happens in an isolated, ephemeral environment, cmake's paths will point to non-existing directories. CMake itself
122
+ will be missing.
123
+ - You should install all development dependencies, and then build the project without build isolation, in two separate
124
+ steps. After this you can happily keep building and running, as long as you don't forget to pass in the
125
+ `--no-build-isolation` flag.
126
+
127
+ ```bash
128
+ # install all dev dependencies without building the project (needed once)
129
+ uv sync -p 3.11 --no-install-project
130
+ # build and install without build isolation
131
+ uv sync --no-build-isolation
132
+ ```
133
+
134
+ ### Editable installs (IDEs)
135
+
136
+ If you're using an IDE then life is a little simpler. You install build dependencies and the project in the two
137
+ steps outlined above, and from that point on you can rely on e.g. CLion's cmake capabilities to do incremental
138
+ compilation and editable rebuilds. This will skip scikit-build-core's build backend and all of uv's dependency
139
+ management, so for "real" builds you better revert to the CLI. However, this should work fine for coding and debugging.
140
+
141
+
142
+ ### Cleaning
143
+
144
+ ```shell
145
+ uv cache clean
146
+ rm -rf build .venv uv.lock
147
+ ```
148
+
149
+
150
+ ### Building wheels and sdists
151
+
152
+ To build a wheel and sdist for your system and the default Python version:
153
+ ```bash
154
+ uv build
155
+ ````
156
+
157
+ To build a wheel for a different Python version:
158
+ ```bash
159
+ # E.g. for Python 3.9
160
+ uv build -p 3.9
161
+ ```
162
+
163
+ ### Running tests
164
+
165
+ Run all pytests:
166
+ ```bash
167
+ uv run --no-build-isolation pytest ./tests --verbose
168
+ ```
169
+
170
+ Exclude the test/slow directory:
171
+ ```bash
172
+ uv run --no-build-isolation pytest ./tests --verbose --ignore=./tests/slow
173
+ ```
174
+
175
+ ### Test coverage
176
+
177
+ Run with coverage (during development you probably want to specify which tests to run):
178
+ ```bash
179
+ COVERAGE=1 uv run --no-build-isolation coverage run -m pytest ./tests --verbose
180
+ ```
181
+
182
+ The `COVERAGE` env var will compile the extension with `--coverage`, allowing us to collect coverage stats of C++
183
+ code as well as Python code.
184
+
185
+ Check coverage for Python code:
186
+ ```bash
187
+ uvx coverage html -d htmlcov-python
188
+ uvx coverage report --format=markdown
189
+ ```
190
+
191
+ Check coverage for C++ code (note: this will clutter your project dir with html files, consider saving them in some
192
+ other place):
193
+ ```bash
194
+ uvx gcovr \
195
+ --gcov-ignore-errors all \
196
+ --root "$PWD" \
197
+ --filter "${PWD}/src/duckdb_py" \
198
+ --exclude '.*/\.cache/.*' \
199
+ --gcov-exclude '.*/\.cache/.*' \
200
+ --gcov-exclude '.*/external/.*' \
201
+ --gcov-exclude '.*/site-packages/.*' \
202
+ --exclude-unreachable-branches \
203
+ --exclude-throw-branches \
204
+ --html --html-details -o coverage-cpp.html \
205
+ build/coverage/src/duckdb_py \
206
+ --print-summary
207
+ ```
208
+
209
+ ### Typechecking and linting
210
+
211
+ - We're not running any mypy typechecking tests at the moment
212
+ - We're not running any Ruff / linting / formatting at the moment
213
+
214
+ ### Cibuildwheel
215
+
216
+ You can run cibuildwheel locally for Linux. E.g. limited to Python 3.9:
217
+ ```bash
218
+ CIBW_BUILD='cp39-*' uvx cibuildwheel --platform linux .
219
+ ```
220
+
221
+ ### Code conventions
222
+
223
+ * Follow the [Google Python styleguide](https://google.github.io/styleguide/pyguide.html)
224
+ * See the section on [Comments and Docstrings](https://google.github.io/styleguide/pyguide.html#s3.8-comments-and-docstrings)
225
+
226
+ ### Tooling
227
+
228
+ This codebase is developed with the following tools:
229
+ - [Astral uv](https://docs.astral.sh/uv/) - for dependency management across all platforms we provide wheels for,
230
+ and for Python environment management. It will be hard to work on this codebase without having UV installed.
231
+ - [Scikit-build-core](https://scikit-build-core.readthedocs.io/en/latest/index.html) - the build backend for
232
+ building the extension. On the background, scikit-build-core uses cmake and ninja for compilation.
233
+ - [pybind11](https://pybind11.readthedocs.io/en/stable/index.html) - a bridge between C++ and Python.
234
+ - [CMake](https://cmake.org/) - the build system for both DuckDB itself and the DuckDB Python module.
235
+ - Cibuildwheel
236
+
237
+ ### Merging changes to pythonpkg from duckdb main
238
+
239
+ 1. Checkout main
240
+ 2Identify the merge commits that brought in tags to main:
241
+ ```bash
242
+ git log --graph --oneline --decorate main --simplify-by-decoration
243
+ ```
244
+
245
+ 3. Get the log of commits
246
+ ```bash
247
+ git log --oneline 71c5c07cdd..c9254ecff2 -- tools/pythonpkg/
248
+ ```
249
+
250
+ 4. Checkout v1.3-ossivalis
251
+ 5. Get the log of commits
252
+ ```bash
253
+ git log --oneline v1.3.0..v1.3.1 -- tools/pythonpkg/
254
+ ```
255
+ git diff --name-status 71c5c07cdd c9254ecff2 -- tools/pythonpkg/
256
+
257
+ ```bash
258
+ git log --oneline 71c5c07cdd..c9254ecff2 -- tools/pythonpkg/
259
+ git diff --name-status <HASH_A> <HASH_B> -- tools/pythonpkg/
260
+ ```
261
+
262
+
263
+ ## Versioning and Releases
264
+
265
+ The DuckDB Python package versioning and release scheme follows that of DuckDB itself. This means that a `X.Y.Z[.
266
+ postN]` release of the Python package ships the DuckDB stable release `X.Y.Z`. The optional `.postN` releases ship the same stable release of DuckDB as their predecessors plus Python package-specific fixes and / or features.
267
+
268
+ | Types | DuckDB Version | Resulting Python Extension Version |
269
+ |------------------------------------------------------------------------|----------------|------------------------------------|
270
+ | Stable release: DuckDB stable release | `1.3.1` | `1.3.1` |
271
+ | Stable post release: DuckDB stable release + Python fixes and features | `1.3.1` | `1.3.1.postX` |
272
+ | Nightly micro: DuckDB next micro nightly + Python next micro nightly | `1.3.2.devM` | `1.3.2.devN` |
273
+ | Nightly minor: DuckDB next minor nightly + Python next minor nightly | `1.4.0.devM` | `1.4.0.devN` |
274
+
275
+ Note that we do not ship nightly post releases (e.g. we don't ship `1.3.1.post2.dev3`).
276
+
277
+ ### Branch and Tag Strategy
278
+
279
+ We cut releases as follows:
280
+
281
+ | Type | Tag | How |
282
+ |----------------------|--------------|---------------------------------------------------------------------------------|
283
+ | Stable minor release | vX.Y.0 | Adding a tag on `main` |
284
+ | Stable micro release | vX.Y.Z | Adding a tag on a minor release branch (e.g. `v1.3-ossivalis`) |
285
+ | Stable post release | vX.Y.Z-postN | Adding a tag on a post release branch (e.g. `v1.3.1-post`) |
286
+ | Nightly micro | _not tagged_ | Combining HEAD of the _micro_ release branches of DuckDB and the Python package |
287
+ | Nightly minor | _not tagged_ | Combining HEAD of the _minor_ release branches of DuckDB and the Python package |
288
+
289
+ ### Release Runbooks
290
+
291
+ We cut a new **stable minor release** with the following steps:
292
+ 1. Create a PR on `main` to pin the DuckDB submodule to the tag of its current release.
293
+ 1. Iff all tests pass in CI, merge the PR.
294
+ 1. Manually start the release workflow with the hash of this commit, and the tag name.
295
+ 1. Iff all goes well, create a new PR to let the submodule track DuckDB main.
296
+
297
+ We cut a new **stable micro release** with the following steps:
298
+ 1. Create a PR on the minor release branch to pin the DuckDB submodule to the tag of its current release.
299
+ 1. Iff all tests pass in CI, merge the PR.
300
+ 1. Manually start the release workflow with the hash of this commit, and the tag name.
301
+ 1. Iff all goes well, create a new PR to let the submodule track DuckDB's minor release branch.
302
+
303
+ We cut a new **stable post release** with the following steps:
304
+ 1. Create a PR on the post release branch to pin the DuckDB submodule to the tag of its current release.
305
+ 1. Iff all tests pass in CI, merge the PR.
306
+ 1. Manually start the release workflow with the hash of this commit, and the tag name.
307
+ 1. Iff all goes well, create a new PR to let the submodule track DuckDB's minor release branch.
308
+
309
+ ### Dynamic Versioning Integration
310
+
311
+ The package uses `setuptools_scm` with `scikit-build` for automatic version determination, and implements a custom
312
+ versioning scheme.
313
+
314
+ - **pyproject.toml configuration**:
315
+ ```toml
316
+ [tool.scikit-build]
317
+ metadata.version.provider = "scikit_build_core.metadata.setuptools_scm"
318
+
319
+ [tool.setuptools_scm]
320
+ version_scheme = "duckdb_packaging._setuptools_scm_version:version_scheme"
321
+ ```
322
+
323
+ - **Environment variables**:
324
+ - `MAIN_BRANCH_VERSIONING=0`: Use release branch versioning (patch increments)
325
+ - `MAIN_BRANCH_VERSIONING=1`: Use main branch versioning (minor increments)
326
+ - `OVERRIDE_GIT_DESCRIBE`: Override version detection
@@ -1,31 +1,27 @@
1
- adbc_driver_duckdb/__init__.py,sha256=hHAwFLPujXrsm024U7AVua8bftOC4yNgc2GGdkXNrLI,1674
2
- adbc_driver_duckdb/dbapi.py,sha256=NaanPiS8P8AE_sjd9vhKKSaIG3aTB2MWo_sTNHQVbjM,3578
3
- duckdb/__init__.py,sha256=VL8M090Sri9GBu42CNahkBWM27Sw9bcnVrTrKmSRJsU,7755
1
+ _duckdb.cp313-win_amd64.pyd,sha256=dGDxOxPS_ucL8_FlbqQYJE2iPuwRog46rxfFn6lePlo,35433984
2
+ duckdb/__init__.py,sha256=GmG-Z_dhIy3P8e-AuGz0-rkduKa6SqMqsIot7MMJ1CA,9240
3
+ duckdb/__init__.pyi,sha256=_WQXdLMIiVjpJqSdHGm4a4-EjpzOPU5Mcc0AJEh3G6I,48357
4
4
  duckdb/bytes_io_wrapper.py,sha256=o5WcKIHA6EoZTsssRNeoohLeGtCPKY-8yQw-iP1k0SY,3050
5
- duckdb/duckdb.cp313-win_amd64.pyd,sha256=8rZS9U0r1cTepL4YQxTFSih-dk06JM58ZfZsFymBVEc,35154944
6
- duckdb/filesystem.py,sha256=WMVzCQ2gbe9T60hMw7aAajVqUOHRJvG0XvfgMkKi6hg,1019
7
- duckdb/polars_io.py,sha256=zFDL_JvFHXje3PCoR55xQWZPQibXkeoVBNSJC5PMtNE,7834
8
- duckdb/udf.py,sha256=-Y1DTF3uZgvufqO7ihvWXbFqWHu8LSME48NLyOeQKEk,693
9
5
  duckdb/experimental/__init__.py,sha256=JTAdXBrgCCenIGe3vzm7a3BuE1jOmgd9yMHG1ZEFSQA,46
10
- duckdb/experimental/spark/LICENSE,sha256=vCGc3GQQzJKXFfRiLOJCSviQBJsHHzTWjewZVVVL8zI,13646
11
6
  duckdb/experimental/spark/__init__.py,sha256=BKd5s6LUBabQjxliNhs4lAZx48a81Ch5E2NHS-udU3A,291
12
7
  duckdb/experimental/spark/_globals.py,sha256=cYR8qr7E5fMAp7vsM8CjpwoLI4-_tnuhRS4qf7b0Vr8,2511
13
8
  duckdb/experimental/spark/_typing.py,sha256=D4Q7AvSyVgNxnmJc3nYKgt3S7cgoRbf-YWo-8Mu54jI,1573
14
9
  duckdb/experimental/spark/conf.py,sha256=N3PqcMyyNlgJQdjLKTVA_UH_isp7657tcvurp9CU0DE,1443
15
10
  duckdb/experimental/spark/context.py,sha256=_1A8A7mlF1QSdeQ0XjPv2ImhN4ajziW7lxo2L4Ul3Ao,6373
16
- duckdb/experimental/spark/exception.py,sha256=r3hWeu2EZ9ri0PAyTw38aD7G5qKVsOi8YgtgXMiGfts,550
17
11
  duckdb/experimental/spark/errors/__init__.py,sha256=JikuqdfaCy_Nti4A_yXYk-z1m5sXab83rovIXjKfoH4,2218
18
12
  duckdb/experimental/spark/errors/error_classes.py,sha256=5xPdevsInQCcA8NI7Hytzh1mrmX5WvHxe4jUKzocwUc,28167
19
- duckdb/experimental/spark/errors/utils.py,sha256=EnzRDKIciMDORkbZKWrn5KJuZkKtBSCpX9ok7qmRfEo,4554
20
13
  duckdb/experimental/spark/errors/exceptions/__init__.py,sha256=skcDKqKaQuFEltWKiUwvSpw1Kzelup5daCFKByxT-Gk,800
21
14
  duckdb/experimental/spark/errors/exceptions/base.py,sha256=p3Pp5GQIWLBK-ApWWGOCQJ1YA0LgWgZ9_N94O08Rj-U,5577
15
+ duckdb/experimental/spark/errors/utils.py,sha256=EnzRDKIciMDORkbZKWrn5KJuZkKtBSCpX9ok7qmRfEo,4554
16
+ duckdb/experimental/spark/exception.py,sha256=r3hWeu2EZ9ri0PAyTw38aD7G5qKVsOi8YgtgXMiGfts,550
17
+ duckdb/experimental/spark/LICENSE,sha256=vCGc3GQQzJKXFfRiLOJCSviQBJsHHzTWjewZVVVL8zI,13646
22
18
  duckdb/experimental/spark/sql/__init__.py,sha256=e_-3pLvS6PteoCxxCRgQHD_Mpd0JBXpbiNXTU47yjQ4,263
23
19
  duckdb/experimental/spark/sql/_typing.py,sha256=FyJ1vvx5et2yH_YatPaLtI4Z40BK7Xwdtvw-GV13bTw,2454
24
20
  duckdb/experimental/spark/sql/catalog.py,sha256=_8bruV2yeUk0HRhnY9lsyGRyXPLW1gtODU3V4UfIYJI,2362
25
21
  duckdb/experimental/spark/sql/column.py,sha256=SJZWSZZTohHw7wTrS9DjpuzmPtid5Cee78I0o3Vi5hY,11076
26
22
  duckdb/experimental/spark/sql/conf.py,sha256=eB1W0-wUa_fNJ0AAFMNxIGmhqr9a0IhPyr9Xesy-pes,679
27
- duckdb/experimental/spark/sql/dataframe.py,sha256=lWONADE-fWfLVuHsndF2vBbjwtG7qC0QyJTssZZxMGE,47017
28
- duckdb/experimental/spark/sql/functions.py,sha256=kImXKi_Jf3bsyeoqdGgkljPNIGLLllUIIFjwMtOA-aI,175126
23
+ duckdb/experimental/spark/sql/dataframe.py,sha256=BBeacpAuo9cjvVjC1qAsEJk5rddasuy9mIyffvGzQqM,47835
24
+ duckdb/experimental/spark/sql/functions.py,sha256=V_oFdX9eG-ZC9-y_1wqwYRZlge4ZmVBqxJE_BWzSU_Q,179329
29
25
  duckdb/experimental/spark/sql/group.py,sha256=DLX16aSVFMV6xRvVJ1KCh7um09qTYJb3jQv_FQtTvy4,13695
30
26
  duckdb/experimental/spark/sql/readwriter.py,sha256=ie5ENJX9Mxy6eBP9oNS-t5KMEQ3pfHfPvEdXDrVWGt0,17750
31
27
  duckdb/experimental/spark/sql/session.py,sha256=XxzgYp78ZrDHyUcH42buJmODQo21-61YWF5hI3fRwsU,9290
@@ -33,16 +29,19 @@ duckdb/experimental/spark/sql/streaming.py,sha256=B0TyLDqG79fLU6Fz7x6TxmcoY5_o0b
33
29
  duckdb/experimental/spark/sql/type_utils.py,sha256=ks6YA2-4JUOHv3xrN3O6nT0d76CKVVxS0qNSS028uBE,3059
34
30
  duckdb/experimental/spark/sql/types.py,sha256=Qqx9R65HA-WUT9MlGzy9b25RqfVdn_BW_ms6_DNRBmA,40434
35
31
  duckdb/experimental/spark/sql/udf.py,sha256=hwWIvO0o3ipCGtmx9aUtpyC10PQ3NyQL102QB3Q1VqU,1118
36
- duckdb/functional/__init__.py,sha256=at68LoHNhVX5kSKjEIdbz-joKO0ELUszIvwp95cqZ7A,235
32
+ duckdb/filesystem.py,sha256=WMVzCQ2gbe9T60hMw7aAajVqUOHRJvG0XvfgMkKi6hg,1019
33
+ duckdb/functional/__init__.py,sha256=d8qY_IjItw-81ZWXnE_cLmgmEeHzRcmwaEPqHKf_ej8,229
34
+ duckdb/functional/__init__.pyi,sha256=02Yn2rP7YVGnJmCZsXnuvteurPc60qgfy0JEyTi5DNA,805
35
+ duckdb/polars_io.py,sha256=0ezW1ZiII_A3N4GjJDDieCKb6uE4swZXFMxVUgEOmPQ,8221
37
36
  duckdb/query_graph/__main__.py,sha256=BWDGf2LKiSXHhQWbIuvc-IXTjE_DqYISGvmtSBBYcx0,11622
38
- duckdb/typing/__init__.py,sha256=OkjQrgmqY046kGMf2IdcSXawL9GjjY8acNNxpbq41Fc,921
39
- duckdb/value/constant.py,sha256=cbTGO63hXI7tkoa6Sjw2S_PJYV6IAC8R88n2yVzPuNo,5784
40
- duckdb-stubs/__init__.pyi,sha256=tI-c3i6ewqv8DeS1wzjdrtmkWyoKIN3FqtIYbw9H51U,48201
41
- duckdb-stubs/functional/__init__.pyi,sha256=xJ3b7MdZpnU3NiCpN8WYudu4pHRE7YUPYTcc2TSR9hg,842
42
- duckdb-stubs/typing/__init__.pyi,sha256=VHseLxfiq-RrlX881MGW1NYV3TsG2q0VmDGtbSx-8og,984
43
- duckdb-stubs/value/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
- duckdb-stubs/value/constant/__init__.pyi,sha256=ITxzXcoDUMwTpgblD6TP5njqnsa2GYfPrVD2e4qhBvQ,3426
45
- duckdb-1.4.0.dev2778.dist-info/METADATA,sha256=A8ZjlpT07rdkahOYl4ftu7JVUdyvkmPBSDrJ06u2WPg,2055
46
- duckdb-1.4.0.dev2778.dist-info/WHEEL,sha256=qV0EIPljj1XC_vuSatRWjn02nZIz3N1t8jsZz7HBr2U,101
47
- duckdb-1.4.0.dev2778.dist-info/top_level.txt,sha256=PJ5o847brKVXDprOLYKxfLtb6iH7NVZtotg7NxIkG-4,39
48
- duckdb-1.4.0.dev2778.dist-info/RECORD,,
37
+ duckdb/typing/__init__.py,sha256=Z5Bd4OzV8NWzrzeo06evSDTbwcknZBAgzCapxgaKEWM,915
38
+ duckdb/typing/__init__.pyi,sha256=sshKVD1s7TqWGCZvVKMVmZe64SsRUZHIt8f5gZ_CPxA,963
39
+ duckdb/udf.py,sha256=-Y1DTF3uZgvufqO7ihvWXbFqWHu8LSME48NLyOeQKEk,693
40
+ duckdb/value/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
+ duckdb/value/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
+ duckdb/value/constant/__init__.py,sha256=cbTGO63hXI7tkoa6Sjw2S_PJYV6IAC8R88n2yVzPuNo,5784
43
+ duckdb/value/constant/__init__.pyi,sha256=Q51_wc2jVyBE7tzeH5X49e6XCs4JJD8a9asX-nqw4ow,3394
44
+ duckdb-1.5.0.dev32.dist-info/METADATA,sha256=h9fDfFkEprPBwtXrSmgIuJ6rGhXZ53A7emTUYakVyE0,14185
45
+ duckdb-1.5.0.dev32.dist-info/WHEEL,sha256=vkL3wTIkhjZa3RmEXX20hldNp6Q8qtwRjrXW6K5sw_Q,106
46
+ duckdb-1.5.0.dev32.dist-info/licenses/LICENSE,sha256=QACFao8AflP8UxUFM9ZEvK78ZLdGHkPBTMudPWalnNI,1079
47
+ duckdb-1.5.0.dev32.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: scikit-build-core 0.11.6
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp313-cp313-win_amd64
5
5
 
@@ -0,0 +1,7 @@
1
+ Copyright 2018-2025 Stichting DuckDB Foundation
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,47 +0,0 @@
1
- # Licensed to the Apache Software Foundation (ASF) under one
2
- # or more contributor license agreements. See the NOTICE file
3
- # distributed with this work for additional information
4
- # regarding copyright ownership. The ASF licenses this file
5
- # to you under the Apache License, Version 2.0 (the
6
- # "License"); you may not use this file except in compliance
7
- # with the License. You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing,
12
- # software distributed under the License is distributed on an
13
- # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
- # KIND, either express or implied. See the License for the
15
- # specific language governing permissions and limitations
16
- # under the License.
17
-
18
- """Low-level ADBC bindings for the DuckDB driver."""
19
-
20
- import enum
21
- import functools
22
- import typing
23
-
24
- import adbc_driver_manager
25
-
26
- __all__ = ["StatementOptions", "connect"]
27
-
28
-
29
- class StatementOptions(enum.Enum):
30
- """Statement options specific to the DuckDB driver."""
31
-
32
- #: The number of rows per batch. Defaults to 2048.
33
- BATCH_ROWS = "adbc.duckdb.query.batch_rows"
34
-
35
-
36
- def connect(path: typing.Optional[str] = None) -> adbc_driver_manager.AdbcDatabase:
37
- """Create a low level ADBC connection to DuckDB."""
38
- if path is None:
39
- return adbc_driver_manager.AdbcDatabase(driver=_driver_path(), entrypoint="duckdb_adbc_init")
40
- return adbc_driver_manager.AdbcDatabase(driver=_driver_path(), entrypoint="duckdb_adbc_init", path=path)
41
-
42
-
43
- @functools.cache
44
- def _driver_path() -> str:
45
- import duckdb
46
-
47
- return duckdb.duckdb.__file__
@@ -1,116 +0,0 @@
1
- # Licensed to the Apache Software Foundation (ASF) under one
2
- # or more contributor license agreements. See the NOTICE file
3
- # distributed with this work for additional information
4
- # regarding copyright ownership. The ASF licenses this file
5
- # to you under the Apache License, Version 2.0 (the
6
- # "License"); you may not use this file except in compliance
7
- # with the License. You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing,
12
- # software distributed under the License is distributed on an
13
- # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
- # KIND, either express or implied. See the License for the
15
- # specific language governing permissions and limitations
16
- # under the License.
17
-
18
- """
19
- DBAPI 2.0-compatible facade for the ADBC DuckDB driver.
20
- """
21
-
22
- import typing
23
-
24
- import adbc_driver_manager
25
- import adbc_driver_manager.dbapi
26
- import adbc_driver_duckdb
27
-
28
- __all__ = [
29
- "BINARY",
30
- "DATETIME",
31
- "NUMBER",
32
- "ROWID",
33
- "STRING",
34
- "Connection",
35
- "Cursor",
36
- "DataError",
37
- "DatabaseError",
38
- "Date",
39
- "DateFromTicks",
40
- "Error",
41
- "IntegrityError",
42
- "InterfaceError",
43
- "InternalError",
44
- "NotSupportedError",
45
- "OperationalError",
46
- "ProgrammingError",
47
- "Time",
48
- "TimeFromTicks",
49
- "Timestamp",
50
- "TimestampFromTicks",
51
- "Warning",
52
- "apilevel",
53
- "connect",
54
- "paramstyle",
55
- "threadsafety",
56
- ]
57
-
58
- # ----------------------------------------------------------
59
- # Globals
60
-
61
- apilevel = adbc_driver_manager.dbapi.apilevel
62
- threadsafety = adbc_driver_manager.dbapi.threadsafety
63
- paramstyle = "qmark"
64
-
65
- Warning = adbc_driver_manager.dbapi.Warning
66
- Error = adbc_driver_manager.dbapi.Error
67
- InterfaceError = adbc_driver_manager.dbapi.InterfaceError
68
- DatabaseError = adbc_driver_manager.dbapi.DatabaseError
69
- DataError = adbc_driver_manager.dbapi.DataError
70
- OperationalError = adbc_driver_manager.dbapi.OperationalError
71
- IntegrityError = adbc_driver_manager.dbapi.IntegrityError
72
- InternalError = adbc_driver_manager.dbapi.InternalError
73
- ProgrammingError = adbc_driver_manager.dbapi.ProgrammingError
74
- NotSupportedError = adbc_driver_manager.dbapi.NotSupportedError
75
-
76
- # ----------------------------------------------------------
77
- # Types
78
-
79
- Date = adbc_driver_manager.dbapi.Date
80
- Time = adbc_driver_manager.dbapi.Time
81
- Timestamp = adbc_driver_manager.dbapi.Timestamp
82
- DateFromTicks = adbc_driver_manager.dbapi.DateFromTicks
83
- TimeFromTicks = adbc_driver_manager.dbapi.TimeFromTicks
84
- TimestampFromTicks = adbc_driver_manager.dbapi.TimestampFromTicks
85
- STRING = adbc_driver_manager.dbapi.STRING
86
- BINARY = adbc_driver_manager.dbapi.BINARY
87
- NUMBER = adbc_driver_manager.dbapi.NUMBER
88
- DATETIME = adbc_driver_manager.dbapi.DATETIME
89
- ROWID = adbc_driver_manager.dbapi.ROWID
90
-
91
- # ----------------------------------------------------------
92
- # Functions
93
-
94
-
95
- def connect(path: typing.Optional[str] = None, **kwargs) -> "Connection":
96
- """Connect to DuckDB via ADBC."""
97
- db = None
98
- conn = None
99
-
100
- try:
101
- db = adbc_driver_duckdb.connect(path)
102
- conn = adbc_driver_manager.AdbcConnection(db)
103
- return adbc_driver_manager.dbapi.Connection(db, conn, **kwargs)
104
- except Exception:
105
- if conn:
106
- conn.close()
107
- if db:
108
- db.close()
109
- raise
110
-
111
-
112
- # ----------------------------------------------------------
113
- # Classes
114
-
115
- Connection = adbc_driver_manager.dbapi.Connection
116
- Cursor = adbc_driver_manager.dbapi.Cursor
@@ -1,47 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: duckdb
3
- Version: 1.4.0.dev2778
4
- Summary: DuckDB in-process database
5
- Author-email: Hannes Muehleisen <hannes@cwi.nl>
6
- Project-URL: Documentation, https://duckdb.org/docs/stable/clients/python/overview
7
- Project-URL: Source, https://github.com/duckdb/duckdb/blob/main/tools/pythonpkg
8
- Project-URL: Issues, https://github.com/duckdb/duckdb/issues
9
- Project-URL: Changelog, https://github.com/duckdb/duckdb/releases
10
- Keywords: DuckDB,Database,SQL,OLAP
11
- Classifier: Topic :: Database :: Database Engines/Servers
12
- Classifier: Intended Audience :: Developers
13
- Classifier: License :: OSI Approved :: MIT License
14
- Requires-Python: >=3.7.0
15
- Description-Content-Type: text/markdown
16
- Provides-Extra: dev
17
- Requires-Dist: numpy>=1.14; extra == "dev"
18
- Requires-Dist: pybind11[global]>=2.9.0; extra == "dev"
19
- Requires-Dist: pytest; extra == "dev"
20
- Requires-Dist: pytest-reraise; extra == "dev"
21
- Requires-Dist: pytest-timeout; extra == "dev"
22
- Requires-Dist: pandas; extra == "dev"
23
- Requires-Dist: mypy<=1.13; extra == "dev"
24
-
25
- # DuckDB Python package
26
-
27
- ## Where to get it
28
-
29
- You can install the latest release of DuckDB directly from [PyPi](https://pypi.org/project/duckdb/):
30
-
31
- ```bash
32
- pip install duckdb
33
- ```
34
-
35
- ## Documentation
36
-
37
- [DuckDB.org](https://duckdb.org) is a great resource for documentation:
38
- * We recommend the [Python user guide](https://duckdb.org/docs/stable/guides/python/install) to get started.
39
- * And make sure to check out [the latest API documentation](https://duckdb.org/docs/stable/clients/python/overview).
40
-
41
- ## Getting Help
42
-
43
- See the [DuckDB Community Support Policy](https://duckdblabs.com/community_support_policy/). DuckDB Labs also provides [custom support](https://duckdblabs.com/#support).
44
-
45
- ## Source Code
46
-
47
- The Python package is part of the duckdb source tree. If you want to make changes and / or build the package from source, see the [development documentation](https://duckdb.org/docs/stable/dev/building/python) for build instructions, IDE integration, debugging, and other relevant information.
@@ -1,3 +0,0 @@
1
- adbc_driver_duckdb
2
- duckdb
3
- duckdb-stubs
File without changes