async def _request_execute(app_engine: AppEngine, event_name: str, context: EventContext, query_args: Dict[str, Any], payload: Optional[EventPayloadType], preprocess_hook: PreprocessHook) -> ResponseType: """ Executes request using engine event handler """ response_hook = PostprocessHook() result = await app_engine.preprocess(context=context, query_args=query_args, payload=payload, request=preprocess_hook) if (preprocess_hook.status is None) or (preprocess_hook.status == 200): result = await app_engine.execute(context=context, query_args=query_args, payload=result) result = await app_engine.postprocess(context=context, payload=result, response=response_hook) else: response_hook.set_status(preprocess_hook.status) # body = Json.to_json(result, key=event_name) response = _response(track_ids=context.track_ids, key=event_name, payload=result, hook=response_hook) logger.done(context, extra=combined(_response_info(response), metrics(context))) return response
async def postprocess(self, *, context: EventContext, payload: Optional[EventPayload], response: PostprocessHook) -> Optional[EventPayload]: response.set_header("PluginHeader", "PluginHeaderValue") response.set_cookie("PluginCookie", "PluginCookieValue") response.set_status(999) return payload
async def __postprocess__(payload: str, context: EventContext, response: PostprocessHook) -> str: if payload.startswith('ok:'): response.set_status(200) response.set_header('X-Status', 'ok') response.set_cookie('Test-Cookie', 'ok') else: response.set_status(400) return payload
async def __postprocess__(img_file: ImagePng, context: EventContext, response: PostprocessHook) -> str: if os.path.isfile(img_file.file_path): response.set_header('Content-Disposition', f'attachment; filename="{img_file.file_name}"') response.set_content_type(img_file.content_type) response.set_file_response(img_file.file_path) return f"File {img_file.file_name}" response.set_status(400) return f"File {img_file.file_name} not found"
async def execute_event( app_config: AppConfig, event_name: str, payload: Optional[EventPayload], mocks: Optional[List[Callable[[ModuleType, EventContext], None]]] = None, *, fields: Optional[Dict[str, str]] = None, upload: Optional[Dict[str, bytes]] = None, preprocess: bool = False, postprocess: bool = False, **kwargs ) -> Union[Optional[EventPayload], List[EventPayload], Tuple[ Optional[EventPayload], EventPayload, PostprocessHook], Tuple[ List[EventPayload], EventPayload, PostprocessHook]]: """ Test executes an app event. Notice that event implementation file needs to be saved to disk since this will simulate execution similar to how engine actually execute events. Writing to stream will be ignored. :param app_config: AppConfig, load using `app_config = config('path/to/app-config.json')` :param event_name: str, name of the event / module to execute :param payload: test payload to send to initial step :param mocks: lists of functions to execute in order to mock functionality :param postprocess: enables testing __postprocess__ called with last step result or result before a SHUFFLE step if present. :param kwargs: that will be forwarded to the initial step of the event :return: the results of executing the event, for simple events it will be a single object, for events with initial Spawn[...] the results will be collected as a list. If postprocess is true, a tuple of 3 elements is return, first element is results as described above, second element the output of call to __postprocess__, and third one a PostprocessHook with response information used during call to __postprocess__ """ async def _postprocess(hook: PostprocessHook, results: List[EventPayload]) -> EventPayload: pp_payload = results[-1] if len(results) > 0 else None return await handler.postprocess(context=context, payload=pp_payload, response=hook) async def _preprocess(hook: PreprocessHook, payload: EventPayload) -> EventPayload: return await handler.preprocess(context=context, query_args=kwargs, payload=payload, request=hook) context = create_test_context(app_config, event_name) impl = find_event_handler(app_config=app_config, event_name=event_name) event_info = app_config.events[event_name] effective_events = { **split_event_stages(app_config.app, event_name, event_info, impl) } handler = EventHandler(app_config=app_config, plugins=[], effective_events=effective_events) preprocess_hook, postprocess_hook = None, None if preprocess: preprocess_hook = PreprocessHook( headers=CIMultiDictProxy(CIMultiDict()), multipart_reader=MockMultipartReader(fields or {}, upload or {}), # type: ignore file_hook_factory=MockFileHook) if postprocess: postprocess_hook = PostprocessHook() if mocks is not None: _apply_mocks(context, handler, event_name, effective_events, preprocess_hook, postprocess_hook, mocks) if preprocess_hook: payload = await _preprocess(preprocess_hook, payload) if postprocess_hook and preprocess_hook.status is not None: postprocess_hook.set_status(preprocess_hook.status) datatype = find_datatype_handler(app_config=app_config, event_name=event_name) if datatype is None: if payload is not None: return (payload, payload, postprocess_hook) if postprocess else payload elif not isinstance(payload, datatype): return (payload, payload, postprocess_hook) if postprocess else payload on_queue, pp_result, pp_called = [payload], None, False for effective_event_name, event_info in effective_events.items(): context = create_test_context(app_config, effective_event_name) stage_results = [] for elem in on_queue: async for res in handler.handle_async_event(context=context, query_args=kwargs, payload=elem): stage_results.append(res) on_queue = stage_results if len(stage_results) > 0 else on_queue if postprocess_hook and not pp_called: pp_called = True pp_result = await _postprocess(postprocess_hook, on_queue) kwargs = {} if postprocess: if len(on_queue) == 0: return None, pp_result, postprocess_hook if len(on_queue) == 1: return on_queue[0], pp_result, postprocess_hook return list(on_queue), pp_result, postprocess_hook if len(on_queue) == 0: return None if len(on_queue) == 1: return on_queue[0] return list(on_queue)
async def __postprocess__(payload: str, context: EventContext, *, response: PostprocessHook) -> str: response.set_header("PluginHeader", "PluginHeaderValue") response.set_cookie("PluginCookie", "PluginCookieValue") response.set_status(999) return "PluginEvent.postprocess"