Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 11 additions & 18 deletions skyvern/client/core/http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,8 @@ def remove_omit_from_dict(
) -> typing.Dict[str, typing.Any]:
if omit is None:
return original
new: typing.Dict[str, typing.Any] = {}
for key, value in original.items():
if value is not omit:
new[key] = value
return new
# optimized with dict comprehension
return {key: value for key, value in original.items() if value is not omit}


def maybe_filter_request_body(
Expand All @@ -108,22 +105,18 @@ def maybe_filter_request_body(
omit: typing.Optional[typing.Any],
) -> typing.Optional[typing.Any]:
if data is None:
return (
jsonable_encoder(request_options.get("additional_body_parameters", {})) or {}
if request_options is not None
else None
)
if request_options is not None:
return jsonable_encoder(request_options.get("additional_body_parameters", {})) or {}
else:
return None
elif not isinstance(data, typing.Mapping):
data_content = jsonable_encoder(data)
else:
data_content = {
**(jsonable_encoder(remove_omit_from_dict(data, omit))), # type: ignore
**(
jsonable_encoder(request_options.get("additional_body_parameters", {})) or {}
if request_options is not None
else {}
),
}
merged_dict = dict(jsonable_encoder(remove_omit_from_dict(data, omit))) # type: ignore
if request_options is not None:
additional = jsonable_encoder(request_options.get("additional_body_parameters", {})) or {}
merged_dict.update(additional)
data_content = merged_dict
return data_content


Expand Down
64 changes: 33 additions & 31 deletions skyvern/client/core/jsonable_encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,41 @@

def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None) -> Any:
custom_encoder = custom_encoder or {}

obj_type = type(obj)
if custom_encoder:
if type(obj) in custom_encoder:
return custom_encoder[type(obj)](obj)
if obj_type in custom_encoder:
return custom_encoder[obj_type](obj)
else:
for encoder_type, encoder_instance in custom_encoder.items():
if isinstance(obj, encoder_type):
return encoder_instance(obj)

if isinstance(obj, (str, int, float, type(None))):
return obj
if isinstance(obj, Enum):
return obj.value
if isinstance(obj, PurePath):
return str(obj)
if isinstance(obj, bytes):
return base64.b64encode(obj).decode("utf-8")
if isinstance(obj, dt.datetime):
return serialize_datetime(obj)
if isinstance(obj, dt.date):
return str(obj)

if isinstance(obj, pydantic.BaseModel):
if IS_PYDANTIC_V2:
encoder = getattr(obj.model_config, "json_encoders", {}) # type: ignore # Pydantic v2
else:
encoder = getattr(obj.__config__, "json_encoders", {}) # type: ignore # Pydantic v1
if custom_encoder:
encoder.update(custom_encoder)
# Avoid mutating original encoder dict
if encoder and custom_encoder:
new_encoder = dict(encoder)
new_encoder.update(custom_encoder)
encoder = new_encoder
elif custom_encoder and not encoder:
encoder = custom_encoder
obj_dict = obj.dict(by_alias=True)
if "__root__" in obj_dict:
obj_dict = obj_dict["__root__"]
Expand All @@ -53,32 +74,13 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any]
if dataclasses.is_dataclass(obj):
obj_dict = dataclasses.asdict(obj) # type: ignore
return jsonable_encoder(obj_dict, custom_encoder=custom_encoder)
if isinstance(obj, bytes):
return base64.b64encode(obj).decode("utf-8")
if isinstance(obj, Enum):
return obj.value
if isinstance(obj, PurePath):
return str(obj)
if isinstance(obj, (str, int, float, type(None))):
return obj
if isinstance(obj, dt.datetime):
return serialize_datetime(obj)
if isinstance(obj, dt.date):
return str(obj)
if isinstance(obj, dict):
encoded_dict = {}
allowed_keys = set(obj.keys())
for key, value in obj.items():
if key in allowed_keys:
encoded_key = jsonable_encoder(key, custom_encoder=custom_encoder)
encoded_value = jsonable_encoder(value, custom_encoder=custom_encoder)
encoded_dict[encoded_key] = encoded_value
return encoded_dict
return {jsonable_encoder(key, custom_encoder=custom_encoder): jsonable_encoder(value, custom_encoder=custom_encoder)
for key, value in obj.items()}

if isinstance(obj, (list, set, frozenset, GeneratorType, tuple)):
encoded_list = []
for item in obj:
encoded_list.append(jsonable_encoder(item, custom_encoder=custom_encoder))
return encoded_list
return [jsonable_encoder(item, custom_encoder=custom_encoder) for item in obj]


def fallback_serializer(o: Any) -> Any:
attempt_encode = encode_by_type(o)
Expand All @@ -92,9 +94,9 @@ def fallback_serializer(o: Any) -> Any:
errors.append(e)
try:
data = vars(o)
except Exception as e:
errors.append(e)
raise ValueError(errors) from e
except Exception as e2:
errors.append(e2)
raise ValueError(errors) from e2
return jsonable_encoder(data, custom_encoder=custom_encoder)

return to_jsonable_with_fallback(obj, fallback_serializer)