Skip to content

Commit 67a97b4

Browse files
authored
Merge pull request #10 from deepnote/fpyrek/grn-4947-support-python-313
feat: python 3.13 support
2 parents 059d347 + b0ca5c6 commit 67a97b4

File tree

14 files changed

+904
-143
lines changed

14 files changed

+904
-143
lines changed

.cursorrules

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ Supported versions:
137137
- Python 3.10
138138
- Python 3.11
139139
- Python 3.12
140+
- Python 3.13
140141

141142
## Code Examples
142143

.github/workflows/cd.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
strategy:
3636
fail-fast: false
3737
matrix:
38-
python_version: ["3.9", "3.10", "3.11", "3.12"]
38+
python_version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
3939
permissions:
4040
id-token: write
4141
contents: read
@@ -413,7 +413,7 @@ jobs:
413413
needs: build-and-push-artifacts-status
414414
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
415415
env:
416-
PYTHON_VERSIONS: "3.9,3.10,3.11,3.12"
416+
PYTHON_VERSIONS: "3.9,3.10,3.11,3.12,3.13"
417417
steps:
418418
- name: Checkout code
419419
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4

.github/workflows/ci.yml

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ jobs:
158158
strategy:
159159
fail-fast: false
160160
matrix:
161-
python-version: ["3.9", "3.10", "3.11", "3.12"]
161+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
162162

163163
steps:
164164
- name: Checkout code
@@ -277,7 +277,7 @@ jobs:
277277
strategy:
278278
fail-fast: false
279279
matrix:
280-
python-version: ["3.9", "3.10", "3.11", "3.12"]
280+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
281281
steps:
282282
- name: Checkout code
283283
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
@@ -293,11 +293,11 @@ jobs:
293293
with:
294294
python-version: ${{ matrix.python-version }}
295295

296-
- name: Set up Java 11
296+
- name: Set up Java 17
297297
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4
298298
with:
299299
distribution: 'temurin'
300-
java-version: '11'
300+
java-version: '17'
301301

302302
- name: Load cached Poetry installation
303303
id: cached-poetry
@@ -322,6 +322,10 @@ jobs:
322322
path: .venv
323323
key: venv-v2-${{ github.event.pull_request.head.repo.full_name || github.repository }}-py${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}
324324

325+
- name: Add venv to PATH
326+
if: steps.cache-deps.outputs.cache-hit == 'true'
327+
run: echo "${{ github.workspace }}/.venv/bin" >> $GITHUB_PATH
328+
325329
- name: Install dependencies
326330
if: steps.cache-deps.outputs.cache-hit != 'true'
327331
run: poetry install --no-interaction --no-root --with dev
@@ -363,6 +367,14 @@ jobs:
363367
echo "Warning: No coverage file generated"
364368
fi
365369
370+
- name: Per-version coverage summary
371+
if: steps.test-unit.outputs.coverage_generated == 'true'
372+
env:
373+
PYTHON_VERSION: ${{ matrix.python-version }}
374+
run: |
375+
echo "## Python ${PYTHON_VERSION} Coverage" >> $GITHUB_STEP_SUMMARY
376+
poetry run coverage report --data-file=coverage/.coverage.${PYTHON_VERSION} --format=markdown >> $GITHUB_STEP_SUMMARY
377+
366378
- name: Upload test results to Codecov (these are results not coverage reports)
367379
if: ${{ !cancelled() }}
368380
uses: codecov/test-results-action@47f89e9acb64b76debcd5ea40642d25a4adced9f # v1
@@ -378,13 +390,6 @@ jobs:
378390
files: ./coverage/coverage-${{ matrix.python-version }}.xml
379391
fail_ci_if_error: ${{ github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'push' }}
380392

381-
- name: Per-version coverage summary
382-
if: steps.test-unit.outputs.coverage_generated == 'true'
383-
env:
384-
PYTHON_VERSION: ${{ matrix.python-version }}
385-
run: |
386-
echo "## Python ${PYTHON_VERSION} Coverage" >> $GITHUB_STEP_SUMMARY
387-
poetry run coverage report --data-file=coverage/.coverage.${PYTHON_VERSION} --format=markdown >> $GITHUB_STEP_SUMMARY
388393
audit-prod:
389394
name: Audit - Production
390395
runs-on: ubuntu-latest

.mise.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
# Then run: mise install
44

55
[tools]
6-
python = "3.12"
7-
java = "temurin-11"
6+
python = "3.13"
7+
java = "temurin-17"
88
poetry = "2.2.0"
99

1010
[tasks.setup]

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ repos:
1111
hooks:
1212
- id: flake8
1313
name: flake8
14-
entry: poetry run flake8 -j auto
14+
entry: mise exec -- poetry run flake8 -j auto
1515
language: system
1616
types: [python]
1717

1818
- id: isort
1919
name: isort
20-
entry: poetry run isort
20+
entry: mise exec -- poetry run isort
2121
language: system
2222
types: [python]
2323
args: ["--filter-files"]

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252

5353
## Python Version Support
5454

55-
- Python 3.9, 3.10, 3.11, 3.12
55+
- Python 3.9, 3.10, 3.11, 3.12, 3.13
5656

5757
## Dependencies
5858

CONTRIBUTING.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Contributing
22

3-
All contributions are highly appreciated!
3+
All contributions are highly appreciated!
44
Start by [forking the repository](https://github.com/deepnote/deepnote-toolkit/fork) on GitHub and setting up Deepnote Toolkit for local development.
55

66
## Local development setup
@@ -13,17 +13,17 @@ Start by [forking the repository](https://github.com/deepnote/deepnote-toolkit/f
1313
2. Run setup:
1414

1515
```bash
16-
mise install # Installs Python 3.12 and Java 11
16+
mise install # Installs Python 3.12 and Java 17
1717
mise run setup # Installs dependencies and pre-commit hooks
1818
```
1919

2020
#### Option 2: Manual setup
2121

2222
1. Install poetry: [Installation](https://python-poetry.org/docs/#installation)
23-
2. Install Java 11 (required for PySpark tests):
24-
- macOS: `brew install openjdk@11`
25-
- Ubuntu/Debian: `sudo apt-get install openjdk-11-jdk`
26-
- RHEL/Fedora: `sudo dnf install java-11-openjdk-devel`
23+
2. Install Java 17 (required for PySpark tests):
24+
- macOS: `brew install openjdk@17`
25+
- Ubuntu/Debian: `sudo apt-get install openjdk-17-jdk`
26+
- RHEL/Fedora: `sudo dnf install java-17-openjdk-devel`
2727
3. Set up venv for development package:
2828

2929
```bash

deepnote_toolkit/ocelots/pandas/analyze.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,25 @@ def _get_histogram(pd_series):
7878
# let's drop infinite values because they break histograms
7979
np_array = np.array(pd_series.replace([np.inf, -np.inf], np.nan).dropna())
8080

81+
# Check if array is empty after dropping NaN/NaT values
82+
if len(np_array) == 0:
83+
return None
84+
8185
y, bins = np.histogram(np_array, bins=10)
8286
return [
8387
{"bin_start": bins[i], "bin_end": bins[i + 1], "count": count.item()}
8488
for i, count in enumerate(y)
8589
]
86-
except IndexError:
87-
# numpy bug https://github.com/numpy/numpy/issues/8627
90+
except (ValueError, IndexError) as e:
91+
# NumPy 2.2+ raises "Too many bins for data range" when:
92+
# - Data range is zero (all values identical), or
93+
# - For integer data, bin width would be < 1.0, or
94+
# - Floating point precision prevents creating finite-sized bins at large scales
95+
# Numpy implementation: https://github.com/numpy/numpy/blob/e7a123b2d3eca9897843791dd698c1803d9a39c2/numpy/lib/_histograms_impl.py#L454
96+
# IndexError can occur in NumPy 2.x with edge cases involving large integers or datetime conversions
97+
if isinstance(e, ValueError) and "Too many bins for data range" in str(e):
98+
return None
99+
# For IndexError or other ValueError cases, return None to gracefully handle edge cases
88100
return None
89101

90102

deepnote_toolkit/variable_explorer.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,27 @@ def _to_int(x):
407407
return int(x) if x else None
408408

409409

410+
def _get_type_name(v):
411+
"""
412+
Get the normalized type name for a variable with backwards compatibility.
413+
414+
In Python 3.13, NumPy's bool_ type may report as 'bool' instead of 'bool_'.
415+
This function ensures we always return 'bool_' for NumPy bool types to maintain
416+
compatibility with older Python versions.
417+
"""
418+
# Check for NumPy bool_ type first (most reliable check)
419+
# This handles the case where Python 3.13 reports np.bool_ as 'bool'
420+
try:
421+
if np is not None and isinstance(v, np.bool_):
422+
return "bool_"
423+
except (AttributeError, TypeError):
424+
# If numpy types change or there's an issue with the comparison
425+
pass
426+
427+
# Fall back to standard type name
428+
return type(v).__name__
429+
430+
410431
def _get_variable_dict_entry(var_name, v):
411432
try:
412433
shape = _get_shape(v)
@@ -415,7 +436,7 @@ def _get_variable_dict_entry(var_name, v):
415436
underlying_data_type = _get_underlying_data_type(v)
416437
var_result = {
417438
"varName": var_name,
418-
"varType": type(v).__name__,
439+
"varType": _get_type_name(v),
419440
"varSize": _to_int(_get_size(v)),
420441
"varShape": shape,
421442
"varContent": _get_content(v),

dockerfiles/test.Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ FROM quay.io/pypa/manylinux_2_28_x86_64:2025.05.28-1
22
RUN pipx install nox poetry==2.2.0
33

44
RUN dnf -y update && \
5-
dnf -y install java-11-openjdk-devel \
5+
dnf -y install java-17-openjdk-devel \
66
# Required for pymssql - provides sqlfront.h header file
77
freetds-devel \
88
# Required for database connectivity through ODBC

0 commit comments

Comments
 (0)