scripts/qom-fuse: add static type hints

Because fusepy does not have type hints, add some targeted warning
suppressions.

Namely, we need to allow subclassing something of an unknown type (in
qom_fuse.py), and we need to allow missing imports (recorded against
fuse itself) because mypy will be unable to import fusepy (even when
installed) as it has no types nor type stubs available.

Note: Until now, it was possible to run invocations like 'mypy qemu/'
from ./python and have that work. However, these targeted suppressions
require that you run 'mypy -p qemu/' instead. The correct, canonical
invocation is recorded in ./python/tests/mypy.sh and all of the various
CI invocations always use this correct form.

Signed-off-by: John Snow <jsnow@redhat.com>
Message-id: 20210603003719.1321369-16-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
This commit is contained in:
John Snow 2021-06-02 20:37:15 -04:00
parent 2cea713462
commit 30ec845c59
2 changed files with 25 additions and 9 deletions

View File

@ -57,6 +57,14 @@ python_version = 3.6
warn_unused_configs = True warn_unused_configs = True
namespace_packages = True namespace_packages = True
[mypy-qemu.qmp.qom_fuse]
# fusepy has no type stubs:
allow_subclassing_any = True
[mypy-fuse]
# fusepy has no type stubs:
ignore_missing_imports = True
[pylint.messages control] [pylint.messages control]
# Disable the message, report, category or checker with the given id(s). You # Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this # can either give multiple identifiers separated by comma (,) or put this

View File

@ -38,7 +38,14 @@ from errno import ENOENT, EPERM
import os import os
import stat import stat
import sys import sys
from typing import Dict from typing import (
IO,
Dict,
Iterator,
Mapping,
Optional,
Union,
)
import fuse import fuse
from fuse import FUSE, FuseOSError, Operations from fuse import FUSE, FuseOSError, Operations
@ -83,7 +90,7 @@ class QOMFuse(QOMCommand, Operations):
self.fuse = FUSE(self, self.mount, foreground=True) self.fuse = FUSE(self, self.mount, foreground=True)
return 0 return 0
def get_ino(self, path): def get_ino(self, path: str) -> int:
"""Get an inode number for a given QOM path.""" """Get an inode number for a given QOM path."""
if path in self.ino_map: if path in self.ino_map:
return self.ino_map[path] return self.ino_map[path]
@ -91,7 +98,7 @@ class QOMFuse(QOMCommand, Operations):
self.ino_count += 1 self.ino_count += 1
return self.ino_map[path] return self.ino_map[path]
def is_object(self, path): def is_object(self, path: str) -> bool:
"""Is the given QOM path an object?""" """Is the given QOM path an object?"""
try: try:
self.qom_list(path) self.qom_list(path)
@ -99,7 +106,7 @@ class QOMFuse(QOMCommand, Operations):
except QMPResponseError: except QMPResponseError:
return False return False
def is_property(self, path): def is_property(self, path: str) -> bool:
"""Is the given QOM path a property?""" """Is the given QOM path a property?"""
path, prop = path.rsplit('/', 1) path, prop = path.rsplit('/', 1)
if path == '': if path == '':
@ -112,7 +119,7 @@ class QOMFuse(QOMCommand, Operations):
except QMPResponseError: except QMPResponseError:
return False return False
def is_link(self, path): def is_link(self, path: str) -> bool:
"""Is the given QOM path a link?""" """Is the given QOM path a link?"""
path, prop = path.rsplit('/', 1) path, prop = path.rsplit('/', 1)
if path == '': if path == '':
@ -125,7 +132,7 @@ class QOMFuse(QOMCommand, Operations):
except QMPResponseError: except QMPResponseError:
return False return False
def read(self, path, size, offset, fh): def read(self, path: str, size: int, offset: int, fh: IO[bytes]) -> bytes:
if not self.is_property(path): if not self.is_property(path):
raise FuseOSError(ENOENT) raise FuseOSError(ENOENT)
@ -143,7 +150,7 @@ class QOMFuse(QOMCommand, Operations):
return bytes(data[offset:][:size], encoding='utf-8') return bytes(data[offset:][:size], encoding='utf-8')
def readlink(self, path): def readlink(self, path: str) -> Union[bool, str]:
if not self.is_link(path): if not self.is_link(path):
return False return False
path, prop = path.rsplit('/', 1) path, prop = path.rsplit('/', 1)
@ -151,7 +158,8 @@ class QOMFuse(QOMCommand, Operations):
return prefix + str(self.qmp.command('qom-get', path=path, return prefix + str(self.qmp.command('qom-get', path=path,
property=prop)) property=prop))
def getattr(self, path, fh=None): def getattr(self, path: str,
fh: Optional[IO[bytes]] = None) -> Mapping[str, object]:
if self.is_link(path): if self.is_link(path):
value = { value = {
'st_mode': 0o755 | stat.S_IFLNK, 'st_mode': 0o755 | stat.S_IFLNK,
@ -195,7 +203,7 @@ class QOMFuse(QOMCommand, Operations):
raise FuseOSError(ENOENT) raise FuseOSError(ENOENT)
return value return value
def readdir(self, path, fh): def readdir(self, path: str, fh: IO[bytes]) -> Iterator[str]:
yield '.' yield '.'
yield '..' yield '..'
for item in self.qom_list(path): for item in self.qom_list(path):