Skip to content

Commit

Permalink
Issue #195 #196 use official spec of text_concat
Browse files Browse the repository at this point in the history
also support custom spec in `add_simple_function`
  • Loading branch information
soxofaan committed May 30, 2023
1 parent 1bb4e30 commit 8b97377
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 14 deletions.
11 changes: 3 additions & 8 deletions openeo_driver/ProcessGraphDeserializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2068,16 +2068,11 @@ def text_merge(
return str(separator).join(str(d) for d in data)


# TODO #195 #196 use official spec instead of custom openeo-processes/experimental/text_concat.json
@process_registry_100.add_function(spec=read_spec("openeo-processes/experimental/text_concat.json"))
@process_registry_100.add_simple_function(spec=read_spec("openeo-processes/2.x/text_concat.json"))
def text_concat(
args: Dict,
env: EvalEnv
# data: List[Union[str, int, float, bool, None]],
# separator: Union[str, int, float, bool, None] = ""
data: List[Union[str, int, float, bool, None]],
separator: str = "",
) -> str:
data = extract_arg(args, "data")
separator = args.get("separator", "")
return str(separator).join(str(d) for d in data)


Expand Down
13 changes: 9 additions & 4 deletions openeo_driver/processes.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,17 +178,20 @@ def add_function(
)
return f

def add_simple_function(self, f: Callable = None, name: str = None):
def add_simple_function(
self, f: Optional[Callable] = None, name: Optional[str] = None, spec: Optional[dict] = None
):
"""
Register a simple function that uses normal arguments instead of `args: dict, env: EvalEnv`:
wrap it in a wrapper that automatically extracts these arguments
:param f:
:param name: process_id (when guessing from `f.__name__` doesn't work)
:param spec: optional spec dict
:return:
"""
if f is None:
# Called as parameterized decorator
return functools.partial(self.add_simple_function, name=name)
return functools.partial(self.add_simple_function, name=name, spec=spec)

process_id = name or f.__name__
# Detect arguments without and with defaults
Expand All @@ -201,18 +204,20 @@ def add_simple_function(self, f: Callable = None, name: str = None):
else:
defaults[param.name] = param.default

# TODO: avoid this local import, e.g. by encapsulating all extrac_ functions in some kind of ProcessArgs object
# TODO: avoid this local import, e.g. by encapsulating all extract_ functions in some kind of ProcessArgs object
from openeo_driver.ProcessGraphDeserializer import extract_arg

# TODO: can we generalize this assumption?
assert self._argument_names == ["args", "env"]

# TODO: option to also pass `env: EvalEnv` to `f`?
def wrapped(args: dict, env: EvalEnv):
kwargs = {a: extract_arg(args, a, process_id=process_id) for a in required}
kwargs.update({a: args.get(a, d) for a, d in defaults.items()})
return f(**kwargs)

self.add_process(name=process_id, function=wrapped, spec=self.load_predefined_spec(process_id))
spec = spec or self.load_predefined_spec(process_id)
self.add_process(name=process_id, function=wrapped, spec=spec)
return f

def add_hidden(self, f: Callable, name: str = None, namespace: str = DEFAULT_NAMESPACE):
Expand Down
21 changes: 19 additions & 2 deletions tests/test_processes.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ def add(x: int, y: int = 100):

assert process(args={"x": 2, "y": 3}, env=None) == 5
assert process(args={"x": 2}, env=None) == 102
with pytest.raises(ProcessParameterRequiredException):
with pytest.raises(ProcessParameterRequiredException, match="Process 'add' parameter 'x' is required."):
_ = process(args={}, env=None)


Expand All @@ -408,5 +408,22 @@ def if_(value, accept, reject=None):
assert process(args={"value": True, "accept": 3}, env=None) == 3
assert process(args={"value": False, "accept": 3}, env=None) is None
assert process(args={"value": False, "accept": 3, "reject": 5}, env=None) == 5
with pytest.raises(ProcessParameterRequiredException):
with pytest.raises(ProcessParameterRequiredException, match="Process 'if' parameter 'value' is required."):
_ = process(args={}, env=None)


def test_process_registry_add_simple_function_with_spec():
reg = ProcessRegistry(argument_names=["args", "env"])

@reg.add_simple_function(spec={"id": "something_custom"})
def something_custom(x: int, y: int = 123):
return x + y

process = reg.get_function("something_custom")

assert process(args={"x": 5, "y": 3}, env=None) == 8
assert process(args={"x": 5}, env=None) == 128
with pytest.raises(
ProcessParameterRequiredException, match="Process 'something_custom' parameter 'x' is required."
):
_ = process(args={}, env=None)
1 change: 1 addition & 0 deletions tests/test_views_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -2449,6 +2449,7 @@ def test_execute_no_cube_logic(api100, process_graph, expected):
("text_ends", {"data": "FooBar", "pattern": "Foo"}, False),
("text_ends", {"data": "FooBar", "pattern": "bar"}, False),
("text_ends", {"data": "FooBar", "pattern": "bar", "case_sensitive": False}, True),
# TODO: `text_merge` is deprecated (in favor of `text_concat`)
("text_merge", {"data": ["foo", "bar"]}, "foobar"),
("text_merge", {"data": ["foo", "bar"], "separator": "--"}, "foo--bar"),
("text_merge", {"data": [1, 2, 3], "separator": "/"}, "1/2/3"),
Expand Down

0 comments on commit 8b97377

Please sign in to comment.