Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Union deserialization algorithm more robust #256

Merged
merged 6 commits into from
Nov 12, 2024
Merged

Conversation

Fatal1ty
Copy link
Owner

@Fatal1ty Fatal1ty commented Nov 11, 2024

Closes #42, #221, #252, #255

This PR brings a new type of expression TypeMatchEligibleExpression. It conveys that the expression built for a ValueSpec is eligible for direct processing the value if the type matches, but doesn’t guarantee that it will always be processed that way. This information is used in Union deserialization algorithm to return the input value as is only when its type is in the list of expected types. The order of variant types still matters. The following value types will have TypeMatchEligibleExpression:

  • str
  • bool
  • int
  • float
  • NoneType

If the input value type doesn't match any of the expected types, it will be processed as before or as written below.

This PR also changes the way how str, bool and NoneType values are processed on deserialization outside on Union:

  • Expected str value will processed as str(value)
  • Expected bool value will be processed as bool(value)
  • Expected NoneType value will always be None regardless of the input value

Some examples:

@dataclass
class Foo(DataClassDictMixin):
    foo: str | int

Foo.from_dict({"foo": "1"})  # Foo(foo="1")
Foo.from_dict({"foo": 1})    # Foo(foo=1)
@dataclass
class Foo(DataClassDictMixin):
    foo: int | str

Foo.from_dict({"foo": "1"})  # Foo(foo="1")
Foo.from_dict({"foo": 1})    # Foo(foo=1)
@dataclass
class Foo(DataClassDictMixin):
    foo: str | date

Foo.from_dict({"foo": "2024-11-11"})  # Foo(foo="2024-11-11")
@dataclass
class Foo(DataClassDictMixin):
    foo: date | str

Foo.from_dict({"foo": "2024-11-11"})  # Foo(foo=date(2024, 11, 11))
@dataclass
class Foo(DataClassDictMixin):
    foo: int | float

Foo.from_dict({"foo": 1})      # Foo(foo=1)
Foo.from_dict({"foo": 1.0})    # Foo(foo=1.0)
Foo.from_dict({"foo": "1"})    # Foo(foo=1)
Foo.from_dict({"foo": "1.0"})  # Foo(foo=1.0)
@dataclass
class Foo(DataClassDictMixin):
    foo: float | int

Foo.from_dict({"foo": 1})      # Foo(foo=1)
Foo.from_dict({"foo": 1.0})    # Foo(foo=1.0)
Foo.from_dict({"foo": "1"})    # Foo(foo=1)
Foo.from_dict({"foo": "1.0"})  # Foo(foo=1.0)
@dataclass
class Foo(DataClassDictMixin):
    foo: bool | int

Foo.from_dict({"foo": 1})          # Foo(foo=1)
Foo.from_dict({"foo": True})       # Foo(foo=True)
Foo.from_dict({"foo": "1"})        # Foo(foo=True)
Foo.from_dict({"foo": [1, 2, 3]})  # Foo(foo=True)
Foo.from_dict({"foo": "1.2"})      # Foo(foo=True)
Foo.from_dict({"foo": [1, 2, 3]})  # Foo(foo=True)
@dataclass
class Foo(DataClassDictMixin):
    foo: int | bool

Foo.from_dict({"foo": 1})          # Foo(foo=1)
Foo.from_dict({"foo": True})       # Foo(foo=True)
Foo.from_dict({"foo": "1"})        # Foo(foo=1)
Foo.from_dict({"foo": [1, 2, 3]})  # Foo(foo=True)
Foo.from_dict({"foo": "1.2"})      # Foo(foo=True)
Foo.from_dict({"foo": [1, 2, 3]})  # Foo(foo=True)
@dataclass
class Foo(DataClassDictMixin):
    foo: type(None)

Foo.from_dict({"foo": 1})      # Foo(foo=None)
Foo.from_dict({"foo": "bar"})  # Foo(foo=None)
@dataclass
class Foo(DataClassDictMixin):
    foo: tuple[type(None), type(None), type(None)]

Foo.from_dict({"foo": [1, 2, 3]})  # Foo(foo=(None, None, None))

@Fatal1ty Fatal1ty changed the title Make Union deserialization algorithn more robust Make Union deserialization algorithm more robust Nov 12, 2024
@Fatal1ty Fatal1ty merged commit ad41838 into master Nov 12, 2024
52 checks passed
@Fatal1ty Fatal1ty deleted the new-union-unpacker branch November 12, 2024 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Inconsistent checks for invalid value type for str field type
1 participant