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)
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(