VSCode MyPy error: "ioctl" has incompatible type "my_struct"; expected "Union[int, str]"
VSCode MyPy error: "ioctl" has incompatible type "my_struct"; expected "Union[int, str]"
我有以下 python 片段生成 MyPy“问题”(在 vscode 中)。
my_struct = MyStruct()
#! set mutable flag to true to place data in our object.
fcntl.ioctl( dev_hand.fileno(), my_ioctl_id, my_struct, True )
错误是:
“ioctl”的参数 3 具有不兼容的类型“my_struct”;预期“联合 [int, str]”
MyStruct 是一个 ctypes 结构。使用 ioctl()
和 ctypes 结构的所有示例都显示将实例传递给 ioctl()
。这确实有效,除了现在 MyPy 正在抱怨。
我不想转换为字节并使用 struct
模块手动 pack/unpack(我认为这是一种解决方案)。
我在 Linux (Debian Buster) 上使用 Python 3.7.3
,mypy 0.782
谢谢布伦丹。
注意:我忘了说我的代码是针对 Python 2.7 的,因为它是 Debian Jessie 目标系统的遗留物。我正在为 mypy
使用 --py2
开关(在 Python 3 上必须 运行)。
ioctl()
函数具有以下签名,似乎来自 vscode 服务器(远程 ssh)ms-python .... typeshed/stdlib/3/fcntl。 pyi`
def ioctl(fd: _AnyFile,
request: int,
arg: Union[int, bytes] = ...,
mutate_flag: bool = ...) -> Any: ...
这是一个更完整的代码示例。
from typing import ( BinaryIO, )
import ioctl
import fcntl
from ctypes import ( c_uint32, Structure, addressof )
class Point ( Structure ) :
_fields_ = [ ( 'x', c_uint32 ), ( 'y', c_uint32 ) ]
def ioctl_get_point (
dev_hand,
) :
point = Point()
fcntl.ioctl( dev_hand, 0x12345678, point, True ) #! ** MyPy does NOT complain at all **
def ioctl_get_point_2 (
dev_hand, # type: BinaryIO
) :
point = Point()
fcntl.ioctl( dev_hand, 0x12345678, point, True ) #! ** MyPy complains about arg 3 **
return point
def ioctl_get_point_3 (
dev_hand,
) : # type: (...) -> Point
point = Point()
fcntl.ioctl( dev_hand, 0x12345678, point, True ) #! ** MyPy complains about arg 3 **
return point
def ioctl_get_point_4 (
dev_hand, # type: BinaryIO
) : # type: (...) -> Point
point = Point()
fcntl.ioctl( dev_hand, 0x12345678, point, True ) #! ** MyPy complains about arg 3 **
return point
def ioctl_get_point_5 (
dev_hand, # type: BinaryIO
) : # type: (...) -> Point
point = Point()
fcntl.ioctl( dev_hand, 0x12345678, addressof( point ), True ) #! ** MyPy does NOT complain at all **
return point
对我来说,使用@CristiFati 建议的 ctypes.addressof()
函数似乎是最简单的解决方案。
不幸的是,这不起作用。 ioctl()
函数需要知道对象的大小。
谢谢布伦丹。
mypy
在此处遵循 fnctl.ioctl
函数的规范:
The parameter arg can be one of an integer, an object supporting the read-only buffer interface (like bytes
) or an object supporting the read-write buffer interface (like bytearray
).
因此投诉是合法的。
I'd prefer not to convert to bytes and manually pack/unpack with the struct module
在 TYPE_CHECKING
常量的帮助下,您可以为 fnctl.ioctl
引入一个带有类型提示的本地存根,它将覆盖 stdlib 的类型提示:
import ctypes
from typing import TYPE_CHECKING
class MyStruct(ctypes.Structure):
_fields_ = [...]
if TYPE_CHECKING: # this is only processed by mypy
from typing import Protocol, Union, TypeVar
class HasFileno(Protocol):
def fileno(self) -> int: ...
FileDescriptorLike = Union[int, HasFileno]
_S = TypeVar('_S', bound=ctypes.Structure)
def ioctl(__fd: FileDescriptorLike, __request: int, __arg: Union[int, bytes, _S] = ..., __mutate_flag: bool = ...) -> int: ...
else: # this will be executed at runtime and ignored by mypy
from fcntl import ioctl
my_struct = MyStruct(...)
my_ioctl_id = ...
dev_hand = ...
ioctl(dev_hand.fileno(), my_ioctl_id, my_struct, True) # mypy won't complain here anymore
首先,该错误消息看起来像 Python 2 mypy 错误消息,而不是 Python 3 mypy 错误消息。 Python 3 的 stubs 的 fcntl.ioctl
声明与该错误消息不匹配。 (你仍然会收到 Python 3 mypy 的错误消息,但它会是不同的消息。)
其次,fcntl.ioctl
接受任何支持缓冲区接口的对象(包括您的结构),但 mypy 甚至不知道缓冲区接口是什么。支持buffer接口的对象没有annotation,也没有办法静态识别支持buffer接口的对象。目前 不可能 正确注释像 fcntl.ioctl
这样的函数。关于此问题有 open issues,但看不到解决方案。
您最好的选择可能是在该行上添加 # type: ignore
评论。
我有以下 python 片段生成 MyPy“问题”(在 vscode 中)。
my_struct = MyStruct()
#! set mutable flag to true to place data in our object.
fcntl.ioctl( dev_hand.fileno(), my_ioctl_id, my_struct, True )
错误是:
“ioctl”的参数 3 具有不兼容的类型“my_struct”;预期“联合 [int, str]”
MyStruct 是一个 ctypes 结构。使用 ioctl()
和 ctypes 结构的所有示例都显示将实例传递给 ioctl()
。这确实有效,除了现在 MyPy 正在抱怨。
我不想转换为字节并使用 struct
模块手动 pack/unpack(我认为这是一种解决方案)。
我在 Linux (Debian Buster) 上使用 Python 3.7.3
,mypy 0.782
谢谢布伦丹。
注意:我忘了说我的代码是针对 Python 2.7 的,因为它是 Debian Jessie 目标系统的遗留物。我正在为 mypy
使用 --py2
开关(在 Python 3 上必须 运行)。
ioctl()
函数具有以下签名,似乎来自 vscode 服务器(远程 ssh)ms-python .... typeshed/stdlib/3/fcntl。 pyi`
def ioctl(fd: _AnyFile,
request: int,
arg: Union[int, bytes] = ...,
mutate_flag: bool = ...) -> Any: ...
这是一个更完整的代码示例。
from typing import ( BinaryIO, )
import ioctl
import fcntl
from ctypes import ( c_uint32, Structure, addressof )
class Point ( Structure ) :
_fields_ = [ ( 'x', c_uint32 ), ( 'y', c_uint32 ) ]
def ioctl_get_point (
dev_hand,
) :
point = Point()
fcntl.ioctl( dev_hand, 0x12345678, point, True ) #! ** MyPy does NOT complain at all **
def ioctl_get_point_2 (
dev_hand, # type: BinaryIO
) :
point = Point()
fcntl.ioctl( dev_hand, 0x12345678, point, True ) #! ** MyPy complains about arg 3 **
return point
def ioctl_get_point_3 (
dev_hand,
) : # type: (...) -> Point
point = Point()
fcntl.ioctl( dev_hand, 0x12345678, point, True ) #! ** MyPy complains about arg 3 **
return point
def ioctl_get_point_4 (
dev_hand, # type: BinaryIO
) : # type: (...) -> Point
point = Point()
fcntl.ioctl( dev_hand, 0x12345678, point, True ) #! ** MyPy complains about arg 3 **
return point
def ioctl_get_point_5 (
dev_hand, # type: BinaryIO
) : # type: (...) -> Point
point = Point()
fcntl.ioctl( dev_hand, 0x12345678, addressof( point ), True ) #! ** MyPy does NOT complain at all **
return point
对我来说,使用@CristiFati 建议的 ctypes.addressof()
函数似乎是最简单的解决方案。
不幸的是,这不起作用。 ioctl()
函数需要知道对象的大小。
谢谢布伦丹。
mypy
在此处遵循 fnctl.ioctl
函数的规范:
The parameter arg can be one of an integer, an object supporting the read-only buffer interface (like
bytes
) or an object supporting the read-write buffer interface (likebytearray
).
因此投诉是合法的。
I'd prefer not to convert to bytes and manually pack/unpack with the struct module
在 TYPE_CHECKING
常量的帮助下,您可以为 fnctl.ioctl
引入一个带有类型提示的本地存根,它将覆盖 stdlib 的类型提示:
import ctypes
from typing import TYPE_CHECKING
class MyStruct(ctypes.Structure):
_fields_ = [...]
if TYPE_CHECKING: # this is only processed by mypy
from typing import Protocol, Union, TypeVar
class HasFileno(Protocol):
def fileno(self) -> int: ...
FileDescriptorLike = Union[int, HasFileno]
_S = TypeVar('_S', bound=ctypes.Structure)
def ioctl(__fd: FileDescriptorLike, __request: int, __arg: Union[int, bytes, _S] = ..., __mutate_flag: bool = ...) -> int: ...
else: # this will be executed at runtime and ignored by mypy
from fcntl import ioctl
my_struct = MyStruct(...)
my_ioctl_id = ...
dev_hand = ...
ioctl(dev_hand.fileno(), my_ioctl_id, my_struct, True) # mypy won't complain here anymore
首先,该错误消息看起来像 Python 2 mypy 错误消息,而不是 Python 3 mypy 错误消息。 Python 3 的 stubs 的 fcntl.ioctl
声明与该错误消息不匹配。 (你仍然会收到 Python 3 mypy 的错误消息,但它会是不同的消息。)
其次,fcntl.ioctl
接受任何支持缓冲区接口的对象(包括您的结构),但 mypy 甚至不知道缓冲区接口是什么。支持buffer接口的对象没有annotation,也没有办法静态识别支持buffer接口的对象。目前 不可能 正确注释像 fcntl.ioctl
这样的函数。关于此问题有 open issues,但看不到解决方案。
您最好的选择可能是在该行上添加 # type: ignore
评论。