You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
RFE: uuid.UUID(bytes=...): support bytes-like types, not only bytes #73915
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=Nonecreated_at=<Date2017-03-05.19:59:58.391>labels= ['3.7', 'type-feature', 'library']
title='RFE: uuid.UUID(bytes=...): support bytes-like types, not only bytes'updated_at=<Date2017-09-28.20:43:09.315>user='https://github.com/jnwatson'
File "/usr/lib/python3.6/uuid.py", line 150, in __init__
assert isinstance(bytes, bytes_), repr(bytes)
is too specific (and IMHO, unpythonic). One may want to pass a bytearray or a memoryview. See int.from_bytes for an example that takes "bytes" but accepts anything that acts like a bytes.
A simple solution may be to delete the assertion (it worked for me).
Example code:
importuuidb=uuid.uuid1().bytesba=bytearray(b)
print(uuid.UUID(bytes=b))
# another API that works similarly, accepts a bytearrayprint(int.from_bytes(ba, byteorder='big'))
# fails on assertionprint(uuid.UUID(bytes=ba))
changed the title [-]UUID bytes constructor has too-tight an assertion[/-][+]RFE: uuid.UUID(bytes=...): support bytes-like types, not only bytes[/+]on Sep 28, 2017
I agree. In any case assert is a bad way of checking argument types. It was
added in 65b6a80 as a part of migration to
Python 3. I guess for debugging purposes. Now it isn't needed,
int.from_bytes() checks whether the type is appropriate.
The code doesn't work nice with general objects supporting the buffer protocol. The length check suppose that the value has a length, and it is the size in bytes. The code for bytes_le suppose that the value supports slicing and concatenating results of the slicing. And all this code is made as fast as possible. Additional checks and conversions will slowdown it.
The code doesn't work nice with general objects supporting the buffer protocol. The length check suppose that the value has a length, and it is the size in bytes. The code for bytes_le suppose that the value supports slicing and concatenating results of the slicing. And all this code is made as fast as possible. Additional checks and conversions will slowdown it.
I enhanced my PR to also accept memoryview and bytearray in bytes_le. I don't think that performance matters so much here. First we need correctness, accept any bytes-like objects, no?
Considering the history of the PR and how hard it was to ensure that we accept a bytes-like object, I would prefer rejecting this feature altogether. It's common to create a UUID from a bytes (e.g., if the latter comes from a process output or a database query), but I don't think it's common enough to construct a UUID from a memoryview, or a bytearray. If this is a concern, I would advise wrapping it in bytes(...) call.
AFAICT, most of the issue stems from bytes_le where we need slicing. We could have a generic way to transform bytes_le without slicing and only assuming memoryview support, but I don't think it's worth the change. Accepting bytes_le is only internally used to get the node value of a UUIDv1 created on Windows for subsequent calls and it's only used once.
Unless we want to change the AssertionError into a TypeError (which would make sense here) or explicitly document that values passed via bytes_le and bytes MUST be bytes instances (and not anything else), I will close this issue.
Activity
jnwatson commentedon Mar 5, 2017
The assertion:
File "/usr/lib/python3.6/uuid.py", line 150, in __init__
assert isinstance(bytes, bytes_), repr(bytes)
is too specific (and IMHO, unpythonic). One may want to pass a bytearray or a memoryview. See int.from_bytes for an example that takes "bytes" but accepts anything that acts like a bytes.
A simple solution may be to delete the assertion (it worked for me).
Example code:
[-]UUID bytes constructor has too-tight an assertion[/-][+]RFE: uuid.UUID(bytes=...): support bytes-like types, not only bytes[/+]serhiy-storchaka commentedon Sep 28, 2017
I agree. In any case assert is a bad way of checking argument types. It was
added in 65b6a80 as a part of migration to
Python 3. I guess for debugging purposes. Now it isn't needed,
int.from_bytes() checks whether the type is appropriate.
Do you want to create a pull request Nic?
serhiy-storchaka commentedon Sep 28, 2017
Ah, Victor already have created a PR!
vstinner commentedon Sep 28, 2017
Serhiy: is it safe to accept any memoryview? Or should we call explicitly .cast('B') on memory views to prevent bad surprises?
The asyncio module doesn't do anything special in sock_sendall(). "data" is passed directly to socket.send(), unchanged.
So maybe it's just fine to not do anything special.
serhiy-storchaka commentedon Sep 28, 2017
The code doesn't work nice with general objects supporting the buffer protocol. The length check suppose that the value has a length, and it is the size in bytes. The code for bytes_le suppose that the value supports slicing and concatenating results of the slicing. And all this code is made as fast as possible. Additional checks and conversions will slowdown it.
vstinner commentedon Sep 28, 2017
I enhanced my PR to also accept memoryview and bytearray in bytes_le. I don't think that performance matters so much here. First we need correctness, accept any bytes-like objects, no?
serhiy-storchaka commentedon Sep 28, 2017
I have tested, this doesn't affect performance.
vstinner commentedon Sep 28, 2017
Serhiy: "I have tested, this doesn't affect performance."
Oh, thank you for testing that :-)
picnixz commentedon Sep 17, 2025
Considering the history of the PR and how hard it was to ensure that we accept a bytes-like object, I would prefer rejecting this feature altogether. It's common to create a UUID from a bytes (e.g., if the latter comes from a process output or a database query), but I don't think it's common enough to construct a UUID from a memoryview, or a bytearray. If this is a concern, I would advise wrapping it in
bytes(...)call.AFAICT, most of the issue stems from
bytes_lewhere we need slicing. We could have a generic way to transformbytes_lewithout slicing and only assumingmemoryviewsupport, but I don't think it's worth the change. Acceptingbytes_leis only internally used to get the node value of a UUIDv1 created on Windows for subsequent calls and it's only used once.Unless we want to change the AssertionError into a TypeError (which would make sense here) or explicitly document that values passed via
bytes_leandbytesMUST bebytesinstances (and not anything else), I will close this issue.vstinner commentedon Sep 18, 2025
I agree to close the PR and leave the code as it is.