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
3 changes: 1 addition & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ repos:
- id: mypy
files: "^src/"
additional_dependencies:
- pydantic >2
- pydantic-compat
- pydantic >2.8
- in-n-out

- repo: local
Expand Down
7 changes: 2 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ classifiers = [
dynamic = ["version"]
dependencies = [
"psygnal>=0.10",
"pydantic>=1.10.18",
"pydantic-compat>=0.1.1",
"pydantic>=2.8",
"in-n-out>=0.1.5",
"typing_extensions>=4.12",
]
Expand All @@ -53,7 +52,7 @@ qt = ["qtpy>=2.4.0", "superqt[iconify]>=0.7.2"]
pyqt5 = [
"app-model[qt]",
"PyQt5>=5.15.10",
"pyqt5-qt5<=5.15.2; sys_platform == 'win32'",
"pyqt5-qt5==5.15.2; sys_platform == 'win32'",
"pyqt5-qt5>=5.15.4; sys_platform != 'win32'",
]
pyqt6 = ["app-model[qt]", "PyQt6>=6.4.0"]
Expand Down Expand Up @@ -154,8 +153,6 @@ filterwarnings = [
"error",
"ignore:Enum value:DeprecationWarning:superqt",
"ignore:Failed to disconnect::pytestqt",
"ignore:Failing to pass a value to the 'type_params' parameter::pydantic",
"ignore:`__get_validators__` is deprecated and will be removed",
]

# https://mypy.readthedocs.io/en/stable/config_file.html
Expand Down
6 changes: 0 additions & 6 deletions src/app_model/expressions/_expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from typing import (
TYPE_CHECKING,
Any,
Callable,
Generic,
SupportsIndex,
TypeVar,
Expand Down Expand Up @@ -342,11 +341,6 @@ def __reduce_ex__(self, protocol: SupportsIndex) -> tuple[Any, ...]:
rv[1] = tuple(getattr(self, f) for f in self._fields)
return tuple(rv)

@classmethod
def __get_validators__(cls) -> Iterator[Callable[[Any], Expr]]:
"""Pydantic validators for this class."""
yield cls._validate

@classmethod
def __get_pydantic_core_schema__(
cls, source: type, handler: GetCoreSchemaHandler
Expand Down
2 changes: 1 addition & 1 deletion src/app_model/types/_action.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import TYPE_CHECKING, Callable, Generic, Optional, TypeVar, Union

from pydantic_compat import Field, field_validator
from pydantic import Field, field_validator

from ._command_rule import CommandRule
from ._keybinding_rule import KeyBindingRule
Expand Down
2 changes: 1 addition & 1 deletion src/app_model/types/_base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import TYPE_CHECKING, ClassVar

from pydantic_compat import BaseModel
from pydantic import BaseModel

if TYPE_CHECKING:
from pydantic import ConfigDict
Expand Down
2 changes: 1 addition & 1 deletion src/app_model/types/_command_rule.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Callable, Optional, Union

from pydantic_compat import Field
from pydantic import Field

from app_model import expressions

Expand Down
9 changes: 2 additions & 7 deletions src/app_model/types/_icon.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from collections.abc import Generator
from typing import Any, Callable, Optional, TypedDict, Union
from typing import Any, Optional, TypedDict, Union

from pydantic_compat import Field, model_validator
from pydantic import Field, model_validator

from ._base import _BaseModel

Expand Down Expand Up @@ -30,10 +29,6 @@ class Icon(_BaseModel):
" keys, such as `fa6s.arrow_down`",
)

@classmethod
def __get_validators__(cls) -> Generator[Callable[..., Any], None, None]:
yield cls._validate

@classmethod
def _validate(cls, v: Any) -> "Icon":
"""Validate icon."""
Expand Down
34 changes: 9 additions & 25 deletions src/app_model/types/_keybinding_rule.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any, Callable, Optional, TypedDict, TypeVar, Union

from pydantic_compat import PYDANTIC2, Field, model_validator
from pydantic import Field, model_validator

from app_model import expressions

Expand Down Expand Up @@ -63,30 +63,14 @@ def _bind_to_current_platform(self) -> Optional[KeyEncoding]:
return self.linux
return self.primary

# These methods are here to make KeyBindingRule work as a field
# there are better ways to do this now with pydantic v2... but it still
# feels a bit in flux. pydantic_compat might not yet work for this (or
# at least in my playing around i couldn't get it)
# so sticking with this one conditional method here...
if PYDANTIC2:
# for v2
@model_validator(mode="wrap")
@classmethod
def _model_val(
cls: type[M], v: Any, handler: Callable[[Any], M]
) -> "KeyBindingRule":
if isinstance(v, StandardKeyBinding):
return v.to_keybinding_rule()
return handler(v) # type: ignore

else:

@classmethod
def validate(cls, value: Any) -> "KeyBindingRule":
"""Validate keybinding rule."""
if isinstance(value, StandardKeyBinding):
return value.to_keybinding_rule()
return super().validate(value)
@model_validator(mode="wrap")
@classmethod
def _model_val(
cls: type[M], v: Any, handler: Callable[[Any], M]
) -> "KeyBindingRule":
if isinstance(v, StandardKeyBinding):
return v.to_keybinding_rule()
return handler(v) # type: ignore


class KeyBindingRuleDict(TypedDict, total=False):
Expand Down
3 changes: 0 additions & 3 deletions src/app_model/types/_keys/_key_codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,6 @@ def from_event_code(cls, event_code: int) -> 'KeyCode':
"""
return _EVENTCODE_TO_KEYCODE.get(event_code, KeyCode.UNKNOWN)

@classmethod
def __get_validators__(cls) -> Generator[Callable[..., 'KeyCode'], None, None]:
yield cls.validate

@classmethod
def __get_pydantic_core_schema__(
Expand Down
11 changes: 3 additions & 8 deletions src/app_model/types/_keys/_keybindings.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import re
from collections.abc import Generator
from typing import TYPE_CHECKING, Any, Callable, Optional
from typing import TYPE_CHECKING, Any, Optional

from pydantic_compat import PYDANTIC2, BaseModel, Field, model_validator
from pydantic import BaseModel, Field, model_validator

from app_model.types._constants import OperatingSystem

Expand Down Expand Up @@ -166,7 +165,7 @@ def _model_val(cls, instance: "SimpleKeyBinding") -> "SimpleKeyBinding":
return cls._parse_input(instance)


MIN1 = {"min_length": 1} if PYDANTIC2 else {"min_items": 1}
MIN1 = {"min_length": 1}


class KeyBinding:
Expand Down Expand Up @@ -277,10 +276,6 @@ def __int__(self) -> int:
def __hash__(self) -> int:
return hash(tuple(self.parts))

@classmethod
def __get_validators__(cls) -> Generator[Callable[..., Any], None, None]:
yield cls.validate # pragma: no cover

@classmethod
def __get_pydantic_core_schema__(
cls, source: type, handler: "GetCoreSchemaHandler"
Expand Down
17 changes: 2 additions & 15 deletions src/app_model/types/_menu_rule.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
from collections.abc import Generator
from typing import (
Any,
Callable,
Optional,
TypedDict,
Union,
)

from pydantic_compat import Field, field_validator, model_validator
from pydantic import Field, field_validator, model_validator

from app_model import expressions

Expand Down Expand Up @@ -37,10 +35,6 @@ class MenuItemBase(_BaseModel):
"and the syntax 'group@order'. If not provided, items are sorted by title.",
)

@classmethod
def __get_validators__(cls) -> Generator[Callable[..., Any], None, None]:
yield cls._validate

@classmethod
def _validate(cls: type["MenuItemBase"], v: Any) -> "MenuItemBase":
"""Validate icon."""
Expand All @@ -64,15 +58,8 @@ class MenuRule(MenuItemBase):

id: str = Field(..., description="Menu in which to place this item.")

# for v1
@classmethod
def _validate(cls: type["MenuRule"], v: Any) -> Any:
if isinstance(v, str):
v = {"id": v}
return super()._validate(v)

# for v2
@model_validator(mode="before")
@classmethod
def _validate_model(cls, v: Any) -> Any:
"""If a single string is provided, convert to a dict with `id` key."""
return {"id": v} if isinstance(v, str) else v
Expand Down
11 changes: 2 additions & 9 deletions tests/test_keybindings.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import itertools
import sys
from typing import ClassVar

import pytest
from pydantic_compat import PYDANTIC2, BaseModel
from pydantic import BaseModel

from app_model.types import (
KeyBinding,
Expand Down Expand Up @@ -179,14 +178,8 @@ def test_in_model() -> None:
class M(BaseModel):
key: KeyBinding

if not PYDANTIC2:

class Config:
json_encoders: ClassVar[dict] = {KeyBinding: str}

m = M(key="Shift+A B")
# pydantic v1 and v2 have slightly different json outputs
assert m.model_dump_json().replace('": "', '":"') == '{"key":"Shift+A B"}'
assert m.model_dump_json() == '{"key":"Shift+A B"}'


def test_standard_keybindings() -> None:
Expand Down
Loading