Fix UnionType type var replacement (#25566)

[langchain_core] Fix UnionType type var replacement

- Added types.UnionType to typing.Union mapping

Type replacement cause `TypeError: 'type' object is not subscriptable`
if any of union type comes as function `_py_38_safe_origin` return
`types.UnionType` instead of `typing.Union`

```python
>>> from types import UnionType
>>> from typing import Union, get_origin
>>> type_ = get_origin(str | None)
>>> type_
<class 'types.UnionType'>
>>> UnionType[(str, None)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'type' object is not subscriptable
>>> Union[(str, None)]
typing.Optional[str]
```

---------

Co-authored-by: Chester Curme <chester.curme@gmail.com>
This commit is contained in:
Ivan 2024-08-22 21:22:09 +03:00 committed by GitHub
parent 8230ba47f3
commit 5b9290a449
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 22 additions and 0 deletions

View File

@ -5,6 +5,7 @@ from __future__ import annotations
import collections
import inspect
import logging
import types
import typing
import uuid
from typing import (
@ -575,6 +576,10 @@ def _parse_google_docstring(
def _py_38_safe_origin(origin: Type) -> Type:
origin_union_type_map: Dict[Type, Any] = (
{types.UnionType: Union} if hasattr(types, "UnionType") else {}
)
origin_map: Dict[Type, Any] = {
dict: Dict,
list: List,
@ -584,5 +589,6 @@ def _py_38_safe_origin(origin: Type) -> Type:
collections.abc.Mapping: typing.Mapping,
collections.abc.Sequence: typing.Sequence,
collections.abc.MutableMapping: typing.MutableMapping,
**origin_union_type_map,
}
return cast(Type, origin_map.get(origin, origin))

View File

@ -1,4 +1,5 @@
# mypy: disable-error-code="annotation-unchecked"
import sys
from typing import (
Any,
Callable,
@ -702,3 +703,18 @@ def test__convert_typed_dict_to_openai_function_fail(typed_dict: Type) -> None:
with pytest.raises(TypeError):
_convert_typed_dict_to_openai_function(Tool)
@pytest.mark.skipif(
sys.version_info < (3, 10), reason="Requires python version >= 3.10 to run."
)
def test_convert_union_type_py_39() -> None:
@tool
def magic_function(input: int | float) -> str:
"""Compute a magic function."""
pass
result = convert_to_openai_function(magic_function)
assert result["parameters"]["properties"]["input"] == {
"anyOf": [{"type": "integer"}, {"type": "number"}]
}