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
5 changes: 4 additions & 1 deletion src/openai/_qs.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,12 @@ def _stringify_item(
items: list[tuple[str, str]] = []
nested_format = opts.nested_format
for subkey, subvalue in value.items():
if nested_format not in get_args(NestedFormat):
raise NotImplementedError(
f"Unknown nested_format value: {nested_format}, choose from {', '.join(get_args(NestedFormat))}"
)
items.extend(
self._stringify_item(
# TODO: error if unknown format
f"{key}.{subkey}" if nested_format == "dots" else f"{key}[{subkey}]",
subvalue,
opts,
Expand Down
4 changes: 2 additions & 2 deletions src/openai/_utils/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,8 @@ def wrapper(*args: object, **kwargs: object) -> object:
else:
assert len(variants) > 0

# TODO: this error message is not deterministic
missing = list(set(variants[0]) - given_params)
# preserve declaration order for deterministic error messages
missing = [param for param in variants[0] if param not in given_params]
if len(missing) > 1:
msg = f"Missing required arguments: {human_join([quote(arg) for arg in missing])}"
else:
Expand Down
25 changes: 24 additions & 1 deletion tests/test_qs.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,29 @@ def test_array_brackets(method: str) -> None:
assert unquote(serialise({"a": {"b": [True, False, None, True]}})) == "a[b][]=true&a[b][]=false&a[b][]=true"


@pytest.mark.parametrize("method", ["class", "function"])
def test_array_indices(method: str) -> None:
if method == "class":
serialise = Querystring(array_format="indices").stringify
else:
serialise = partial(stringify, array_format="indices")

assert unquote(serialise({"in": ["foo", "bar"]})) == "in[0]=foo&in[1]=bar"
assert unquote(serialise({"a": {"b": [True, False]}})) == "a[b][0]=true&a[b][1]=false"
assert (
unquote(serialise({"a": {"b": [True, False, None, True]}}))
== "a[b][0]=true&a[b][1]=false&a[b][3]=true"
)


def test_unknown_array_format() -> None:
with pytest.raises(NotImplementedError, match="Unknown array_format value: foo, choose from comma, repeat"):
with pytest.raises(
NotImplementedError,
match="Unknown array_format value: foo, choose from comma, repeat, indices, brackets",
):
stringify({"a": ["foo", "bar"]}, array_format=cast(Any, "foo"))


def test_unknown_nested_format() -> None:
with pytest.raises(NotImplementedError, match="Unknown nested_format value: foo, choose from dots, brackets"):
stringify({"a": {"b": "c"}}, nested_format=cast(Any, "foo"))
11 changes: 4 additions & 7 deletions tests/test_required_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,16 @@ def foo(a: str = "", *, b: str = "", c: str = "") -> str | None:

assert foo(a="a", b="b", c="c") == "a b c"

error_message = r"Missing required arguments.*"

with pytest.raises(TypeError, match=error_message):
with pytest.raises(TypeError, match=r"Missing required arguments: 'a', 'b' or 'c'"):
foo()

with pytest.raises(TypeError, match=error_message):
with pytest.raises(TypeError, match=r"Missing required arguments: 'b' or 'c'"):
foo(a="a")

with pytest.raises(TypeError, match=error_message):
with pytest.raises(TypeError, match=r"Missing required arguments: 'a' or 'c'"):
foo(b="b")

with pytest.raises(TypeError, match=error_message):
with pytest.raises(TypeError, match=r"Missing required arguments: 'a' or 'b'"):
foo(c="c")

with pytest.raises(TypeError, match=r"Missing required argument: 'a'"):
Expand All @@ -78,7 +76,6 @@ def foo(*, a: str | None = None, b: str | None = None) -> str | None:
assert foo(a=None) is None
assert foo(b=None) is None

# TODO: this error message could probably be improved
with pytest.raises(
TypeError,
match=r"Missing required arguments; Expected either \('a'\) or \('b'\) arguments to be given",
Expand Down