Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ Supported versions:
- Python 3.10
- Python 3.11
- Python 3.12
- Python 3.13

## Code Examples

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python_version: ["3.9", "3.10", "3.11", "3.12"]
python_version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
permissions:
id-token: write
contents: read
Expand Down Expand Up @@ -413,7 +413,7 @@ jobs:
needs: build-and-push-artifacts-status
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
env:
PYTHON_VERSIONS: "3.9,3.10,3.11,3.12"
PYTHON_VERSIONS: "3.9,3.10,3.11,3.12,3.13"
steps:
- name: Checkout code
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
Expand Down
27 changes: 16 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- name: Checkout code
Expand Down Expand Up @@ -277,7 +277,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- name: Checkout code
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
Expand All @@ -293,11 +293,11 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Set up Java 11
- name: Set up Java 17
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4
with:
distribution: 'temurin'
java-version: '11'
java-version: '17'

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

- name: Add venv to PATH
if: steps.cache-deps.outputs.cache-hit == 'true'
run: echo "${{ github.workspace }}/.venv/bin" >> $GITHUB_PATH

- name: Install dependencies
if: steps.cache-deps.outputs.cache-hit != 'true'
run: poetry install --no-interaction --no-root --with dev
Expand Down Expand Up @@ -363,6 +367,14 @@ jobs:
echo "Warning: No coverage file generated"
fi

- name: Per-version coverage summary
if: steps.test-unit.outputs.coverage_generated == 'true'
env:
PYTHON_VERSION: ${{ matrix.python-version }}
run: |
echo "## Python ${PYTHON_VERSION} Coverage" >> $GITHUB_STEP_SUMMARY
poetry run coverage report --data-file=coverage/.coverage.${PYTHON_VERSION} --format=markdown >> $GITHUB_STEP_SUMMARY

- name: Upload test results to Codecov (these are results not coverage reports)
if: ${{ !cancelled() }}
uses: codecov/test-results-action@47f89e9acb64b76debcd5ea40642d25a4adced9f # v1
Expand All @@ -378,13 +390,6 @@ jobs:
files: ./coverage/coverage-${{ matrix.python-version }}.xml
fail_ci_if_error: ${{ github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'push' }}

- name: Per-version coverage summary
if: steps.test-unit.outputs.coverage_generated == 'true'
env:
PYTHON_VERSION: ${{ matrix.python-version }}
run: |
echo "## Python ${PYTHON_VERSION} Coverage" >> $GITHUB_STEP_SUMMARY
poetry run coverage report --data-file=coverage/.coverage.${PYTHON_VERSION} --format=markdown >> $GITHUB_STEP_SUMMARY
audit-prod:
name: Audit - Production
runs-on: ubuntu-latest
Expand Down
4 changes: 2 additions & 2 deletions .mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
# Then run: mise install

[tools]
python = "3.12"
java = "temurin-11"
python = "3.13"
java = "temurin-17"
poetry = "2.2.0"

[tasks.setup]
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ repos:
hooks:
- id: flake8
name: flake8
entry: poetry run flake8 -j auto
entry: mise exec -- poetry run flake8 -j auto
language: system
types: [python]

- id: isort
name: isort
entry: poetry run isort
entry: mise exec -- poetry run isort
language: system
types: [python]
args: ["--filter-files"]
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@

## Python Version Support

- Python 3.9, 3.10, 3.11, 3.12
- Python 3.9, 3.10, 3.11, 3.12, 3.13

## Dependencies

Expand Down
12 changes: 6 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributing

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

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

```bash
mise install # Installs Python 3.12 and Java 11
mise install # Installs Python 3.12 and Java 17
mise run setup # Installs dependencies and pre-commit hooks
```

#### Option 2: Manual setup

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

```bash
Expand Down
16 changes: 14 additions & 2 deletions deepnote_toolkit/ocelots/pandas/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,25 @@ def _get_histogram(pd_series):
# let's drop infinite values because they break histograms
np_array = np.array(pd_series.replace([np.inf, -np.inf], np.nan).dropna())

# Check if array is empty after dropping NaN/NaT values
if len(np_array) == 0:
return None

y, bins = np.histogram(np_array, bins=10)
return [
{"bin_start": bins[i], "bin_end": bins[i + 1], "count": count.item()}
for i, count in enumerate(y)
]
except IndexError:
# numpy bug https://github.com/numpy/numpy/issues/8627
except (ValueError, IndexError) as e:
# NumPy 2.2+ raises "Too many bins for data range" when:
# - Data range is zero (all values identical), or
# - For integer data, bin width would be < 1.0, or
# - Floating point precision prevents creating finite-sized bins at large scales
# Numpy implementation: https://github.com/numpy/numpy/blob/e7a123b2d3eca9897843791dd698c1803d9a39c2/numpy/lib/_histograms_impl.py#L454
# IndexError can occur in NumPy 2.x with edge cases involving large integers or datetime conversions
if isinstance(e, ValueError) and "Too many bins for data range" in str(e):
return None
# For IndexError or other ValueError cases, return None to gracefully handle edge cases
return None


Expand Down
23 changes: 22 additions & 1 deletion deepnote_toolkit/variable_explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,27 @@ def _to_int(x):
return int(x) if x else None


def _get_type_name(v):
"""
Get the normalized type name for a variable with backwards compatibility.

In Python 3.13, NumPy's bool_ type may report as 'bool' instead of 'bool_'.
This function ensures we always return 'bool_' for NumPy bool types to maintain
compatibility with older Python versions.
"""
# Check for NumPy bool_ type first (most reliable check)
# This handles the case where Python 3.13 reports np.bool_ as 'bool'
try:
if np is not None and isinstance(v, np.bool_):
return "bool_"
except (AttributeError, TypeError):
# If numpy types change or there's an issue with the comparison
pass

# Fall back to standard type name
return type(v).__name__


def _get_variable_dict_entry(var_name, v):
try:
shape = _get_shape(v)
Expand All @@ -415,7 +436,7 @@ def _get_variable_dict_entry(var_name, v):
underlying_data_type = _get_underlying_data_type(v)
var_result = {
"varName": var_name,
"varType": type(v).__name__,
"varType": _get_type_name(v),
"varSize": _to_int(_get_size(v)),
"varShape": shape,
"varContent": _get_content(v),
Expand Down
2 changes: 1 addition & 1 deletion dockerfiles/test.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM quay.io/pypa/manylinux_2_28_x86_64:2025.05.28-1
RUN pipx install nox poetry==2.2.0

RUN dnf -y update && \
dnf -y install java-11-openjdk-devel \
dnf -y install java-17-openjdk-devel \
# Required for pymssql - provides sqlfront.h header file
freetds-devel \
# Required for database connectivity through ODBC
Expand Down
4 changes: 2 additions & 2 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from nox import session


@session(python=["3.9", "3.10", "3.11", "3.12"], reuse_venv=True)
@session(python=["3.9", "3.10", "3.11", "3.12", "3.13"], reuse_venv=True)
def unit(session):
"""Run unit tests. Coverage is disabled by default, use --coverage to enable."""

Expand Down Expand Up @@ -67,7 +67,7 @@ def unit(session):
)


@session(python=["3.9", "3.10", "3.11", "3.12"], reuse_venv=True)
@session(python=["3.9", "3.10", "3.11", "3.12", "3.13"], reuse_venv=True)
def integration(session):
"""Run integration tests. Coverage is disabled by default, use --coverage to enable."""
# Validate required environment variables
Expand Down
Loading