apache / apache/iceberg-python

Expression constructors are not mypy-compatible without the pydantic plugin

Aberta
#3,101 1 comentário 0 reações 0 responsáveis Ver no GitHub
Linguagem predominante
Python
Estrelas
1.1k
Forks
581
Merge médio
1d 17h
PRs com merge (30d)
78

Descrição

Constructing expression predicates like `EqualTo("col", value)` produces mypy errors because the Pydantic model field declarations use `UnboundTerm` as the type for `term`, and without the pydantic mypy plugin active, mypy generates `__init__` signatures from the field types rather than from the explicit `__init__` overrides.

**Example:**

```python
from pyiceberg import expressions as ice

expr = ice.EqualTo("my_column", 42)
```

**mypy output (v1.19.1, pyiceberg 0.11.0, no pydantic mypy plugin):**

```
error: Argument 1 to "EqualTo" has incompatible type "str"; expected "UnboundTerm" [arg-type]
```

**Root cause:**

The base classes define explicit `__init__` methods that accept `str | UnboundTerm`:

- [`UnboundPredicate.__init__`](https://github.com/apache/iceberg-python/blob/main/pyiceberg/expressions/__init__.py#L500): `def __init__(self, term: str | UnboundTerm, **kwargs: Any) -> None`
- [`LiteralPredicate.__init__`](https://github.com/apache/iceberg-python/blob/main/pyiceberg/expressions/__init__.py#L864): `def __init__(self, term: str | UnboundTerm, literal: Any | None = None, **kwargs: Any) -> None`
- [`UnaryPredicate.__init__`](https://github.com/apache/iceberg-python/blob/main/pyiceberg/expressions/__init__.py#L520): `def __init__(self, term: str | UnboundTerm, **_: Any) -> None`

But since these classes extend `IcebergBaseModel` (Pydantic `BaseModel`), mypy ignores the explicit `__init__` and instead generates the constructor signature from the field declaration `term: UnboundTerm`, which does not include `str`.

This affects all predicate constructors: `EqualTo`, `NotEqualTo`, `GreaterThan`, `GreaterThanOrEqual`, `LessThan`, `LessThanOrEqual`, `IsNull`, `NotNull`, `IsNaN`, `NotNaN`, `In`, `NotIn`, `StartsWith`, `NotStartsWith`.

**Workaround:**

Downstream projects can either enable the pydantic mypy plugin or suppress type checking for the affected call sites.

**Possible fix:**

Widen the field type annotation on `UnboundPredicate` from `term: UnboundTerm` to `term: str | UnboundTerm` with a validator that coerces `str` to `UnboundTerm`. This way the type seen by mypy (from the field declaration) matches what the constructor actually accepts at runtime, regardless of whether the pydantic mypy plugin is enabled.

Guia de contribuição

Nenhum guia de contribuição indexado para este repositório

Direção de pesquisa

Comece em pyiceberg/expressions/__init__.py, nos construtores de UnboundPredicate, LiteralPredicate e UnaryPredicate e nas declarações de seus campos term. Verifique o comportamento existente do validator e, em seguida, confirme que o mypy sem o plugin do Pydantic aceita os construtores de predicados listados e que os termos string continuam sendo convertidos corretamente em tempo de execução.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
python
Domínio
developer-experience
Tipo de issue
Bug
Dificuldade
3/5
Tempo estimado
1-2 dias
Status de atividade
Pouca atividade
Clareza
Razoavelmente clara
Facilidade para iniciantes
65/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.