Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
5dceb64
Bump submodule
duckdblabs-bot Dec 16, 2025
56ed765
[duckdb-labs bot] Bump DuckDB submodule (#228)
evertlammerts Dec 16, 2025
7aa8cae
Bump submodule
duckdblabs-bot Dec 17, 2025
7faa30d
[duckdb-labs bot] Bump DuckDB submodule (#230)
evertlammerts Dec 17, 2025
89b12d4
Bump submodule
duckdblabs-bot Dec 18, 2025
4ef5288
[duckdb-labs bot] Bump DuckDB submodule (#231)
evertlammerts Dec 18, 2025
d1743d8
Bump submodule
duckdblabs-bot Dec 19, 2025
f446e01
[duckdb-labs bot] Bump DuckDB submodule (#232)
evertlammerts Dec 19, 2025
8aa268a
Bump submodule
duckdblabs-bot Dec 21, 2025
bd5ed7a
[duckdb-labs bot] Bump DuckDB submodule (#233)
evertlammerts Dec 21, 2025
1567cc3
Bump submodule
duckdblabs-bot Dec 23, 2025
1b1183e
[duckdb-labs bot] Bump DuckDB submodule (#235)
evertlammerts Dec 23, 2025
6866a36
Bump submodule
duckdblabs-bot Dec 25, 2025
cca6ba9
[duckdb-labs bot] Bump DuckDB submodule (#236)
evertlammerts Dec 25, 2025
2951073
Bump submodule
duckdblabs-bot Jan 1, 2026
ccf35c8
[duckdb-labs bot] Bump DuckDB submodule (#241)
evertlammerts Jan 1, 2026
20d4328
Bump submodule
duckdblabs-bot Jan 5, 2026
c1d9eab
[duckdb-labs bot] Bump DuckDB submodule (#244)
evertlammerts Jan 5, 2026
29e1a06
Bump submodule
duckdblabs-bot Jan 6, 2026
2061e76
[duckdb-labs bot] Bump DuckDB submodule (#251)
evertlammerts Jan 6, 2026
dc1aa44
Bump submodule
duckdblabs-bot Jan 7, 2026
283330f
[duckdb-labs bot] Bump DuckDB submodule (#253)
evertlammerts Jan 7, 2026
cad0cd2
Bump submodule
duckdblabs-bot Jan 8, 2026
1f61b20
[duckdb-labs bot] Bump DuckDB submodule (#255)
evertlammerts Jan 8, 2026
8540a89
Bump submodule
duckdblabs-bot Jan 11, 2026
4626f32
[duckdb-labs bot] Bump DuckDB submodule (#258)
evertlammerts Jan 11, 2026
c2e7da2
Bump submodule
duckdblabs-bot Jan 13, 2026
2fbcd17
[duckdb-labs bot] Bump DuckDB submodule (#264)
evertlammerts Jan 13, 2026
75fdbd3
escape idenitifiers in relation aggregations
evertlammerts Jan 14, 2026
2cb7abe
Escape identifiers in relation aggregations (#272)
evertlammerts Jan 15, 2026
eeac44a
Bump submodule
duckdblabs-bot Jan 16, 2026
3ca4738
[duckdb-labs bot] Bump DuckDB submodule (#273)
evertlammerts Jan 16, 2026
39c384b
Fix DECREF bug during interpreter shutdown
evertlammerts Jan 21, 2026
e32ed3e
Fix DECREF bug during interpreter shutdown (#275)
evertlammerts Jan 21, 2026
c2e6505
Support Pandas' new str type
evertlammerts Jan 22, 2026
9d6edb6
dependency updates and fix for lazy attribute accessors
evertlammerts Jan 23, 2026
5a654d3
pandas default backend fixes
evertlammerts Jan 23, 2026
0576a1c
bump submodule
evertlammerts Jan 23, 2026
5d9b64e
Add timedelta[s|ms|us|ns] numpy types
evertlammerts Jan 23, 2026
8361d73
Move slow tests to slow and fix test error when pyarrow is missing
evertlammerts Jan 23, 2026
f1711b5
Support for Pandas 3.0.0 (#277)
evertlammerts Jan 23, 2026
77a3f8d
Set submodule to release hash
evertlammerts Jan 23, 2026
c5e764a
Fix logical type creation
evertlammerts Jan 26, 2026
ae1fc0b
Bump submodule to pull in fixes
evertlammerts Jan 26, 2026
fcdc93b
Missing import
evertlammerts Jan 26, 2026
9861312
Merge remote-tracking branch 'origin/v1.4-andium' into v1.5-variegata
evertlammerts Jan 26, 2026
ab2d2a3
check conversion errors in time
evertlammerts Jan 26, 2026
7e5a18c
Fix transaction errors and more
evertlammerts Jan 26, 2026
f4a82b6
bump submodule
evertlammerts Jan 26, 2026
bbb418b
Fix last failing tests and remove support for Python 3.9
evertlammerts Jan 27, 2026
05989c4
bump python version for code quality workflow
evertlammerts Jan 27, 2026
1acece4
auto fixes
evertlammerts Jan 27, 2026
23d3cf9
Bump submodule
evertlammerts Jan 27, 2026
f150134
auto fixes
evertlammerts Jan 27, 2026
2214a6c
Merge branch 'v1.5-variegata' into v1.5-variegata
evertlammerts Jan 27, 2026
ac97da3
skip pandas arrow tests if pyarrow not available
evertlammerts Jan 27, 2026
11b65f0
move from tyiping.Self to type_extensions.Self for py310
evertlammerts Jan 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/code_quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
uses: astral-sh/setup-uv@v7
with:
version: "0.9.0"
python-version: 3.9
python-version: "3.12"

- name: pre-commit (cache)
uses: actions/cache@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
uses: astral-sh/setup-uv@v7
with:
version: "0.9.0"
python-version: 3.9
python-version: 3.12
enable-cache: true
cache-suffix: -${{ github.workflow }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/packaging_sdist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
uses: astral-sh/setup-uv@v7
with:
version: "0.9.0"
python-version: 3.11
python-version: 3.12

- name: Build sdist
run: uv build --sdist
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/packaging_wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python: [ cp39, cp310, cp311, cp312, cp313, cp314 ]
python: [ cp310, cp311, cp312, cp313, cp314 ]
platform:
- { os: windows-2025, arch: amd64, cibw_system: win }
- { os: windows-11-arm, arch: ARM64, cibw_system: win } # cibw requires ARM64 to be uppercase
Expand All @@ -47,7 +47,6 @@ jobs:
- { minimal: true, python: cp312 }
- { minimal: true, python: cp313 }
- { minimal: true, platform: { arch: universal2 } }
- { python: cp39, platform: { os: windows-11-arm, arch: ARM64 } } # too many dependency problems for win arm64
- { python: cp310, platform: { os: windows-11-arm, arch: ARM64 } } # too many dependency problems for win arm64
runs-on: ${{ matrix.platform.os }}
env:
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/targeted_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ on:
required: true
type: choice
options:
- '3.9'
- '3.10'
- '3.11'
- '3.12'
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2018-2025 Stichting DuckDB Foundation
Copyright 2018-2026 Stichting DuckDB Foundation

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:

Expand Down
3 changes: 1 addition & 2 deletions adbc_driver_duckdb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import enum
import functools
import importlib.util
import typing

import adbc_driver_manager

Expand All @@ -32,7 +31,7 @@ class StatementOptions(enum.Enum):
BATCH_ROWS = "adbc.duckdb.query.batch_rows"


def connect(path: typing.Optional[str] = None) -> adbc_driver_manager.AdbcDatabase:
def connect(path: str | None = None) -> adbc_driver_manager.AdbcDatabase:
"""Create a low level ADBC connection to DuckDB."""
if path is None:
return adbc_driver_manager.AdbcDatabase(driver=driver_path(), entrypoint="duckdb_adbc_init")
Expand Down
4 changes: 1 addition & 3 deletions adbc_driver_duckdb/dbapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@

"""DBAPI 2.0-compatible facade for the ADBC DuckDB driver."""

import typing

import adbc_driver_manager
import adbc_driver_manager.dbapi

Expand Down Expand Up @@ -91,7 +89,7 @@
# Functions


def connect(path: typing.Optional[str] = None, **kwargs) -> "Connection":
def connect(path: str | None = None, **kwargs) -> "Connection":
"""Connect to DuckDB via ADBC."""
db = None
conn = None
Expand Down
6 changes: 3 additions & 3 deletions duckdb/bytes_io_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"""

from io import StringIO, TextIOBase
from typing import Any, Union
from typing import Any


class BytesIOWrapper:
Expand All @@ -43,7 +43,7 @@ class BytesIOWrapper:
Created for compat with pyarrow read_csv.
"""

def __init__(self, buffer: Union[StringIO, TextIOBase], encoding: str = "utf-8") -> None: # noqa: D107
def __init__(self, buffer: StringIO | TextIOBase, encoding: str = "utf-8") -> None: # noqa: D107
self.buffer = buffer
self.encoding = encoding
# Because a character can be represented by more than 1 byte,
Expand All @@ -55,7 +55,7 @@ def __init__(self, buffer: Union[StringIO, TextIOBase], encoding: str = "utf-8")
def __getattr__(self, attr: str) -> Any: # noqa: D105, ANN401
return getattr(self.buffer, attr)

def read(self, n: Union[int, None] = -1) -> bytes: # noqa: D102
def read(self, n: int | None = -1) -> bytes: # noqa: D102
assert self.buffer is not None
bytestring = self.buffer.read(n).encode(self.encoding)
# When n=-1/n greater than remaining bytes: Read entire file/rest of file
Expand Down
3 changes: 2 additions & 1 deletion duckdb/experimental/spark/_globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def foo(arg=pyducdkb.spark._NoValue):

__ALL__ = ["_NoValue"]

from typing_extensions import Self

# Disallow reloading this module so as to preserve the identities of the
# classes defined here.
Expand All @@ -54,7 +55,7 @@ class _NoValueType:

__instance = None

def __new__(cls) -> "_NoValueType":
def __new__(cls) -> Self:
# ensure that only one instance exists
if not cls.__instance:
cls.__instance = super().__new__(cls)
Expand Down
8 changes: 4 additions & 4 deletions duckdb/experimental/spark/_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@
# specific language governing permissions and limitations
# under the License.

from collections.abc import Iterable, Sized
from typing import Callable, TypeVar, Union
from collections.abc import Callable, Iterable, Sized
from typing import Literal, TypeVar

from numpy import float32, float64, int32, int64, ndarray
from typing_extensions import Literal, Protocol, Self
from typing_extensions import Protocol, Self

F = TypeVar("F", bound=Callable)
T_co = TypeVar("T_co", covariant=True)

PrimitiveType = Union[bool, float, int, str]
PrimitiveType = bool | float | int | str

NonUDFType = Literal[0]

Expand Down
6 changes: 2 additions & 4 deletions duckdb/experimental/spark/conf.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Optional # noqa: D100

from duckdb.experimental.spark.exception import ContributionsAcceptedError


Expand All @@ -10,7 +8,7 @@ def __init__(self) -> None: # noqa: D107
def contains(self, key: str) -> bool: # noqa: D102
raise ContributionsAcceptedError

def get(self, key: str, defaultValue: Optional[str] = None) -> Optional[str]: # noqa: D102
def get(self, key: str, defaultValue: str | None = None) -> str | None: # noqa: D102
raise ContributionsAcceptedError

def getAll(self) -> list[tuple[str, str]]: # noqa: D102
Expand All @@ -26,7 +24,7 @@ def setAppName(self, value: str) -> "SparkConf": # noqa: D102
raise ContributionsAcceptedError

def setExecutorEnv( # noqa: D102
self, key: Optional[str] = None, value: Optional[str] = None, pairs: Optional[list[tuple[str, str]]] = None
self, key: str | None = None, value: str | None = None, pairs: list[tuple[str, str]] | None = None
) -> "SparkConf":
raise ContributionsAcceptedError

Expand Down
8 changes: 3 additions & 5 deletions duckdb/experimental/spark/context.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Optional # noqa: D100

import duckdb
from duckdb import DuckDBPyConnection
from duckdb.experimental.spark.conf import SparkConf
Expand All @@ -20,7 +18,7 @@ def stop(self) -> None: # noqa: D102
self._connection.close()

@classmethod
def getOrCreate(cls, conf: Optional[SparkConf] = None) -> "SparkContext": # noqa: D102
def getOrCreate(cls, conf: SparkConf | None = None) -> "SparkContext": # noqa: D102
raise ContributionsAcceptedError

@classmethod
Expand Down Expand Up @@ -93,13 +91,13 @@ def dump_profiles(self, path: str) -> None: # noqa: D102
# def emptyRDD(self) -> duckdb.experimental.spark.rdd.RDD[typing.Any]:
# pass

def getCheckpointDir(self) -> Optional[str]: # noqa: D102
def getCheckpointDir(self) -> str | None: # noqa: D102
raise ContributionsAcceptedError

def getConf(self) -> SparkConf: # noqa: D102
raise ContributionsAcceptedError

def getLocalProperty(self, key: str) -> Optional[str]: # noqa: D102
def getLocalProperty(self, key: str) -> str | None: # noqa: D102
raise ContributionsAcceptedError

# def hadoopFile(self, path: str, inputFormatClass: str, keyClass: str, valueClass: str,
Expand Down
2 changes: 1 addition & 1 deletion duckdb/experimental/spark/errors/error_classes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ruff: noqa: D100, E501
# ruff: noqa: E501
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
Expand Down
12 changes: 6 additions & 6 deletions duckdb/experimental/spark/errors/exceptions/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional, cast # noqa: D100
from typing import cast

from ..utils import ErrorClassesReader

Expand All @@ -8,11 +8,11 @@ class PySparkException(Exception):

def __init__( # noqa: D107
self,
message: Optional[str] = None,
message: str | None = None,
# The error class, decides the message format, must be one of the valid options listed in 'error_classes.py'
error_class: Optional[str] = None,
error_class: str | None = None,
# The dictionary listing the arguments specified in the message (or the error_class)
message_parameters: Optional[dict[str, str]] = None,
message_parameters: dict[str, str] | None = None,
) -> None:
# `message` vs `error_class` & `message_parameters` are mutually exclusive.
assert (message is not None and (error_class is None and message_parameters is None)) or (
Expand All @@ -31,7 +31,7 @@ def __init__( # noqa: D107
self.error_class = error_class
self.message_parameters = message_parameters

def getErrorClass(self) -> Optional[str]:
def getErrorClass(self) -> str | None:
"""Returns an error class as a string.

.. versionadded:: 3.4.0
Expand All @@ -43,7 +43,7 @@ def getErrorClass(self) -> Optional[str]:
"""
return self.error_class

def getMessageParameters(self) -> Optional[dict[str, str]]:
def getMessageParameters(self) -> dict[str, str] | None:
"""Returns a message parameters as a dictionary.

.. versionadded:: 3.4.0
Expand Down
2 changes: 1 addition & 1 deletion duckdb/experimental/spark/errors/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# # noqa: D100
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
Expand Down
6 changes: 1 addition & 5 deletions duckdb/experimental/spark/exception.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
# ruff: noqa: D100
from typing import Optional


class ContributionsAcceptedError(NotImplementedError):
"""This method is not planned to be implemented, if you would like to implement this method
or show your interest in this method to other members of the community,
feel free to open up a PR or a Discussion over on https://github.com/duckdb/duckdb.
""" # noqa: D205

def __init__(self, message: Optional[str] = None) -> None: # noqa: D107
def __init__(self, message: str | None = None) -> None: # noqa: D107
doc = self.__class__.__doc__
if message:
doc = message + "\n" + doc
Expand Down
18 changes: 9 additions & 9 deletions duckdb/experimental/spark/sql/_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@
# specific language governing permissions and limitations
# under the License.

from collections.abc import Callable
from typing import (
Any,
Callable,
Optional,
TypeVar,
Union,
)

try:
from typing import Literal, Protocol
except ImportError:
from typing_extensions import Literal, Protocol
from typing import Literal

from typing_extensions import Protocol

import datetime
import decimal
Expand All @@ -36,14 +36,14 @@
from . import types
from .column import Column

ColumnOrName = Union[Column, str]
ColumnOrName = Column | str
ColumnOrName_ = TypeVar("ColumnOrName_", bound=ColumnOrName)
DecimalLiteral = decimal.Decimal
DateTimeLiteral = Union[datetime.datetime, datetime.date]
DateTimeLiteral = datetime.datetime | datetime.date
LiteralType = PrimitiveType
AtomicDataTypeOrString = Union[types.AtomicType, str]
DataTypeOrString = Union[types.DataType, str]
OptionalPrimitiveType = Optional[PrimitiveType]
AtomicDataTypeOrString = types.AtomicType | str
DataTypeOrString = types.DataType | str
OptionalPrimitiveType = PrimitiveType | None

AtomicValue = TypeVar(
"AtomicValue",
Expand Down
18 changes: 9 additions & 9 deletions duckdb/experimental/spark/sql/catalog.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
from typing import NamedTuple, Optional, Union # noqa: D100
from typing import NamedTuple

from .session import SparkSession


class Database(NamedTuple): # noqa: D101
name: str
description: Optional[str]
description: str | None
locationUri: str


class Table(NamedTuple): # noqa: D101
name: str
database: Optional[str]
description: Optional[str]
database: str | None
description: str | None
tableType: str
isTemporary: bool


class Column(NamedTuple): # noqa: D101
name: str
description: Optional[str]
description: str | None
dataType: str
nullable: bool
isPartition: bool
Expand All @@ -28,7 +28,7 @@ class Column(NamedTuple): # noqa: D101

class Function(NamedTuple): # noqa: D101
name: str
description: Optional[str]
description: str | None
className: str
isTemporary: bool

Expand All @@ -55,21 +55,21 @@ def transform_to_table(x: list[str]) -> Table:
tables = [transform_to_table(x) for x in res]
return tables

def listColumns(self, tableName: str, dbName: Optional[str] = None) -> list[Column]: # noqa: D102
def listColumns(self, tableName: str, dbName: str | None = None) -> list[Column]: # noqa: D102
query = f"""
select column_name, data_type, is_nullable from duckdb_columns() where table_name = '{tableName}'
"""
if dbName:
query += f" and database_name = '{dbName}'"
res = self._session.conn.sql(query).fetchall()

def transform_to_column(x: list[Union[str, bool]]) -> Column:
def transform_to_column(x: list[str | bool]) -> Column:
return Column(name=x[0], description=None, dataType=x[1], nullable=x[2], isPartition=False, isBucket=False)

columns = [transform_to_column(x) for x in res]
return columns

def listFunctions(self, dbName: Optional[str] = None) -> list[Function]: # noqa: D102
def listFunctions(self, dbName: str | None = None) -> list[Function]: # noqa: D102
raise NotImplementedError

def setCurrentDatabase(self, dbName: str) -> None: # noqa: D102
Expand Down
Loading