def _post_render_validation(self, rendered_value, params): """ Validation function executed after rendering """ # TODO: we should be able to perform this validation from dotted # paths as well if not self._callable_loader.from_dotted_path: to_validate = set(params) fn_params = inspect.signature(self.primitive).parameters if not self._needs_product and 'product' in fn_params: raise TypeError( f'Function {self.name!r} should not have ' 'a \'product\' parameter, but return its result instead') # if source does not need product to be called and we got # a product parameter, remove it. NOTE: Task.render removes # product from params if dealing with an EmptyProduct - it's # better to always pass it and just remove it here to avoid # the second condition. i don't think there is any other # condition were we don't receive product here if not self._needs_product and 'product' in to_validate: to_validate.remove('product') signature_check(self.primitive, to_validate, self.name)
def test_signature_check_extra(): def fn(): pass with pytest.raises(TaskRenderError) as excinfo: signature_check(fn, {'b': 1}, 'task') error = ('Error rendering task "task" initialized with function "fn". ' 'Got unexpected arguments: [\'b\']') assert error == str(excinfo.value)
def test_signature_check_params_missing(): def fn(a, b): pass with pytest.raises(TaskRenderError) as excinfo: signature_check(fn, {'b': 1}, 'task') error = ('Error rendering task "task" initialized with function ' '"fn". Missing arguments: [\'a\']. ' 'Pass [\'a\'] in "params"') assert error == str(excinfo.value)
def test_signature_check_upstream_missing(): def fn(upstream): pass with pytest.raises(TaskRenderError) as excinfo: signature_check(fn, dict(), 'task') error = ('Error rendering task "task" initialized with function ' '"fn". Missing arguments: [\'upstream\']. ' 'Verify this task declared upstream depedencies or remove the ' '"upstream" argument from the function') assert error == str(excinfo.value)
def test_signature_check_params_and_upstream_missing(): def fn(upstream, a): pass with pytest.raises(TaskRenderError) as excinfo: signature_check(fn, dict(), 'task') error = ('Error rendering task "task" initialized with function "fn". ' 'Missing arguments: [\'a\', \'upstream\']. Verify this ' 'task declared upstream depedencies or remove the "upstream" ' 'argument from the function. ' 'Pass [\'a\'] in "params"') assert error == str(excinfo.value)
def test_signature_check_ignores_params_w_default(): def fn(a, b=1): pass assert signature_check(fn, {'a': 1}, 'task')