diff --git a/mlair/helpers/join.py b/mlair/helpers/join.py index 409a15466214a6c3bd389f6e4671984275ef38b1..6d38887cdacfa4a84d83ca20d17e8bb92f020d1b 100644 --- a/mlair/helpers/join.py +++ b/mlair/helpers/join.py @@ -247,6 +247,7 @@ def _create_network_name_opts(network_name): for v in network_name.values(): _network.extend(helpers.to_list(v)) network_name_opts = ",".join(filter(lambda x: x is not None, set(_network))) + network_name_opts = None if len(network_name_opts) == 0 else network_name_opts else: raise TypeError(f"network_name parameter must be of type None, list, or dict. Given is {type(network_name)}.") return network_name_opts @@ -286,7 +287,7 @@ def _select_distinct_network(vars: dict, network_name: Union[list, dict]) -> dic selected = {} for var, series in vars.items(): res = [] - network_list = network_name.get(var, []) or [] + network_list = helpers.to_list(network_name.get(var, []) or []) for network in network_list: res.extend(list(filter(lambda x: x["network_name"].upper() == network.upper(), series))) if len(res) > 0: # use first match which has the highest priority @@ -379,12 +380,14 @@ def _lower_list(args: List[str]) -> Iterator[str]: yield string.lower() -def create_url(base: str, service: str, param_id: str = None, **kwargs: Union[str, int, float, None]) -> str: +def create_url(base: str, service: str, param_id: Union[str, int, None] = None, + **kwargs: Union[str, int, float, None]) -> str: """ Create a request url with given base url, service type and arbitrarily many additional keyword arguments. :param base: basic url of the rest service :param service: service type, e.g. series, stats + :param param_id: id for a distinct service, is added between ending / of service and ? of kwargs :param kwargs: keyword pairs for optional request specifications, e.g. 'statistics=maximum' :return: combined url as string diff --git a/test/test_helpers/test_join.py b/test/test_helpers/test_join.py index c309b26f597a812d7296872ee4f7c4c9f0baffea..9a79d45ee4ae37c8dd75a2c3d2cce691bbfe017a 100644 --- a/test/test_helpers/test_join.py +++ b/test/test_helpers/test_join.py @@ -30,7 +30,7 @@ class TestDownloadJoin: with pytest.raises(EmptyQueryResult) as e: download_join("DEBW107", {"o3": "dma8eu", "o10": "maximum"}, "background", data_origin={"o10": ""}) assert e.value.args[-1] == "No data found for variables {'o10'} and options station=['DEBW107'], " \ - "type=background, network=None, origin={'o10': ''} in JOIN." + "type=background, network={'o10': None}, origin={'o10': ''} in JOIN." class TestCorrectDataFormat: @@ -160,7 +160,8 @@ class TestSelectDistinctNetwork: 'parameter_label': 'PRESS-REA-MIUB', 'parameter_attribute': 'REA'}} assert check_nested_equality(res, expected) is True - message = "Could not find a valid match for variable %s and networks []! Therefore, use first answer from JOIN:" + message = "Could not find a valid match for variable %s and networks {'no2': [], 'o3': [], 'cloudcover': [], " \ + "'temp': [], 'press': []}! Therefore, use first answer from JOIN:" assert message % "no2" in caplog.messages[0] assert message % "o3" in caplog.messages[1] assert message % "cloudcover" in caplog.messages[2] @@ -185,13 +186,16 @@ class TestSelectDistinctNetwork: def test_single_network_given_no_match(self, vars): with pytest.raises(ValueError) as e: # AIRBASE not avail for all variables _select_distinct_network(vars, ["AIRBASE"]) - assert e.value.args[-1] == "Cannot find a valid match for requested networks ['AIRBASE'] and variable " \ - "no2 as only following networks are available in JOIN: ['UBA']" + assert e.value.args[-1] == "Cannot find a valid match for requested networks {'no2': ['AIRBASE'], 'o3': " \ + "['AIRBASE'], 'cloudcover': ['AIRBASE'], 'temp': ['AIRBASE'], 'press': ['AIRBASE']" \ + "} and variable no2 as only following networks are available in JOIN: ['UBA']" with pytest.raises(ValueError) as e: # both requested networks are not available for all variables _select_distinct_network(vars, ["LUBW", "EMEP"]) - assert e.value.args[-1] == "Cannot find a valid match for requested networks ['LUBW', 'EMEP'] and variable " \ - "no2 as only following networks are available in JOIN: ['UBA']" + assert e.value.args[-1] == "Cannot find a valid match for requested networks {'no2': ['LUBW', 'EMEP'], 'o3': " \ + "['LUBW', 'EMEP'], 'cloudcover': ['LUBW', 'EMEP'], 'temp': ['LUBW', 'EMEP'], " \ + "'press': ['LUBW', 'EMEP']} and variable no2 as only following networks are " \ + "available in JOIN: ['UBA']" def test_multiple_networks_given(self, vars): res = _select_distinct_network(vars, ["UBA", "AIRBASE"]) @@ -222,6 +226,22 @@ class TestSelectDistinctNetwork: 'parameter_name': 'press', 'parameter_label': 'PRESS', 'parameter_attribute': 'REA'}} assert check_nested_equality(res, expected) is True + def test_multiple_networks_given_by_dict(self, vars): + res = _select_distinct_network(vars, {"no2": "UBA", "o3": ["UBA", "AIRBASE"], "temp": ["AIRBASE", "UBA"], + "press": ["AIRBASE", "UBA"]}) + expected = { + "no2": {'id': 16686, 'network_name': 'UBA', 'station_id': 'DENW053', 'parameter_name': 'no2', + 'parameter_label': 'NO2', 'parameter_attribute': ''}, + "o3": {'id': 16687, 'network_name': 'UBA', 'station_id': 'DENW053', 'parameter_name': 'o3', + 'parameter_label': 'O3', 'parameter_attribute': ''}, + "cloudcover": {'id': 54036, 'network_name': 'UBA', 'station_id': 'DENW053', 'parameter_name': 'cloudcover', + 'parameter_label': 'CLOUDCOVER', 'parameter_attribute': 'REA'}, + "temp": {'id': 88491, 'network_name': 'UBA', 'station_id': 'DENW053', 'parameter_name': 'temp', + 'parameter_label': 'TEMP-REA-MIUB', 'parameter_attribute': 'REA'}, + "press": {'id': 26692, 'network_name': 'AIRBASE', 'station_id': 'DENW053', + 'parameter_name': 'press', 'parameter_label': 'PRESS', 'parameter_attribute': 'REA'}} + assert check_nested_equality(res, expected) is True + class TestSelectDistinctSeries: @@ -274,8 +294,9 @@ class TestSelectDistinctSeries: def test_network_not_available(self, vars): with pytest.raises(ValueError) as e: _select_distinct_series(vars, network_name="AIRBASE") - assert e.value.args[-1] == "Cannot find a valid match for requested networks ['AIRBASE'] and variable " \ - "no2 as only following networks are available in JOIN: ['UBA']" + assert e.value.args[-1] == "Cannot find a valid match for requested networks {'no2': ['AIRBASE'], 'o3': " \ + "['AIRBASE'], 'cloudcover': ['AIRBASE'], 'temp': ['AIRBASE'], 'press': ['AIRBASE']" \ + "} and variable no2 as only following networks are available in JOIN: ['UBA']" def test_different_network_and_origin(self, vars): origin = {"no2": "test", "temp": "", "cloudcover": "REA"} @@ -349,7 +370,7 @@ class TestCreateUrl: def test_minimal_args_given(self): url = create_url("www.base.edu", "testingservice") - assert url == "www.base.edu/testingservice/?" + assert url == "www.base.edu/testingservice/" def test_given_kwargs(self): url = create_url("www.base2.edu/", "testingservice", mood="happy", confidence=0.98) @@ -362,3 +383,12 @@ class TestCreateUrl: def test_none_kwargs(self): url = create_url("www.base2.edu/", "testingservice", mood="sad", happiness=None, stress_factor=100) assert url == "www.base2.edu/testingservice/?mood=sad&stress_factor=100" + + def test_param_id(self): + url = create_url("www.base.edu", "testingservice", param_id="2001") + assert url == "www.base.edu/testingservice/2001" + + def test_param_id_kwargs(self): + url = create_url("www.base.edu", "testingservice", param_id=2001, mood="sad", happiness=None, stress_factor=100) + assert url == "www.base.edu/testingservice/?2001&mood=sad&stress_factor=100" +