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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR

### Corrigido

- Os imports de `datetime` usam o alias `dt`, exigido pelo Ruff 0.17, para manter a verificação de lint aprovada (#319).



## [0.11.1] - 2026-10-29
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ dev = [
"pytest>=7.0",
"pytest-cov>=4.0",
"pytest-repeat>=0.9.4",
"ruff>=0.16,<0.17",
"ruff>=0.16,<0.18",
"ty==0.0.91",
"vulture>=2.16,<3",
"deptry>=0.25,<0.26",
Expand Down
6 changes: 3 additions & 3 deletions src/dataframeit/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

import dataclasses
import datetime
import datetime as dt
import hashlib
import importlib.util
import itertools
Expand Down Expand Up @@ -672,8 +672,8 @@ def _same_value(validated: object, value: object) -> bool: # noqa: PLR0911 (uma
and abs(value) >= _EXACT_INT_IN_FLOAT
):
return False
if type(validated) is datetime.date and isinstance(value, datetime.datetime):
return value == datetime.datetime.combine(validated, datetime.time())
if type(validated) is dt.date and isinstance(value, dt.datetime):
return value == dt.datetime.combine(validated, dt.time())
return bool(validated == value)


Expand Down
29 changes: 14 additions & 15 deletions src/dataframeit/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import ast
import collections.abc
import datetime
import datetime as dt
import json
import math
import numbers
Expand Down Expand Up @@ -491,7 +491,7 @@ def _without_optional(annotation: object) -> object:
# Data, hora e duração: o pyarrow converte cada um destes tipos nos outros e o
# número em cada um deles. O datetime depois de um date perde a hora, e o int
# depois de um date ou de um timedelta vira data ou duração.
_TEMPORAL = (datetime.date, datetime.datetime, datetime.time, datetime.timedelta)
_TEMPORAL = (dt.date, dt.datetime, dt.time, dt.timedelta)
# Pares que o pyarrow converte um no outro quando o primeiro vem antes: o True
# depois de um float vira 1.0, e o texto depois de um bytes vira bytes.
_CONVERTED_PAIRS = ((float, bool), (bytes, str))
Expand Down Expand Up @@ -534,10 +534,10 @@ def _mixes_converted_types(annotation: object) -> bool:
Decimal,
str,
bytes,
datetime.datetime,
datetime.date,
datetime.time,
datetime.timedelta,
dt.datetime,
dt.date,
dt.time,
dt.timedelta,
)
_NUMBERS = (int, float, Decimal)
# A classe de `_KINDS` do número que não é subclasse de nenhuma delas, como o
Expand Down Expand Up @@ -571,16 +571,15 @@ def _group_kinds(group: list, classes: set) -> set | None:
if cls is type(None) or cls is type(pd.NaT) or issubclass(cls, (dict, *_SEQUENCES)):
continue
members = [value for value in group if type(value) is cls]
if issubclass(cls, datetime.datetime):
if issubclass(cls, dt.datetime):
kinds.update(
_AWARE_DATETIME if value.tzinfo is not None else datetime.datetime
for value in members
_AWARE_DATETIME if value.tzinfo is not None else dt.datetime for value in members
)
elif issubclass(cls, float):
if not all(math.isnan(value) for value in members):
kinds.add(float)
elif (issubclass(cls, Decimal) and any(value.is_nan() for value in members)) or (
issubclass(cls, datetime.time) and any(value.tzinfo is not None for value in members)
issubclass(cls, dt.time) and any(value.tzinfo is not None for value in members)
):
return None
else:
Expand Down Expand Up @@ -683,8 +682,8 @@ def _to_polars(values: pd.Series, annotation: object) -> PolarsSeries:
(int, polars.Int64),
(float, polars.Float64),
(bool, polars.Boolean),
(datetime.date, polars.Date),
(datetime.datetime, polars.Datetime),
(dt.date, polars.Date),
(dt.datetime, polars.Datetime),
)
if _mixes_converted_types(annotation):
msg = f"A anotação {annotation} junta tipos que o pyarrow converte uns nos outros."
Expand Down Expand Up @@ -1314,9 +1313,9 @@ def list_layers(annotation: object, target: type) -> int | None:
complex,
Decimal,
Enum,
datetime.date,
datetime.time,
datetime.timedelta,
dt.date,
dt.time,
dt.timedelta,
)


Expand Down
4 changes: 2 additions & 2 deletions tests/test_checkpoint_robusto.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Checkpoint que falha ao gravar e retomada a partir de CSV/XLSX."""

import datetime
import datetime as dt
import warnings
from enum import Enum
from typing import Annotated, Literal, NewType, Optional, TypeVar
Expand Down Expand Up @@ -418,7 +418,7 @@ def grava(df, path, *_):
def test_checkpoint_textual_serializa_data_dentro_de_dict(tmp_path):

ckpt = tmp_path / "ckpt.csv"
_save_checkpoint(pd.DataFrame({"meta": [{"quando": datetime.date(2026, 9, 24)}]}), ckpt)
_save_checkpoint(pd.DataFrame({"meta": [{"quando": dt.date(2026, 9, 24)}]}), ckpt)
assert pd.read_csv(ckpt)["meta"][0] == '{"quando": "2026-09-24"}'


Expand Down
8 changes: 4 additions & 4 deletions tests/test_conditional.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import collections
import collections.abc
import datetime
import datetime as dt
import logging
import os
import re
Expand Down Expand Up @@ -1487,12 +1487,12 @@ class _Cadastro(BaseModel):
porte: Literal["pequeno", "grande"] = "pequeno"
rotulo: Annotated[str, "rótulo"] = ""
codigo: str | int = ""
inicio: datetime.date | None = None
inicio: dt.date | None = None
bruto: bytes = b""
fase: complex = 0j
preco: Decimal | None = None
hora: datetime.time | None = None
prazo: datetime.timedelta | None = None
hora: dt.time | None = None
prazo: dt.timedelta | None = None


@pytest.mark.parametrize(
Expand Down
6 changes: 3 additions & 3 deletions tests/test_multiple_data_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- dict
"""

import datetime
import datetime as dt
import importlib.util
import sys
import warnings
Expand Down Expand Up @@ -305,13 +305,13 @@ def test_inteiro_sem_nulo_fica_como_estava(self):
assert from_pandas(df, info)["id"].dtype == pl.UInt8

def test_coluna_de_data_continua_data(self):
data = pl.DataFrame({"texto": ["a"], "dia": [datetime.date(2024, 1, 2)]})
data = pl.DataFrame({"texto": ["a"], "dia": [dt.date(2024, 1, 2)]})

df, info = to_pandas(data)
result = from_pandas(df, info)

assert result["dia"].dtype == pl.Date
assert result["dia"].to_list() == [datetime.date(2024, 1, 2)]
assert result["dia"].to_list() == [dt.date(2024, 1, 2)]

def test_campo_do_modelo_que_estava_na_entrada_sai_do_pandas(self):
data = pl.DataFrame({"texto": ["a"], "nota": [7]})
Expand Down
36 changes: 18 additions & 18 deletions tests/test_retomada_assinada.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import contextlib
import csv
import datetime
import datetime as dt
import warnings
from collections.abc import Mapping, Sequence
from collections.abc import Set as AbstractSet
Expand Down Expand Up @@ -633,7 +633,7 @@ def llm(text, *args, **kwargs):


class ComData(BaseModel):
quando: dict[str, datetime.date]
quando: dict[str, dt.date]


class ComTupla(BaseModel):
Expand All @@ -645,7 +645,7 @@ class ComChaveInt(BaseModel):


_TIPADOS = {
ComData: ("quando", lambda texto: {texto: datetime.date(2024, 1, 2)}),
ComData: ("quando", lambda texto: {texto: dt.date(2024, 1, 2)}),
ComTupla: ("par", lambda texto: (1, texto)),
ComChaveInt: ("mapa", lambda texto: {1: texto, 10: texto, 2: texto}),
}
Expand Down Expand Up @@ -736,8 +736,8 @@ def so_com_itens(cls, valor, info):


class DatasDepoisDoInicio(BaseModel):
inicio: datetime.date
datas: list[datetime.date]
inicio: dt.date
datas: list[dt.date]

@model_validator(mode="after")
def depois_do_inicio(self):
Expand All @@ -748,7 +748,7 @@ def depois_do_inicio(self):


class DatasEmTexto(BaseModel):
datas: list[datetime.date]
datas: list[dt.date]

@field_serializer("datas")
def em_texto(self, valor):
Expand Down Expand Up @@ -787,10 +787,10 @@ def avanca(cls, valor):
ExclamaAteDuasVezes: lambda texto: {"n": [texto]},
FiltraPorOutroCampo: lambda texto: {"tem_itens": True, "itens": [texto]},
DatasDepoisDoInicio: lambda texto: {
"inicio": datetime.date(2024, 1, 1),
"datas": [datetime.date(2024, 1, 2)],
"inicio": dt.date(2024, 1, 1),
"datas": [dt.date(2024, 1, 2)],
},
DatasEmTexto: lambda texto: {"datas": [datetime.date(2024, 1, 2)]},
DatasEmTexto: lambda texto: {"datas": [dt.date(2024, 1, 2)]},
}


Expand Down Expand Up @@ -987,11 +987,11 @@ class Nota(Enum):

class Estrito(BaseModel):
model_config = ConfigDict(strict=True)
datas: list[datetime.date]
datas: list[dt.date]
par: tuple[int, str]
cores: list[Cor]
dia: datetime.date
quando: datetime.datetime
dia: dt.date
quando: dt.datetime
cor: Cor
nivel: Nivel
nota: Nota
Expand All @@ -1000,8 +1000,8 @@ class Estrito(BaseModel):


class Escalares(BaseModel):
dia: datetime.date
quando: datetime.datetime
dia: dt.date
quando: dt.datetime
cor: Cor
nivel: Nivel
nota: Nota
Expand All @@ -1010,11 +1010,11 @@ class Escalares(BaseModel):


_RESPOSTA_TIPADA = {
"datas": [datetime.date(2024, 1, 2)],
"datas": [dt.date(2024, 1, 2)],
"par": (1, "a"),
"cores": [Cor.AZUL],
"dia": datetime.date(2024, 1, 2),
"quando": datetime.datetime(2024, 1, 2, 3, 4, 5), # noqa: DTZ001 (o XLSX não guarda fuso)
"dia": dt.date(2024, 1, 2),
"quando": dt.datetime(2024, 1, 2, 3, 4, 5), # noqa: DTZ001 (o XLSX não guarda fuso)
"cor": Cor.AZUL,
"nivel": Nivel.BAIXO,
"nota": Nota.A,
Expand Down Expand Up @@ -1064,7 +1064,7 @@ def resposta(text):

class EstritoComNumero(BaseModel):
model_config = ConfigDict(strict=True)
datas: list[datetime.date]
datas: list[dt.date]
n: int


Expand Down
Loading