I have this code:
from pydantic import BaseModel, constr
DeptNumber = constr(min_length=6, max_length=6)
class MyStuff(BaseModel):
dept: DeptNumber
ms = MyStuff(dept = "123456")
deptnr.py:6: error: Variable "deptnr.DeptNumber" is not valid as a type
deptnr.py:6: note: See https://mypy.readthedocs.io/en/latest/common_issues.html#variables-vs-type-aliases
The provided link doesn't seem to really address my problem (I'm not using Type
).
This happens with or without this mypy.ini
:
[mypy]
plugins = pydantic.mypy
[pydantic-mypy]
init_typed = true
Initially I also had that error in a Pydantic choice
as below, but I got around that by using Python's Literal
instead.
DIR = choice(["North", "East", "South", "West"])
What do I need to change to make mypy happy with my Pydantic constr
?
This incompatibility with mypy has been discussed in this Github issue https://github.com/samuelcolvin/pydantic/issues/156. Sadly, no concrete solution that uses constr
and keeps mypy happy was found.
On Pydantic v1 note 1, instead of constr
, you can subclass pydantic's ConstrainedStr
, which offers the same configurations and options as constr
, but without mypy complaining about type aliases.
from pydantic import BaseModel, ConstrainedStr
class DeptNumber(ConstrainedStr):
min_length = 6
max_length = 6
class MyStuff(BaseModel):
dept: DeptNumber
ms = MyStuff(dept='123456')
The Constrained*
classes are briefly mentioned in the Strict Types section of the docs. It is defined in pydantic/types.py and as you can see is basically the same as constr
:
class ConstrainedStr(str):
strip_whitespace = False
to_lower = False
min_length: OptionalInt = None
max_length: OptionalInt = None
curtail_length: OptionalInt = None
regex: Optional[Pattern[str]] = None
strict = False
...
Validation works the same:
Traceback (most recent call last):
File "test-2.py", line 13, in <module>
ms = MyStuff(dept='123456789')
File "pydantic/main.py", line 406, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for MyStuff
dept
ensure this value has at most 6 characters (type=value_error.any_str.max_length; limit_value=6)
note 1:
I haven't gotten a chance to work with Pydantic v2 yet, so I don't know if it still works on that version.
I can only guarantee that the answer works on v1.
In Pydantic V2, you can use the StringConstraints
type along with Annotated
:
from pydantic import stringConstraints
from typing import Annotated
DeptNumber = Annotated[
str,
StringConstraints(
min_length=6,
max_length=6,
)
]
Annotated
makes sure that DeptNumber
is a str
type, while adding some functionality on top of it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With