Pydantic: Support empty string with EmailStr validation

Created on 21 May 2018  路  5Comments  路  Source: samuelcolvin/pydantic

Hello,

I configured the following field:

representative_email: EmailStr = None

When passing an empty string "" as value, I get the following error:

Email address is not valid (error_type=ValueError track=EmailStr)

How can I configure va validator to support those values a I can't change the incoming format?

Most helpful comment

For anyone curious on a working solution here:

class EmailEmptyAllowedStr(EmailStr):
    @classmethod
    def validate(cls, value: str) -> str:
        if value == "":
            return value
        return super().validate(value)

All 5 comments

You should be able to use a validator function and return none instead of an empty string.

On mobile so I can't give a more complete answer, but feel free to ask again if you're still not sure.

Hello,

I tried it with the following code but it doesn't seem to work:

from pydantic import BaseModel, validator, EmailStr

class Demo(BaseModel):
    e: EmailStr: None

    @validator('e', pre=True, always=False)
    def validate_e(cls, val):
        if val == "":
            return None
        return val

Demo()
Demo(e=None)
Demo(e="")

The traceback is the following one:

Traceback (most recent call last):
  File "test.py", line 14, in <module>
    Demo(e="")
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pydantic/main.py", line 153, in __init__
    self.__setstate__(self._process_values(data))
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pydantic/main.py", line 297, in _process_values
    raise ValidationError(errors)
pydantic.exceptions.ValidationError: error validating input
e:
  expected string or bytes-like object (error_type=TypeError track=EmailStr)

In case the validator alway parameter is set to True, the traceback is:

Traceback (most recent call last):
  File "test.py", line 12, in <module>
    Demo()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pydantic/main.py", line 153, in __init__
    self.__setstate__(self._process_values(data))
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pydantic/main.py", line 297, in _process_values
    raise ValidationError(errors)
pydantic.exceptions.ValidationError: error validating input
e:
  expected string or bytes-like object (error_type=TypeError track=EmailStr)

What am I doing wrong?

Maybe you need Optional[EmailStr]

For anyone curious on a working solution here:

class EmailEmptyAllowedStr(EmailStr):
    @classmethod
    def validate(cls, value: str) -> str:
        if value == "":
            return value
        return super().validate(value)

I've also made this generic solution for using with ints, Literal or other types as well:

PydanticField = TypeVar("PydanticField")


class EmptyStrToNone(Generic[PydanticField]):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v: PydanticField, field: ModelField) -> Optional[PydanticField]:
        if v == "":
            return None
        return v

Then you can use as:

LiteralExample = Literal["A", "B"]

class Example(BaseModel):
    literal_example: Optional[EmptyStrToNone[LiteralExample]]
    int_example: Optional[EmptyStrToNone[int]]
Was this page helpful?
0 / 5 - 0 ratings

Related issues

bradodarb picture bradodarb  路  22Comments

jasonkuhrt picture jasonkuhrt  路  21Comments

chopraaa picture chopraaa  路  18Comments

rrbarbosa picture rrbarbosa  路  35Comments

Gaunt picture Gaunt  路  19Comments