Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions polytope_server/common/datasource/datasource.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def match(ds_config, coerced_ur: Dict[str, Any], user: User) -> str:
)
match_rules = ds_config.get("match", {})
for rule_key, allowed_values in match_rules.items():
allowed_values = [allowed_values] if not isinstance(allowed_values, (list, tuple)) else allowed_values

# An empty match rule means that the key must not be present
if allowed_values is None or len(allowed_values) == 0:
Expand Down Expand Up @@ -123,11 +124,10 @@ def match(ds_config, coerced_ur: Dict[str, Any], user: User) -> str:
continue

# check that all values in request are allowed
allowed_values = [allowed_values] if not isinstance(allowed_values, (list, tuple)) else allowed_values
request_values = (
[coerced_ur[rule_key]] if not isinstance(coerced_ur[rule_key], (list, tuple)) else coerced_ur[rule_key]
)
if not set(request_values).issubset(set(allowed_values)):
if not set(request_values).issubset(set(coerce_value(rule_key, allowed_values))):
return (
f"Skipping datasource {DataSource.repr(ds_config)}: "
f"got {rule_key} : {coerced_ur[rule_key]}, but expected one of {allowed_values}"
Expand Down
24 changes: 21 additions & 3 deletions polytope_server/common/datasource/date_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,24 @@ def parse_relativedelta(time_str):
return relativedelta(days=time_dict["d"], hours=time_dict["h"], minutes=time_dict["m"])


def date_check(date, allowed_values: str):
def date_check(date, allowed_values: list):
"""
Process special match rules for DATE constraints

:param date: Date to check, can be a string or list of strings
:param allowed_values: List of allowed values for the date in the format >1d, <2d, >1m, <2h, r"(\\d+)([dhm])".
"""
if not isinstance(allowed_values, list):
raise DateError("Allowed values must be a list")

for allowed in allowed_values:
if not date_check_single_rule(date, allowed):
return False

return True


def date_check_single_rule(date, allowed_values: str):
"""
Process special match rules for DATE constraints

Expand All @@ -65,13 +82,14 @@ def date_check(date, allowed_values: str):
date = str(date)

# Parse allowed values
comp, offset = allowed_values.split(" ", 1)
comp = allowed_values[0]
offset = allowed_values[1:].strip()
if comp == "<":
after = False
elif comp == ">":
after = True
else:
raise DateError("Invalid date comparison")
raise DateError(f"Invalid date comparison {comp}, expected < or >")
now = datetime.today()
offset = now - parse_relativedelta(offset)
offset_fmted = offset.strftime("%Y%m%d")
Expand Down
20 changes: 17 additions & 3 deletions tests/unit/test_datasource_matching.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# does it submit to any jurisdiction.
#

from copy import deepcopy
from datetime import datetime, timedelta

import pytest # noqa: F401
Expand Down Expand Up @@ -45,9 +46,6 @@ class TestDataSourceMatching:
def setup_method(self):

self.mars_config = {
"type": "mars",
"command": "mars",
"tmp_dir": "/home/polytope/data",
"name": "mars",
"match": {"class": ["od"], "stream": ["oper", "enfo", "something"], "date": "> 30d"},
}
Expand Down Expand Up @@ -123,6 +121,22 @@ def test_mars_match_two_lists(self, monkeypatch, user_request):
req["stream"] = ["oper", "enfo", "something_else"]
assert "success" != DataSource.match(self.mars_config, req, None)

def test_mars_match_rule_formatting(self, monkeypatch, user_request):
self._mock_auth(monkeypatch)
config = deepcopy(self.mars_config)

# list of date rules works
config["match"]["date"] = [">30d", "< 40d"]
assert "success" == DataSource.match(config, user_request, None)

# single number rules works
config["match"]["step"] = 0
assert "success" == DataSource.match(config, user_request, None)
config["match"]["step"] = [0, 6]
assert "success" == DataSource.match(config, user_request, None)
config["match"]["step"] = [6]
assert "success" != DataSource.match(config, user_request, None)


def set_request_date(user_request, days_offset):
date = datetime.today() + timedelta(days=days_offset)
Expand Down