Beispiel #1
0
        def decorated_service(*args, **kwargs):
            kwargs[
                "resolution"
            ] = None  # using this decorator means you can expect this attribute, None means default
            form = get_form_from_request(request)
            if form is None:
                current_app.logger.warning(
                    "Unsupported request method for unpacking 'resolution' from request."
                )
                return invalid_method(request.method)

            if "resolution" in form and form["resolution"]:
                ds_resolution = parse_duration(form["resolution"])
                if ds_resolution is None:
                    return invalid_resolution_str(form["resolution"])
                # Check if the resolution can be applied to all assets (if it is a multiple
                # of the event_resolution(s) and thus downsampling is possible)
                for asset_group in kwargs["generic_asset_name_groups"]:
                    for asset_descriptor in asset_group:
                        generic_asset = get_generic_asset(asset_descriptor, entity_type)
                        if generic_asset is None:
                            return unrecognized_asset()
                        asset_resolution = generic_asset.event_resolution
                        if ds_resolution % asset_resolution != timedelta(minutes=0):
                            return unapplicable_resolution(
                                f"{isodate.duration_isoformat(asset_resolution)} or a multiple hereof."
                            )
                kwargs["resolution"] = to_offset(
                    isodate.parse_duration(form["resolution"])
                ).freqstr  # Convert ISO period string to pandas frequency string

            return fn(*args, **kwargs)
Beispiel #2
0
        def decorated_service(*args, **kwargs):
            form = get_form_from_request(request)
            if form is None:
                current_app.logger.warning(
                    "Unsupported request method for inferring resolution from request."
                )
                return invalid_method(request.method)

            if not all(
                key in kwargs
                for key in [
                    "value_groups",
                    "start",
                    "duration",
                ]
            ):
                current_app.logger.warning("Could not infer resolution.")
                fields = ("values", "start", "duration")
                return required_info_missing(fields, "Resolution cannot be inferred.")
            if "generic_asset_name_groups" not in kwargs:
                return required_info_missing(
                    (entity_type),
                    "Required resolution cannot be found without asset info.",
                )

            # Calculating (inferring) the resolution in the POSTed data
            inferred_resolution = (
                (kwargs["start"] + kwargs["duration"]) - kwargs["start"]
            ) / len(kwargs["value_groups"][0])

            # Finding the required resolution for assets affected in this request
            required_resolution = None
            last_asset = None
            for asset_group in kwargs["generic_asset_name_groups"]:
                for asset_descriptor in asset_group:
                    # Getting the asset
                    generic_asset = get_generic_asset(asset_descriptor, entity_type)
                    if generic_asset is None:
                        return unrecognized_asset(
                            f"Failed to look up asset by {asset_descriptor}"
                        )
                    # Complain if assets don't all require the same resolution
                    if (
                        required_resolution is not None
                        and generic_asset.event_resolution != required_resolution
                    ):
                        return conflicting_resolutions(
                            f"Cannot send data for both {generic_asset} and {last_asset}."
                        )
                    # Setting the resolution & remembering last looked-at asset
                    required_resolution = generic_asset.event_resolution
                    last_asset = generic_asset

            # if inferred resolution is a multiple from required_solution, we can upsample_values
            if inferred_resolution % required_resolution == timedelta(hours=0):
                for i in range(len(kwargs["value_groups"])):
                    kwargs["value_groups"][i] = upsample_values(
                        kwargs["value_groups"][i],
                        from_resolution=inferred_resolution,
                        to_resolution=required_resolution,
                    )
                inferred_resolution = required_resolution

            if inferred_resolution != required_resolution:
                current_app.logger.warning(
                    f"Resolution {inferred_resolution} is not accepted. We require {required_resolution}."
                )
                return unapplicable_resolution(
                    isodate.duration_isoformat(required_resolution)
                )
            else:
                kwargs["resolution"] = inferred_resolution
                return fn(*args, **kwargs)
    assert post_price_data_response.json["type"] == "PostPriceDataResponse"
    market = parse_entity_address(post_message["market"], "market")
    market_name = market["market_name"]
    market = Market.query.filter_by(name=market_name).one_or_none()
    assert (post_price_data_response.json["message"] == invalid_unit(
        "%s prices" % market.display_name, ["EUR/MWh"])[0]["message"])


@pytest.mark.parametrize(
    "post_message,status,msg",
    [
        (
            message_for_post_price_data(
                duration=duration_isoformat(timedelta(minutes=2))),
            400,
            unapplicable_resolution()[0]["message"],
        ),
        (message_for_post_price_data(compress_n=4), 200,
         "Request has been processed."),
    ],
)
def test_post_price_data_unexpected_resolution(db, app, post_message, status,
                                               msg):
    """
    Try to post price data with an unexpected resolution,
    which might be fixed with upsampling or otherwise fail.
    """
    with app.test_client() as client:
        auth_token = get_auth_token(client, "*****@*****.**",
                                    "testtest")
        post_price_data_response = client.post(