]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
python-common: Type annotation for ServiceSpec.from_json
authorSebastian Wagner <sebastian.wagner@suse.com>
Mon, 1 Feb 2021 15:13:19 +0000 (16:13 +0100)
committerSebastian Wagner <sebastian.wagner@suse.com>
Tue, 2 Feb 2021 14:16:54 +0000 (15:16 +0100)
Signed-off-by: Sebastian Wagner <sebastian.wagner@suse.com>
src/pybind/mgr/cephadm/module.py
src/pybind/mgr/orchestrator/_interface.py
src/pybind/mgr/orchestrator/module.py
src/python-common/ceph/deployment/service_spec.py

index a6ffdb4a037be383e43f5b8c03f58502757cfc60..7034336b5c13e0fe5281412e314187ff991880cc 100644 (file)
@@ -12,7 +12,7 @@ from threading import Event
 
 import string
 from typing import List, Dict, Optional, Callable, Tuple, TypeVar, \
-    Any, Set, TYPE_CHECKING, cast, Iterator, NamedTuple
+    Any, Set, TYPE_CHECKING, cast, Iterator, NamedTuple, Sequence
 
 import datetime
 import os
@@ -2003,7 +2003,7 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule,
         }
 
     @trivial_completion
-    def plan(self, specs: List[GenericSpec]) -> List:
+    def plan(self, specs: Sequence[GenericSpec]) -> List:
         results = [{'warning': 'WARNING! Dry-Runs are snapshots of a certain point in time and are bound \n'
                                'to the current inventory setup. If any on these conditions changes, the \n'
                                'preview will be invalid. Please make sure to have a minimal \n'
@@ -2054,7 +2054,7 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule,
         return "Scheduled %s update..." % spec.service_name()
 
     @trivial_completion
-    def apply(self, specs: List[GenericSpec]) -> List[str]:
+    def apply(self, specs: Sequence[GenericSpec]) -> List[str]:
         results = []
         for spec in specs:
             results.append(self._apply(spec))
index 6034e219daf0b8887e8f715a9164c8b5a0e1d600..1a247a5dce25835494489bef786e23dda7e3b056 100644 (file)
@@ -882,7 +882,7 @@ class Orchestrator(object):
         """
         raise NotImplementedError()
 
-    def apply(self, specs: List["GenericSpec"]) -> Completion[List[str]]:
+    def apply(self, specs: Sequence["GenericSpec"]) -> Completion[List[str]]:
         """
         Applies any spec
         """
@@ -921,7 +921,7 @@ class Orchestrator(object):
             completion = completion.then(next)
         return completion
 
-    def plan(self, spec: List["GenericSpec"]) -> Completion[List]:
+    def plan(self, spec: Sequence["GenericSpec"]) -> Completion[List]:
         """
         Plan (Dry-run, Preview) a List of Specs.
         """
index 534da49bde458cf1d7e02184b92fd8334ac8a362..1ed7124068e7632f37ca701e5decc98b3f5e9dc1 100644 (file)
@@ -883,9 +883,10 @@ Usage:
                 raise OrchestratorValidationError(usage)
             spec = ServiceSpec.from_json(yaml.safe_load(inbuf))
         else:
-            spec = PlacementSpec.from_string(placement)
-            assert daemon_type
-            spec = ServiceSpec(daemon_type.value, placement=spec)
+            if not placement or not daemon_type:
+                raise OrchestratorValidationError(usage)
+            placement_spec = PlacementSpec.from_string(placement)
+            spec = ServiceSpec(daemon_type.value, placement=placement_spec)
 
         if daemon_type == ServiceType.mon:
             completion = self.add_mon(spec)
@@ -906,11 +907,11 @@ Usage:
         elif daemon_type == ServiceType.mds:
             completion = self.add_mds(spec)
         elif daemon_type == ServiceType.rgw:
-            completion = self.add_rgw(spec)
+            completion = self.add_rgw(cast(RGWSpec, spec))
         elif daemon_type == ServiceType.nfs:
-            completion = self.add_nfs(spec)
+            completion = self.add_nfs(cast(NFSServiceSpec, spec))
         elif daemon_type == ServiceType.iscsi:
-            completion = self.add_iscsi(spec)
+            completion = self.add_iscsi(cast(IscsiServiceSpec, spec))
         elif daemon_type == ServiceType.cephadm_exporter:
             completion = self.add_cephadm_exporter(spec)
         else:
index 6602c10f9dddafd6492c2dc68b115eb9b5ad1ce5..f10823a78c35fef2f418620e0adbeb56c18c0695 100644 (file)
@@ -3,13 +3,16 @@ import fnmatch
 import re
 from collections import namedtuple, OrderedDict
 from functools import wraps
-from typing import Optional, Dict, Any, List, Union, Callable, Iterable
+from typing import Optional, Dict, Any, List, Union, Callable, Iterable, Type, TypeVar, cast
 
 import yaml
 
 from ceph.deployment.hostspec import HostSpec
 from ceph.deployment.utils import unwrap_ipv6
 
+ServiceSpecT = TypeVar('ServiceSpecT', bound='ServiceSpec')
+FuncT = TypeVar('FuncT', bound=Callable)
+
 
 class ServiceSpecValidationError(Exception):
     """
@@ -35,7 +38,7 @@ def assert_valid_host(name):
         raise ServiceSpecValidationError(e)
 
 
-def handle_type_error(method):
+def handle_type_error(method: FuncT) -> FuncT:
     @wraps(method)
     def inner(cls, *args, **kwargs):
         try:
@@ -43,7 +46,7 @@ def handle_type_error(method):
         except (TypeError, AttributeError) as e:
             error_msg = '{}: {}'.format(cls.__name__, e)
             raise ServiceSpecValidationError(error_msg)
-    return inner
+    return cast(FuncT, inner)
 
 
 class HostPlacementSpec(namedtuple('HostPlacementSpec', ['hostname', 'network', 'name'])):
@@ -436,11 +439,7 @@ class ServiceSpec(object):
 
     @classmethod
     @handle_type_error
-    def from_json(cls, json_spec):
-        # type: (dict) -> Any
-        # Python 3:
-        # >>> ServiceSpecs = TypeVar('Base', bound=ServiceSpec)
-        # then, the real type is: (dict) -> ServiceSpecs
+    def from_json(cls: Type[ServiceSpecT], json_spec: Dict) -> ServiceSpecT:
         """
         Initialize 'ServiceSpec' object data from a json structure