-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
add UUID1, UUID3, UUID4 and UUID5 types
#167
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
Conversation
Codecov Report
@@ Coverage Diff @@
## master #167 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 9 9
Lines 938 950 +12
Branches 206 207 +1
=====================================
+ Hits 938 950 +12 |
pydantic/types.py
Outdated
| def conuuid(*, version=4) -> Type[UUID]: | ||
| # use kwargs then define conf in a dict to aid with IDE type hinting | ||
| namespace = dict(version_=version) | ||
| return type('ConstrainedUUIDValue', (ConstrainedUUID,), namespace) |
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.
Given that there are only 4 times, should it would be cleaner to just have 4 tyes: Uuid1, Uuid2, ...
Rather than having to implement conuuid
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.
You're right!
add ``ConstrainedUUID``, ``UUID1``, ``UUID3``, ``UUID4`` and ``UUID5`` types (pydantic#167)
Config.uuid_version; add ConstrainedUUID and conuuid typesConfig.uuid_version; add ConstrainedUUID, UUID1, UUID3, UUID4 and UUID5 types
|
@samuelcolvin, updated, please review |
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.
Looking good, but I think we can make it simpler.
pydantic/main.py
Outdated
| @@ -20,6 +20,7 @@ class BaseConfig: | |||
| max_anystr_length = 2 ** 16 | |||
| min_number_size = -2 ** 64 | |||
| max_number_size = 2 ** 64 | |||
| uuid_version = None | |||
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.
I think adding this is unnecessarily confusing. The 5 types UUID, UUID1, UUID3, UUID4 and UUID5 are sufficient.
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.
Then you can remove the duplicated logic in ConstrainedUUID and uuid_version_validator
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.
Done
docs/examples/exotic.py
Outdated
| @@ -48,7 +52,11 @@ class Model(BaseModel): | |||
| neg_float=-2.3, | |||
| email_address='Samuel Colvin <s@muelcolvin.com >', | |||
| email_and_name='Samuel Colvin <s@muelcolvin.com >', | |||
| uuid='ebcdab58-6eb8-46fb-a190-d07a33e9eac8' | |||
| uuid='ebcdab58-6eb8-46fb-a190-d07a33e9eac8', | |||
| uuid_v1='c96e505c-4c62-11e8-a27c-dca90496b483', | |||
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.
It'll be much clearer to read if you show how these were generated, eg.
uuid=uuid.uuid4(),
uuid_v1=uuid.uuid1(),
....
uuid_v=uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
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.
same in tests.
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.
Done
pydantic/types.py
Outdated
| @@ -237,4 +243,36 @@ class NegativeFloat(ConstrainedFloat): | |||
| lt = 0 | |||
|
|
|||
|
|
|||
| class ConstrainedUUID(UUID): | |||
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.
ConstrainedUUID could lead to confusion, I think we can remove it altogether.
I think best to just have
class UUID1(UUID):
_required_version = 1
...Then change uuid_validator:
def uuid_validator(v) -> UUID:
if isinstance(v, str):
v = UUID(v)
elif isinstance(v, (bytes, bytearray)):
v = UUID(v.decode())
elif not isinstance(v, UUID):
raise ValueError(f'str, byte or native UUID type expected not {type(v)}')
required_version = getattr(v, '_required_version', None)
if required_version and required_version != v.version:
...
return vThere 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.
This is a good idea, but I think this is impossible to implement (or I don't know how :). As I see in my tests in uuid_validator v is instance of UUID type, not UUID1 or UUID2...
Validator implementation:
def uuid_validator(v) -> UUID:
if isinstance(v, str):
v = UUID(v)
elif isinstance(v, (bytes, bytearray)):
v = UUID(v.decode())
elif not isinstance(v, UUID):
raise ValueError(f'str, byte or native UUID type expected not {type(v)}')
required_version = getattr(v, '_required_version', None)
if required_version and v.version != required_version:
raise ValueError(f'uuid version {required_version} expected, not {v.version}')
return v
And test:
class UUIDModel(BaseModel):
a: UUID1
b: UUID3
c: UUID4
d: UUID5
def test_uuid_validation():
a = uuid.uuid1()
b = uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
c = uuid.uuid4()
d = uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
m = UUIDModel(a=a, b=b, c=c, d=d)
assert m.dict() == {
'a': a,
'b': b,
'c': c,
'd': d,
}
with pytest.raises(ValidationError) as exc_info:
UUIDModel(a=d, b=c, c=b, d=a)
assert exc_info.value.message == '4 errors validating input'
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.
Done! :)
Config.uuid_version; add ConstrainedUUID, UUID1, UUID3, UUID4 and UUID5 typesConstrainedUUID, UUID1, UUID3, UUID4 and UUID5 types
ConstrainedUUID, UUID1, UUID3, UUID4 and UUID5 typesUUID1, UUID3, UUID4 and UUID5 types
|
@samuelcolvin please review again! |
|
Looks good, thank you very much. Sorry for the mistake in my comment code! |
* make strict runtime * remove validate_strict * reverting some input methods * proper separation of errors * make strict argument optional * fix benchmarks * fix signature, see which test is the problem * skip another test * skip another test * change skip message * try setting recursion limit 👀 * set BACKUP_GUARD_LIMIT for wasm * improve coverage
No description provided.