diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4cec015a..89478015 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -50,7 +50,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['3.10', '3.13'] + python-version: ['3.11', '3.13'] steps: - uses: actions/checkout@v7 @@ -101,7 +101,8 @@ jobs: # pode subir o piso de uma dependência base (claude-agent-sdk puxa pydantic # >= 2.12) e esconder um piso quebrado. Uma dependência transitiva na versão # mais alta ainda pode subir um piso direto, como o langgraph faz com o - # langchain-core. Roda em 3.10 porque o pandas no piso não tem wheel para 3.13. + # langchain-core. Roda em 3.11 porque o pandas no piso não tem wheel para 3.13 + # e o pyarrow no piso não tem para 3.12. lowest-direct: runs-on: ubuntu-latest strategy: @@ -114,7 +115,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v7 with: - python-version: '3.10' + python-version: '3.11' - name: Setup uv uses: astral-sh/setup-uv@v10.2.0 @@ -127,8 +128,8 @@ jobs: run: | flags="--extra dev" for extra in $EXTRAS; do flags="$flags --extra $extra"; done - uv pip compile pyproject.toml $flags --resolution lowest-direct --python-version 3.10 -o "$RUNNER_TEMP/requisitos.txt" - uv venv --python 3.10 "$RUNNER_TEMP/venv" + uv pip compile pyproject.toml $flags --resolution lowest-direct --python-version 3.11 -o "$RUNNER_TEMP/requisitos.txt" + uv venv --python 3.11 "$RUNNER_TEMP/venv" export VIRTUAL_ENV="$RUNNER_TEMP/venv" uv pip install -r "$RUNNER_TEMP/requisitos.txt" uv pip install --no-deps -e . @@ -139,7 +140,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['3.10', '3.13'] + python-version: ['3.11', '3.13'] steps: - uses: actions/checkout@v7 diff --git a/.python-version b/.python-version index c8cfe395..2c073331 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.10 +3.11 diff --git a/CHANGELOG.md b/CHANGELOG.md index 8657978d..1260cea5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,8 @@ e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR - Com `resume=True` e `checkpoint_path` existente, rodar a mesma chamada de novo continua do checkpoint, sem carregá-lo à mão; antes, a execução recomeçava e o sobrescrevia. `.dataframeit.json`, gravado a cada gravação do checkpoint, guarda a assinatura da execução, o hash do texto de cada linha e o do próprio arquivo, e o checkpoint só é retomado quando os três batem; com outra configuração ou entrada, a execução avisa e recomeça como antes. Das linhas concluídas, com sucesso ou com erro, vêm também os campos do modelo, sobre o que a entrada trazia neles. - No provider `codex`, o app-server roda com `HOME` no diretório isolado da execução, e as skills do usuário, como as de `~/.agents/skills`, deixam de ser carregadas. - Com `search_per_field=True`, o modo por grupo também devolve `search_provider` no uso, e o modo por campo devolve os campos na ordem do modelo, como o modo por grupo. O campo pulado por condição é registrado uma vez no log, e não duas. +- O Python mínimo sobe para 3.11. O 3.10 saiu de suporte em outubro de 2026, e as versões atuais do numpy e do pandas já não o aceitam (#229). +- O piso do pyarrow nos extras `polars` e `all` sobe para 10.0.1, a primeira versão com wheel para Python 3.11 (#229). ### Corrigido diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 63344de2..a673b909 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,7 +23,7 @@ Os testes não chamam nenhum provider de verdade e não precisam de chave de API 1. Abra uma issue antes de uma mudança grande, para combinar o desenho. 2. Crie uma branch a partir da `main` com o prefixo do tipo de mudança: `feature/`, `fix/`, `docs/` ou `refactor/`. 3. Escreva o teste junto com a mudança. Uma correção de bug vem com o teste que falhava antes dela. -4. Abra o PR contra a `main`. O CI roda lint, testes em Python 3.10 e 3.13, os testes com as versões mínimas das dependências e o build da documentação. +4. Abra o PR contra a `main`. O CI roda lint, testes em Python 3.11 e 3.13, os testes com as versões mínimas das dependências e o build da documentação. ## Convenções diff --git a/README.es.md b/README.es.md index 381f80e1..b06f03f0 100644 --- a/README.es.md +++ b/README.es.md @@ -1,7 +1,7 @@ # DataFrameIt [![PyPI version](https://badge.fury.io/py/dataframeit.svg)](https://badge.fury.io/py/dataframeit) -[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) +[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Tests](https://github.com/bdcdo/dataframeit/actions/workflows/tests.yml/badge.svg)](https://github.com/bdcdo/dataframeit/actions/workflows/tests.yml) diff --git a/README.md b/README.md index 30f7cdc0..79276407 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # DataFrameIt [![PyPI version](https://badge.fury.io/py/dataframeit.svg)](https://badge.fury.io/py/dataframeit) -[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) +[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Tests](https://github.com/bdcdo/dataframeit/actions/workflows/tests.yml/badge.svg)](https://github.com/bdcdo/dataframeit/actions/workflows/tests.yml) diff --git a/README.pt-BR.md b/README.pt-BR.md index 16c56961..65c60e48 100644 --- a/README.pt-BR.md +++ b/README.pt-BR.md @@ -1,7 +1,7 @@ # DataFrameIt [![PyPI version](https://badge.fury.io/py/dataframeit.svg)](https://badge.fury.io/py/dataframeit) -[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) +[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Tests](https://github.com/bdcdo/dataframeit/actions/workflows/tests.yml/badge.svg)](https://github.com/bdcdo/dataframeit/actions/workflows/tests.yml) diff --git a/docs/en/index.md b/docs/en/index.md index 1cb2a4f0..ef39e4ae 100644 --- a/docs/en/index.md +++ b/docs/en/index.md @@ -6,7 +6,7 @@
PyPI version - Python 3.10+ + Python 3.11+ License: MIT
diff --git a/docs/index.md b/docs/index.md index c1a560da..0f58c2a3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,7 +6,7 @@
PyPI version - Python 3.10+ + Python 3.11+ License: MIT
diff --git a/pyproject.toml b/pyproject.toml index 1f3ff27f..165e9441 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ version = "0.10.0" description = "Enrich DataFrames with LLM-based text analysis. Extract structured information from text with Pydantic." readme = "README.md" license = "MIT" -requires-python = ">=3.10" +requires-python = ">=3.11" authors = [ { name = "Bruno da Cunha de Oliveira" } ] @@ -41,7 +41,6 @@ classifiers = [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", @@ -87,7 +86,8 @@ codex = [ ] polars = [ "polars>=1.0", - "pyarrow>=10", + # A 10.0.0 não tem wheel para Python 3.11, e a compilação do fonte falha. + "pyarrow>=10.0.1", ] excel = [ "openpyxl>=3.1", @@ -111,7 +111,7 @@ all = [ "langchain-exa>=1.0.0", "claude-agent-sdk>=0.1.48", "polars>=1.0", - "pyarrow>=10", + "pyarrow>=10.0.1", "openpyxl>=3.1", ] dev = [ @@ -145,7 +145,7 @@ include = [ packages = ["src/dataframeit"] [tool.ruff] -target-version = "py310" +target-version = "py311" line-length = 100 [tool.ruff.lint] diff --git a/src/dataframeit/core.py b/src/dataframeit/core.py index bae66793..301857d4 100644 --- a/src/dataframeit/core.py +++ b/src/dataframeit/core.py @@ -2740,7 +2740,7 @@ def process_single_row(row_data: tuple) -> dict: # a retomada. Como 'error', o resume=True a preservaria. try: futures[executor.submit(process_single_row, row)] = row - except Exception as e: # noqa: BLE001, PERF203 (ver o comentário acima) + except Exception as e: # noqa: BLE001 (ver o comentário acima) with lock: token_stats.setdefault("abort", _error_text(e)) abort_event.set() diff --git a/src/dataframeit/utils.py b/src/dataframeit/utils.py index ef6e5189..8332dcdd 100644 --- a/src/dataframeit/utils.py +++ b/src/dataframeit/utils.py @@ -407,7 +407,7 @@ def is_complex_type(field_type: object) -> bool: args = get_args(field_type) return any(is_complex_type(arg) for arg in args if arg is not type(None)) - # types.UnionType para sintaxe X | Y (Python 3.10+) + # types.UnionType para sintaxe X | Y if isinstance(field_type, types.UnionType): args = get_args(field_type) return any(is_complex_type(arg) for arg in args if arg is not type(None)) diff --git a/tests/test_tipo_de_retorno.py b/tests/test_tipo_de_retorno.py index 6a5f4b51..4ca28c25 100644 --- a/tests/test_tipo_de_retorno.py +++ b/tests/test_tipo_de_retorno.py @@ -9,10 +9,11 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: + from typing import assert_type + import pandas as pd import polars as pl from pydantic import BaseModel - from typing_extensions import assert_type from dataframeit import dataframeit