Skip to content

Commit

Permalink
SDK regeneration (#465)
Browse files Browse the repository at this point in the history
Co-authored-by: fern-api <115122769+fern-api[bot]@users.noreply.github.com>
  • Loading branch information
fern-api[bot] authored Apr 8, 2024
1 parent 2c493eb commit 5a4e732
Show file tree
Hide file tree
Showing 122 changed files with 1,198 additions and 454 deletions.
12 changes: 6 additions & 6 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "cohere"
version = "5.2.2"
version = "5.2.3"
description = ""
readme = "README.md"
authors = []
Expand Down
232 changes: 171 additions & 61 deletions src/cohere/base_client.py

Large diffs are not rendered by default.

226 changes: 163 additions & 63 deletions src/cohere/connectors/client.py

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/cohere/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .pydantic_utilities import pydantic_v1
from .remove_none_from_dict import remove_none_from_dict
from .request_options import RequestOptions
from .unchecked_base_model import UncheckedBaseModel, UnionMetadata, construct_type

__all__ = [
"ApiError",
Expand All @@ -19,6 +20,9 @@
"HttpClient",
"RequestOptions",
"SyncClientWrapper",
"UncheckedBaseModel",
"UnionMetadata",
"construct_type",
"convert_file_dict_to_httpx_tuples",
"jsonable_encoder",
"pydantic_v1",
Expand Down
2 changes: 1 addition & 1 deletion src/cohere/core/client_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def get_headers(self) -> typing.Dict[str, str]:
headers: typing.Dict[str, str] = {
"X-Fern-Language": "Python",
"X-Fern-SDK-Name": "cohere",
"X-Fern-SDK-Version": "5.2.2",
"X-Fern-SDK-Version": "5.2.3",
}
if self._client_name is not None:
headers["X-Client-Name"] = self._client_name
Expand Down
191 changes: 191 additions & 0 deletions src/cohere/core/unchecked_base_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
# This file was auto-generated by Fern from our API Definition.

import datetime as dt
import inspect
import typing
import uuid

import typing_extensions

from .datetime_utils import serialize_datetime
from .pydantic_utilities import pydantic_v1


class UnionMetadata:
discriminant: str

def __init__(self, *, discriminant: str) -> None:
self.discriminant = discriminant


Model = typing.TypeVar("Model", bound=pydantic_v1.BaseModel)


class UncheckedBaseModel(pydantic_v1.BaseModel):
# Allow extra fields
class Config:
extra = pydantic_v1.Extra.allow
smart_union = True
allow_population_by_field_name = True
populate_by_name = True
extra = pydantic_v1.Extra.allow
json_encoders = {dt.datetime: serialize_datetime}

# Allow construct to not validate model
# Implementation taken from: https://github.com/pydantic/pydantic/issues/1168#issuecomment-817742836
@classmethod
def construct(
cls: typing.Type["Model"], _fields_set: typing.Optional[typing.Set[str]] = None, **values: typing.Any
) -> "Model":
m = cls.__new__(cls) # type: ignore
fields_values = {}

config = cls.__config__

if _fields_set is None:
_fields_set = set(values.keys())

for name, field in cls.__fields__.items():
key = field.alias
if (
key not in values and config.allow_population_by_field_name
): # Added this to allow population by field name
key = name

if key in values:
if (
values[key] is None and not field.required
): # Moved this check since None value can be passed for Optional nested field
fields_values[name] = field.get_default()
else:
type_ = typing.cast(typing.Type, field.outer_type_) # type: ignore
fields_values[name] = construct_type(object_=values[key], type_=type_)
elif not field.required:
default = field.get_default()
fields_values[name] = default

# If the default values are non-null act like they've been set
# This effectively allows exclude_unset to work like exclude_none where
# the latter passes through intentionally set none values.
if default != None:
_fields_set.add(key)

# Add extras back in
for key, value in values.items():
if key not in cls.__fields__:
_fields_set.add(key)
fields_values[key] = value

object.__setattr__(m, "__dict__", fields_values)
object.__setattr__(m, "__fields_set__", _fields_set)
m._init_private_attributes()
return m


def _convert_undiscriminated_union_type(union_type: typing.Type[typing.Any], object_: typing.Any) -> typing.Any:
inner_types = pydantic_v1.typing.get_args(union_type)
if typing.Any in inner_types:
return object_

for inner_type in inner_types:
try:
if inspect.isclass(inner_type) and issubclass(inner_type, pydantic_v1.BaseModel):
# Attempt a validated parse until one works
return pydantic_v1.parse_obj_as(inner_type, object_)
except Exception:
continue

# If none of the types work, just return the first successful cast
for inner_type in inner_types:
try:
return construct_type(object_=object_, type_=inner_type)
except Exception:
continue


def _convert_union_type(type_: typing.Type[typing.Any], object_: typing.Any) -> typing.Any:
base_type = pydantic_v1.typing.get_origin(type_) or type_
union_type = type_
if base_type == typing_extensions.Annotated:
union_type = pydantic_v1.typing.get_args(type_)[0]
annotated_metadata = pydantic_v1.typing.get_args(type_)[1:]
for metadata in annotated_metadata:
if isinstance(metadata, UnionMetadata):
try:
# Cast to the correct type, based on the discriminant
for inner_type in pydantic_v1.typing.get_args(union_type):
if inner_type.__fields__[metadata.discriminant].default == getattr(
object_, metadata.discriminant
):
return construct_type(object_=object_, type_=inner_type)
except Exception:
# Allow to fall through to our regular union handling
pass
return _convert_undiscriminated_union_type(union_type, object_)


def construct_type(*, type_: typing.Type[typing.Any], object_: typing.Any) -> typing.Any:
"""
Here we are essentially creating the same `construct` method in spirit as the above, but for all types, not just
Pydantic models.
The idea is to essentially attempt to coerce object_ to type_ (recursively)
"""
base_type = pydantic_v1.typing.get_origin(type_) or type_
is_annotated = base_type == typing_extensions.Annotated
maybe_annotation_members = pydantic_v1.typing.get_args(type_)
is_annotated_union = is_annotated and pydantic_v1.typing.is_union(
pydantic_v1.typing.get_origin(maybe_annotation_members[0])
)

if base_type == typing.Any:
return object_

if base_type == dict:
if not isinstance(object_, typing.Mapping):
return object_

_, items_type = pydantic_v1.typing.get_args(type_)
return {key: construct_type(object_=item, type_=items_type) for key, item in object_.items()}

if base_type == list:
if not isinstance(object_, list):
return object_

inner_type = pydantic_v1.typing.get_args(type_)[0]
return [construct_type(object_=entry, type_=inner_type) for entry in object_]

if base_type == set:
if not isinstance(object_, set) and not isinstance(object_, list):
return object_

inner_type = pydantic_v1.typing.get_args(type_)[0]
return {construct_type(object_=entry, type_=inner_type) for entry in object_}

if pydantic_v1.typing.is_union(base_type) or is_annotated_union:
return _convert_union_type(type_, object_)

# Cannot do an `issubclass` with a literal type, let's also just confirm we have a class before this call
if not pydantic_v1.typing.is_literal_type(type_) and (
inspect.isclass(base_type) and issubclass(base_type, pydantic_v1.BaseModel)
):
return type_.construct(**object_)

if base_type == dt.datetime:
try:
return pydantic_v1.datetime_parse.parse_datetime(object_)
except Exception:
return object_

if base_type == dt.date:
try:
return pydantic_v1.datetime_parse.parse_date(object_)
except Exception:
return object_

if base_type == uuid.UUID:
try:
return uuid.UUID(object_)
except Exception:
return object_

return object_
Loading

0 comments on commit 5a4e732

Please sign in to comment.