openai/openai-python

Public

mirrored fromhttps://github.com/openai/openai-pythonAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
codex/bedrock-thin-provider-rewrite

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

tests/test_utils/test_path.py

89lines · modecode

1from __future__ import annotations
2
3from typing import Any
4
5import pytest
6
7from openai._utils._path import path_template
8
9
10@pytest.mark.parametrize(
11 "template, kwargs, expected",
12 [
13 ("/v1/{id}", dict(id="abc"), "/v1/abc"),
14 ("/v1/{a}/{b}", dict(a="x", b="y"), "/v1/x/y"),
15 ("/v1/{a}{b}/path/{c}?val={d}#{e}", dict(a="x", b="y", c="z", d="u", e="v"), "/v1/xy/path/z?val=u#v"),
16 ("/{w}/{w}", dict(w="echo"), "/echo/echo"),
17 ("/v1/static", {}, "/v1/static"),
18 ("", {}, ""),
19 ("/v1/?q={n}&count=10", dict(n=42), "/v1/?q=42&count=10"),
20 ("/v1/{v}", dict(v=None), "/v1/null"),
21 ("/v1/{v}", dict(v=True), "/v1/true"),
22 ("/v1/{v}", dict(v=False), "/v1/false"),
23 ("/v1/{v}", dict(v=".hidden"), "/v1/.hidden"), # dot prefix ok
24 ("/v1/{v}", dict(v="file.txt"), "/v1/file.txt"), # dot in middle ok
25 ("/v1/{v}", dict(v="..."), "/v1/..."), # triple dot ok
26 ("/v1/{a}{b}", dict(a=".", b="txt"), "/v1/.txt"), # dot var combining with adjacent to be ok
27 ("/items?q={v}#{f}", dict(v=".", f=".."), "/items?q=.#.."), # dots in query/fragment are fine
28 (
29 "/v1/{a}?query={b}",
30 dict(a="../../other/endpoint", b="a&bad=true"),
31 "/v1/..%2F..%2Fother%2Fendpoint?query=a%26bad%3Dtrue",
32 ),
33 ("/v1/{val}", dict(val="a/b/c"), "/v1/a%2Fb%2Fc"),
34 ("/v1/{val}", dict(val="a/b/c?query=value"), "/v1/a%2Fb%2Fc%3Fquery=value"),
35 ("/v1/{val}", dict(val="a/b/c?query=value&bad=true"), "/v1/a%2Fb%2Fc%3Fquery=value&bad=true"),
36 ("/v1/{val}", dict(val="%20"), "/v1/%2520"), # escapes escape sequences in input
37 # Query: slash and ? are safe, # is not
38 ("/items?q={v}", dict(v="a/b"), "/items?q=a/b"),
39 ("/items?q={v}", dict(v="a?b"), "/items?q=a?b"),
40 ("/items?q={v}", dict(v="a#b"), "/items?q=a%23b"),
41 ("/items?q={v}", dict(v="a b"), "/items?q=a%20b"),
42 # Fragment: slash and ? are safe
43 ("/docs#{v}", dict(v="a/b"), "/docs#a/b"),
44 ("/docs#{v}", dict(v="a?b"), "/docs#a?b"),
45 # Path: slash, ? and # are all encoded
46 ("/v1/{v}", dict(v="a/b"), "/v1/a%2Fb"),
47 ("/v1/{v}", dict(v="a?b"), "/v1/a%3Fb"),
48 ("/v1/{v}", dict(v="a#b"), "/v1/a%23b"),
49 # same var encoded differently by component
50 (
51 "/v1/{v}?q={v}#{v}",
52 dict(v="a/b?c#d"),
53 "/v1/a%2Fb%3Fc%23d?q=a/b?c%23d#a/b?c%23d",
54 ),
55 ("/v1/{val}", dict(val="x?admin=true"), "/v1/x%3Fadmin=true"), # query injection
56 ("/v1/{val}", dict(val="x#admin"), "/v1/x%23admin"), # fragment injection
57 ],
58)
59def test_interpolation(template: str, kwargs: dict[str, Any], expected: str) -> None:
60 assert path_template(template, **kwargs) == expected
61
62
63def test_missing_kwarg_raises_key_error() -> None:
64 with pytest.raises(KeyError, match="org_id"):
65 path_template("/v1/{org_id}")
66
67
68@pytest.mark.parametrize(
69 "template, kwargs",
70 [
71 ("{a}/path", dict(a=".")),
72 ("{a}/path", dict(a="..")),
73 ("/v1/{a}", dict(a=".")),
74 ("/v1/{a}", dict(a="..")),
75 ("/v1/{a}/path", dict(a=".")),
76 ("/v1/{a}/path", dict(a="..")),
77 ("/v1/{a}{b}", dict(a=".", b=".")), # adjacent vars → ".."
78 ("/v1/{a}.", dict(a=".")), # var + static → ".."
79 ("/v1/{a}{b}", dict(a="", b=".")), # empty + dot → "."
80 ("/v1/%2e/{x}", dict(x="ok")), # encoded dot in static text
81 ("/v1/%2e./{x}", dict(x="ok")), # mixed encoded ".." in static
82 ("/v1/.%2E/{x}", dict(x="ok")), # mixed encoded ".." in static
83 ("/v1/{v}?q=1", dict(v="..")),
84 ("/v1/{v}#frag", dict(v="..")),
85 ],
86)
87def test_dot_segment_rejected(template: str, kwargs: dict[str, Any]) -> None:
88 with pytest.raises(ValueError, match="dot-segment"):
89 path_template(template, **kwargs)
90