python / python/mypy

mypy seems to use type from field definition instead of type of field_validator

オープン
#15,977 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

bug
主要言語
Python
スター
20.6k
フォーク
3.3k
PR マージ指標
PR 指標を取得中

説明

Description
I created a class that accepts a field with both a list[float] and a NDArray which converts it to NDArray after field validation (set to always via ConfigDict(validate_assignment = True)). However mypy complains about divide and substract operations over the vector field which should not as the field cannot be of type list[float] after validation.

At the moment I am using the # type: ignore[call-overload, operator] (Without those I get mypy errors).

image

Note: I have raised same issue in pydantic (https://github.com/pydantic/pydantic/issues/7262)

Example Code

import numpy as np
from numpy.typing import NDArray
from pydantic import BaseModel, ConfigDict, Field, computed_field, field_validator

class Vector(BaseModel):
    model_config = ConfigDict(arbitrary_types_allowed=True, validate_assignment=True)

    vector: NDArray[np.float64] | list[float] = Field(default=np.array([0.0, 0.0, 0.0]), min_length=3, max_length=3)

    @field_validator("vector")
    @classmethod
    def vector_validator(cls, v: NDArray[np.float64] | list[float]) -> NDArray:
        if isinstance(v, list):
            return np.array(v)
        return v

    @computed_field  # type: ignore[misc]
    @property
    def x(self) -> NDArray:
        return self.vector[0]

    @x.setter
    def x(self, value: float) -> None:
        self.vector[0] = value

    @computed_field  # type: ignore[misc]
    @property
    def y(self) -> NDArray:
        return self.vector[1]

    @y.setter
    def y(self, value: float) -> None:
        self.vector[1] = value

    @computed_field  # type: ignore[misc]
    @property
    def z(self) -> NDArray:
        return self.vector[2]

    @z.setter
    def z(self, value: float) -> None:
        self.vector[2] = value

    def to_unit(self) -> "Vector":
        return Vector(vector=self.vector / np.linalg.norm(self.vector))  # type: ignore[call-overload, operator]

    def __add__(self, other: "Vector") -> "Vector":
        return Vector(vector=self.vector + other.vector)

    def __sub__(self, other: "Vector") -> "Vector":
        return Vector(vector=self.vector - other.vector)  # type: ignore[operator]

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

まず Example Code を mypy で実行し、報告されたエラーを validator の戻り値の型と比較します。mypy が宣言されたベクトルフィールドの型をどのように表現するか、また field_validator の情報が型チェックで利用可能かを調査します。示されている除算および減算の操作で、一覧にある type: ignore コメントが不要になり、既存の動作が維持されれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
numpy, python
領域
devtools, tooling
issue の種類
バグ
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。