diff --git a/metobsapi/common_config.py b/metobsapi/common_config.py index eaed3dccfdb02459fdac10dcd3b9336dc7711203..7987531bb25ab060cbcf56c12aa4046755e37054 100644 --- a/metobsapi/common_config.py +++ b/metobsapi/common_config.py @@ -19,3 +19,4 @@ INFLUXDB_PASS = "root" # noqa: S105 INFLUXDB_TOKEN = "" INFLUXDB_ORG = "metobs" INFLUXDB_DB = "metobs" +INFLUXDB_BUCKET = "metobs_realtime" diff --git a/metobsapi/tests/test_data_api.py b/metobsapi/tests/test_data_api.py index 69009aa5f72dabac7080d4886cda914a53525762..645be8c780294bb1f6cf2f24cf3468025e03a3d6 100644 --- a/metobsapi/tests/test_data_api.py +++ b/metobsapi/tests/test_data_api.py @@ -27,6 +27,9 @@ if TYPE_CHECKING: from metobsapi.util.query_influx import QueryResult +FAKE_DATA_START = datetime(2017, 3, 5, 19, 0, 0) + + @pytest.fixture(params=["1", "2"], ids=["influxdbv1", "influxdbv2"]) def influxdb_version(request): return request.param @@ -112,21 +115,21 @@ def _fake_data_to_v1_resultset(fake_data: list[dict]) -> QueryResult: @pytest.fixture() -def influxdb_air_temp_9_values(mock_influxdb_query) -> Iterable[None]: +def influxdb_air_temp_9_values(mock_influxdb_query) -> Iterable[mock.Mock]: fake_result = _fake_data("1m", {("aoss", "tower"): ["time", "air_temp"]}, 9) with mock_influxdb_query(fake_result) as query_func: yield query_func @pytest.fixture() -def influxdb_3_symbols_9_values(mock_influxdb_query) -> Iterable[None]: +def influxdb_3_symbols_9_values(mock_influxdb_query) -> Iterable[mock.Mock]: fake_result = _fake_data("1m", {("aoss", "tower"): ["time", "air_temp", "rel_hum", "wind_speed"]}, 9) with mock_influxdb_query(fake_result) as query_func: yield query_func @pytest.fixture() -def influxdb_wind_fields_9_values(mock_influxdb_query) -> Iterable[None]: +def influxdb_wind_fields_9_values(mock_influxdb_query) -> Iterable[mock.Mock]: fake_result = _fake_data( "1m", {("aoss", "tower"): ["time", "wind_speed", "wind_direction", "wind_east", "wind_north"]}, @@ -137,7 +140,7 @@ def influxdb_wind_fields_9_values(mock_influxdb_query) -> Iterable[None]: def _fake_data(interval: str, symbols: dict[tuple[str, str], list[str]], num_vals: int) -> list[dict[str, Any]]: - now = datetime(2017, 3, 5, 19, 0, 0) + now = FAKE_DATA_START measurement_name = "metobs_" + interval series = [] for (site, inst), columns in symbols.items(): @@ -295,11 +298,26 @@ def test_too_many_points(client): assert res["status"] == "fail" -@pytest.mark.usefixtures("influxdb_air_temp_9_values") -def test_shorthand_one_symbol_json_row(client): +@pytest.mark.parametrize( + ("begin", "end", "exp_query_time"), + [ + ("-00:10:00", None, "-600s"), + ( + FAKE_DATA_START.strftime("%Y-%m-%dT%H:%M:%S"), + (FAKE_DATA_START + timedelta(minutes=10)).strftime("%Y-%m-%dT%H:%M:%S"), + "range(start: 2017-03-05T19:00:00Z, stop: 2017-03-05T19:10:00Z)", + ), + ], +) +def test_shorthand_one_symbol_json_row(client, influxdb_air_temp_9_values, begin, end, exp_query_time): + end = "" if not end else f"&end={end}" # row should be the default - res = client.get("/api/data.json?site=aoss&inst=tower&symbols=air_temp&begin=-00:10:00") + res = client.get(f"/api/data.json?site=aoss&inst=tower&symbols=air_temp&begin={begin}{end}") res = json.loads(res.data.decode()) + influxdb_air_temp_9_values.assert_called_once() + query_str_arg = influxdb_air_temp_9_values.call_args[0][0] + if not query_str_arg.startswith("SELECT"): + assert exp_query_time in query_str_arg assert res["code"] == 200 assert res["num_results"] == 9 assert res["results"]["symbols"] == ["air_temp"] diff --git a/metobsapi/util/query_influx.py b/metobsapi/util/query_influx.py index 317fbd24136271ca352b81d9e8bf44d1fda134d0..4b35afd10ed0f601623a9ad83165996a506ef0af 100644 --- a/metobsapi/util/query_influx.py +++ b/metobsapi/util/query_influx.py @@ -134,7 +134,7 @@ def parse_dt_v2(d): if isinstance(d, timedelta): total_seconds = int(d.total_seconds()) return f"-{total_seconds:d}s" - return d.strftime("'%Y-%m-%dT%H:%M:%SZ'") + return d.strftime("%Y-%m-%dT%H:%M:%SZ") def _query_influxdbv1(query_str, epoch) -> QueryResult: @@ -167,7 +167,7 @@ def _build_queries_v2( interval: str, ) -> str: query_format = """ -from(bucket:"metobs/forever") +from(bucket:"{bucket}") |> range(start: {start}, stop: {stop}) |> filter(fn: (r) => r["_measurement"] == "metobs_{interval}" and r["site"] == "{site}" and r["inst"] == "{inst}") |> filter(fn: (r) => contains(value: r["_field"], set: ["_time", "site", "inst", {symbols_csv}])) @@ -182,6 +182,7 @@ from(bucket:"metobs/forever") for (site, inst), symbol_names in symbols.items(): symbol_csv_str = ", ".join(f'"{sname}"' for sname in symbol_names) this_query = query_format.format( + bucket=current_app.config["INFLUXDB_BUCKET"], interval=interval, symbols_csv=symbol_csv_str, site=site,