pydantic: mypy: invalid type comment or annotation
Hi,
I think this issue related more to mypy
, but maybe you know about any workaround or how to solve this.
Here is my code:
class Test(BaseModel):
k: constr(min_length=2)
And when I run mypy
I got:
error: invalid type comment or annotation
note: Suggestion: use constr[...] instead of constr(...)
Any ideas?
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 61
- Comments: 40 (15 by maintainers)
Commits related to this issue
- Fix errors from CI - Linting - ISort - Workaround for https://github.com/samuelcolvin/pydantic/issues/156 — committed to trickeydan/monzo-webhook-schema by trickeydan 3 years ago
- Common: Ignore valid-type on con{int,float} mypy can't handle pydantic's conint and confloat. See https://github.com/pydantic/pydantic/issues/239 and https://github.com/pydantic/pydantic/issues/156 f... — committed to guardicore/monkey by mssalvatore 2 years ago
- (BSR)[API] fix: Fix usage of pydantic constrained fields to please mypy With the following pydantic model: class M(pydantic.BaseModel): name: pydantic.constr(max_length=200) ... mypy re... — committed to pass-culture/pass-culture-main by dbaty 2 years ago
- (BSR)[API] fix: Fix usage of pydantic constrained fields to please mypy With the following pydantic model: class M(pydantic.BaseModel): name: pydantic.constr(max_length=200) ... mypy re... — committed to pass-culture/pass-culture-main by dbaty 2 years ago
- (BSR)[API] fix: Fix usage of pydantic constrained fields to please mypy With the following pydantic model: class M(pydantic.BaseModel): name: pydantic.constr(max_length=200) ... mypy re... — committed to pass-culture/pass-culture-main by dbaty 2 years ago
- (BSR)[API] fix: Fix usage of pydantic constrained fields to please mypy With the following pydantic model: class M(pydantic.BaseModel): name: pydantic.constr(max_length=200) ... mypy re... — committed to pass-culture/pass-culture-main by dbaty 2 years ago
- (BSR)[API] fix: Fix usage of pydantic constrained fields to please mypy With the following pydantic model: class M(pydantic.BaseModel): name: pydantic.constr(max_length=200) ... mypy re... — committed to pass-culture/pass-culture-main by dbaty 2 years ago
- (BSR)[API] fix: Fix usage of pydantic constrained fields to please mypy With the following pydantic model: class M(pydantic.BaseModel): name: pydantic.constr(max_length=200) ... mypy re... — committed to pass-culture/pass-culture-main by dbaty 2 years ago
- (BSR)[API] fix: Fix usage of pydantic constrained fields to please mypy With the following pydantic model: class M(pydantic.BaseModel): name: pydantic.constr(max_length=200) ... mypy re... — committed to pass-culture/pass-culture-main by dbaty 2 years ago
- (BSR)[API] fix: Fix usage of pydantic constrained fields to please mypy With the following pydantic model: class M(pydantic.BaseModel): name: pydantic.constr(max_length=200) ... mypy re... — committed to pass-culture/pass-culture-main by dbaty 2 years ago
- (BSR)[API] fix: Fix usage of pydantic constrained fields to please mypy With the following pydantic model: class M(pydantic.BaseModel): name: pydantic.constr(max_length=200) ... mypy re... — committed to pass-culture/pass-culture-main by dbaty 2 years ago
- (BSR)[API] fix: Fix usage of pydantic constrained fields to please mypy With the following pydantic model: class M(pydantic.BaseModel): name: pydantic.constr(max_length=200) ... mypy re... — committed to pass-culture/pass-culture-main by dbaty 2 years ago
- (BSR)[API] fix: Fix usage of pydantic constrained fields to please mypy With the following pydantic model: class M(pydantic.BaseModel): name: pydantic.constr(max_length=200) ... mypy re... — committed to pass-culture/pass-culture-main by dbaty 2 years ago
- (BSR)[API] fix: Fix usage of pydantic constrained fields to please mypy With the following pydantic model: class M(pydantic.BaseModel): name: pydantic.constr(max_length=200) ... mypy re... — committed to pass-culture/pass-culture-main by dbaty 2 years ago
Why is this issue closed? From my understanding the typing behavior with
mypy
is still not fixed - or am I misunderstanding something?For me I found simple solution how to use
constr
withoutmypy
warnings. Look at example below:Also using this approach you can share your validation types, for example, between engineers in your company.
The above is not quite right as well, because the first parameter to
Field
is the default value. In this case the default would be the typestr
, which is not astr
.Another possible issue is that a default value was supplied, making this field optional.
Updated example:
If you want to make the field a Required field, use an ellipsis:
Something like
required=True
would feel more natural, but that’s not an option as of v1.4. Please be aware that supplying a default ofNone
is not the same as supplying no default value.This should be mentioned in the documentation:
https://pydantic-docs.helpmanual.io/usage/types/#constrained-types
is incompatible with mypy at the moment
@Gr1N That did it, thanks!
The final line is simply
I believe the problem and the workaround should be explained in the docs.
sorry for the dumb question , shouldn’t the plugin handle this ?
@nandoflorestan @Gr1N that does not look correct, and in fact only works because you probably run
mypy --follow-imports=skip
, if you runmypy
this would be the outputthe best is explained by @samuelcolvin here: https://github.com/samuelcolvin/pydantic/issues/975#issuecomment-551147305
Another approach is to inherit from ConstrainedStr:
For future people who find this issue, in v1 you can use
Field
for this:EDIT: See comment below for an example https://github.com/samuelcolvin/pydantic/issues/156#issuecomment-614748288
Humans! Whoever thinks that Mypy does more evil than goodness by forcing developers to serve the code and not vice versa give it a thumbs up! May Mypy be eliminated from the entire history of the Universe…
Using Annotated for constraining decimals as
price: Annotated[Decimal, Field(gt=Decimal("0.00"), decimal_places=2)
with fastapi on 0.75.2 , Python 3.9.* and pydantic on 1.9.0 -> works! Swagger shows correct doc and validation is happening on runtime. No bypass needed now. Thanks!This doesn’t work –
constr
constraints are not applied. max_length is neither in schema ofItem
nor during runtime/parsing (eg.field
can be longer then 2).I’m using Python 3.9.* and pydantic 1.9.0.
Now that we have Annotated available, should this ticket be reopened? (I recognise it might not currently apply constraints correctly, but support could be implemented as part of this ticket)
This part of the Pydantic docs suggests the example should work “as is” and I would expect that to include type checking (I got this issue when trying it).
@nandoflorestan try this:
Sadly since pep 472 was never implemented and keyword arguments to
__getitem__
are not permitted this is not possible.Even the works arounds suggested in pep472
foobar[{'min_length': 123}]
orfoobar['min_length':123]
are both syntax errors in mypy so they’re not an option.I’m closing this but happy to come back to it if anyone has a bright idea.
Even with
Annotated[]
now supported, defining strict fields with validation inline (while keeping mypy happy) is still not possible:The workaround of:
…is not so great, as it’s so verbose.
…could be better (far from perfect, though) but it just doesn’t comply with
mypy
.StrictStr
now inherits fromConstrainedStr
which supports validators, and for that reasonfield: Constrained* = Field(...validators...)
are not supported.However, what if
Strict*
did not inherit fromConstrained*
classes and were simply:In this case, you would need to define the validators via
Field()
(but it could be supported as there wouldn’t be possibility for clashes):But I guess that would be too limited, as
Constrained*
classes do more than duplicate JSON schema validators (likeconstr(strip_whitespace=True, curtail_length=10)
) and you would lose those.I think now it should be better with
Annotated
that ismypy
compliant So with author examplebecomes
To anyone still running into this,
# type: ignore
now works. Its error code if you want to be pedantic (heh) isvalid-type
. The specific usage would be# type: ignore["valid-type"]
.Quoting https://github.com/samuelcolvin/pydantic/issues/156#issuecomment-1073876877:
The following isn’t pretty, but I believe it works at runtime and typecheck-time:
Running the above in an interpreter yields
and mypy seems content:
Ah yes. Like PrettyWood said. Waiting on a PR 😄
Is there a reason why
Field(..., strict=True)
is not supported? Wouldn’t that do it?I can attempt to work it, if that’s a viable solution.
Yes, it does work. But I just wanted to know if there was a more robust or appropriate way to do it. I am working on a rather large project and I didn’t want to use
# type: ignore
excessively on several lines in different files.But exactly this one gives the mypy error.
That’s pretty verbose. Lots of “wasted” characters, surely there’s a more compact way?
Like, if you could
StrictStr(max_length=2)
(but there’s no constructor, so you cannot directly do that). And, I guess it would fail with mypy the same way asconstr()
et al. now do.Yeah, I’ve read those, but I think they miss this one. For example, there’s no similar example than what you just pasted (setting
max_length
in sub-class).Field(..., max_length=2)
is just useful for the schema. You should door create a custom class
For more info check out the doc Hope it helps