-
Notifications
You must be signed in to change notification settings - Fork 31
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
Fix QByteArray to bytes conversion #143
Conversation
Looks like these changes cause the tests to fail in CI. Also can you add an entry to the |
The error reported by the CI is :
Indeed, the method |
I don't have a good answer, but is it possible that PyQt does something really bizarre and makes just |
It does not even exist on the instance. I suppose that it uses a Python C API trick to trigger the bytes conversion. See example :
So, this CI test will never succeed. Is there a way to bypass this check ? |
The CI complains about method not present in the object, but the equivalent python operation actually works. So, what's correct ? |
If we can't find a solution, I think we can add This may be a question for the |
https://gitter.im/python/typing?at=605e63159ebdfd16409efe93 I think that https://github.com/python/typeshed is missing a class bytes(ByteString):
@overload
def __new__(cls: Type[_T], ints: Iterable[int]) -> _T: ...
@overload
def __new__(cls: Type[_T], string: str, encoding: str, errors: str = ...) -> _T: ...
@overload
def __new__(cls: Type[_T], length: int) -> _T: ...
@overload
def __new__(cls: Type[_T]) -> _T: ...
@overload
def __new__(cls: Type[_T], o: SupportsBytes) -> _T: ... |
Hum... So this is kinda nice. https://mypy-play.net/?mypy=latest&python=3.9&gist=974b35693fd30dcfb0c655ed9d4d847e from collections.abc import ByteString
from typing import Iterable, Generic, overload, Protocol, Type, TypeVar
class E:
def __getitem__(self, item) -> int:
pass
_T = TypeVar("_T")
_T_co = TypeVar("_T_co", covariant=True)
_T_contra = TypeVar("_T_contra", contravariant=True)
class _SupportsGetItem(Protocol, Generic[_T_contra, _T_co]):
def __getitem__(self, item: _T_contra) -> _T_co: ...
class MyBytes(ByteString):
@overload
def __new__(cls: Type[_T], ints: Iterable[int]) -> _T: ...
@overload
def __new__(cls: Type[_T], ints: _SupportsGetItem[object, int]) -> _T: ...
@overload
def __new__(cls: Type[_T], string: str, encoding: str, errors: str = ...) -> _T: ...
@overload
def __new__(cls: Type[_T], length: int) -> _T: ...
@overload
def __new__(cls: Type[_T]) -> _T: ...
# @overload
# def __new__(cls: Type[_T], o: SupportsBytes) -> _T: ...
def __new__(cls, *args, **kwargs):
return 0
def __getitem__(self, item): ...
def __len__(self, item): ...
e = E()
MyBytes(e) But not quite since indexing a >>> b = QtCore.QByteArray(b'12')
>>> b
PyQt5.QtCore.QByteArray(b'12')
>>> b[0]
b'1' And of course https://replit.com/@altendky/PuzzlingGigaCustomers-1#main.py class C:
def __getitem__(self, item):
if item == 0:
return b'3'
raise IndexError()
c = C()
b = bytes(c)
print(b) Traceback (most recent call last):
File "main.py", line 9, in <module>
b = bytes(c)
TypeError: 'bytes' object cannot be interpreted as an integer That makes it seem like this isn't actually the means by which Maybe python/typeshed@2cb4a2a is still a good change but I'm not convinced it is the proper one for us. |
Maybe the buffer C-api interface? /* Use the modern buffer interface */
if (PyObject_CheckBuffer(x))
return _PyBytes_FromBuffer(x); I think this is a hint that that may be true. Python 3.9.1 (default, Jan 6 2021, 10:22:00)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from PyQt5 import QtCore
>>> application = QtCore.QCoreApplication([])
>>> qba = QtCore.QByteArray(b'\x01\x02')
>>> qba
PyQt5.QtCore.QByteArray(b'\x01\x02')
>>> memoryview(qba)
<memory at 0x7ff838f9d400> https://bugs.python.org/issue27501 Maybe I'll look those over tomorrow to see if there are any good workarounds. |
I didn't see anything as I read over the links. As is the hints are incorrect due to rejecting I don't like being wrong nor lying... I'm not sure which is worse. Can anyone think of significant scenarios where incorrectly hinting |
The class would also incorrectly satisfy a |
Phil Thompson confirmed (in case there was any doubt left) that the conversion is using the buffer protocol : http://python.6.x6.nabble.com/How-does-QByteArray-convert-to-bytes-td5289854.html I'll go ahead and fix the CI properly. |
There is no other way to support the buffer protocol than prentending to support bytes conversion.
This is probably ready to be merged. |
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.
If you would prefer that I run through these boilerplate changes myself, just ask, I am happy to. I just don't like to take over other people's branches and PRs without their request.
-
Adding
.__bytes__()
is a lie so we should be very clear about it. See the suggestion and apply if you agree. -
I can't add a formal GitHub suggestion for this, but there should be a changelog entry for this. Something like below.
* [#143](https://github.com/python-qt-tools/PyQt5-stubs/pull/143) make `bytes(QByteArray())` valid by incorrectly adding `.__bytes__()` until a proper solution is developed upstream
Other than that I'm ready to merge this.
Thanks for the effort, patience, and contribution.
Co-authored-by: Kyle Altendorf <[email protected]>
Thanks again for the contribution and your patience. I hope that in the future I can enable a quicker workflow. |
Thanks for merging this. |
Fix QByteArray failing to convert to bytes