From 807b1a71759318f6ff9fbf8c29b5fc21086f54dd Mon Sep 17 00:00:00 2001 From: getzze Date: Fri, 9 Feb 2024 14:10:19 +0000 Subject: [PATCH] remove compatibility with pydantic.v1, not pydantic v1 --- src/psygnal/_dataclass_utils.py | 53 ++++++++++++++++++++++---------- src/psygnal/_group_descriptor.py | 2 +- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/psygnal/_dataclass_utils.py b/src/psygnal/_dataclass_utils.py index bbde288c..ac66eeeb 100644 --- a/src/psygnal/_dataclass_utils.py +++ b/src/psygnal/_dataclass_utils.py @@ -324,9 +324,6 @@ class Foo: # Add metadata for pydantic dataclass if is_pydantic_model(cls): - # Pydantic v2 - if not hasattr(cls, "model_fields"): - return """ Example ------- @@ -335,12 +332,14 @@ class Foo: from pydantic import BaseModel, Field + # Only works with Pydantic v2 class Foo(BaseModel): bar: Annotated[ str, {'__psygnal_metadata': {"alias": "bar_alias"}} ] = Field(...) + # Working with Pydantic v2 and partially with v1 # Alternative, using Field `json_schema_extra` keyword argument class Bar(BaseModel): bar: str = Field( @@ -358,20 +357,40 @@ class Bar(BaseModel): ) """ - for field_name, p_field in cls.model_fields.items(): - if not p_field.frozen or not exclude_frozen: - metadata_list = getattr(p_field, "metadata", []) - metadata = {} - for field in metadata_list: - metadata.update(field.get(PSYGNAL_METADATA, {})) - # Compatibility with using Field `json_schema_extra` keyword argument - if isinstance(getattr(p_field, "json_schema_extra", None), Mapping): - extra = cast(Mapping, p_field.json_schema_extra) - metadata.update(extra.get(PSYGNAL_METADATA, {})) - metadata = sanitize_field_options_dict(metadata) - options = FieldOptions(field_name, p_field.annotation, **metadata) - yield options - return + if hasattr(cls, "model_fields"): + # Pydantic v2 + for field_name, p_field in cls.model_fields.items(): + if not p_field.frozen or not exclude_frozen: + metadata_list = getattr(p_field, "metadata", []) + metadata = {} + for field in metadata_list: + metadata.update(field.get(PSYGNAL_METADATA, {})) + # Compat with using Field `json_schema_extra` keyword argument + if isinstance(getattr(p_field, "json_schema_extra", None), Mapping): + meta_dict = cast(Mapping, p_field.json_schema_extra) + metadata.update(meta_dict.get(PSYGNAL_METADATA, {})) + metadata = sanitize_field_options_dict(metadata) + options = FieldOptions(field_name, p_field.annotation, **metadata) + yield options + return + + else: + # Pydantic v1, metadata is not always working + for pv1_field in cls.__fields__.values(): # type: ignore [attr-defined] + if pv1_field.field_info.allow_mutation or not exclude_frozen: # type: ignore [attr-defined] + meta_dict = getattr(pv1_field.field_info, "extra", {}).get( # type: ignore [attr-defined] + "json_schema_extra", {} + ) + metadata = meta_dict.get(PSYGNAL_METADATA, {}) + + metadata = sanitize_field_options_dict(metadata) + options = FieldOptions( + pv1_field.name, # type: ignore [attr-defined] + pv1_field.outer_type_, # type: ignore [attr-defined] + **metadata, + ) + yield options + return # Add metadata for attrs dataclass attrs_fields = getattr(cls, "__attrs_attrs__", None) diff --git a/src/psygnal/_group_descriptor.py b/src/psygnal/_group_descriptor.py index b0d4352a..3bc9dc11 100644 --- a/src/psygnal/_group_descriptor.py +++ b/src/psygnal/_group_descriptor.py @@ -232,7 +232,7 @@ def _build_dataclass_signal_group( # Overwrite the signal aliases with user defined signal_aliases = {**signal_aliases, **_fields_table} - # print(f"Create SignalGroup: {group_name}, {signal_aliases=}, {signals=}") + # Create SignalGroup subclass with the attached signals and signal_aliases return type(group_name, (SignalGroup,), signals, signal_aliases=signal_aliases)