sqltypes.Enum not generic enough
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
- #13492 @waterWang による — マージされずにクローズ
評価
調査の方向性
lib/sqlalchemy/sql/sqltypes.py の String と Enum の定義から始め、pyright エラーと提案されている型付けの変更について、リンクされている議論を読んでください。Enum(MyEnum, native_enum=False) と column_property を使う例を確認してください。報告されている pyright の指摘なしに、ジェネリックな Enum の型付けでその使用方法をサポートできれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Discussed in https://github.com/sqlalchemy/sqlalchemy/discussions/11548
The generic type for Enum needs to be a typevar for pyright:
from __future__ import annotations
import enum
from sqlalchemy import Enum
from sqlalchemy import func
from sqlalchemy.orm import column_property
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
class MyEnum(enum.Enum):
one = "one"
two = "two"
class Base(DeclarativeBase):
pass
class A(Base):
__tablename__ = "a"
id: Mapped[int] = mapped_column(primary_key=True)
data: Mapped[MyEnum] = column_property(
func.some_func(type_=Enum(MyEnum, native_enum=False))
)
seems to pass in mypy
a quick fix looks like:
@@ -1179,8 +1186,9 @@ class SchemaType(SchemaEventTarget, TypeEngineMixin):
elif dialect.name not in variant_mapping:
return _we_are_the_impl(variant_mapping["_default"])
+_TEE = TypeVar("_TEE", bound=Union[str, enum.Enum])
-class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]):
+class Enum(String, SchemaType, Emulated, TypeEngine[_TEE]):
"""Generic Enum Type.
The :class:`.Enum` type provides a set of possible string values
@@ -1483,7 +1491,7 @@ class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]):
self.enum_class = None
return enums, enums
- def _resolve_for_literal(self, value: Any) -> Enum:
+ def _resolve_for_literal(self, value: Any) -> Enum[Any]:
tv = type(value)
typ = self._resolve_for_python_type(tv, tv, tv)
assert typ is not None
@@ -1494,7 +1502,7 @@ class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]):
python_type: Type[Any],
matched_on: _MatchedOnType,
matched_on_flattened: Type[Any],
- ) -> Optional[Enum]:
+ ) -> Optional[Enum[Any]]:
# "generic form" indicates we were placed in a type map
# as ``sqlalchemy.Enum(enum.Enum)`` which indicates we need to
# get enumerated values from the datatype
@@ -1538,7 +1546,7 @@ class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]):
kw["length"] = NO_ARG if self.length == 0 else self.length
return cast(
- Enum,
+ Enum[Any],
self._generic_type_affinity(_enums=enum_args, **kw), # type: ignore # noqa: E501
)
to go further we might want to remove String from Enum's inherits, since pyright still complains about the signature
diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py
index c20df07a6..f948ee01d 100644
--- a/lib/sqlalchemy/sql/sqltypes.py
+++ b/lib/sqlalchemy/sql/sqltypes.py
@@ -256,6 +256,13 @@ class String(Concatenable, TypeEngine[str]):
return dbapi.STRING
+if TYPE_CHECKING:
+ class StringNoGeneric(Concatenable):
+ pass
+else:
+ StringNoGeneric = String
+
+
class Text(String):
"""A variably sized string type.
@@ -1179,8 +1186,9 @@ class SchemaType(SchemaEventTarget, TypeEngineMixin):
elif dialect.name not in variant_mapping:
return _we_are_the_impl(variant_mapping["_default"])
+_TEE = TypeVar("_TEE", bound=Union[str, enum.Enum])
-class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]):
+class Enum(StringNoGeneric, SchemaType, Emulated, TypeEngine[_TEE]):
"""Generic Enum Type.
The :class:`.Enum` type provides a set of possible string values
@@ -1483,7 +1491,7 @@ class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]):
self.enum_class = None
return enums, enums
- def _resolve_for_literal(self, value: Any) -> Enum:
+ def _resolve_for_literal(self, value: Any) -> Enum[Any]:
tv = type(value)
typ = self._resolve_for_python_type(tv, tv, tv)
assert typ is not None
@@ -1494,7 +1502,7 @@ class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]):
python_type: Type[Any],
matched_on: _MatchedOnType,
matched_on_flattened: Type[Any],
- ) -> Optional[Enum]:
+ ) -> Optional[Enum[Any]]:
# "generic form" indicates we were placed in a type map
# as ``sqlalchemy.Enum(enum.Enum)`` which indicates we need to
# get enumerated values from the datatype
@@ -1538,7 +1546,7 @@ class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]):
kw["length"] = NO_ARG if self.length == 0 else self.length
return cast(
- Enum,
+ Enum[Any],
self._generic_type_affinity(_enums=enum_args, **kw), # type: ignore # noqa: E501
)
- 主要言語
- Python
- スター
- 12.3k
- フォーク
- 1.8k
- 平均マージ
- 2日 10時間
- マージ済み PR(30日)
- 9
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
sqlalchemy/sqlalchemy のほかの issue
-
requires triage
難易度 1/5 1〜3時間 初心者へのやさしさ 85/100
sqlalchemy/sqlalchemy#13784 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
bug engine
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
sqlalchemy/sqlalchemy#13770 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
declared_attr.cascading fails to typecheck under mypy / pyright on documented usage再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンbug orm typing
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
sqlalchemy/sqlalchemy#13731 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
PostgreSQL multihost URL with bracketed IPv6 hosts raises ValueError: too many values to unpack再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンbug engine postgresql
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
sqlalchemy/sqlalchemy#13637 · コメント 6 件 ·
メンテナーはふだん 1 日以内に返信
-
asyncpg dialect raises DBAPIError, not DataError, for SQLSTATE class 22 errors対応中かも @HardMax71 が 21 日前に担当しました。 オープンbug code review in progress dialects
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
sqlalchemy/sqlalchemy#13636 · コメント 19 件 ·
メンテナーはふだん 1 日以内に返信
sqlalchemy/sqlalchemy の issue をすべて見る
似ている issue
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 80/100
glossyio/traffic-monitor#312 ·
メンテナーはふだん 1 日以内に返信
-
local devenv exampleオープンdocumentation enhancement
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
es-ude/elastic-ai.creator#1046 ·
メンテナーはふだん 3 日以内に返信
-
feature request
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
confident-ai/deepteam#306 ·
メンテナーはふだん 1 日以内に返信
-
SslLibrary crashes with unhandled OSError: port/proto not found on non-standard SSL ports対応中かも @himanchalkaushale が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
OWASP/Nettacker#1884 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信