def _python_type_to_json_schema(type_hint: Any) -> dict:
    """Convert a Python type hint to a JSON schema."""
    if type_hint is type(None):
        return {"type": "null"}
    if type_hint is Any:
        return {}
    if type_hint is str:
        return {"type": "string"}
    if type_hint is int:
        return {"type": "integer"}
    if type_hint is float:
        return {"type": "number"}
    if type_hint is bool:
        return {"type": "boolean"}
    if type_hint is dict:
        return {"type": "object", "additionalProperties": {}}
    if type_hint is list:
        return {"type": "array", "items": {}}
    if type_hint is tuple:
        return {"type": "array"}
    if type_hint is set or type_hint is frozenset:
        return {"type": "array", "uniqueItems": True}
    if type_hint is bytes or type_hint is bytearray:
        return {"type": "string", "format": "byte"}

    origin = get_origin(type_hint)

    if origin is Literal:
        literal_values = get_args(type_hint)
        if len(literal_values) == 1:
            return {"const": literal_values[0]}
        return {"enum": list(literal_values)}

    if (
        origin is Union
        or (hasattr(origin, "__name__") and origin.__name__ == "UnionType")
        or str(origin) == "|"
    ):
        types = get_args(type_hint)
        if len(types) == 2 and type(None) in types:
            other_type = next(t for t in types if t is not type(None))
            schema = _python_type_to_json_schema(other_type)
            return {"oneOf": [{"type": "null"}, schema]}
        return {"anyOf": [_python_type_to_json_schema(t) for t in types]}

    if origin is list:
        args = get_args(type_hint)
        if not args:
            return {"type": "array", "items": {}}
        item_type = args[0]
        return {"type": "array", "items": _python_type_to_json_schema(item_type)}
    if origin is tuple:
        types = get_args(type_hint)
        if not types:
            return {"type": "array"}
        if len(types) == 2 and types[1] is ...:
            return {"type": "array", "items": _python_type_to_json_schema(types[0])}
        return {
            "type": "array",
            "prefixItems": [_python_type_to_json_schema(t) for t in types],
            "minItems": len(types),
            "maxItems": len(types),
        }
    if origin is set or origin is frozenset:
        args = get_args(type_hint)
        if not args:
            return {"type": "array", "uniqueItems": True}
        item_type = args[0]
        return {
            "type": "array",
            "uniqueItems": True,
            "items": _python_type_to_json_schema(item_type),
        }

    if origin is dict:
        args = get_args(type_hint)
        if not args:
            return {"type": "object", "additionalProperties": {}}
        key_type, value_type = args
        if key_type is not str:
            raise ValueError("JSON Schema only supports string keys in objects")
        schema = {
            "type": "object",
            "additionalProperties": _python_type_to_json_schema(value_type),
        }
        return schema

    if inspect.isclass(type_hint) and issubclass(type_hint, Enum):
        enum_values = [item.value for item in type_hint]
        return {"enum": enum_values}

    if inspect.isclass(type_hint) and hasattr(type_hint, "__annotations__"):
        properties = {}
        required = []

        hints = get_type_hints(type_hint)
        for field_name, field_type in hints.items():
            properties[field_name] = _python_type_to_json_schema(field_type)
            if hasattr(type_hint, "__total__"):
                if type_hint.__total__:
                    required.append(field_name)
            elif (
                not hasattr(type_hint, "__dataclass_fields__")
                or not type_hint.__dataclass_fields__[field_name].default
            ):
                required.append(field_name)

        schema = {"type": "object", "properties": properties}
        if required:
            schema["required"] = required
        return schema

    return {}
Convert a Python type hint to a JSON schema.
client/python/gradio_client/utils.py