Expanding controller.py with basic user functions, get_models and destroy (#89)
[osm/N2VC.git] / juju / client / facade.py
index 59163a9..a6fd9f6 100644 (file)
@@ -124,7 +124,7 @@ class Args(list):
                     self.append((name, rtype))
 
     def do_explode(self, kind):
-        if kind in basic_types:
+        if kind in basic_types or type(kind) is typing.TypeVar:
             return False
         if not issubclass(kind, (typing.Sequence,
                                  typing.Mapping)):
@@ -188,9 +188,9 @@ def buildTypes(schema, capture):
     for kind in sorted((k for k in _types if not isinstance(k, str)),
                        key=lambda x: str(x)):
         name = _types[kind]
-        args = Args(kind)
         if name in classes:
             continue
+        args = Args(kind)
         source = ["""
 class {}(Type):
     _toSchema = {}
@@ -200,8 +200,9 @@ class {}(Type):
 {}
         '''""".format(
             name,
-            args.PyToSchemaMapping(),
-            args.SchemaToPyMapping(),
+            # pprint these to get stable ordering across regens
+            pprint.pformat(args.PyToSchemaMapping(), width=999),
+            pprint.pformat(args.SchemaToPyMapping(), width=999),
             ", " if args else "",
             args.as_kwargs(),
             textwrap.indent(args.get_doc(), INDENT * 2))
@@ -218,14 +219,22 @@ class {}(Type):
                 if arg_type in basic_types:
                     source.append("{}self.{} = {}".format(INDENT * 2, arg_name, arg_name))
                 elif issubclass(arg_type, typing.Sequence):
-                    value_type = arg_type_name.__parameters__[0]
+                    value_type = (
+                        arg_type_name.__parameters__[0]
+                        if len(arg_type_name.__parameters__)
+                        else None
+                    )
                     if type(value_type) is typing.TypeVar:
                         source.append("{}self.{} = [{}.from_json(o) for o in {} or []]".format(
                             INDENT * 2, arg_name, strcast(value_type), arg_name))
                     else:
                         source.append("{}self.{} = {}".format(INDENT * 2, arg_name, arg_name))
                 elif issubclass(arg_type, typing.Mapping):
-                    value_type = arg_type_name.__parameters__[1]
+                    value_type = (
+                        arg_type_name.__parameters__[1]
+                        if len(arg_type_name.__parameters__) > 1
+                        else None
+                    )
                     if type(value_type) is typing.TypeVar:
                         source.append("{}self.{} = {{k: {}.from_json(v) for k, v in ({} or dict()).items()}}".format(
                             INDENT * 2, arg_name, strcast(value_type), arg_name))
@@ -255,6 +264,8 @@ def retspec(defs):
     # Error or the expected Type
     if not defs:
         return None
+    if defs in basic_types:
+        return strcast(defs, False)
     rtypes = _registry.getObj(_types[defs])
     if not rtypes:
         return None
@@ -315,6 +326,13 @@ def ReturnMapping(cls):
                 item_cls = cls.__parameters__[0]
                 for item in reply:
                     result.append(item_cls.from_json(item))
+                    """
+                    if 'error' in item:
+                        cls = classes['Error']
+                    else:
+                        cls = item_cls
+                    result.append(cls.from_json(item))
+                    """
             else:
                 result = cls.from_json(reply['response'])
 
@@ -329,9 +347,9 @@ def makeFunc(cls, name, params, result, async=True):
     assignments = []
     toschema = args.PyToSchemaMapping()
     for arg in args._get_arg_str(False, False):
-        assignments.append("{}params[\'{}\'] = {}".format(INDENT,
-                                                          toschema[arg],
-                                                          arg))
+        assignments.append("{}_params[\'{}\'] = {}".format(INDENT,
+                                                           toschema[arg],
+                                                           arg))
     assignments = "\n".join(assignments)
     res = retspec(result)
     source = """
@@ -343,8 +361,8 @@ def makeFunc(cls, name, params, result, async=True):
     Returns -> {res}
     '''
     # map input types to rpc msg
-    params = dict()
-    msg = dict(Type='{cls.name}', Request='{name}', Version={cls.version}, Params=params)
+    _params = dict()
+    msg = dict(type='{cls.name}', request='{name}', version={cls.version}, params=_params)
 {assignments}
     reply = {await}self.rpc(msg)
     return reply
@@ -383,10 +401,17 @@ def _buildMethod(cls, name):
         prop = method['properties']
         spec = prop.get('Params')
         if spec:
-            params = _types.get(spec['$ref'])
+            result = _types.get(spec['$ref'])
+            if '$ref' in spec:
+                result = _types.get(spec['$ref'])
+            else:
+                result = SCHEMA_TO_PYTHON[spec['type']]
         spec = prop.get('Result')
         if spec:
-            result = _types.get(spec['$ref'])
+            if '$ref' in spec:
+                result = _types.get(spec['$ref'])
+            else:
+                result = SCHEMA_TO_PYTHON[spec['type']]
     return makeFunc(cls, name, params, result)
 
 
@@ -422,6 +447,8 @@ class Type:
 
     @classmethod
     def from_json(cls, data):
+        if isinstance(data, cls):
+            return data
         if isinstance(data, str):
             data = json.loads(data)
         d = {}
@@ -431,7 +458,6 @@ class Type:
         try:
             return cls(**d)
         except TypeError:
-            print(cls)
             raise
 
     def serialize(self):
@@ -603,6 +629,5 @@ def main():
         print(capture, file=fp)
 
 
-
 if __name__ == '__main__':
     main()