コード例 #1
0
class SensorDataDescriptionSchema(ma.Schema):
    """
    Schema describing sensor data (specifically, the sensor and the timing of the data).
    """

    sensor = SensorField(required=True, entity_type="sensor", fm_scheme="fm1")
    start = AwareDateTimeField(required=True, format="iso")
    duration = DurationField(required=True)
    horizon = DurationField(required=False)
    prior = AwareDateTimeField(required=False, format="iso")
    unit = fields.Str(required=True)

    @validates_schema
    def check_schema_unit_against_sensor_unit(self, data, **kwargs):
        """Allows units compatible with that of the sensor.
        For example, a sensor with W units allows data to be posted with units:
        - W, kW, MW, etc. (i.e. units with different prefixes)
        - J/s, Nm/s, etc. (i.e. units that can be converted using some multiplier)
        - Wh, kWh, etc. (i.e. units that represent a stock delta, which knowing the duration can be converted to a flow)
        For compatible units, the SensorDataSchema converts values to the sensor's unit.
        """
        posted_unit = data["unit"]
        required_unit = data["sensor"].unit

        if posted_unit != required_unit and not units_are_convertible(
            posted_unit, required_unit
        ):
            raise ValidationError(
                f"Required unit for this sensor is {data['sensor'].unit}, got incompatible unit: {data['unit']}"
            )
コード例 #2
0
class ChartRequestSchema(Schema):
    """
    This schema describes the request for a chart.
    """

    resource = fields.Str(required=True)
    start_time = fields.DateTime(required=True)
    end_time = fields.DateTime(required=True)
    resolution = DurationField(required=True)
    show_consumption_as_positive = fields.Bool(missing=True)
    show_individual_traces_for = fields.Str(
        missing="none",
        validate=validate.OneOf(["none", "schedules", "power"]))
    forecast_horizon = DurationField(missing="PT6H")
コード例 #3
0
ファイル: test_times.py プロジェクト: SeitaBV/flexmeasures
def test_duration_field_nominal_grounded(
    duration_input, exp_deserialization, grounded_timedelta
):
    """Nominal durations are tricky:
    https://en.wikipedia.org/wiki/Talk:ISO_8601/Archive_2#Definition_of_Duration_is_incorrect
    We want to test if we can ground them as expected.
    We use a particular datetime to ground, in a leap year February.
    For the Europe/Amsterdam timezone, daylight saving time started on March 29th 2020.
    # todo: the commented out tests would work if isodate.parse_duration would have the option to stop coercing ISO 8601 days into datetime.timedelta days
    """
    df = DurationField()
    deser = df.deserialize(duration_input, None, None)
    assert deser == exp_deserialization
    dummy_time = pytz.timezone("Europe/Amsterdam").localize(
        datetime(2020, 2, 22, 18, 7)
    )
    grounded = DurationField.ground_from(deser, dummy_time)
    assert grounded == grounded_timedelta
コード例 #4
0
 def decorated_service(*args, **kwargs):
     duration_arg = parser.parse(
         {"duration": DurationField()},
         request,
         location="args_and_json",
         unknown=marshmallow.EXCLUDE,
     )
     if "duration" in duration_arg:
         duration = duration_arg["duration"]
         duration = DurationField.ground_from(
             duration,
             kwargs.get("start", kwargs.get("datetime", None)),
         )
         if not duration:  # TODO: deprecate
             extra_info = "Cannot parse 'duration' value."
             current_app.logger.warning(extra_info)
             return invalid_period(extra_info)
         kwargs["duration"] = duration
     else:
         kwargs["duration"] = default_duration
     return fn(*args, **kwargs)
コード例 #5
0
    required=True,
    multiple=True,
    type=SensorIdField(),
    help="ID of sensor(s). This argument can be given multiple times.",
)
@click.option(
    "--start",
    "start",
    type=AwareDateTimeField(),
    required=True,
    help="Plot starting at this datetime. Follow up with a timezone-aware datetime in ISO 6801 format.",
)
@click.option(
    "--duration",
    "duration",
    type=DurationField(),
    required=True,
    help="Duration of the plot, after --start. Follow up with a duration in ISO 6801 format, e.g. PT1H (1 hour) or PT45M (45 minutes).",
)
@click.option(
    "--belief-time-before",
    "belief_time_before",
    type=AwareDateTimeField(),
    required=False,
    help="Time at which beliefs had been known. Follow up with a timezone-aware datetime in ISO 6801 format.",
)
@click.option(
    "--source-id",
    "source",
    required=False,
    type=DataSourceIdField(),
コード例 #6
0
ファイル: test_times.py プロジェクト: SeitaBV/flexmeasures
def test_duration_field_invalid(duration_input, error_msg):
    df = DurationField()
    with pytest.raises(DurationValidationError) as ve:
        df.deserialize(duration_input, None, None)
    assert error_msg in str(ve)
コード例 #7
0
ファイル: test_times.py プロジェクト: SeitaBV/flexmeasures
def test_duration_field_straightforward(duration_input, exp_deserialization):
    """Testing straightforward cases"""
    df = DurationField()
    deser = df.deserialize(duration_input, None, None)
    assert deser == exp_deserialization
    assert df.serialize("duration", {"duration": deser}) == duration_input