def get_artist_by_music(self, music): meta = self.__nirum_service_methods__['get_artist_by_music'] payload = {meta['_names']['music']: serialize_meta(music)} return deserialize_meta( meta['_return'], json.loads( self.remote_call( self.__nirum_method_names__['get_artist_by_music'], payload=payload)))
def _catch_exception(self, method_facial_name, exception): method_error_types = self.service.__nirum_method_error_types__ if not callable(method_error_types): # generated by the oldest compilers method_error_types = method_error_types.get method_error = method_error_types(method_facial_name, ()) if isinstance(exception, method_error): return True, serialize_meta(exception) return False, None
def _check_return_type(self, type_hint, procedure_result): if procedure_result is None: none_type = type(None) return type_hint is none_type or is_optional_type(type_hint) try: deserialize_meta(type_hint, serialize_meta(procedure_result)) except ValueError: return False else: return True
def get_music_by_artist_name(self, artist_name: str) -> typing.Sequence[str]: meta = self.__nirum_service_methods__['get_music_by_artist_name'] payload = {meta['_names']['artist_name']: serialize_meta(artist_name)} return deserialize_meta( meta['_return'], json.loads( self.remote_call( self.__nirum_method_names__['get_music_by_artist_name'], payload=payload)))
def _respond_with_result(self, method_facial_name, result): type_hints = self.service.__nirum_service_methods__[method_facial_name] return_type = type_hints['_return'] if type_hints.get('_v', 1) >= 2: return_type = return_type() none_type = type(None) if return_type is none_type or is_optional_type(return_type): if result is None: return True, None return False, None if result is None: return False, TypeError('the return type cannot be None') try: serialized = serialize_meta(result) deserialize_meta(return_type, serialized) except ValueError as e: return False, e else: return True, serialized
def test_serialize_meta_map(fx_point): record = ComplexKeyMap(value={ fx_point: Point(left=Offset(1.23), top=Offset(4.56)), Point(left=Offset(1.23), top=Offset(4.56)): Point(left=Offset(7.89), top=Offset(10.11)), }) result = serialize_meta(record) assert sorted(result) == sorted({ '_type': 'complex_key_map', 'value': [ { 'key': {'_type': 'point', 'x': 3.14, 'top': 1.592}, 'value': {'_type': 'point', 'x': 1.23, 'top': 4.56}, }, { 'key': {'_type': 'point', 'x': 1.23, 'top': 4.56}, 'value': {'_type': 'point', 'x': 7.89, 'top': 10.11}, }, ], })
def test_serialize_meta_set(d, expect): serialized = serialize_meta(d) for e in expect: e in serialized
def test_serialize_meta(d, expect): assert serialize_meta(d) == expect
def rpc(self, request, service_method, request_json): name_map = self.service.__nirum_method_names__ try: method_facial_name = name_map.behind_names[service_method] except KeyError: raise ServiceMethodError() try: func = getattr(self.service, method_facial_name) except AttributeError: return self.error(400, request, message="Service has no procedure '{}'.".format( service_method)) if not callable(func): return self.error( 400, request, message="Remote procedure '{}' is not callable.".format( service_method)) type_hints = self.service.__nirum_service_methods__[method_facial_name] try: arguments = self._parse_procedure_arguments( type_hints, request_json) except (NirumProcedureArgumentValueError, NirumProcedureArgumentRequiredError) as e: return self.error(400, request, message=str(e)) method_error_types = self.service.__nirum_method_error_types__ if not callable(method_error_types): # generated by older compiler method_error_types = method_error_types.get method_error = method_error_types(method_facial_name, ()) try: result = func(**arguments) except method_error as e: return self._raw_response(400, serialize_meta(e)) return_type = type_hints['_return'] if type_hints.get('_v', 1) >= 2: return_type = return_type() if not self._check_return_type(return_type, result): service_class = type(self.service) logger = logging.getLogger(typing._type_repr(service_class)) \ .getChild(str(method_facial_name)) return_type_repr = typing._type_repr(return_type) logger.error( '%r is an invalid return value for the return type (%s) of ' '%s.%s() method.', result, return_type_repr, typing._type_repr(service_class), method_facial_name) hyphened_service_method = service_method.replace('_', '-') message = '''The return type of the {0}() method is {1}, but its \ server-side implementation has tried to return a value of an invalid type. \ It is an internal server error and should be fixed by server-side.'''.format( hyphened_service_method, return_type_repr, # FIXME: It'd better not show Python name of the return type, # but its IDL behind name instead. Currently the Nirum # compiler doesn't generate metadata having behind names of # nethod return/parameter types. ) if result is None: message = '''The return type of {0}() method is not optional \ (i.e., no trailing question mark), but its server-side implementation has \ tried to return nothing (i.e., null, nil, None). It is an internal server \ error and should be fixed by server-side.'''.format(hyphened_service_method) return self.error(500, request, message=message) else: return self._raw_response(200, serialize_meta(result))
def rpc(self, request, args): """RPC :param request: :args ???: """ if request.method != 'POST': return self.error(405, request) payload = request.get_data(as_text=True) or '{}' request_method = request.args.get('method') if not request_method: return self.error( 400, request, message="A query string parameter method= is missing.") name_map = self.service.__nirum_method_names__ try: method_facial_name = name_map.behind_names[request_method] except KeyError: return self.error( 400, request, message="Service dosen't have procedure named '{}'.".format( request_method)) try: service_method = getattr(self.service, method_facial_name) except AttributeError: return self.error(400, request, message="Service has no procedure '{}'.".format( request_method)) if not callable(service_method): return self.error( 400, request, message="Remote procedure '{}' is not callable.".format( request_method)) try: request_json = json.loads(payload) except ValueError: return self.error( 400, request, message="Invalid JSON payload: '{}'.".format(payload)) type_hints = self.service.__nirum_service_methods__[method_facial_name] try: arguments = self._parse_procedure_arguments( type_hints, request_json) except (NirumProcedureArgumentValueError, NirumProcedureArgumentRequiredError) as e: return self.error(400, request, message=str(e)) method_error_types = self.service.__nirum_method_error_types__ if not callable(method_error_types): # generated by older compiler method_error_types = method_error_types.get method_error = method_error_types(method_facial_name, ()) try: result = service_method(**arguments) except method_error as e: return self._raw_response(400, serialize_meta(e)) return_type = type_hints['_return'] if type_hints.get('_v', 1) >= 2: return_type = return_type() if not self._check_return_type(return_type, result): return self.error(400, request, message="Incorrect return type '{0}' " "for '{1}'. expected '{2}'.".format( typing._type_repr(result.__class__), request_method, typing._type_repr(return_type))) else: return self._raw_response(200, serialize_meta(result))