Skip to content

Commit 786d8f0

Browse files
authored
feat(python): support python 3.9 again (ibis-project#10949)
1 parent 63a75f4 commit 786d8f0

39 files changed

+179
-101
lines changed

.github/workflows/ibis-backends-cloud.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
os:
3838
- ubuntu-latest
3939
python-version:
40-
- "3.10"
40+
- "3.9"
4141
- "3.13"
4242
backend:
4343
- name: snowflake
@@ -54,7 +54,7 @@ jobs:
5454
- --extra athena
5555
include:
5656
- os: ubuntu-latest
57-
python-version: "3.10"
57+
- python-version: "3.9"
5858
backend:
5959
name: bigquery
6060
title: BigQuery

.github/workflows/ibis-backends.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
- ubuntu-latest
5353
- windows-latest
5454
python-version:
55-
- "3.10"
55+
- "3.9"
5656
- "3.13"
5757
steps:
5858
- name: checkout
@@ -92,7 +92,7 @@ jobs:
9292
- ubuntu-latest
9393
- windows-latest
9494
python-version:
95-
- "3.10"
95+
- "3.9"
9696
- "3.13"
9797
backend:
9898
- name: duckdb
@@ -547,7 +547,7 @@ jobs:
547547
fail-fast: false
548548
matrix:
549549
include:
550-
- python-version: "3.10"
550+
- python-version: "3.9"
551551
pyspark-minor-version: "3.3"
552552
tag: local
553553
deps:

.github/workflows/ibis-main.yml

+5-3
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ jobs:
4444
matrix:
4545
os:
4646
- ubuntu-latest
47+
- ubuntu-24.04-arm
4748
- windows-latest
4849
python-version:
50+
- "3.9"
4951
- "3.10"
5052
- "3.11"
5153
- "3.12"
@@ -67,7 +69,7 @@ jobs:
6769
uses: astral-sh/[email protected]
6870

6971
- name: install ${{ matrix.os }} system dependencies
70-
if: matrix.os == 'ubuntu-latest'
72+
if: startsWith(matrix.os, 'ubuntu')
7173
run: |
7274
set -euo pipefail
7375
@@ -117,7 +119,7 @@ jobs:
117119
uses: actions/setup-python@v5
118120
id: install_python
119121
with:
120-
python-version: "3.13"
122+
python-version: "3.9"
121123

122124
- name: install uv
123125
uses: astral-sh/[email protected]
@@ -150,7 +152,7 @@ jobs:
150152
uses: actions/setup-python@v5
151153
id: install_python
152154
with:
153-
python-version: "3.10"
155+
python-version: "3.12"
154156

155157
- name: install uv
156158
uses: astral-sh/[email protected]

.github/workflows/nix-skip-helper.yml

+8
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,17 @@ jobs:
4040
- "3.12"
4141
- "3.13"
4242
include:
43+
- os: ubuntu-latest
44+
python-version: "3.9"
4345
- os: ubuntu-latest
4446
python-version: "3.10"
4547
- os: ubuntu-latest
4648
python-version: "3.11"
49+
- os: ubuntu-24.04-arm
50+
python-version: "3.9"
51+
- os: ubuntu-24.04-arm
52+
python-version: "3.10"
53+
- os: ubuntu-24.04-arm
54+
python-version: "3.11"
4755
steps:
4856
- run: echo "No build required"

.github/workflows/nix.yml

+8
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,18 @@ jobs:
4242
- "3.12"
4343
- "3.13"
4444
include:
45+
- os: ubuntu-latest
46+
python-version: "3.9"
4547
- os: ubuntu-latest
4648
python-version: "3.10"
4749
- os: ubuntu-latest
4850
python-version: "3.11"
51+
- os: ubuntu-24.04-arm
52+
python-version: "3.9"
53+
- os: ubuntu-24.04-arm
54+
python-version: "3.10"
55+
- os: ubuntu-24.04-arm
56+
python-version: "3.11"
4957
steps:
5058
- name: checkout
5159
uses: actions/checkout@v4

flake.nix

+3-4
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,6 @@
9393
9494
# Get repository root using git. This is expanded at runtime by the editable `.pth` machinery.
9595
export REPO_ROOT=$(git rev-parse --show-toplevel)
96-
97-
# Prevent uv from downloading managed Python's
98-
export UV_PYTHON_DOWNLOADS=never
9996
'';
10097

10198
preCommitDeps = with pkgs; [
@@ -163,18 +160,20 @@
163160
packages = {
164161
default = packages.ibis313;
165162

166-
inherit (pkgs) ibis310 ibis311 ibis312 ibis313
163+
inherit (pkgs) ibis39 ibis310 ibis311 ibis312 ibis313
167164
update-lock-files check-release-notes-spelling;
168165
};
169166

170167
checks = {
168+
ibis39-pytest = pkgs.ibis39.passthru.tests.pytest;
171169
ibis310-pytest = pkgs.ibis310.passthru.tests.pytest;
172170
ibis311-pytest = pkgs.ibis311.passthru.tests.pytest;
173171
ibis312-pytest = pkgs.ibis312.passthru.tests.pytest;
174172
ibis313-pytest = pkgs.ibis313.passthru.tests.pytest;
175173
};
176174

177175
devShells = rec {
176+
ibis39 = mkDevShell pkgs.ibisDevEnv39;
178177
ibis310 = mkDevShell pkgs.ibisDevEnv310;
179178
ibis311 = mkDevShell pkgs.ibisDevEnv311;
180179
ibis312 = mkDevShell pkgs.ibisDevEnv312;

ibis/backends/__init__.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1528,7 +1528,10 @@ def _get_backend_names(*, exclude: tuple[str] = ()) -> frozenset[str]:
15281528
15291529
"""
15301530

1531-
entrypoints = importlib.metadata.entry_points(group="ibis.backends")
1531+
if sys.version_info < (3, 10):
1532+
entrypoints = importlib.metadata.entry_points()["ibis.backends"]
1533+
else:
1534+
entrypoints = importlib.metadata.entry_points(group="ibis.backends")
15321535
return frozenset(ep.name for ep in entrypoints).difference(exclude)
15331536

15341537

ibis/backends/postgres/tests/test_udf.py

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import annotations
44

55
import functools
6+
import sys
67

78
import pytest
89

@@ -118,6 +119,11 @@ def mult_a_b(a: int, b: int) -> int:
118119
assert result["mult_result"].iat[0] == 8
119120

120121

122+
@pytest.mark.xfail(
123+
condition=sys.version_info[:2] < (3, 9),
124+
raises=TypeError,
125+
reason="no straightforward way to use new (Python 3.9) annotations syntax",
126+
)
121127
def test_array_type(test_database, table):
122128
"""Test that usage of Array types work Other scalar types can be
123129
represented either by the class or an instance, but Array types work

ibis/backends/sql/compilers/base.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import operator
88
import string
99
from functools import partial, reduce
10-
from typing import TYPE_CHECKING, Any, ClassVar
10+
from typing import TYPE_CHECKING, Any, Callable, ClassVar
1111

1212
import sqlglot as sg
1313
import sqlglot.expressions as sge
@@ -51,7 +51,7 @@ def AlterTable(*args, kind="TABLE", **kwargs):
5151

5252

5353
if TYPE_CHECKING:
54-
from collections.abc import Callable, Iterable, Mapping
54+
from collections.abc import Iterable, Mapping
5555

5656
import ibis.expr.schema as sch
5757
import ibis.expr.types as ir

ibis/backends/sql/compilers/bigquery/udf/core.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,11 @@
99
import textwrap
1010
from collections import ChainMap
1111
from inspect import _empty as EMPTY
12-
from typing import TYPE_CHECKING
12+
from typing import Callable
1313

1414
from ibis.backends.sql.compilers.bigquery.udf.find import find_names
1515
from ibis.backends.sql.compilers.bigquery.udf.rewrite import rewrite
1616

17-
if TYPE_CHECKING:
18-
from collections.abc import Callable
19-
2017

2118
class SymbolTable(ChainMap):
2219
"""ChainMap subclass implementing scope for the translator.

ibis/backends/sqlite/udf.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@
66
import operator
77
from collections import defaultdict
88
from datetime import date
9-
from typing import TYPE_CHECKING, Any, NamedTuple
9+
from typing import Any, Callable, NamedTuple
1010
from urllib.parse import parse_qs, urlsplit
1111
from uuid import uuid4
1212

13-
if TYPE_CHECKING:
14-
from collections.abc import Callable
15-
1613
try:
1714
import regex as re
1815
except ImportError:

ibis/backends/tests/test_udf.py

+10
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ def num_vowels(s: str, include_y: bool = False) -> int:
6363
["postgres"], raises=TypeError, reason="postgres only supports map<string, string>"
6464
)
6565
@mark.notimpl(["polars"])
66+
@mark.never(
67+
["flink"],
68+
condition=sys.version_info < (3, 10),
69+
reason="broken with Python 3.9; works in Python 3.10",
70+
)
6671
@mark.notyet(["datafusion"], raises=NotImplementedError)
6772
@mark.notyet(
6873
["sqlite"], raises=com.IbisTypeError, reason="sqlite doesn't support map types"
@@ -92,6 +97,11 @@ def num_vowels_map(s: str, include_y: bool = False) -> dict[str, int]:
9297
["postgres"], raises=TypeError, reason="postgres only supports map<string, string>"
9398
)
9499
@mark.notimpl(["polars"])
100+
@mark.never(
101+
["flink"],
102+
condition=sys.version_info < (3, 10),
103+
reason="broken with Python 3.9; works in Python 3.10",
104+
)
95105
@mark.notyet(["datafusion"], raises=NotImplementedError)
96106
@mark.notyet(["sqlite"], raises=TypeError, reason="sqlite doesn't support map types")
97107
def test_map_merge_udf(batting):

ibis/common/annotations.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import functools
44
import inspect
55
import types
6-
from typing import TYPE_CHECKING
6+
from typing import TYPE_CHECKING, Callable
77
from typing import Any as AnyType
88

99
from typing_extensions import Self
@@ -21,7 +21,7 @@
2121
from ibis.common.typing import format_typehint, get_type_hints
2222

2323
if TYPE_CHECKING:
24-
from collections.abc import Callable, Sequence
24+
from collections.abc import Sequence
2525

2626
EMPTY = inspect.Parameter.empty # marker for missing argument
2727
KEYWORD_ONLY = inspect.Parameter.KEYWORD_ONLY

ibis/common/caching.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
from __future__ import annotations
22

33
import functools
4-
from typing import TYPE_CHECKING
5-
6-
if TYPE_CHECKING:
7-
from collections.abc import Callable
4+
from typing import Callable
85

96

107
def memoize(func: Callable) -> Callable:

ibis/common/deferred.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
import inspect
66
import operator
77
from abc import abstractmethod
8-
from collections.abc import Callable
9-
from typing import Any, TypeVar, overload
8+
from typing import Any, Callable, TypeVar, overload
109

1110
from ibis.common.bases import Final, FrozenSlotted, Hashable, Immutable, Slotted
1211
from ibis.common.collections import FrozenDict

ibis/common/dispatch.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,9 @@
33
import abc
44
import functools
55
from collections import defaultdict
6-
from types import UnionType
76
from typing import Union
87

9-
from ibis.common.typing import (
10-
evaluate_annotations,
11-
get_args,
12-
get_origin,
13-
)
8+
from ibis.common.typing import UnionType, evaluate_annotations, get_args, get_origin
149
from ibis.util import import_object, unalias_package
1510

1611

ibis/common/exceptions.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515

1616
from __future__ import annotations
1717

18-
from typing import TYPE_CHECKING, Any
19-
20-
if TYPE_CHECKING:
21-
from collections.abc import Callable
18+
from typing import Any, Callable
2219

2320

2421
class TableNotFound(Exception):

ibis/common/graph.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
import itertools
66
from abc import abstractmethod
77
from collections import deque
8-
from collections.abc import Callable, Iterable, Iterator, KeysView, Mapping, Sequence
9-
from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union
8+
from collections.abc import Iterable, Iterator, KeysView, Mapping, Sequence
9+
from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union
1010

1111
from ibis.common.bases import Hashable
1212
from ibis.common.patterns import NoMatch, Pattern
@@ -22,7 +22,7 @@
2222
Finder = Callable[["Node"], bool]
2323
FinderLike = Union[Finder, Pattern, _ClassInfo]
2424

25-
Replacer = Callable[["Node", dict["Node", Any] | None], "Node"]
25+
Replacer = Callable[["Node", Optional[dict["Node", Any]]], "Node"]
2626
ReplacerLike = Union[Replacer, Pattern, Mapping]
2727

2828

0 commit comments

Comments
 (0)