コード例 #1
0
def test_from_json_malformed():
    with pytest.raises(ValueError):
        Payload.from_json(
            '{"item1": {"id": "1", "value": "ok-1", "nested": {"ts": "1970-01-01T00:00:00+00:00"}',
            MockData)

    with pytest.raises(ValueError):
        Payload.from_json('BAD STRING', MockData)
コード例 #2
0
def test_from_json_missing_fields():
    with pytest.raises(ValueError):
        Payload.from_json('{"id": "1", "value": "ok-1", "nested": {}',
                          MockData)

    with pytest.raises(ValueError):
        Payload.from_json(
            '{"value": 42, "nested": {"ts": "1970-01-01T00:00:00+00:00"}}',
            MockData)
コード例 #3
0
def test_from_json_invalid_types():
    with pytest.raises(ValueError):
        Payload.from_json(
            '{"id": "1", "value": "ok-1", "nested": {"ts": "INVALID DATE"}}',
            MockData)

    with pytest.raises(ValueError):
        Payload.from_json(
            '{"id": 42, "value": 42, "nested": {"ts": "1970-01-01T00:00:00+00:00"}}',
            MockData)
コード例 #4
0
def test_to_obj_invalid_types():
    with pytest.raises(ValueError):
        Payload.to_obj(
            MockData(id=42,
                     value='ok-value',
                     nested=MockNested(ts=datetime.now(
                         tz=timezone.utc))))  # type: ignore

    with pytest.raises(ValueError):
        Payload.to_obj(
            MockData(id='1',
                     value='ok-value',
                     nested=MockNested(ts="NOT A DATETIME")))  # type: ignore
コード例 #5
0
async def __preprocess__(payload: None, context: EventContext,
                         request: PreprocessHook, *,
                         something_id: str) -> Union[str, FileUploadInfo]:
    uploaded_files = []
    save_path = Path(str(context.env['upload_something']['save_path']))
    chunk_size = int(context.env['upload_something']['chunk_size'])
    async for file_hook in request.files():
        file_name = f"{file_hook.name}-{file_hook.file_name}"
        path = save_path / file_name
        logger.info(context, f"Saving {path}...")
        await save_multipart_attachment(file_hook, path, chunk_size=chunk_size)
        uploaded_file = UploadedFile(file_hook.name,
                                     file_name,
                                     save_path.as_posix(),
                                     size=file_hook.size)
        uploaded_files.append(uploaded_file)
    args = await request.parsed_args()
    if not all(x in args for x in ('id', 'user', 'attachment', 'object')):
        request.status = 400
        return "Missing required fields"
    something_obj = Payload.parse_form_field(args['object'], Something)
    return FileUploadInfo(id=args['id'],
                          user=args['user'],
                          object=something_obj,
                          uploaded_files=uploaded_files)
コード例 #6
0
async def test_buffer_object_and_flush_signal(app_config,
                                              test_objs):  # noqa: F811
    test_save_path = app_config.settings["test_stream_batch_storage"]["path"]

    # Buffer single object
    test_obj = test_objs[0]
    result = await execute_event(app_config=app_config,
                                 event_name='test_stream_batch_storage',
                                 payload=test_obj)
    assert result is None

    # Send flush partition signal to force flush single object
    partition_key = test_obj.object_ts.strftime("%Y/%m/%d/%H") + '/'
    signal = FlushSignal(partition_key)
    result = await execute_event(app_config=app_config,
                                 event_name='test_stream_batch_storage',
                                 payload=signal)
    assert result is None

    # Load saved object and check is correct
    await asyncio.sleep(1)  # Allow aiofiles to save
    saved_objects = {}
    for file_name in glob(f'{test_save_path}/{partition_key}/*.jsonlines'):
        with open(file_name) as f:
            for line in f:
                obj = Payload.from_json(line, datatype=MyObject)
                saved_objects[obj.object_id] = obj
    assert len(saved_objects) == 1
    assert test_obj == saved_objects[test_obj.object_id]
コード例 #7
0
def test_to_json_dataobject():
    assert Payload.to_json(
        MockData(
            id='test',
            value='ok',
            nested=MockNested(ts=datetime.fromtimestamp(0, tz=timezone.utc)))
    ) == '{"id": "test", "value": "ok", "nested": {"ts": "1970-01-01T00:00:00+00:00"}}'
コード例 #8
0
    async def store(self, key: str, value: DataObject, **kwargs):
        """
        Stores value under specified key

        :param key: str
        :param value: DataObject, instance of dataclass annotated with @dataobject
        :param **kwargs: You can use arguments expected by the set method in the aioredis library i.e.:
            ex sets an expire flag on key name for ex seconds.
            px sets an expire flag on key name for px milliseconds.
            nx if set to True, set the value at key name to value only if it does not exist.
            xx if set to True, set the value at key name to value only if it already exists.
            keepttl if True, retain the time to live associated with the key. (Available since Redis 6.0).
            *These arguments may vary depending on the version of aioredis installed.

        i.e. store object:
        ```
        redis_store.store(key='my_key', value=my_dataobject)
        ```

        i.e. store object with kwargs option, adding `ex=60` redis set a ttl of 60 seconds for the object:
        ```
        redis_store.store(key='my_key', value=my_dataobject, ex=60)
        ```

        """
        assert self._conn
        payload_str = str(Payload.to_json(value))
        await self._conn.set(key, payload_str, **kwargs)
コード例 #9
0
ファイル: __init__.py プロジェクト: hopeit-git/hopeit.engine
 def __init__(self, app_config: AppConfig, app_connection: str):
     self.app_key = app_config.app_key()
     self.app_conn_key = app_connection
     self.app_connection = app_config.app_connections[app_connection]
     settings_key = self.app_connection.settings or app_connection
     self.settings = Payload.from_obj(
         app_config.settings.get(settings_key, {}), AppsClientSettings)
     self.event_connections = {
         event_name: {
             conn.event: conn
             for conn in event_info.connections
             if conn.app_connection == app_connection
         }
         for event_name, event_info in app_config.events.items()
     }
     self.routes = {
         conn.event: self._get_route(conn.event)
         for event_info in app_config.events.values()
         for conn in event_info.connections
         if conn.app_connection == app_connection
     }
     self.conn_state: Optional[AppConnectionState] = None
     self.session: Optional[Any] = None
     self.token: Optional[str] = None
     self.token_expire: int = 0
コード例 #10
0
async def __preprocess__(payload: None, context: EventContext,
                         request: PreprocessHook) -> MockData:
    args = await request.parsed_args()
    data = Payload.parse_form_field(args['field2'], MockData)
    return MockData(
        value=f"field1:{args['field1']} field2:{data.value} file:{args['file']}"
    )
コード例 #11
0
def test_from_obj_dataobject_list():
    assert Payload.from_obj(
        [{
            "id": "test1",
            "value": "ok",
            "nested": {
                "ts": "1970-01-01T00:00:00+00:00"
            }
        }, {
            "id": "test2",
            "value": "ok",
            "nested": {
                "ts": "1970-01-01T00:00:00+00:00"
            }
        }],
        list,
        item_datatype=MockData) == [
            MockData(
                id='test1',
                value='ok',
                nested=MockNested(
                    ts=datetime.fromtimestamp(0.0).astimezone(timezone.utc))),
            MockData(
                id='test2',
                value='ok',
                nested=MockNested(
                    ts=datetime.fromtimestamp(0.0).astimezone(timezone.utc)))
        ]
コード例 #12
0
def test_to_json_dict_dataobject():
    assert json.loads(
        Payload.to_json({
            'item1':
            MockData(id='1',
                     value='ok-1',
                     nested=MockNested(
                         ts=datetime.fromtimestamp(0, tz=timezone.utc))),
            'item2':
            MockData(id='2',
                     value='ok-2',
                     nested=MockNested(
                         ts=datetime.fromtimestamp(0, tz=timezone.utc))),
        })) == {
            "item1": {
                "id": "1",
                "value": "ok-1",
                "nested": {
                    "ts": "1970-01-01T00:00:00+00:00"
                }
            },
            "item2": {
                "id": "2",
                "value": "ok-2",
                "nested": {
                    "ts": "1970-01-01T00:00:00+00:00"
                }
            }
        }
コード例 #13
0
def test_from_obj_python_types():
    assert Payload.from_obj({"value": "str"}, str) == "str"
    assert Payload.from_obj({"value": 123}, int) == int(123)
    assert Payload.from_obj({"value": 123.45}, float) == float(123.45)
    assert Payload.from_obj({"value": True}, bool) is True
    assert Payload.from_obj({"custom": "str"}, str, key='custom') == "str"
    assert Payload.from_obj({"test": "dict"}, dict) == {'test': 'dict'}
    assert Payload.from_obj(["test1", "test2"], set) == {'test2', 'test1'}
    assert Payload.from_obj(["test1", "test2"], list) == ['test1', 'test2']
コード例 #14
0
def test_from_json_python_types():
    assert Payload.from_json('{"value": "str"}', str) == "str"
    assert Payload.from_json('{"value": 123}', int) == int(123)
    assert Payload.from_json('{"value": 123.45}', float) == float(123.45)
    assert Payload.from_json('{"value": true}', bool) is True
    assert Payload.from_json('{"custom": "str"}', str, key='custom') == "str"
    assert Payload.from_json('{"test": "dict"}', dict) == {'test': 'dict'}
    assert Payload.from_json('["test1", "test2"]', set) == {'test2', 'test1'}
    assert Payload.from_json('["test1", "test2"]', list) == ['test1', 'test2']
コード例 #15
0
ファイル: conftest.py プロジェクト: hopeit-git/hopeit.engine
def mock_client_app_config():
    return AppConfig(
        app=AppDescriptor(name='mock_client_app', version='test'),
        engine=AppEngineConfig(import_modules=['mock_client_app']),
        app_connections={
            "test_app_connection":
            AppConnection(name="test_app",
                          version=APPS_API_VERSION,
                          client="hopeit.apps_client.AppsClient"),
            "test_app_plugin_connection":
            AppConnection(name="test_app",
                          version=APPS_API_VERSION,
                          client="hopeit.apps_client.AppsClient",
                          plugin_name="test_plugin",
                          plugin_version=APPS_API_VERSION)
        },
        settings={
            "test_app_connection":
            Payload.to_obj(
                AppsClientSettings(
                    connection_str="http://test-host1,http://test-host2")),
            "test_app_plugin_connection":
            Payload.to_obj(
                AppsClientSettings(
                    connection_str="http://test-host1,http://test-host2",
                    auth_strategy=ClientAuthStrategy.FORWARD_CONTEXT))
        },
        events={
            "mock_client_event":
            EventDescriptor(
                type=EventType.GET,
                connections=[
                    EventConnection(app_connection="test_app_connection",
                                    event="test_event_get",
                                    type=EventConnectionType.GET),
                    EventConnection(app_connection="test_app_connection",
                                    event="test_event_post",
                                    type=EventConnectionType.POST),
                    EventConnection(
                        app_connection="test_app_plugin_connection",
                        event="test_event_plugin",
                        type=EventConnectionType.GET)
                ])
        },
        server=ServerConfig(logging=LoggingConfig(
            log_level="DEBUG", log_path="work/logs/test/"))).setup()
コード例 #16
0
def test_from_json_dataobject():
    assert Payload.from_json(
        '{"id": "test", "value": "ok", "nested": {"ts": "1970-01-01T00:00:00+00:00"}}',
        MockData) == MockData(
            id='test',
            value='ok',
            nested=MockNested(
                ts=datetime.fromtimestamp(0.0).astimezone(timezone.utc)))
コード例 #17
0
def _ignored_response(context: Optional[EventContext], status: int,
                      e: BaseException) -> web.Response:
    if context:
        logger.error(context, e)
        logger.ignored(context)
    else:
        logger.error(__name__, e)
    info = ErrorInfo.from_exception(e)
    return web.Response(status=status, body=Payload.to_json(info))
コード例 #18
0
def _failed_response(context: Optional[EventContext],
                     e: Exception) -> web.Response:
    if context:
        logger.error(context, e)
        logger.failed(context)
    else:
        logger.error(__name__, e)
    info = ErrorInfo.from_exception(e)
    return web.Response(status=500, body=Payload.to_json(info))
コード例 #19
0
def test_from_obj_list():
    assert Payload.from_obj([{
        "value": "ok1"
    }, {
        "value": "ok2"
    }],
                            list,
                            key='value',
                            item_datatype=str) == ["ok1", "ok2"]
コード例 #20
0
def test_to_obj_python_types():
    assert Payload.to_obj('str', key='test') == {"test": "str"}
    assert Payload.to_obj(123, key='test') == {"test": 123}
    assert Payload.to_obj(123.45, key='test') == {"test": 123.45}
    assert Payload.to_obj(True, key='test') == {"test": True}
    assert Payload.to_obj({'test': 'dict'}) == {"test": "dict"}
    assert Payload.to_obj({'test2', 'test1'}) == ["test1", "test2"]
    assert Payload.to_obj(['test2', 'test1']) == ["test2", "test1"]
コード例 #21
0
async def _save_partition(partition_key: str, items: List[DataObject],
                          context: EventContext):
    settings = context.settings(datatype=FileStorageSettings)
    path = Path(settings.path) / partition_key
    file = path / f"{uuid.uuid4()}{SUFFIX}"
    logger.info(context, f"Saving {file}...")
    os.makedirs(path.resolve(), exist_ok=True)
    async with aiofiles.open(file, 'w') as f:
        for item in items:
            await f.write(Payload.to_json(item) + "\n")
コード例 #22
0
ファイル: __init__.py プロジェクト: hopeit-git/hopeit.engine
 async def _parse_response(
         self, response, context: EventContext,
         datatype: Type[EventPayloadType],
         target_event_name: str) -> List[EventPayloadType]:
     """
     Parses http response from external App, catching Unathorized errors
     and converting the result to the desired datatype
     """
     if response.status == 200:
         data = await response.json()
         if isinstance(data, list):
             return Payload.from_obj(data, list,
                                     item_datatype=datatype)  # type: ignore
         return [Payload.from_obj(data, datatype, key=target_event_name)]
     if response.status == 401:
         raise Unauthorized(context.app_key)
     if response.status >= 500:
         raise ServerException(await response.text())
     raise RuntimeError(await response.text())
コード例 #23
0
ファイル: conftest.py プロジェクト: hopeit-git/hopeit.engine
def effective_events_example():
    res = EFFECTIVE_EVENTS_EXAMPLE
    res = res.replace("${ENGINE_VERSION}", ENGINE_VERSION)
    res = res.replace("${APPS_API_VERSION}", APPS_API_VERSION)
    res = res.replace("${APPS_ROUTE_VERSION}", APPS_ROUTE_VERSION)
    res = json.loads(res)

    result = Payload.from_obj(res,
                              datatype=dict,
                              item_datatype=EventDescriptor)

    return result
コード例 #24
0
async def __preprocess__(payload: None, context: EventContext,
                         request: PreprocessHook, *,
                         query_arg1: str) -> Union[str, MockData]:
    fields = await request.parsed_args()
    if any(x not in fields for x in ('field1', 'field2', 'attachment')):
        request.set_status(400)
        return "Missing required fields"
    data = Payload.parse_form_field(fields['field2'], MockData)
    return MockData(
        value=
        f"field1={fields['field1']} field2={data.value} attachment={fields['attachment']}"
    )
コード例 #25
0
ファイル: conftest.py プロジェクト: hopeit-git/hopeit.engine
def _get_runtime_simple_example(url: str, source: str):
    with open(Path(__file__).parent / source) as f:
        res = f.read()
        res = res.replace("${HOST_NAME}", socket.gethostname())
        res = res.replace("${PID}", str(os.getpid()))
        res = res.replace("${URL}", url)
        res = res.replace("${ENGINE_VERSION}", ENGINE_VERSION)
        res = res.replace("${APPS_API_VERSION}", APPS_API_VERSION)
        res = res.replace("${APPS_ROUTE_VERSION}", APPS_ROUTE_VERSION)

    result = Payload.from_json(res, RuntimeApps)

    return result
コード例 #26
0
def mock_runtime(monkeypatch, effective_events):
    setattr(apps, "_expire", 0.0)
    monkeypatch.setattr(server_config.os, 'getenv', mock_getenv)
    app_config = config('apps/examples/simple-example/config/app-config.json')
    basic_auth_config = config(
        'plugins/auth/basic-auth/config/plugin-config.json')
    client_app_config = config(
        'apps/examples/client-example/config/app-config.json')
    server = MockServer(basic_auth_config, app_config, client_app_config)
    for app_key, app_effective_events in effective_events.items():
        server.app_engines[app_key].effective_events = Payload.from_obj(
            app_effective_events, datatype=dict, item_datatype=EventDescriptor)
    monkeypatch.setattr(runtime, "server", server)
コード例 #27
0
    async def get(self, key: str, *,
                  datatype: Type[DataObject]) -> Optional[DataObject]:
        """
        Retrieves value under specified key, converted to datatype

        :param key: str
        :param datatype: dataclass implementing @dataobject (@see DataObject)
        :return: instance of datatype or None if not found
        """
        assert self._conn
        payload_str = await self._conn.get(key)
        if payload_str:
            return Payload.from_json(payload_str, datatype)
        return None
コード例 #28
0
ファイル: __init__.py プロジェクト: hopeit-git/hopeit.engine
    async def store(self, key: str, value: DataObject) -> str:
        """
        Stores value under specified key

        :param key: str
        :param value: DataObject, instance of dataclass annotated with @dataobject
        :return: str, path where the object was stored
        """
        payload_str = Payload.to_json(value)
        path = self.path
        if self.partition_dateformat:
            path = path / get_partition_key(value, self.partition_dateformat)
            os.makedirs(path.resolve().as_posix(), exist_ok=True)
        return await self._save_file(payload_str, path=path, file_name=key + SUFFIX)
コード例 #29
0
def test_from_obj_dict():
    assert Payload.from_obj(
        {
            "item1": {
                "value": "ok1"
            },
            "item2": {
                "value": "ok2"
            }
        },
        dict,
        key='value',
        item_datatype=str) == {
            "item1": "ok1",
            "item2": "ok2"
        }
コード例 #30
0
async def _request_process_payload(
    context: EventContext, datatype: Optional[Type[EventPayloadType]],
    request: web.Request
) -> Tuple[Optional[EventPayloadType], Optional[bytes]]:
    """
    Extract payload from request.
    Returns payload if parsing succeeded. Raises BadRequest if payload fails to parse
    """
    try:
        payload_raw = await request.read()
        if datatype is not None:
            return Payload.from_json(payload_raw,
                                     datatype), payload_raw  # type: ignore
        return None, payload_raw
    except ValueError as e:
        logger.error(context, e)
        raise BadRequest(e) from e