Pydantic: mypy: invalid type comment or annotation

Created on 12 Apr 2018  路  13Comments  路  Source: samuelcolvin/pydantic

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?

Most helpful comment

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 type str, which is not a str.

Another possible issue is that a default value was supplied, making this field optional.

Updated example:

class User(BaseModel):
    name: str = Field('Default name', max_length=255, strip_whitespace=True)

If you want to make the field a Required field,
use an ellipsis:

class User(BaseModel):
    name: str = Field(..., max_length=255, strip_whitespace=True)

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 of None is not the same as supplying no default value.

All 13 comments

Afraid I don't know how to fix this.

Might be possible to modify constr to [].

Will look when I have a chance of you're welcome to submit a pr.

I will try to find solution too.

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}] or foobar['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.

I am running into the same issue. We cannot just shrug this off because adding # type: ignore to the end of the field line does not make the mypy warning go away. In fact, I only got the mypy warning to go away by not using constr at all.

This difficulty must be mentioned in the documentation.

For me I found simple solution how to use constr without mypy warnings. Look at example below:

UserName = constr(max_length=255, strip_whitespace=True)

class User(BaseModel):
    name: UserName

Also using this approach you can share your validation types, for example, between engineers in your company.

@Gr1N nice idea, thank you!

But now mypy gives me error: Invalid type "keepluggable.orchestrator.AtLeastOneChar"

Here's my code:

AtLeastOneChar = constr(min_length=1, strip_whitespace=True)


class Configuration(BaseModel):

    name:  AtLeastOneChar = Required

The error is on the last line. Removing the "Required" doesn't change the result. I also upgraded mypy from 0.570 to 0.600, but no luck. In setup.cfg I have:

[mypy]
# http://mypy.readthedocs.io/en/latest/config_file.html
ignore_missing_imports = True
strict_optional = True

@nandoflorestan try this:

from pydantic import BaseModel, ConstrainedStr, Required, constr

AtLeastOneChar: ConstrainedStr = constr(min_length=1, strip_whitespace=True)


class Configuration(BaseModel):
    name: AtLeastOneChar = Required

@Gr1N That did it, thanks!

The final line is simply

AtLeastOneChar: constr = constr(min_length=1, strip_whitespace=True)

I believe the problem and the workaround should be explained in the docs.

@nandoflorestan you're welcome :)

@nandoflorestan @Gr1N that does not look correct, and in fact only works because you probably run mypy --follow-imports=skip, if you run mypy this would be the output

error: Function "pydantic.types.constr" is not valid as a type
note: Perhaps you need "Callable[...]" or a callback protocol?

the best is explained by @samuelcolvin here: https://github.com/samuelcolvin/pydantic/issues/975#issuecomment-551147305

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

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 type str, which is not a str.

Another possible issue is that a default value was supplied, making this field optional.

Updated example:

class User(BaseModel):
    name: str = Field('Default name', max_length=255, strip_whitespace=True)

If you want to make the field a Required field,
use an ellipsis:

class User(BaseModel):
    name: str = Field(..., max_length=255, strip_whitespace=True)

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 of None is not the same as supplying no default value.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nav picture nav  路  3Comments

vvoody picture vvoody  路  3Comments

dconathan picture dconathan  路  3Comments

sommd picture sommd  路  3Comments

ashears picture ashears  路  3Comments