Repository: pydantic/pydantic

Issue:
Skip signature check for functions in the standard library, or give users control over whether the check is performed
### Initial Checks

- [X] I have searched Google & GitHub for similar requests and couldn't find anything
- [X] I have read and followed [the docs](https://docs.pydantic.dev) and still think this feature is missing

### Description

This fails:

```python
from datetime import datetime

from pydantic import AfterValidator, TypeAdapter
from typing_extensions import Annotated

ISOTimestamp = Annotated[datetime, AfterValidator(datetime.isoformat)]
print(TypeAdapter(ISOTimestamp).validate_python(1651576501.0))
# ValueError: no signature found for builtin <method 'isoformat' of 'datetime.datetime' objects>
```

A simple workaround is to call `datetime.isoformat` from a lambda, but that's a bit ugly.

[inspect_validator](https://github.com/pydantic/pydantic/blob/da7ed9be87b54bb5a2b9b46e759a01fd0ba0b4f2/pydantic/_internal/_decorators.py#L507) excludes builtins from the inspection that fails, but does not exclude methods like `datetime.timestamp` from the inspection. I think it should. Or give the user control over whether the inspection takes place.

### Affected Components

- [ ] [Compatibility between releases](https://docs.pydantic.dev/changelog/)
- [X] [Data validation/parsing](https://docs.pydantic.dev/usage/models/#basic-model-usage)
- [ ] [Data serialization](https://docs.pydantic.dev/usage/exporting_models/) - `.model_dump()` and `.model_dump_json()`
- [ ] [JSON Schema](https://docs.pydantic.dev/usage/schema/)
- [ ] [Dataclasses](https://docs.pydantic.dev/usage/dataclasses/)
- [ ] [Model Config](https://docs.pydantic.dev/usage/model_config/)
- [ ] [Field Types](https://docs.pydantic.dev/usage/types/) - adding or changing a particular data type
- [ ] [Function validation decorator](https://docs.pydantic.dev/usage/validation_decorator/)
- [ ] [Generic Models](https://docs.pydantic.dev/usage/models/#generic-models)
- [ ] [Other Model behaviour](https://docs.pydantic.dev/usage/models/) - `model_construct()`, pickling, private attributes, ORM mode
- [ ] [Plugins](https://docs.pydantic.dev/) and integration with other tools - mypy, FastAPI, python-devtools, Hypothesis, VS Code, PyCharm, etc.

Selected Assignee: @adriangb


Discussion:
I agree that it'd be nice if this just worked, but it's going to be hard to special case everything.
Maybe if we can't get the signature we can assume one, e.g. a single argument that is the input value?

@dmontagu I'm curious what you think
Yeah, I think that's reasonable.

Resolving patch:
diff --git a/pydantic/_internal/_decorators.py b/pydantic/_internal/_decorators.py
--- a/pydantic/_internal/_decorators.py
+++ b/pydantic/_internal/_decorators.py
@@ -493,7 +493,7 @@ def build(model_dc: type[Any]) -> DecoratorInfos:  # noqa: C901 (ignore complexi
 
 
 def inspect_validator(validator: Callable[..., Any], mode: FieldValidatorModes) -> bool:
-    """Look at a field or model validator function and determine if it whether it takes an info argument.
+    """Look at a field or model validator function and determine whether it takes an info argument.
 
     An error is raised if the function has an invalid signature.
 
@@ -504,10 +504,13 @@ def inspect_validator(validator: Callable[..., Any], mode: FieldValidatorModes)
     Returns:
         Whether the validator takes an info argument.
     """
-    if getattr(validator, '__module__', None) == 'builtins':
-        # int, str, etc.
+    try:
+        sig = signature(validator)
+    except ValueError:
+        # builtins and some C extensions don't have signatures
+        # assume that they don't take an info argument and only take a single argument
+        # e.g. `str.strip` or `datetime.datetime`
         return False
-    sig = signature(validator)
     n_positional = count_positional_params(sig)
     if mode == 'wrap':
         if n_positional == 3:


Test patch:
diff --git a/tests/test_validators.py b/tests/test_validators.py
--- a/tests/test_validators.py
+++ b/tests/test_validators.py
@@ -61,11 +61,15 @@ class Model(BaseModel):
 def test_annotated_validator_builtin() -> None:
     """https://github.com/pydantic/pydantic/issues/6752"""
     TruncatedFloat = Annotated[float, BeforeValidator(int)]
+    DateTimeFromIsoFormat = Annotated[datetime, BeforeValidator(datetime.fromisoformat)]
 
     class Model(BaseModel):
         x: TruncatedFloat
+        y: DateTimeFromIsoFormat
 
-    assert Model(x=1.234).x == 1
+    m = Model(x=1.234, y='2011-11-04T00:05:23')
+    assert m.x == 1
+    assert m.y == datetime(2011, 11, 4, 0, 5, 23)
 
 
 def test_annotated_validator_plain() -> None: