Repository: pydantic/pydantic

Issue:
Validate towards type hinted function signature without calling the function
### Checks

* [X] I added a descriptive title to this issue
* [X] I have searched (google, github) for similar issues and couldn't find anything
* [X] I have read and followed [the docs](https://pydantic-docs.helpmanual.io/) and couldn't find an answer
* [X] After submitting this, I commit to one of:
    * Look through open issues and helped at least one other person
    * Hit the "watch" button on this repo to receive notifications and I commit to help at least 2 people that ask questions in the future
    * Implement a Pull Request for a confirmed bug

<!-- Sorry to sound so draconian, but every second saved replying to issues is time spend improving pydantic :-) -->

# Question

Is there a way to validate data input compared to type hinted function signature, _without_ calling the function? I've seen https://pydantic-docs.helpmanual.io/usage/validation_decorator/ but that appears to do the validation check when calling the function.

**Example use case/context:**
User input (e.g. from a configuration file) is used to call different functions and/or initiate different classes. It would be nice to quickly provide the user with a collection of validation feedback in one go, and not having to wait on e.g. the first `X` function calls to be successful while `X+1` turns out to have invalid data input.


Discussion:

Resolving patch:
diff --git a/docs/examples/validation_decorator_validate.py b/docs/examples/validation_decorator_validate.py
new file mode 100644
--- /dev/null
+++ b/docs/examples/validation_decorator_validate.py
@@ -0,0 +1,17 @@
+from pydantic import validate_arguments, ValidationError
+
+
+@validate_arguments
+def slow_sum(a: int, b: int) -> int:
+    print(f'Called with a={a}, b={b}')
+    return a + b
+
+
+slow_sum(1, 1)
+
+slow_sum.validate(2, 2)
+
+try:
+    slow_sum.validate(1, 'b')
+except ValidationError as exc:
+    print(exc)
diff --git a/pydantic/decorator.py b/pydantic/decorator.py
--- a/pydantic/decorator.py
+++ b/pydantic/decorator.py
@@ -52,6 +52,7 @@ def wrapper_function(*args: Any, **kwargs: Any) -> Any:
             return vd.call(*args, **kwargs)
 
         wrapper_function.vd = vd  # type: ignore
+        wrapper_function.validate = vd.init_model_instance  # type: ignore
         wrapper_function.raw_function = vd.raw_function  # type: ignore
         wrapper_function.model = vd.model  # type: ignore
         return wrapper_function
@@ -134,9 +135,12 @@ def __init__(self, function: 'AnyCallableT', config: 'ConfigType'):  # noqa C901
 
         self.create_model(fields, takes_args, takes_kwargs, config)
 
-    def call(self, *args: Any, **kwargs: Any) -> Any:
+    def init_model_instance(self, *args: Any, **kwargs: Any) -> BaseModel:
         values = self.build_values(args, kwargs)
-        m = self.model(**values)
+        return self.model(**values)
+
+    def call(self, *args: Any, **kwargs: Any) -> Any:
+        m = self.init_model_instance(*args, **kwargs)
         return self.execute(m)
 
     def build_values(self, args: Tuple[Any, ...], kwargs: Dict[str, Any]) -> Dict[str, Any]:


Test patch:
diff --git a/tests/test_decorator.py b/tests/test_decorator.py
--- a/tests/test_decorator.py
+++ b/tests/test_decorator.py
@@ -318,3 +318,17 @@ def foo(a: int, b: EggBox):
             'ctx': {'expected_arbitrary_type': 'EggBox'},
         },
     ]
+
+
+def test_validate(mocker):
+    stub = mocker.stub(name='on_something_stub')
+
+    @validate_arguments
+    def func(s: str, count: int, *, separator: bytes = b''):
+        stub(s, count, separator)
+
+    func.validate('qwe', 2)
+    with pytest.raises(ValidationError):
+        func.validate(['qwe'], 2)
+
+    stub.assert_not_called()