def _on_bootstrap_aggregate_response_message_types(self): """ Build a lookup table of protobuf response Message types for use when routing requests to their downstream actions. """ grpc = self.grpc grpc.response_types = {} for action in self.actions.values(): schema_type_name = get_class_name(action.schemas.response) message_type_name = get_stripped_schema_name( StringUtils.camel(schema_type_name)) response_message_type = getattr(self.grpc.pb2, message_type_name) grpc.response_types[action.name] = response_message_type
def _build_func(self, action): key = StringUtils.camel(action.name) request_type = getattr(self._app.grpc.pb2, f'{key}Request') send_request = getattr(self._grpc_stub, action.name) def func(**kwargs): # prepare and send the request request = request_type(**kwargs) response = send_request(request) # translate the native proto response message to a plain dict if action.streams_response: data = [ self._extract_fields(x, action.schemas.response) for x in response ] else: data = self._extract_fields(response, action.schemas.response) return data return func
def infer( cls, target: Dict, name: Text = None, predicate: Callable = None, depth: int = 0, ) -> Type['Schema']: """ Return a new Schema class that mirrors the structure of the input target object, as best as possible. """ acc = {} depth -= 1 if not name: faker = Faker() name = f'{faker.color_name()}Schema' if predicate is None: predicate = lambda k, v: not k.startswith('_') py_type_2_field_type = { str: fields.String, int: fields.Int, float: fields.Float, bool: fields.Bool, bytes: fields.Bytes, UUID: fields.Uuid, datetime: fields.DateTime, date: fields.DateTime, } def build_nested_field(seq): contained_py_types = {type(x) for x in seq} if len(contained_py_types) == 1: sub_target = list(seq)[0] py_type = list(contained_py_types)[0] if py_type in py_type_2_field_type: field_type = py_type_2_field_type[py_type] return field_type(example=sub_target) elif py_type in (list, tuple, set): nested = build_nested_field(sub_target) return fields.List(nested) elif py_type is dict: return cls.infer(target=sub_target, predicate=predicate, depth=(depth - 1))() return fields.Field() for k, v in target.items(): if not predicate(k, v): continue if isinstance(v, dict): if depth != 0: sub_schema_type = cls.infer( target=v, name=StringUtils.camel(f'{k}Schema'), predicate=predicate, depth=(depth - 1)) acc[k] = fields.Nested(sub_schema_type, name=k, source=k, example=v) else: acc[k] = fields.Dict(name=k, source=k, example=v) else: scalar_field_type = py_type_2_field_type.get(type(v)) if scalar_field_type: if scalar_field_type is fields.String: # TODO resolve String to more specific field type if possible acc[k] = scalar_field_type(name=k, source=k, example=v) else: acc[k] = scalar_field_type(name=k, source=k, example=v) elif isinstance(v, (list, set, tuple)): nested = build_nested_field(v) nested.name = k nested.source = k if isinstance(nested, Schema): type(nested).__name__ = StringUtils.camel( f'{StringUtils.singular(k)}Schema', lower=False) acc[k] = fields.List(nested=nested, name=k, source=k, example=v) else: acc[k] = fields.Field(name=k, source=k, example=v) return type(name, (cls, ), acc)
def on_bootstrap(self): self._msg_name_prefix = StringUtils.camel(self.name) self.schemas.request = self._build_request_schema() self.schemas.response = self._build_response_schema()