From: Volker Theile Date: Mon, 24 Feb 2020 12:03:13 +0000 (+0100) Subject: mgr/dashboard: Fix mypy issues and enable it by default X-Git-Tag: v15.1.1~249^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ba5e1179a47bd04afde54d56b99bb99c9da953b0;p=ceph.git mgr/dashboard: Fix mypy issues and enable it by default The decorator @no_type_check is used: * To prevent a mypy error like 'error: INTERNAL ERROR -- Please try using mypy master on Github:' * '#type: ignore' does not work, e.g. in broken lines Fixes: https://tracker.ceph.com/issues/44269 Signed-off-by: Volker Theile --- diff --git a/src/pybind/mgr/dashboard/__init__.py b/src/pybind/mgr/dashboard/__init__.py index bdcdcc3685ce4..78879986398d8 100644 --- a/src/pybind/mgr/dashboard/__init__.py +++ b/src/pybind/mgr/dashboard/__init__.py @@ -32,7 +32,7 @@ else: os.environ['PATH'] = '{}:{}'.format(os.path.abspath('../../../../build/bin'), os.environ['PATH']) - from tests import mock + from tests import mock # type: ignore mgr = mock.Mock() mgr.get_frontend_path.side_effect = lambda: os.path.abspath("./frontend/dist") diff --git a/src/pybind/mgr/dashboard/awsauth.py b/src/pybind/mgr/dashboard/awsauth.py index fdf87de61377d..5cbb6f297d755 100644 --- a/src/pybind/mgr/dashboard/awsauth.py +++ b/src/pybind/mgr/dashboard/awsauth.py @@ -90,7 +90,7 @@ class S3Auth(AuthBase): key = self.secret_key.encode('utf-8') msg = canonical_string.encode('utf-8') else: - key = self.secret_key + key = self.secret_key # type: ignore msg = canonical_string h = hmac.new(key, msg, digestmod=sha) return encodestring(h.digest()).strip() diff --git a/src/pybind/mgr/dashboard/cherrypy_backports.py b/src/pybind/mgr/dashboard/cherrypy_backports.py index ba5ef2e1a9121..d11b541fab1a1 100644 --- a/src/pybind/mgr/dashboard/cherrypy_backports.py +++ b/src/pybind/mgr/dashboard/cherrypy_backports.py @@ -174,7 +174,7 @@ def patch_request_unique_id(v): It's evaluated lazily on render. """ try: - self._uuid4 + self._uuid4 # type: ignore except AttributeError: # evaluate on first access self._uuid4 = uuid.uuid4() diff --git a/src/pybind/mgr/dashboard/controllers/__init__.py b/src/pybind/mgr/dashboard/controllers/__init__.py index e539008eb5288..3bd4cba8d738a 100644 --- a/src/pybind/mgr/dashboard/controllers/__init__.py +++ b/src/pybind/mgr/dashboard/controllers/__init__.py @@ -24,6 +24,11 @@ from ..exceptions import ScopeNotValid, PermissionNotValid from ..services.auth import AuthManager, JwtManager from ..plugins import PLUGIN_MANAGER +try: + from typing import Any, List, Optional +except ImportError: + pass # For typing only + def EndpointDoc(description="", group="", parameters=None, responses=None): # noqa: N802 if not isinstance(description, str): @@ -86,14 +91,14 @@ def EndpointDoc(description="", group="", parameters=None, responses=None): # n return splitted def _split_list(data, nested): - splitted = [] + splitted = [] # type: List[Any] for item in data: splitted.extend(_split_parameters(item, nested)) return splitted # nested = True means parameters are inside a dict or array def _split_parameters(data, nested=False): - param_list = [] + param_list = [] # type: List[Any] if isinstance(data, dict): param_list.extend(_split_dict(data, nested)) elif isinstance(data, (list, tuple)): @@ -286,7 +291,7 @@ def load_controllers(): return controllers -ENDPOINT_MAP = collections.defaultdict(list) +ENDPOINT_MAP = collections.defaultdict(list) # type: dict def generate_controller_routes(endpoint, mapper, base_url): @@ -589,11 +594,11 @@ class BaseController(object): def __init__(self): logger = logging.getLogger('controller') logger.info('Initializing controller: %s -> %s', - self.__class__.__name__, self._cp_path_) + self.__class__.__name__, self._cp_path_) # type: ignore super(BaseController, self).__init__() def _has_permissions(self, permissions, scope=None): - if not self._cp_config['tools.authenticate.on']: + if not self._cp_config['tools.authenticate.on']: # type: ignore raise Exception("Cannot verify permission in non secured " "controllers") @@ -612,7 +617,7 @@ class BaseController(object): def get_path_param_names(cls, path_extension=None): if path_extension is None: path_extension = "" - full_path = cls._cp_path_[1:] + path_extension + full_path = cls._cp_path_[1:] + path_extension # type: ignore path_params = [] for step in full_path.split('/'): param = None @@ -628,7 +633,7 @@ class BaseController(object): @classmethod def get_path(cls): - return cls._cp_path_ + return cls._cp_path_ # type: ignore @classmethod def endpoints(cls): @@ -728,7 +733,7 @@ class RESTController(BaseController): # to specify a composite id (two parameters) use '/'. e.g., "param1/param2". # If subclasses don't override this property we try to infer the structure # of the resource ID. - RESOURCE_ID = None + RESOURCE_ID = None # type: Optional[str] _permission_map = { 'GET': Permission.READ, @@ -777,7 +782,7 @@ class RESTController(BaseController): permission = None if func.__name__ in cls._method_mapping: - meth = cls._method_mapping[func.__name__] + meth = cls._method_mapping[func.__name__] # type: dict if meth['resource']: if not res_id_params: diff --git a/src/pybind/mgr/dashboard/controllers/cephfs.py b/src/pybind/mgr/dashboard/controllers/cephfs.py index f4c024d619e9b..d482ee6de37cf 100644 --- a/src/pybind/mgr/dashboard/controllers/cephfs.py +++ b/src/pybind/mgr/dashboard/controllers/cephfs.py @@ -74,7 +74,7 @@ class CephFS(RESTController): "mds_mem.ino" ] - result = {} + result = {} # type: dict mds_names = self._get_mds_names(fs_id) for mds_name in mds_names: @@ -129,7 +129,7 @@ class CephFS(RESTController): # pylint: disable=too-many-statements,too-many-branches def fs_status(self, fs_id): - mds_versions = defaultdict(list) + mds_versions = defaultdict(list) # type: dict fsmap = mgr.get("fs_map") filesystem = None diff --git a/src/pybind/mgr/dashboard/controllers/iscsi.py b/src/pybind/mgr/dashboard/controllers/iscsi.py index 843b0fac0b3a8..af5049300001d 100644 --- a/src/pybind/mgr/dashboard/controllers/iscsi.py +++ b/src/pybind/mgr/dashboard/controllers/iscsi.py @@ -22,6 +22,11 @@ from ..services.tcmu_service import TcmuService from ..exceptions import DashboardException from ..tools import str_to_bool, TaskManager +try: + from typing import Any, Dict, List, no_type_check +except ImportError: + no_type_check = object() # Just for type checking + @UiApiController('/iscsi', Scope.ISCSI) class IscsiUi(BaseController): @@ -31,6 +36,7 @@ class IscsiUi(BaseController): @Endpoint() @ReadPermission + @no_type_check def status(self): status = {'available': False} try: @@ -559,7 +565,7 @@ class IscsiTarget(RESTController): code='disk_control_invalid_max', component='iscsi') - initiators = [] + initiators = [] # type: List[Any] for group in groups: initiators = initiators + group['members'] if len(initiators) != len(set(initiators)): @@ -895,7 +901,8 @@ class IscsiTarget(RESTController): @staticmethod def _get_portals_by_host(portals): - portals_by_host = {} + # type: (List[dict]) -> Dict[str, List[str]] + portals_by_host = {} # type: Dict[str, List[str]] for portal in portals: host = portal['host'] ip = portal['ip'] diff --git a/src/pybind/mgr/dashboard/controllers/orchestrator.py b/src/pybind/mgr/dashboard/controllers/orchestrator.py index 6e3f11d7a5c01..642a2f6bab212 100644 --- a/src/pybind/mgr/dashboard/controllers/orchestrator.py +++ b/src/pybind/mgr/dashboard/controllers/orchestrator.py @@ -88,7 +88,8 @@ class Orchestrator(RESTController): """ Identify a device by switching on the device light for N seconds. :param hostname: The hostname of the device to process. - :param device: The device identifier to process, e.g. ``ABC1234DEF567-1R1234_ABC8DE0Q``. + :param device: The device identifier to process, e.g. ``/dev/dm-0`` or + ``ABC1234DEF567-1R1234_ABC8DE0Q``. :param duration: The duration in seconds how long the LED should flash. """ orch = OrchClient.instance() diff --git a/src/pybind/mgr/dashboard/controllers/osd.py b/src/pybind/mgr/dashboard/controllers/osd.py index 064a48be0d8e8..373f66329adcf 100644 --- a/src/pybind/mgr/dashboard/controllers/osd.py +++ b/src/pybind/mgr/dashboard/controllers/osd.py @@ -62,7 +62,7 @@ class Osd(RESTController): @staticmethod def get_osd_map(svc_id=None): - # type: (Union[int, None]) -> Dict[int, Union[Dict[str, Any], Any]] + # type: (Union[int, None]) -> Dict[int, Union[dict, Any]] def add_id(osd): osd['id'] = osd['osd'] return osd diff --git a/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py b/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py index 505787387a7c7..497f8c3d72cb6 100644 --- a/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py +++ b/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py @@ -22,6 +22,11 @@ from ..tools import ViewCache from ..services.exception import handle_rados_error, handle_rbd_error, \ serialize_dashboard_exception +try: + from typing import no_type_check +except ImportError: + no_type_check = object() # Just for type checking + logger = logging.getLogger('controllers.rbd_mirror') @@ -148,7 +153,7 @@ def get_daemons_and_pools(): # pylint: disable=R0915 for daemon in daemons: for _, pool_data in daemon['status'].items(): - stats = pool_stats.get(pool_data['name'], None) + stats = pool_stats.get(pool_data['name'], None) # type: ignore if stats is None: continue @@ -191,6 +196,7 @@ def get_daemons_and_pools(): # pylint: disable=R0915 @ViewCache() +@no_type_check def _get_pool_datum(pool_name): data = {} logger.debug("Constructing IOCtx %s", pool_name) diff --git a/src/pybind/mgr/dashboard/controllers/rgw.py b/src/pybind/mgr/dashboard/controllers/rgw.py index 608093dea8892..4e3f8f2ac9099 100644 --- a/src/pybind/mgr/dashboard/controllers/rgw.py +++ b/src/pybind/mgr/dashboard/controllers/rgw.py @@ -15,6 +15,11 @@ from ..services.ceph_service import CephService from ..services.rgw_client import RgwClient from ..tools import json_str_to_object +try: + from typing import List +except ImportError: + pass # Just for type checking + logger = logging.getLogger('controllers.rgw') @@ -44,7 +49,7 @@ class Rgw(BaseController): raise RequestException(msg) status['available'] = True except (RequestException, LookupError) as ex: - status['message'] = str(ex) + status['message'] = str(ex) # type: ignore return status @@ -52,6 +57,7 @@ class Rgw(BaseController): class RgwDaemon(RESTController): def list(self): + # type: () -> List[dict] daemons = [] for hostname, server in CephService.get_service_map('rgw').items(): for service in server['services']: @@ -69,6 +75,7 @@ class RgwDaemon(RESTController): return sorted(daemons, key=lambda k: k['id']) def get(self, svc_id): + # type: (str) -> dict daemon = { 'rgw_metadata': [], 'rgw_id': svc_id, @@ -150,7 +157,7 @@ class RgwBucket(RgwRESTController): @staticmethod def strip_tenant_from_bucket_name(bucket_name): - # type (str) => str + # type (str) -> str """ >>> RgwBucket.strip_tenant_from_bucket_name('tenant/bucket-name') 'bucket-name' @@ -161,7 +168,7 @@ class RgwBucket(RgwRESTController): @staticmethod def get_s3_bucket_name(bucket_name, tenant=None): - # type (str, str) => str + # type (str, str) -> str """ >>> RgwBucket.get_s3_bucket_name('bucket-name', 'tenant') 'tenant:bucket-name' @@ -176,9 +183,11 @@ class RgwBucket(RgwRESTController): return bucket_name def list(self): + # type: () -> List[str] return self.proxy('GET', 'bucket') def get(self, bucket): + # type: (str) -> dict result = self.proxy('GET', 'bucket', {'bucket': bucket}) result['versioning'] =\ @@ -241,10 +250,11 @@ class RgwUser(RgwRESTController): return user def list(self): - users = [] + # type: () -> List[str] + users = [] # type: List[str] marker = None while True: - params = {} + params = {} # type: dict if marker: params['marker'] = marker result = self.proxy('GET', 'user?list', params) @@ -259,15 +269,17 @@ class RgwUser(RgwRESTController): return users def get(self, uid): + # type: (str) -> dict result = self.proxy('GET', 'user', {'uid': uid}) return self._append_uid(result) @Endpoint() @ReadPermission def get_emails(self): + # type: () -> List[str] emails = [] - for uid in json.loads(self.list()): - user = json.loads(self.get(uid)) + for uid in json.loads(self.list()): # type: ignore + user = json.loads(self.get(uid)) # type: ignore if user["email"]: emails.append(user["email"]) return emails diff --git a/src/pybind/mgr/dashboard/module.py b/src/pybind/mgr/dashboard/module.py index 1815e23f0f9da..d58674c8bb907 100644 --- a/src/pybind/mgr/dashboard/module.py +++ b/src/pybind/mgr/dashboard/module.py @@ -104,20 +104,20 @@ class CherryPyConfig(object): :returns our URI """ - server_addr = self.get_localized_module_option( + server_addr = self.get_localized_module_option( # type: ignore 'server_addr', get_default_addr()) - ssl = self.get_localized_module_option('ssl', True) + ssl = self.get_localized_module_option('ssl', True) # type: ignore if not ssl: - server_port = self.get_localized_module_option('server_port', 8080) + server_port = self.get_localized_module_option('server_port', 8080) # type: ignore else: - server_port = self.get_localized_module_option('ssl_server_port', 8443) + server_port = self.get_localized_module_option('ssl_server_port', 8443) # type: ignore if server_addr is None: raise ServerConfigException( 'no server_addr configured; ' 'try "ceph config set mgr mgr/{}/{}/server_addr "' - .format(self.module_name, self.get_mgr_id())) - self.log.info('server: ssl=%s host=%s port=%d', 'yes' if ssl else 'no', + .format(self.module_name, self.get_mgr_id())) # type: ignore + self.log.info('server: ssl=%s host=%s port=%d', 'yes' if ssl else 'no', # type: ignore server_addr, server_port) # Initialize custom handlers. @@ -155,23 +155,23 @@ class CherryPyConfig(object): if ssl: # SSL initialization - cert = self.get_store("crt") + cert = self.get_store("crt") # type: ignore if cert is not None: self.cert_tmp = tempfile.NamedTemporaryFile() self.cert_tmp.write(cert.encode('utf-8')) self.cert_tmp.flush() # cert_tmp must not be gc'ed cert_fname = self.cert_tmp.name else: - cert_fname = self.get_localized_module_option('crt_file') + cert_fname = self.get_localized_module_option('crt_file') # type: ignore - pkey = self.get_store("key") + pkey = self.get_store("key") # type: ignore if pkey is not None: self.pkey_tmp = tempfile.NamedTemporaryFile() self.pkey_tmp.write(pkey.encode('utf-8')) self.pkey_tmp.flush() # pkey_tmp must not be gc'ed pkey_fname = self.pkey_tmp.name else: - pkey_fname = self.get_localized_module_option('key_file') + pkey_fname = self.get_localized_module_option('key_file') # type: ignore verify_tls_files(cert_fname, pkey_fname) @@ -181,8 +181,8 @@ class CherryPyConfig(object): self.update_cherrypy_config(config) - self._url_prefix = prepare_url_prefix(self.get_module_option('url_prefix', - default='')) + self._url_prefix = prepare_url_prefix(self.get_module_option( # type: ignore + 'url_prefix', default='')) uri = "{0}://{1}:{2}{3}/".format( 'https' if ssl else 'http', @@ -204,13 +204,13 @@ class CherryPyConfig(object): try: uri = self._configure() except ServerConfigException as e: - self.log.info("Config not ready to serve, waiting: {0}".format( - e - )) + self.log.info( # type: ignore + "Config not ready to serve, waiting: {0}".format(e) + ) # Poll until a non-errored config is present self._stopping.wait(5) else: - self.log.info("Configured CherryPy, starting engine...") + self.log.info("Configured CherryPy, starting engine...") # type: ignore return uri @@ -267,7 +267,7 @@ class Module(MgrModule, CherryPyConfig): MODULE_OPTIONS.extend(options) __pool_stats = collections.defaultdict(lambda: collections.defaultdict( - lambda: collections.deque(maxlen=10))) + lambda: collections.deque(maxlen=10))) # type: dict def __init__(self, *args, **kwargs): super(Module, self).__init__(*args, **kwargs) diff --git a/src/pybind/mgr/dashboard/plugins/debug.py b/src/pybind/mgr/dashboard/plugins/debug.py index f85336f50082a..71e56abc6460b 100644 --- a/src/pybind/mgr/dashboard/plugins/debug.py +++ b/src/pybind/mgr/dashboard/plugins/debug.py @@ -8,6 +8,11 @@ from . import PLUGIN_MANAGER as PM from . import interfaces as I # noqa: E741,N812 from .plugin import SimplePlugin as SP +try: + from typing import no_type_check +except ImportError: + no_type_check = object() # Just for type checking + class Actions(Enum): ENABLE = 'enable' @@ -28,6 +33,7 @@ class Debug(SP, I.CanCherrypy, I.ConfiguresCherryPy): ) ] + @no_type_check def handler(self, action): ret = 0 msg = '' diff --git a/src/pybind/mgr/dashboard/plugins/feature_toggles.py b/src/pybind/mgr/dashboard/plugins/feature_toggles.py index 3227a05b1812a..2373df2dea33e 100644 --- a/src/pybind/mgr/dashboard/plugins/feature_toggles.py +++ b/src/pybind/mgr/dashboard/plugins/feature_toggles.py @@ -16,6 +16,11 @@ from ..controllers.iscsi import Iscsi, IscsiTarget from ..controllers.cephfs import CephFS from ..controllers.rgw import Rgw, RgwDaemon, RgwBucket, RgwUser +try: + from typing import no_type_check, Set +except ImportError: + no_type_check = object() # Just for type checking + class Features(Enum): RBD = 'rbd' @@ -25,7 +30,7 @@ class Features(Enum): RGW = 'rgw' -PREDISABLED_FEATURES = set() +PREDISABLED_FEATURES = set() # type: Set[str] Feature2Controller = { @@ -59,7 +64,7 @@ class FeatureToggles(I.CanMgr, I.Setupable, I.HasOptions, self.Controller2Feature = { controller: feature for feature, controllers in Feature2Controller.items() - for controller in controllers} + for controller in controllers} # type: ignore @PM.add_hook def get_options(self): @@ -102,6 +107,7 @@ class FeatureToggles(I.CanMgr, I.Setupable, I.HasOptions, return ret, '\n'.join(msg), '' return {'handle_command': cmd} + @no_type_check # https://github.com/python/mypy/issues/7806 def _get_feature_from_request(self, request): try: return self.Controller2Feature[ @@ -110,6 +116,7 @@ class FeatureToggles(I.CanMgr, I.Setupable, I.HasOptions, return None @ttl_cache(ttl=CACHE_TTL, maxsize=CACHE_MAX_SIZE) + @no_type_check # https://github.com/python/mypy/issues/7806 def _is_feature_enabled(self, feature): return self.mgr.get_module_option(self.OPTION_FMT.format(feature.value)) diff --git a/src/pybind/mgr/dashboard/plugins/interfaces.py b/src/pybind/mgr/dashboard/plugins/interfaces.py index fdf6fdc58d65f..f9169a0d89a6e 100644 --- a/src/pybind/mgr/dashboard/plugins/interfaces.py +++ b/src/pybind/mgr/dashboard/plugins/interfaces.py @@ -6,7 +6,7 @@ from . import PLUGIN_MANAGER as PM, Interface, Mixin # pylint: disable=cyclic-i class CanMgr(Mixin): from .. import mgr - mgr = mgr + mgr = mgr # type: ignore class CanCherrypy(Mixin): diff --git a/src/pybind/mgr/dashboard/plugins/pluggy.py b/src/pybind/mgr/dashboard/plugins/pluggy.py index 844103883fdea..0a1765f1f7f54 100644 --- a/src/pybind/mgr/dashboard/plugins/pluggy.py +++ b/src/pybind/mgr/dashboard/plugins/pluggy.py @@ -40,6 +40,10 @@ distros and releases currently targeted for Ceph Nautilus: TODO: Once this becomes available in the above distros, this file should be REMOVED, and the fully featured python-pluggy should be used instead. """ +try: + from typing import DefaultDict +except ImportError: + pass # For typing only class HookspecMarker(object): @@ -75,7 +79,7 @@ class _HookRelay(object): """ def __init__(self): from collections import defaultdict - self._registry = defaultdict(list) + self._registry = defaultdict(list) # type: DefaultDict[str, list] def __getattr__(self, hook_name): return lambda *args, **kwargs: [ diff --git a/src/pybind/mgr/dashboard/plugins/plugin.py b/src/pybind/mgr/dashboard/plugins/plugin.py index 17225810f0f86..ad8342a20d7db 100644 --- a/src/pybind/mgr/dashboard/plugins/plugin.py +++ b/src/pybind/mgr/dashboard/plugins/plugin.py @@ -3,6 +3,11 @@ from mgr_module import Option, Command from . import PLUGIN_MANAGER as PM from . import interfaces as I # noqa: E741,N812 +try: + from typing import no_type_check +except ImportError: + no_type_check = object() # Just for type checking + class SimplePlugin(I.CanMgr, I.HasOptions, I.HasCommands): """ @@ -17,17 +22,20 @@ class SimplePlugin(I.CanMgr, I.HasOptions, I.HasCommands): @PM.add_hook def get_options(self): - return self.OPTIONS + return self.OPTIONS # type: ignore @PM.final + @no_type_check # https://github.com/python/mypy/issues/7806 def get_option(self, option): return self.mgr.get_module_option(option) @PM.final + @no_type_check # https://github.com/python/mypy/issues/7806 def set_option(self, option, value): self.mgr.set_module_option(option, value) @PM.add_hook + @no_type_check # https://github.com/python/mypy/issues/7806 def register_commands(self): for cmd in self.COMMANDS: cmd.register(instance=self) diff --git a/src/pybind/mgr/dashboard/plugins/ttl_cache.py b/src/pybind/mgr/dashboard/plugins/ttl_cache.py index 4677e20dfbf15..4f4f244d2d77a 100644 --- a/src/pybind/mgr/dashboard/plugins/ttl_cache.py +++ b/src/pybind/mgr/dashboard/plugins/ttl_cache.py @@ -10,13 +10,18 @@ from collections import OrderedDict from threading import RLock from time import time +try: + from typing import Tuple +except ImportError: + pass # For typing only + def ttl_cache(ttl, maxsize=128, typed=False): if typed is not False: raise NotImplementedError("typed caching not supported") def decorating_function(function): - cache = OrderedDict() + cache = OrderedDict() # type: OrderedDict[object, Tuple[bool, float]] stats = [0, 0, 0] rlock = RLock() setattr(function, 'cache_info', lambda: diff --git a/src/pybind/mgr/dashboard/rest_client.py b/src/pybind/mgr/dashboard/rest_client.py index 83d7fc6322f2e..22a36d0e3072c 100644 --- a/src/pybind/mgr/dashboard/rest_client.py +++ b/src/pybind/mgr/dashboard/rest_client.py @@ -24,7 +24,12 @@ from .tools import build_url try: from requests.packages.urllib3.exceptions import SSLError except ImportError: - from urllib3.exceptions import SSLError + from urllib3.exceptions import SSLError # type: ignore + +try: + from typing import List +except ImportError: + pass # Just for type checking logger = logging.getLogger('rest_client') @@ -180,13 +185,13 @@ class _ResponseValidator(object): level_next = path[path_sep + 1:].strip() else: path_sep = len(path) - level_next = None + level_next = None # type: ignore key = path[:path_sep].strip() if key == '*': continue elif key == '': # check all keys - for k in resp.keys(): + for k in resp.keys(): # type: ignore _ResponseValidator._validate_key(k, level_next, resp) else: _ResponseValidator._validate_key(key, level_next, resp) @@ -249,6 +254,7 @@ class _ResponseValidator(object): @staticmethod def _parse_level_paths(level): + # type: (str) -> List[str] level = level.strip() if level[0] == '(': level = level[1:] @@ -446,7 +452,7 @@ class RestClient(object): match = re.match(r'.*: \[Errno (-?\d+)\] (.+)', ex.args[0].reason.args[0]) except AttributeError: - match = False + match = None if match: errno = match.group(1) strerror = match.group(2) diff --git a/src/pybind/mgr/dashboard/services/access_control.py b/src/pybind/mgr/dashboard/services/access_control.py index 6b45b5f9394f4..17d9f71976d69 100644 --- a/src/pybind/mgr/dashboard/services/access_control.py +++ b/src/pybind/mgr/dashboard/services/access_control.py @@ -383,7 +383,8 @@ class User(object): return False def permissions_dict(self): - perms = {} + # type: () -> dict + perms = {} # type: dict for role in self.roles: for scope, perms_list in role.scopes_permissions.items(): if scope in perms: @@ -553,12 +554,12 @@ class AccessControlDB(object): db.check_and_update_db() return db - db = json.loads(json_db) + dict_db = json.loads(json_db) roles = {rn: Role.from_dict(r) - for rn, r in db.get('roles', {}).items()} + for rn, r in dict_db.get('roles', {}).items()} users = {un: User.from_dict(u, dict(roles, **SYSTEM_ROLES)) - for un, u in db.get('users', {}).items()} - return cls(db['version'], users, roles) + for un, u in dict_db.get('users', {}).items()} + return cls(dict_db['version'], users, roles) def load_access_control_db(): diff --git a/src/pybind/mgr/dashboard/services/auth.py b/src/pybind/mgr/dashboard/services/auth.py index afddfd99aa588..d829362e63d3c 100644 --- a/src/pybind/mgr/dashboard/services/auth.py +++ b/src/pybind/mgr/dashboard/services/auth.py @@ -31,7 +31,7 @@ class JwtManager(object): @classmethod def init(cls): - cls.logger = logging.getLogger('jwt') + cls.logger = logging.getLogger('jwt') # type: ignore # generate a new secret if it does not exist secret = mgr.get_store('jwt_secret') if secret is None: @@ -53,13 +53,13 @@ class JwtManager(object): 'iat': now, 'username': username } - return jwt.encode(payload, cls._secret, algorithm=cls.JWT_ALGORITHM) + return jwt.encode(payload, cls._secret, algorithm=cls.JWT_ALGORITHM) # type: ignore @classmethod def decode_token(cls, token): if not cls._secret: cls.init() - return jwt.decode(token, cls._secret, algorithms=cls.JWT_ALGORITHM) + return jwt.decode(token, cls._secret, algorithms=cls.JWT_ALGORITHM) # type: ignore @classmethod def get_token_from_header(cls): @@ -90,16 +90,20 @@ class JwtManager(object): user = AuthManager.get_user(dtoken['username']) if user.last_update <= dtoken['iat']: return user - cls.logger.debug("user info changed after token was issued, iat=%s last_update=%s", - dtoken['iat'], user.last_update) + cls.logger.debug( # type: ignore + "user info changed after token was issued, iat=%s last_update=%s", + dtoken['iat'], user.last_update + ) else: - cls.logger.debug('Token is black-listed') - except jwt.exceptions.ExpiredSignatureError: - cls.logger.debug("Token has expired") - except jwt.exceptions.InvalidTokenError: - cls.logger.debug("Failed to decode token") + cls.logger.debug('Token is black-listed') # type: ignore + except jwt.ExpiredSignatureError: + cls.logger.debug("Token has expired") # type: ignore + except jwt.InvalidTokenError: + cls.logger.debug("Failed to decode token") # type: ignore except UserDoesNotExist: - cls.logger.debug("Invalid token: user %s does not exist", dtoken['username']) + cls.logger.debug( # type: ignore + "Invalid token: user %s does not exist", dtoken['username'] + ) return None @classmethod @@ -140,15 +144,15 @@ class AuthManager(object): @classmethod def get_user(cls, username): - return cls.AUTH_PROVIDER.get_user(username) + return cls.AUTH_PROVIDER.get_user(username) # type: ignore @classmethod def authenticate(cls, username, password): - return cls.AUTH_PROVIDER.authenticate(username, password) + return cls.AUTH_PROVIDER.authenticate(username, password) # type: ignore @classmethod def authorize(cls, username, scope, permissions): - return cls.AUTH_PROVIDER.authorize(username, scope, permissions) + return cls.AUTH_PROVIDER.authorize(username, scope, permissions) # type: ignore class AuthManagerTool(cherrypy.Tool): diff --git a/src/pybind/mgr/dashboard/services/ceph_service.py b/src/pybind/mgr/dashboard/services/ceph_service.py index 506c2f98dfed4..6c83dcc75570f 100644 --- a/src/pybind/mgr/dashboard/services/ceph_service.py +++ b/src/pybind/mgr/dashboard/services/ceph_service.py @@ -11,7 +11,7 @@ from mgr_util import get_time_series_rates, get_most_recent_rate from .. import mgr try: - from typing import Dict, Any # pylint: disable=unused-import + from typing import Dict # pylint: disable=unused-import except ImportError: pass # For typing only @@ -40,7 +40,7 @@ class CephService(object): @classmethod def get_service_map(cls, service_name): - service_map = {} # type: Dict[str, Dict[str, Any]] + service_map = {} # type: Dict[str, dict] for server in mgr.list_servers(): for service in server['services']: if service['type'] == service_name: @@ -192,7 +192,7 @@ class CephService(object): def get_smart_data_by_host(hostname): # type: (str) -> dict devices = CephService.get_devices_by_host(hostname) - smart_data = {} + smart_data = {} # type: dict if devices: for device in devices: if device['devid'] not in smart_data: diff --git a/src/pybind/mgr/dashboard/services/exception.py b/src/pybind/mgr/dashboard/services/exception.py index 4a1f2a105d135..63249eb8ccf60 100644 --- a/src/pybind/mgr/dashboard/services/exception.py +++ b/src/pybind/mgr/dashboard/services/exception.py @@ -83,7 +83,7 @@ def serialize_dashboard_exception(e, include_http_status=False, task=None): if include_http_status: out['status'] = getattr(e, 'status', 500) if task: - out['task'] = dict(name=task.name, metadata=task.metadata) + out['task'] = dict(name=task.name, metadata=task.metadata) # type: ignore return out diff --git a/src/pybind/mgr/dashboard/services/iscsi_client.py b/src/pybind/mgr/dashboard/services/iscsi_client.py index f41639e7a09f3..b82a51a3d4a68 100644 --- a/src/pybind/mgr/dashboard/services/iscsi_client.py +++ b/src/pybind/mgr/dashboard/services/iscsi_client.py @@ -22,7 +22,7 @@ logger = logging.getLogger('iscsi_client') class IscsiClient(RestClient): _CLIENT_NAME = 'iscsi' - _instances = {} + _instances = {} # type: dict service_url = None gateway_name = None diff --git a/src/pybind/mgr/dashboard/services/iscsi_config.py b/src/pybind/mgr/dashboard/services/iscsi_config.py index fa1ec5a21d174..3c0698c574fa1 100644 --- a/src/pybind/mgr/dashboard/services/iscsi_config.py +++ b/src/pybind/mgr/dashboard/services/iscsi_config.py @@ -78,7 +78,7 @@ class IscsiGatewaysConfig(object): @staticmethod def _load_config_from_orchestrator(): - config = {'gateways': {}} + config = {'gateways': {}} # type: dict try: instances = OrchClient.instance().services.list("iscsi") for instance in instances: diff --git a/src/pybind/mgr/dashboard/services/orchestrator.py b/src/pybind/mgr/dashboard/services/orchestrator.py index 355ab9f652e57..b2f282bbc0cb3 100644 --- a/src/pybind/mgr/dashboard/services/orchestrator.py +++ b/src/pybind/mgr/dashboard/services/orchestrator.py @@ -8,7 +8,6 @@ from orchestrator import OrchestratorClientMixin, raise_if_exception, Orchestrat from .. import mgr from ..tools import wraps - logger = logging.getLogger('orchestrator') @@ -16,7 +15,7 @@ logger = logging.getLogger('orchestrator') class OrchestratorAPI(OrchestratorClientMixin): def __init__(self): super(OrchestratorAPI, self).__init__() - self.set_mgr(mgr) + self.set_mgr(mgr) # type: ignore def status(self): try: @@ -24,8 +23,9 @@ class OrchestratorAPI(OrchestratorClientMixin): logger.info("is orchestrator available: %s, %s", status, desc) return dict(available=status, description=desc) except (RuntimeError, OrchestratorError, ImportError): - return dict(available=False, - description='Orchestrator is unavailable for unknown reason') + return dict( + available=False, + description='Orchestrator is unavailable for unknown reason') def orchestrator_wait(self, completions): return self._orchestrator_wait(completions) @@ -38,6 +38,7 @@ def wait_api_result(method): self.api.orchestrator_wait([completion]) raise_if_exception(completion) return completion.result + return inner @@ -47,7 +48,6 @@ class ResourceManager(object): class HostManger(ResourceManager): - @wait_api_result def list(self): return self.api.get_hosts() @@ -66,7 +66,6 @@ class HostManger(ResourceManager): class InventoryManager(ResourceManager): - @wait_api_result def list(self, hosts=None, refresh=False): host_filter = InventoryFilter(hosts=hosts) if hosts else None @@ -74,7 +73,6 @@ class InventoryManager(ResourceManager): class ServiceManager(ResourceManager): - @wait_api_result def list(self, service_type=None, service_id=None, host_name=None): return self.api.list_daemons(service_type, service_id, host_name) @@ -83,16 +81,17 @@ class ServiceManager(ResourceManager): if not isinstance(service_ids, list): service_ids = [service_ids] - completion_list = [self.api.service_action('reload', service_type, - service_name, service_id) - for service_name, service_id in service_ids] + completion_list = [ + self.api.service_action('reload', service_type, service_name, + service_id) + for service_name, service_id in service_ids + ] self.api.orchestrator_wait(completion_list) for c in completion_list: raise_if_exception(c) class OsdManager(ResourceManager): - @wait_api_result def create(self, drive_group): return self.api.create_osds([drive_group]) @@ -125,4 +124,5 @@ class OrchClient(object): @wait_api_result def blink_device_light(self, hostname, device, ident_fault, on): # type: (str, str, str, bool) -> Completion - return self.api.blink_device_light(ident_fault, on, [DeviceLightLoc(hostname, device)]) + return self.api.blink_device_light( + ident_fault, on, [DeviceLightLoc(hostname, device, device)]) diff --git a/src/pybind/mgr/dashboard/services/rbd.py b/src/pybind/mgr/dashboard/services/rbd.py index 1f708eef3ecd7..e1670b696814b 100644 --- a/src/pybind/mgr/dashboard/services/rbd.py +++ b/src/pybind/mgr/dashboard/services/rbd.py @@ -9,6 +9,11 @@ from .. import mgr from ..tools import ViewCache from .ceph_service import CephService +try: + from typing import List +except ImportError: + pass # For typing only + RBD_FEATURES_NAME_MAPPING = { rbd.RBD_FEATURE_LAYERING: "layering", @@ -81,7 +86,7 @@ class RbdConfiguration(object): def __init__(self, pool_name='', namespace='', image_name='', pool_ioctx=None, image_ioctx=None): - # type: (str, str, object, object) -> None + # type: (str, str, str, object, object) -> None assert bool(pool_name) != bool(pool_ioctx) # xor self._pool_name = pool_name self._namespace = namespace if namespace is not None else '' @@ -95,7 +100,7 @@ class RbdConfiguration(object): return option if option.startswith('conf_') else 'conf_' + option def list(self): - # type: () -> [dict] + # type: () -> List[dict] def _list(ioctx): if self._image_name: # image config with rbd.Image(ioctx, self._image_name) as image: @@ -131,23 +136,23 @@ class RbdConfiguration(object): pool_ioctx = self._pool_ioctx if self._pool_name: # open ioctx pool_ioctx = mgr.rados.open_ioctx(self._pool_name) - pool_ioctx.__enter__() - pool_ioctx.set_namespace(self._namespace) + pool_ioctx.__enter__() # type: ignore + pool_ioctx.set_namespace(self._namespace) # type: ignore image_ioctx = self._image_ioctx if self._image_name: image_ioctx = rbd.Image(pool_ioctx, self._image_name) - image_ioctx.__enter__() + image_ioctx.__enter__() # type: ignore if image_ioctx: - image_ioctx.metadata_set(option_name, option_value) + image_ioctx.metadata_set(option_name, option_value) # type: ignore else: self._rbd.pool_metadata_set(pool_ioctx, option_name, option_value) if self._image_name: # Name provided, so we opened it and now have to close it - image_ioctx.__exit__(None, None, None) + image_ioctx.__exit__(None, None, None) # type: ignore if self._pool_name: - pool_ioctx.__exit__(None, None, None) + pool_ioctx.__exit__(None, None, None) # type: ignore def remove(self, option_name): """ diff --git a/src/pybind/mgr/dashboard/services/rgw_client.py b/src/pybind/mgr/dashboard/services/rgw_client.py index 5ec4269ee1916..daf2bb48ed364 100644 --- a/src/pybind/mgr/dashboard/services/rgw_client.py +++ b/src/pybind/mgr/dashboard/services/rgw_client.py @@ -14,7 +14,7 @@ from ..tools import build_url, dict_contains_path, json_str_to_object, partial_d from .. import mgr try: - from typing import Any, Dict, List # pylint: disable=unused-import + from typing import Dict, List, Optional # pylint: disable=unused-import except ImportError: pass # For typing only @@ -179,7 +179,7 @@ def _parse_frontend_config(config): return port, ssl if option_name in ['endpoint', 'ssl_endpoint']: match = re.search(r'([\d.]+|\[.+\])(:(\d+))?', - match.group(2)) + match.group(2)) # type: ignore if match: port = int(match.group(3)) if \ match.group(2) is not None else 443 if \ @@ -187,7 +187,7 @@ def _parse_frontend_config(config): 80 ssl = option_name == 'ssl_endpoint' return port, ssl - if match.group(1) == 'civetweb': + if match.group(1) == 'civetweb': # type: ignore match = re.search(r'port=(.*:)?(\d+)(s)?', config) if match: port = int(match.group(2)) @@ -202,7 +202,7 @@ class RgwClient(RestClient): _host = None _port = None _ssl = None - _user_instances = {} + _user_instances = {} # type: Dict[str, RgwClient] _rgw_settings_snapshot = None @staticmethod @@ -238,10 +238,10 @@ class RgwClient(RestClient): # Append the instance to the internal map. RgwClient._user_instances[RgwClient._SYSTEM_USERID] = instance - def _get_daemon_zone_info(self): # type: () -> Dict[str, Any] + def _get_daemon_zone_info(self): # type: () -> dict return json_str_to_object(self.proxy('GET', 'config?type=zone', None, None)) - def _get_daemon_zonegroup_map(self): # type: () -> List[Dict[str, Any]] + def _get_daemon_zonegroup_map(self): # type: () -> List[dict] zonegroups = json_str_to_object( self.proxy('GET', 'config?type=zonegroup-map', None, None) ) @@ -264,6 +264,7 @@ class RgwClient(RestClient): @staticmethod def instance(userid): + # type: (Optional[str]) -> RgwClient # Discard all cached instances if any rgw setting has changed if RgwClient._rgw_settings_snapshot != RgwClient._rgw_settings(): RgwClient._rgw_settings_snapshot = RgwClient._rgw_settings() @@ -284,11 +285,11 @@ class RgwClient(RestClient): userid)) # Create an instance and append it to the internal map. - RgwClient._user_instances[userid] = RgwClient(userid, + RgwClient._user_instances[userid] = RgwClient(userid, # type: ignore keys['access_key'], keys['secret_key']) - return RgwClient._user_instances[userid] + return RgwClient._user_instances[userid] # type: ignore @staticmethod def admin_instance(): @@ -328,7 +329,7 @@ class RgwClient(RestClient): super(RgwClient, self).__init__(host, port, 'RGW', ssl, s3auth, ssl_verify=ssl_verify) # If user ID is not set, then try to get it via the RGW Admin Ops API. - self.userid = userid if userid else self._get_user_id(self.admin_path) + self.userid = userid if userid else self._get_user_id(self.admin_path) # type: str logger.info("Created new connection for user: %s", self.userid) @@ -457,7 +458,7 @@ class RgwClient(RestClient): return request(data=data) - def get_placement_targets(self): # type: () -> Dict[str, Any] + def get_placement_targets(self): # type: () -> dict zone = self._get_daemon_zone_info() # A zone without realm id can only belong to default zonegroup. zonegroup_name = 'default' diff --git a/src/pybind/mgr/dashboard/services/sso.py b/src/pybind/mgr/dashboard/services/sso.py index 5735d85178b57..ca9a221abcbcb 100644 --- a/src/pybind/mgr/dashboard/services/sso.py +++ b/src/pybind/mgr/dashboard/services/sso.py @@ -15,10 +15,10 @@ from six.moves.urllib import parse from .. import mgr from ..tools import prepare_url_prefix + if six.PY2: FileNotFoundError = IOError # pylint: disable=redefined-builtin - logger = logging.getLogger('sso') try: @@ -91,8 +91,9 @@ class SsoDB(object): db.check_and_update_db() return db - db = json.loads(json_db) - return cls(db['version'], db.get('protocol'), Saml2.from_dict(db.get('saml2'))) + dict_db = json.loads(json_db) # type: dict + return cls(dict_db['version'], dict_db.get('protocol'), + Saml2.from_dict(dict_db.get('saml2'))) def load_sso_db(): diff --git a/src/pybind/mgr/dashboard/services/tcmu_service.py b/src/pybind/mgr/dashboard/services/tcmu_service.py index 1f3e4d8d78b49..183cb29bb37a1 100644 --- a/src/pybind/mgr/dashboard/services/tcmu_service.py +++ b/src/pybind/mgr/dashboard/services/tcmu_service.py @@ -3,6 +3,12 @@ from mgr_util import get_most_recent_rate from dashboard.services.ceph_service import CephService from .. import mgr +try: + from typing import Dict +except ImportError: + pass # Just for type checking + + SERVICE_TYPE = 'tcmu-runner' @@ -10,8 +16,8 @@ class TcmuService(object): # pylint: disable=too-many-nested-blocks @staticmethod def get_iscsi_info(): - daemons = {} - images = {} + daemons = {} # type: Dict[str, dict] + images = {} # type: Dict[str, dict] for service in CephService.get_service_list(SERVICE_TYPE): metadata = service['metadata'] if metadata is None: diff --git a/src/pybind/mgr/dashboard/tools.py b/src/pybind/mgr/dashboard/tools.py index 1d7a46d86b594..ce730862d2201 100644 --- a/src/pybind/mgr/dashboard/tools.py +++ b/src/pybind/mgr/dashboard/tools.py @@ -29,7 +29,8 @@ from .settings import Settings from .services.auth import JwtManager try: - from typing import Any, AnyStr, Dict, List # noqa pylint: disable=unused-import + from typing import Any, AnyStr, Callable, DefaultDict, Deque,\ + Dict, List, Set, Tuple, Union # noqa pylint: disable=unused-import except ImportError: pass # For typing only @@ -251,7 +252,7 @@ class ViewCache(object): rvc = ViewCache.RemoteViewCache(self.timeout) self.cache_by_args[args] = rvc return rvc.run(fn, args, kwargs) - wrapper.reset = self.reset + wrapper.reset = self.reset # type: ignore return wrapper def reset(self): @@ -261,10 +262,10 @@ class ViewCache(object): class NotificationQueue(threading.Thread): _ALL_TYPES_ = '__ALL__' - _listeners = collections.defaultdict(set) + _listeners = collections.defaultdict(set) # type: DefaultDict[str, Set[Tuple[int, Callable]]] _lock = threading.Lock() _cond = threading.Condition() - _queue = collections.deque() + _queue = collections.deque() # type: Deque[Tuple[str, Any]] _running = False _instance = None @@ -279,8 +280,8 @@ class NotificationQueue(threading.Thread): return cls._running = True cls._instance = NotificationQueue() - cls.logger = logging.getLogger('notification_queue') - cls.logger.debug("starting notification queue") + cls.logger = logging.getLogger('notification_queue') # type: ignore + cls.logger.debug("starting notification queue") # type: ignore cls._instance.start() @classmethod @@ -294,9 +295,9 @@ class NotificationQueue(threading.Thread): cls._running = False with cls._cond: cls._cond.notify() - cls.logger.debug("waiting for notification queue to finish") + cls.logger.debug("waiting for notification queue to finish") # type: ignore instance.join() - cls.logger.debug("notification queue stopped") + cls.logger.debug("notification queue stopped") # type: ignore @classmethod def _registered_handler(cls, func, n_types): @@ -327,11 +328,14 @@ class NotificationQueue(threading.Thread): for ev_type in n_types: if not cls._registered_handler(func, ev_type): cls._listeners[ev_type].add((priority, func)) - cls.logger.debug("function %s was registered for events of" - " type %s", func, ev_type) + cls.logger.debug( # type: ignore + "function %s was registered for events of type %s", + func, ev_type + ) @classmethod def deregister(cls, func, n_types=None): + # type: (Callable, Union[str, list, None]) -> None """Removes the listener function from this notification queue If the second parameter `n_types` is omitted, the function is removed @@ -358,11 +362,14 @@ class NotificationQueue(threading.Thread): break if to_remove: listeners.discard(to_remove) - cls.logger.debug("function %s was deregistered for events " - "of type %s", func, ev_type) + cls.logger.debug( # type: ignore + "function %s was deregistered for events of type %s", + func, ev_type + ) @classmethod def new_notification(cls, notify_type, notify_value): + # type: (str, Any) -> None with cls._cond: cls._queue.append((notify_type, notify_value)) cls._cond.notify() @@ -379,10 +386,10 @@ class NotificationQueue(threading.Thread): listener[1](notify_value) def run(self): - self.logger.debug("notification queue started") + self.logger.debug("notification queue started") # type: ignore while self._running: private_buffer = [] - self.logger.debug("processing queue: %s", len(self._queue)) + self.logger.debug("processing queue: %s", len(self._queue)) # type: ignore try: while True: private_buffer.append(self._queue.popleft()) @@ -393,10 +400,10 @@ class NotificationQueue(threading.Thread): while self._running and not self._queue: self._cond.wait() # flush remaining events - self.logger.debug("flush remaining events: %s", len(self._queue)) + self.logger.debug("flush remaining events: %s", len(self._queue)) # type: ignore self._notify_listeners(self._queue) self._queue.clear() - self.logger.debug("notification queue finished") + self.logger.debug("notification queue finished") # type: ignore # pylint: disable=too-many-arguments, protected-access @@ -407,20 +414,20 @@ class TaskManager(object): VALUE_DONE = "done" VALUE_EXECUTING = "executing" - _executing_tasks = set() - _finished_tasks = [] + _executing_tasks = set() # type: Set[Task] + _finished_tasks = [] # type: List[Task] _lock = threading.Lock() _task_local_data = threading.local() @classmethod def init(cls): - cls.logger = logging.getLogger('taskmgr') + cls.logger = logging.getLogger('taskmgr') # type: ignore NotificationQueue.register(cls._handle_finished_task, 'cd_task_finished') @classmethod def _handle_finished_task(cls, task): - cls.logger.info("finished %s", task) + cls.logger.info("finished %s", task) # type: ignore with cls._lock: cls._executing_tasks.remove(task) cls._finished_tasks.append(task) @@ -438,13 +445,13 @@ class TaskManager(object): exception_handler) with cls._lock: if task in cls._executing_tasks: - cls.logger.debug("task already executing: %s", task) + cls.logger.debug("task already executing: %s", task) # type: ignore for t in cls._executing_tasks: if t == task: return t - cls.logger.debug("created %s", task) + cls.logger.debug("created %s", task) # type: ignore cls._executing_tasks.add(task) - cls.logger.info("running %s", task) + cls.logger.info("running %s", task) # type: ignore task._run() return task @@ -522,7 +529,7 @@ class TaskExecutor(object): def start(self): self.logger.debug("executing task %s", self.task) try: - self.task.fn(*self.task.fn_args, **self.task.fn_kwargs) + self.task.fn(*self.task.fn_args, **self.task.fn_kwargs) # type: ignore except Exception as ex: self.logger.exception("Error while calling %s", self.task) self.finish(None, ex) @@ -532,7 +539,7 @@ class TaskExecutor(object): self.logger.debug("successfully finished task: %s", self.task) else: self.logger.debug("task finished with exception: %s", self.task) - self.task._complete(ret_value, exception) + self.task._complete(ret_value, exception) # type: ignore # pylint: disable=protected-access @@ -549,7 +556,7 @@ class ThreadedExecutor(TaskExecutor): TaskManager._task_local_data.task = self.task try: self.logger.debug("executing task %s", self.task) - val = self.task.fn(*self.task.fn_args, **self.task.fn_kwargs) + val = self.task.fn(*self.task.fn_args, **self.task.fn_kwargs) # type: ignore except Exception as ex: self.logger.exception("Error while calling %s", self.task) self.finish(None, ex) @@ -614,7 +621,7 @@ class Task(object): self.end_time = now self.ret_value = ret_value self.exception = exception - self.duration = now - self.begin_time + self.duration = now - self.begin_time # type: ignore if not self.exception: self.set_progress(100, True) NotificationQueue.new_notification('cd_task_finished', self) @@ -648,7 +655,7 @@ class Task(object): raise Exception("Progress delta value must be a positive integer") if not in_lock: self.lock.acquire() - prog = self.progress + delta + prog = self.progress + delta # type: ignore self.progress = prog if prog <= 100 else 100 if not in_lock: self.lock.release() @@ -796,7 +803,7 @@ def json_str_to_object(value): # type: (AnyStr) -> Any try: # json.loads accepts binary input from version >=3.6 - value = value.decode('utf-8') + value = value.decode('utf-8') # type: ignore except AttributeError: pass @@ -821,7 +828,7 @@ def get_request_body_params(request): :return: A dictionary containing the parameters. :rtype: dict """ - params = {} + params = {} # type: dict if request.method not in request.methods_with_bodies: return params diff --git a/src/pybind/mgr/tox.ini b/src/pybind/mgr/tox.ini index 23b0573220b4a..4e365b441c4c0 100644 --- a/src/pybind/mgr/tox.ini +++ b/src/pybind/mgr/tox.ini @@ -15,6 +15,7 @@ deps = commands = mypy --config-file=../../mypy.ini \ cephadm/module.py \ mgr_module.py \ + dashboard/module.py \ mgr_util.py \ orchestrator/__init__.py \ progress/module.py \