-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Add ability to use min_length and max_length constraints with secret types #1974
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to use min_length and max_length constraints with secret types #1974
Conversation
93c5c3b to
d7f897b
Compare
Codecov Report
@@ Coverage Diff @@
## master #1974 +/- ##
===========================================
- Coverage 100.00% 99.90% -0.10%
===========================================
Files 21 21
Lines 3909 4035 +126
Branches 788 805 +17
===========================================
+ Hits 3909 4031 +122
- Misses 0 3 +3
- Partials 0 1 +1
Continue to review full report at Codecov.
|
d7f897b to
43e47c1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks a lot!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good, please also check that schema() is correct.
|
@samuelcolvin Looks like I found a bug, correct me in a case when I missed smth. For instance, I define a custom type which inherits from class CustomStr(str):
...And I have to models: class Foo(BaseModel):
field: CustomStr # without constrain
class Bar(BaseModel):
field: CustomStr = Field(..., min_length=10) # with constrainExample of usage and results: foo = Foo(field='foo')
bar = Bar(field='bar')
print(type(foo.field))
print(type(bar.field))That's because of this code: # schema.py L835
if issubclass(type_, (str, SecretStr)) and not issubclass(type_, (EmailStr, AnyUrl, ConstrainedStr)):
attrs = ('max_length', 'min_length', 'regex')
constraint_func = constrSo with my current implementation, I have a future request and want to hear your opinion. I propose to add So, for instance, class SecretStr:
min_length: OptionalInt = None
max_length: OptionalInt = None
__constraints__: Set[str] = {'min_length', 'max_length'}
@classmethod
def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None:
update_not_none(
field_schema,
type='string',
writeOnly=True,
format='password',
minLength=cls.min_length,
maxLength=cls.max_length,
)With this approach, we can simplify For instance, we can define mixins: class LengthValidation:
min_length: OptionalInt = None
max_length: OptionalInt = None
__constraints__: Set[str] = {'min_length', 'max_length'}
@classmethod
def __modify_schema__(cls: Type[Sized], field_schema: Dict[str, Any]) -> None:
update_not_none(field_schema, minLength=cls.min_length, maxLength=cls.max_length)
@classmethod
def __get_validators__(cls) -> 'CallableGenerator':
yield constr_length_validator
class SecretStr(LengthValidation):
@classmethod
def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None:
super().__modify_schema__(field_schema)
field_schema.update(type='string', writeOnly=True, format='password')
def __len__(self) -> int:
return len(self._secret_value)@samuelcolvin What is your opinion regarding this feature? Also, I thought about API like this: class SecretBytes:
min_length: Constraint[OptionalInt] = None
max_length: Constraint[OptionalInt] = NoneI have already updated my PR using this feature. |
|
I think better to modify if issubclass(type_, SecretStr) and (field_info.min_items is not None or field_info.max_items is not None):
type_.min_length = field_info.min_items
type_.max_length = field_info.max_itemsThen allow yield the length validator from I think that would require a smaller change? |
ed05618 to
ce95302
Compare
|
@samuelcolvin I have updated PR, thanks for your suggestions. And what about the bug and feature request which I described above? |
ce95302 to
cd33263
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
otherwise this looks good.
if you have a bug or feature request, please create an issue or issues. But in general I think the current approach works pretty well, I don't want to change the interface or add more features until it's absolutely necessary. |
|
I have updated PR. |
|
thanks so much. |
|
nice, I am still getting the original error message tho with version 1.7: |
|
Hi @transfluxus, I just test it out, and it works as expected. I have run this code: from pydantic import BaseModel, Field, SecretStr
class Form(BaseModel):
password: SecretStr = Field(min_length=6)
form = Form(password="hello world")And I didn't receive any error. Please, make sure that you are using the latest available version of a pip install -U pydantic |
|
hey @uriyyo Would be nice if the constructor wouldn't have a warning about expecting a "SecretStr" instead of str.
actually fails with but this concerns all Secret Fieldtypes and is another issue. thanks! |
Change Summary
Add ability to use min_length and max_length constraints with
SecretStrandSecretBytestypes.For instance, this model is totally valid:
Related issue number
Fix #1461
Checklist
changes/<pull request or issue id>-<github username>.mdfile added describing change(see changes/README.md for details)