pydantic-core icon indicating copy to clipboard operation
pydantic-core copied to clipboard

Fail-fast feature

Open uriyyo opened this issue 1 year ago • 8 comments

Basic implementation here - #1321

Context: https://github.com/pydantic/pydantic-core/pull/1322#issuecomment-2166806100 https://github.com/pydantic/pydantic/pull/9708#issuecomment-2187337782

fail-fast feature might be extended and used not only for sequence types. It might be useful for other types like mappings or models.

I can see that it can be powerful feature when you can from python validator stop validation process by raising an exception. As was mentioned by @adriangb here - https://github.com/pydantic/pydantic-core/pull/1322#issuecomment-2166806100

I would like to work on both features if you don't mind.

Please let me know if you have some tips and ideas about implementation!

cc @sydney-runkle @adriangb

uriyyo avatar Jun 25 '24 12:06 uriyyo

@uriyyo,

That sounds wonderful. Thanks for your amazing work here.

I like the idea of:

  1. A runtime flag fail_fast that is passed to model_validate
  2. A FailNow data structure that can be used in custom validators
  3. Generally, support for failing early / fast for lots of data types.

Let's confirm with @davidhewitt and @adriangb before moving forwards :).

sydney-runkle avatar Jun 25 '24 15:06 sydney-runkle

Seems fine to me. I'm less sure about the FailNow structure; it might be better to instead pass fail_fast in the info and then let custom validators decide when to fail fast that way.

davidhewitt avatar Jun 26 '24 13:06 davidhewitt

I would love to be able to use FailFast() on Literals. Currently I am having some performance troubles with a large number of different objects that can be passed to a list or Sequence. I am using a field called "name" to differentiate the different models. Do you think that FailFast() could help speed things up in this case or is it really an architectural issue?

BMMevius avatar Nov 18 '24 11:11 BMMevius

Hmm, I don't think Fail-fast makes sense for literals. Could you give an example of your use case here? Guessing that discriminated unions might help here. Thanks!

sydney-runkle avatar Nov 18 '24 14:11 sydney-runkle

I have a list like this:

[
    {
        "name": "Name1",
        "arg1": 1.0
    },
    {
        "name": "Name2",
        "arg2": 3.0
    }
]

The accompanying models are:

from typing import Literal
from pydantic.dataclasses import dataclass

class BaseClass:
    name: str

@dataclass
class Name1(BaseClass):
    name: Literal[”Name1”]
    arg1: float

    def do_something(self):
        return 10 * self.arg1

@dataclass
class Name2(Base class):
    name: Literal["Name2"]
    arg2: float

    def do_something(self):
        return 10 * self.arg2

@dataclass
class Objects:
    objects: list[Name1 | Name2]

# somewhere else in the code 
def do_something_else(objects: Objects):
    for item in objects.objects:
        item.do_something()

pydantic will try to fit the items in the list for each Namex model. Effectively creating a running time of O(nm) with n the length of the list and m the number Namex models. I was hoping that checking for .name first might speed things up.

BMMevius avatar Nov 19 '24 06:11 BMMevius

You can use a tagged union for this case :)

https://docs.pydantic.dev/latest/concepts/unions/#discriminated-unions

sydney-runkle avatar Nov 22 '24 18:11 sydney-runkle

Thank you I believe this will work very well. Of course, I do have objects that are not parsed the same as my previous example (how can I forget?). They require 2 properties instead of 1, lets call them name1 and name2. name1 is not uniquely identifying the objects and neither is name2 but together they are. I searched the documentation for this case but I cant figure out what to do. I guess discriminated unions are not the way to go in that case?

BMMevius avatar Dec 08 '24 12:12 BMMevius

Any updates on this, checking to see if this might be added to pydantic v2 in the near future? (or possibly for consideration into v3), especially looking for

  1. A runtime flag fail_fast that is passed to model_validate (and)
  2. Generally, support for failing early / fast for lots of data types.

Thanks

charleswhchan avatar Jul 09 '25 21:07 charleswhchan