unstructured-platform-plugins 0.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- test/__init__.py +0 -0
- test/assets/__init__.py +0 -0
- test/assets/async_typed_dict_response.py +10 -0
- test/assets/dataclass_response.py +37 -0
- test/assets/empty_input_and_response.py +8 -0
- test/assets/hash_function.py +2 -0
- test/assets/improper_function.py +2 -0
- test/assets/pydantic_response_class_method.py +21 -0
- test/assets/simple_hash_class.py +6 -0
- test/assets/simple_hash_lambda.py +1 -0
- test/assets/simple_hash_value.py +1 -0
- test/assets/typed_dict_response.py +17 -0
- test/test_schema.py +660 -0
- test/test_utils.py +140 -0
- unstructured_platform_plugins/__init__.py +0 -0
- unstructured_platform_plugins/__version__.py +1 -0
- unstructured_platform_plugins/etl_uvicorn/__init__.py +0 -0
- unstructured_platform_plugins/etl_uvicorn/api_generator.py +173 -0
- unstructured_platform_plugins/etl_uvicorn/main.py +121 -0
- unstructured_platform_plugins/etl_uvicorn/utils.py +115 -0
- unstructured_platform_plugins/schema/__init__.py +0 -0
- unstructured_platform_plugins/schema/json_schema.py +344 -0
- unstructured_platform_plugins/schema/model.py +101 -0
- unstructured_platform_plugins/schema/usage.py +7 -0
- unstructured_platform_plugins/schema/utils.py +31 -0
- unstructured_platform_plugins/type_hints.py +106 -0
- unstructured_platform_plugins/validate_api.py +110 -0
- unstructured_platform_plugins-0.0.0.dist-info/LICENSE +201 -0
- unstructured_platform_plugins-0.0.0.dist-info/LICENSE.md +201 -0
- unstructured_platform_plugins-0.0.0.dist-info/METADATA +106 -0
- unstructured_platform_plugins-0.0.0.dist-info/RECORD +34 -0
- unstructured_platform_plugins-0.0.0.dist-info/WHEEL +5 -0
- unstructured_platform_plugins-0.0.0.dist-info/entry_points.txt +3 -0
- unstructured_platform_plugins-0.0.0.dist-info/top_level.txt +2 -0
test/test_schema.py
ADDED
|
@@ -0,0 +1,660 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any, Optional, Union
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
from typing_extensions import TypedDict
|
|
10
|
+
from unstructured.ingest.v2.interfaces import FileData
|
|
11
|
+
|
|
12
|
+
import unstructured_platform_plugins.schema.json_schema as js
|
|
13
|
+
from unstructured_platform_plugins.etl_uvicorn.utils import get_input_schema
|
|
14
|
+
from unstructured_platform_plugins.schema.model import is_valid_input_dict, is_valid_response_dict
|
|
15
|
+
from unstructured_platform_plugins.schema.utils import get_typed_parameters
|
|
16
|
+
from unstructured_platform_plugins.type_hints import get_type_hints
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_string_enum_fn():
|
|
20
|
+
class StringEnum(Enum):
|
|
21
|
+
FIRST = "first"
|
|
22
|
+
SECOND = "second"
|
|
23
|
+
THIRD = "third"
|
|
24
|
+
|
|
25
|
+
def fn(input: StringEnum) -> None:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
sig = inspect.signature(fn)
|
|
29
|
+
input_schema = js.parameters_to_json_schema(parameters=list(sig.parameters.values()))
|
|
30
|
+
expected_schema = {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"required": ["input"],
|
|
33
|
+
"properties": {"input": {"type": "string", "enum": ["first", "second", "third"]}},
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
assert input_schema == expected_schema
|
|
37
|
+
assert is_valid_response_dict(input_schema)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_int_enum_fn():
|
|
41
|
+
class IntEnum(Enum):
|
|
42
|
+
FIRST = 1
|
|
43
|
+
SECOND = 2
|
|
44
|
+
THIRD = 3
|
|
45
|
+
|
|
46
|
+
def fn(input: IntEnum) -> None:
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
sig = inspect.signature(fn)
|
|
50
|
+
input_schema = js.parameters_to_json_schema(parameters=list(sig.parameters.values()))
|
|
51
|
+
expected_schema = {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"required": ["input"],
|
|
54
|
+
"properties": {"input": {"type": "integer", "enum": [1, 2, 3]}},
|
|
55
|
+
}
|
|
56
|
+
assert input_schema == expected_schema
|
|
57
|
+
assert is_valid_response_dict(input_schema)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_mixed_enum_fn():
|
|
61
|
+
class MixedEnum(Enum):
|
|
62
|
+
FIRST = 1
|
|
63
|
+
SECOND = "second"
|
|
64
|
+
THIRD = 3
|
|
65
|
+
|
|
66
|
+
def fn(input: MixedEnum) -> None:
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
sig = inspect.signature(fn)
|
|
70
|
+
with pytest.raises(ValueError):
|
|
71
|
+
js.parameters_to_json_schema(parameters=list(sig.parameters.values()))
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_blank_fn():
|
|
75
|
+
def fn() -> None:
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
sig = inspect.signature(fn)
|
|
79
|
+
input_schema = js.parameters_to_json_schema(parameters=list(sig.parameters.values()))
|
|
80
|
+
expected_schema = {"type": "null"}
|
|
81
|
+
assert input_schema == expected_schema
|
|
82
|
+
assert is_valid_input_dict(input_schema)
|
|
83
|
+
|
|
84
|
+
output_schema = js.response_to_json_schema(return_annotation=sig.return_annotation)
|
|
85
|
+
expected_output_schema = {"type": "null"}
|
|
86
|
+
assert output_schema == expected_output_schema
|
|
87
|
+
assert is_valid_response_dict(output_schema)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def test_simple_fn():
|
|
91
|
+
class Response(TypedDict):
|
|
92
|
+
x: int
|
|
93
|
+
y: str
|
|
94
|
+
|
|
95
|
+
def fn(
|
|
96
|
+
a: int,
|
|
97
|
+
b: Union[float, int],
|
|
98
|
+
c: Optional[str] = "my_string",
|
|
99
|
+
d: bool = False,
|
|
100
|
+
e: dict[str, dict[str, bool]] = None,
|
|
101
|
+
f: list[float] = None,
|
|
102
|
+
) -> Response:
|
|
103
|
+
return Response(x=1, y="y")
|
|
104
|
+
|
|
105
|
+
sig = inspect.signature(fn)
|
|
106
|
+
input_schema = js.parameters_to_json_schema(parameters=list(sig.parameters.values()))
|
|
107
|
+
expected_input_schema = {
|
|
108
|
+
"type": "object",
|
|
109
|
+
"required": ["a", "b"],
|
|
110
|
+
"properties": {
|
|
111
|
+
"a": {"type": "integer"},
|
|
112
|
+
"b": {"anyOf": [{"type": "number"}, {"type": "integer"}]},
|
|
113
|
+
"c": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": "my_string"},
|
|
114
|
+
"d": {"type": "boolean", "default": False},
|
|
115
|
+
"e": {
|
|
116
|
+
"type": "object",
|
|
117
|
+
"items": {
|
|
118
|
+
"key": {"type": "string"},
|
|
119
|
+
"value": {
|
|
120
|
+
"type": "object",
|
|
121
|
+
"items": {"key": {"type": "string"}, "value": {"type": "boolean"}},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
"default": None,
|
|
125
|
+
},
|
|
126
|
+
"f": {"type": "array", "items": {"type": "number"}, "default": None},
|
|
127
|
+
},
|
|
128
|
+
}
|
|
129
|
+
assert input_schema == expected_input_schema
|
|
130
|
+
assert is_valid_input_dict(input_schema)
|
|
131
|
+
|
|
132
|
+
output_schema = js.response_to_json_schema(return_annotation=sig.return_annotation)
|
|
133
|
+
expected_output_schema = {
|
|
134
|
+
"type": "object",
|
|
135
|
+
"properties": {"x": {"type": "integer"}, "y": {"type": "string"}},
|
|
136
|
+
"required": ["x", "y"],
|
|
137
|
+
}
|
|
138
|
+
assert output_schema == expected_output_schema
|
|
139
|
+
assert is_valid_response_dict(output_schema)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def test_incorrect_dict_response():
|
|
143
|
+
def fn() -> dict[str, Any]:
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
sig = inspect.signature(fn)
|
|
147
|
+
with pytest.raises(ValueError):
|
|
148
|
+
js.response_to_json_schema(return_annotation=sig.return_annotation)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def test_incorrect_int_response():
|
|
152
|
+
def fn() -> int:
|
|
153
|
+
pass
|
|
154
|
+
|
|
155
|
+
sig = inspect.signature(fn)
|
|
156
|
+
with pytest.raises(ValueError):
|
|
157
|
+
js.response_to_json_schema(return_annotation=sig.return_annotation)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def test_incorrect_inputs():
|
|
161
|
+
def fn(*args, **kwargs) -> None:
|
|
162
|
+
pass
|
|
163
|
+
|
|
164
|
+
sig = inspect.signature(fn)
|
|
165
|
+
with pytest.raises(TypeError):
|
|
166
|
+
js.parameters_to_json_schema(parameters=list(sig.parameters.values()))
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def test_incorrect_union_response():
|
|
170
|
+
class CorrectResponse(TypedDict):
|
|
171
|
+
x: int
|
|
172
|
+
|
|
173
|
+
def fn() -> Union[CorrectResponse, float]:
|
|
174
|
+
pass
|
|
175
|
+
|
|
176
|
+
sig = inspect.signature(fn)
|
|
177
|
+
with pytest.raises(ValueError):
|
|
178
|
+
js.response_to_json_schema(return_annotation=sig.return_annotation)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def test_dataclass_schema():
|
|
182
|
+
@dataclass
|
|
183
|
+
class Input:
|
|
184
|
+
x: int
|
|
185
|
+
y: Optional[str] = None
|
|
186
|
+
|
|
187
|
+
@dataclass
|
|
188
|
+
class Output:
|
|
189
|
+
a: dict[str, Any]
|
|
190
|
+
b: list[bool]
|
|
191
|
+
c: Optional[float] = 5.46
|
|
192
|
+
|
|
193
|
+
def fn(g: Input) -> Optional[Output]:
|
|
194
|
+
pass
|
|
195
|
+
|
|
196
|
+
sig = inspect.signature(fn)
|
|
197
|
+
input_schema = js.parameters_to_json_schema(parameters=list(sig.parameters.values()))
|
|
198
|
+
expected_input_schema = {
|
|
199
|
+
"type": "object",
|
|
200
|
+
"required": ["g"],
|
|
201
|
+
"properties": {
|
|
202
|
+
"g": {
|
|
203
|
+
"type": "object",
|
|
204
|
+
"properties": {
|
|
205
|
+
"x": {"type": "integer"},
|
|
206
|
+
"y": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": None},
|
|
207
|
+
},
|
|
208
|
+
"required": ["x"],
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
}
|
|
212
|
+
assert input_schema == expected_input_schema
|
|
213
|
+
assert is_valid_input_dict(input_schema)
|
|
214
|
+
|
|
215
|
+
output_schema = js.response_to_json_schema(return_annotation=sig.return_annotation)
|
|
216
|
+
expected_output_schema = {
|
|
217
|
+
"anyOf": [
|
|
218
|
+
{
|
|
219
|
+
"type": "object",
|
|
220
|
+
"properties": {
|
|
221
|
+
"a": {"type": "object", "items": {"key": {"type": "string"}, "value": {}}},
|
|
222
|
+
"b": {"type": "array", "items": {"type": "boolean"}},
|
|
223
|
+
"c": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": 5.46},
|
|
224
|
+
},
|
|
225
|
+
"required": ["a", "b"],
|
|
226
|
+
},
|
|
227
|
+
{"type": "null"},
|
|
228
|
+
]
|
|
229
|
+
}
|
|
230
|
+
assert output_schema == expected_output_schema
|
|
231
|
+
assert is_valid_response_dict(output_schema)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def test_pydantic_base_model():
|
|
235
|
+
class Input(BaseModel):
|
|
236
|
+
x: "int"
|
|
237
|
+
y: Optional[str] = None
|
|
238
|
+
|
|
239
|
+
class Output(BaseModel):
|
|
240
|
+
a: dict[str, Any]
|
|
241
|
+
b: list[bool]
|
|
242
|
+
c: Optional[float] = 5.46
|
|
243
|
+
|
|
244
|
+
def fn(g: Input) -> Optional[Output]:
|
|
245
|
+
pass
|
|
246
|
+
|
|
247
|
+
sig = inspect.signature(fn)
|
|
248
|
+
input_schema = js.parameters_to_json_schema(parameters=list(sig.parameters.values()))
|
|
249
|
+
expected_input_schema = {
|
|
250
|
+
"type": "object",
|
|
251
|
+
"required": ["g"],
|
|
252
|
+
"properties": {
|
|
253
|
+
"g": {
|
|
254
|
+
"type": "object",
|
|
255
|
+
"properties": {
|
|
256
|
+
"x": {"type": "integer"},
|
|
257
|
+
"y": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": None},
|
|
258
|
+
},
|
|
259
|
+
"required": ["x"],
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
}
|
|
263
|
+
assert input_schema == expected_input_schema
|
|
264
|
+
assert is_valid_input_dict(input_schema)
|
|
265
|
+
|
|
266
|
+
output_schema = js.response_to_json_schema(return_annotation=sig.return_annotation)
|
|
267
|
+
expected_output_schema = {
|
|
268
|
+
"anyOf": [
|
|
269
|
+
{
|
|
270
|
+
"type": "object",
|
|
271
|
+
"properties": {
|
|
272
|
+
"a": {"type": "object", "items": {"key": {"type": "string"}, "value": {}}},
|
|
273
|
+
"b": {"type": "array", "items": {"type": "boolean"}},
|
|
274
|
+
"c": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": 5.46},
|
|
275
|
+
},
|
|
276
|
+
"required": ["a", "b"],
|
|
277
|
+
},
|
|
278
|
+
{"type": "null"},
|
|
279
|
+
]
|
|
280
|
+
}
|
|
281
|
+
assert output_schema == expected_output_schema
|
|
282
|
+
assert is_valid_response_dict(output_schema)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def test_typed_dict():
|
|
286
|
+
class Input(TypedDict):
|
|
287
|
+
x: "int"
|
|
288
|
+
y: Optional[str]
|
|
289
|
+
|
|
290
|
+
class Output(TypedDict):
|
|
291
|
+
a: dict[str, Any]
|
|
292
|
+
b: list[bool]
|
|
293
|
+
c: Optional[float]
|
|
294
|
+
|
|
295
|
+
def fn(g: Input) -> Optional[Output]:
|
|
296
|
+
pass
|
|
297
|
+
|
|
298
|
+
sig = inspect.signature(fn)
|
|
299
|
+
input_schema = js.parameters_to_json_schema(parameters=list(sig.parameters.values()))
|
|
300
|
+
expected_input_schema = {
|
|
301
|
+
"type": "object",
|
|
302
|
+
"required": ["g"],
|
|
303
|
+
"properties": {
|
|
304
|
+
"g": {
|
|
305
|
+
"type": "object",
|
|
306
|
+
"properties": {
|
|
307
|
+
"x": {"type": "integer"},
|
|
308
|
+
"y": {"anyOf": [{"type": "string"}, {"type": "null"}]},
|
|
309
|
+
},
|
|
310
|
+
"required": ["x", "y"],
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
}
|
|
314
|
+
assert input_schema == expected_input_schema
|
|
315
|
+
assert is_valid_input_dict(input_schema)
|
|
316
|
+
|
|
317
|
+
output_schema = js.response_to_json_schema(return_annotation=sig.return_annotation)
|
|
318
|
+
expected_output_schema = {
|
|
319
|
+
"anyOf": [
|
|
320
|
+
{
|
|
321
|
+
"type": "object",
|
|
322
|
+
"properties": {
|
|
323
|
+
"a": {"type": "object", "items": {"key": {"type": "string"}, "value": {}}},
|
|
324
|
+
"b": {"type": "array", "items": {"type": "boolean"}},
|
|
325
|
+
"c": {"anyOf": [{"type": "number"}, {"type": "null"}]},
|
|
326
|
+
},
|
|
327
|
+
"required": ["a", "b", "c"],
|
|
328
|
+
},
|
|
329
|
+
{"type": "null"},
|
|
330
|
+
]
|
|
331
|
+
}
|
|
332
|
+
assert output_schema == expected_output_schema
|
|
333
|
+
assert is_valid_response_dict(output_schema)
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def test_nested_complex_types():
|
|
337
|
+
class InputA(TypedDict):
|
|
338
|
+
x: int
|
|
339
|
+
y: Optional[str]
|
|
340
|
+
|
|
341
|
+
class InputB(BaseModel):
|
|
342
|
+
a: float
|
|
343
|
+
b: Optional[InputA] = None
|
|
344
|
+
|
|
345
|
+
@dataclass
|
|
346
|
+
class InputC:
|
|
347
|
+
g: list[InputB]
|
|
348
|
+
h: bool = False
|
|
349
|
+
|
|
350
|
+
def fn(q: InputC) -> None:
|
|
351
|
+
pass
|
|
352
|
+
|
|
353
|
+
sig = inspect.signature(fn)
|
|
354
|
+
input_schema = js.parameters_to_json_schema(parameters=list(sig.parameters.values()))
|
|
355
|
+
expected_input_schema = {
|
|
356
|
+
"type": "object",
|
|
357
|
+
"required": ["q"],
|
|
358
|
+
"properties": {
|
|
359
|
+
"q": {
|
|
360
|
+
"type": "object",
|
|
361
|
+
"properties": {
|
|
362
|
+
"g": {
|
|
363
|
+
"type": "array",
|
|
364
|
+
"items": {
|
|
365
|
+
"type": "object",
|
|
366
|
+
"properties": {
|
|
367
|
+
"a": {"type": "number"},
|
|
368
|
+
"b": {
|
|
369
|
+
"anyOf": [
|
|
370
|
+
{
|
|
371
|
+
"type": "object",
|
|
372
|
+
"properties": {
|
|
373
|
+
"x": {"type": "integer"},
|
|
374
|
+
"y": {
|
|
375
|
+
"anyOf": [{"type": "string"}, {"type": "null"}]
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
"required": ["x", "y"],
|
|
379
|
+
},
|
|
380
|
+
{"type": "null"},
|
|
381
|
+
],
|
|
382
|
+
"default": None,
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
"required": ["a"],
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
"h": {"type": "boolean", "default": False},
|
|
389
|
+
},
|
|
390
|
+
"required": ["g"],
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
}
|
|
394
|
+
assert input_schema == expected_input_schema
|
|
395
|
+
assert is_valid_input_dict(input_schema)
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def test_schema_to_base_model():
|
|
399
|
+
class g_enum(Enum):
|
|
400
|
+
FIRST = "first"
|
|
401
|
+
SECOND = "second"
|
|
402
|
+
THIRD = "third"
|
|
403
|
+
|
|
404
|
+
def fn(
|
|
405
|
+
a: int,
|
|
406
|
+
b: float | int = 4,
|
|
407
|
+
c: str | None = "my_string",
|
|
408
|
+
d: bool = False,
|
|
409
|
+
e: Optional[dict[str, Any]] = None,
|
|
410
|
+
f: list[float] = None,
|
|
411
|
+
g: Optional[g_enum] = None,
|
|
412
|
+
h: FileData | None = None,
|
|
413
|
+
i: Path | None = None,
|
|
414
|
+
) -> None:
|
|
415
|
+
pass
|
|
416
|
+
|
|
417
|
+
class ExpectedInputModel(BaseModel):
|
|
418
|
+
a: int
|
|
419
|
+
b: Union[float, int] = 4
|
|
420
|
+
c: str | None = "my_string"
|
|
421
|
+
d: bool = False
|
|
422
|
+
e: Optional[dict[str, Any]] = None
|
|
423
|
+
f: list[float] = None
|
|
424
|
+
g: Optional[g_enum] = None
|
|
425
|
+
h: FileData | None = None
|
|
426
|
+
i: Path | None = None
|
|
427
|
+
|
|
428
|
+
input_schema = get_input_schema(fn)
|
|
429
|
+
input_model = js.schema_to_base_model(schema=input_schema)
|
|
430
|
+
input_model_schema = input_model.model_json_schema()
|
|
431
|
+
expected_model_schema = ExpectedInputModel.model_json_schema()
|
|
432
|
+
expected_model_schema["title"] = "reconstructed_model"
|
|
433
|
+
assert input_model_schema == expected_model_schema
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
# These need to be defined outside the code of test_forward_reference_typing
|
|
437
|
+
# for references to resolve:
|
|
438
|
+
@dataclass
|
|
439
|
+
class MockInputClass:
|
|
440
|
+
a: str
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
@dataclass
|
|
444
|
+
class MockOutputClass:
|
|
445
|
+
b: bool
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def test_forward_reference_typing():
|
|
449
|
+
|
|
450
|
+
def fn(a: "MockInputClass") -> "MockOutputClass":
|
|
451
|
+
pass
|
|
452
|
+
|
|
453
|
+
parameters = get_typed_parameters(fn)
|
|
454
|
+
input_schema = js.parameters_to_json_schema(parameters=parameters)
|
|
455
|
+
expected_input_schema = {
|
|
456
|
+
"type": "object",
|
|
457
|
+
"required": ["a"],
|
|
458
|
+
"properties": {
|
|
459
|
+
"a": {"type": "object", "properties": {"a": {"type": "string"}}, "required": ["a"]}
|
|
460
|
+
},
|
|
461
|
+
}
|
|
462
|
+
assert input_schema == expected_input_schema
|
|
463
|
+
assert is_valid_input_dict(input_schema)
|
|
464
|
+
|
|
465
|
+
return_annotation = get_type_hints(fn)["return"]
|
|
466
|
+
output_schema = js.response_to_json_schema(return_annotation=return_annotation)
|
|
467
|
+
expected_output_schema = {
|
|
468
|
+
"type": "object",
|
|
469
|
+
"properties": {"b": {"type": "boolean"}},
|
|
470
|
+
"required": ["b"],
|
|
471
|
+
}
|
|
472
|
+
assert output_schema == expected_output_schema
|
|
473
|
+
assert is_valid_response_dict(output_schema)
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def test_file_data():
|
|
477
|
+
def fn(a: FileData) -> list[FileData]:
|
|
478
|
+
pass
|
|
479
|
+
|
|
480
|
+
parameters = get_typed_parameters(fn)
|
|
481
|
+
input_schema = js.parameters_to_json_schema(parameters=parameters)
|
|
482
|
+
expected_input_schema = {
|
|
483
|
+
"type": "object",
|
|
484
|
+
"required": ["a"],
|
|
485
|
+
"properties": {
|
|
486
|
+
"a": {
|
|
487
|
+
"type": "object",
|
|
488
|
+
"is_file_data": True,
|
|
489
|
+
"properties": {
|
|
490
|
+
"identifier": {"type": "string"},
|
|
491
|
+
"connector_type": {"type": "string"},
|
|
492
|
+
"source_identifiers": {
|
|
493
|
+
"anyOf": [
|
|
494
|
+
{
|
|
495
|
+
"type": "object",
|
|
496
|
+
"properties": {
|
|
497
|
+
"filename": {"type": "string"},
|
|
498
|
+
"fullpath": {"type": "string"},
|
|
499
|
+
"rel_path": {
|
|
500
|
+
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
501
|
+
"default": None,
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
"required": ["filename", "fullpath"],
|
|
505
|
+
},
|
|
506
|
+
{"type": "null"},
|
|
507
|
+
],
|
|
508
|
+
"default": None,
|
|
509
|
+
},
|
|
510
|
+
"doc_type": {"type": "string", "enum": ["batch", "file"], "default": "file"},
|
|
511
|
+
"metadata": {
|
|
512
|
+
"type": "object",
|
|
513
|
+
"properties": {
|
|
514
|
+
"url": {
|
|
515
|
+
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
516
|
+
"default": None,
|
|
517
|
+
},
|
|
518
|
+
"version": {
|
|
519
|
+
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
520
|
+
"default": None,
|
|
521
|
+
},
|
|
522
|
+
"record_locator": {
|
|
523
|
+
"anyOf": [
|
|
524
|
+
{
|
|
525
|
+
"type": "object",
|
|
526
|
+
"items": {"key": {"type": "string"}, "value": {}},
|
|
527
|
+
},
|
|
528
|
+
{"type": "null"},
|
|
529
|
+
],
|
|
530
|
+
"default": None,
|
|
531
|
+
},
|
|
532
|
+
"date_created": {
|
|
533
|
+
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
534
|
+
"default": None,
|
|
535
|
+
},
|
|
536
|
+
"date_modified": {
|
|
537
|
+
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
538
|
+
"default": None,
|
|
539
|
+
},
|
|
540
|
+
"date_processed": {
|
|
541
|
+
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
542
|
+
"default": None,
|
|
543
|
+
},
|
|
544
|
+
"permissions_data": {
|
|
545
|
+
"anyOf": [
|
|
546
|
+
{
|
|
547
|
+
"type": "array",
|
|
548
|
+
"items": {
|
|
549
|
+
"type": "object",
|
|
550
|
+
"items": {"key": {"type": "string"}, "value": {}},
|
|
551
|
+
},
|
|
552
|
+
},
|
|
553
|
+
{"type": "null"},
|
|
554
|
+
],
|
|
555
|
+
"default": None,
|
|
556
|
+
},
|
|
557
|
+
},
|
|
558
|
+
"required": [],
|
|
559
|
+
},
|
|
560
|
+
"additional_metadata": {
|
|
561
|
+
"type": "object",
|
|
562
|
+
"items": {"key": {"type": "string"}, "value": {}},
|
|
563
|
+
},
|
|
564
|
+
"reprocess": {"type": "boolean", "default": False},
|
|
565
|
+
},
|
|
566
|
+
"required": ["identifier", "connector_type", "metadata", "additional_metadata"],
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
assert input_schema == expected_input_schema
|
|
572
|
+
assert is_valid_input_dict(input_schema)
|
|
573
|
+
|
|
574
|
+
return_annotation = get_type_hints(fn)["return"]
|
|
575
|
+
output_schema = js.response_to_json_schema(return_annotation=return_annotation)
|
|
576
|
+
expected_output_schema = {
|
|
577
|
+
"type": "array",
|
|
578
|
+
"items": {
|
|
579
|
+
"type": "object",
|
|
580
|
+
"is_file_data": True,
|
|
581
|
+
"properties": {
|
|
582
|
+
"identifier": {"type": "string"},
|
|
583
|
+
"connector_type": {"type": "string"},
|
|
584
|
+
"source_identifiers": {
|
|
585
|
+
"anyOf": [
|
|
586
|
+
{
|
|
587
|
+
"type": "object",
|
|
588
|
+
"properties": {
|
|
589
|
+
"filename": {"type": "string"},
|
|
590
|
+
"fullpath": {"type": "string"},
|
|
591
|
+
"rel_path": {
|
|
592
|
+
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
593
|
+
"default": None,
|
|
594
|
+
},
|
|
595
|
+
},
|
|
596
|
+
"required": ["filename", "fullpath"],
|
|
597
|
+
},
|
|
598
|
+
{"type": "null"},
|
|
599
|
+
],
|
|
600
|
+
"default": None,
|
|
601
|
+
},
|
|
602
|
+
"doc_type": {"type": "string", "enum": ["batch", "file"], "default": "file"},
|
|
603
|
+
"metadata": {
|
|
604
|
+
"type": "object",
|
|
605
|
+
"properties": {
|
|
606
|
+
"url": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": None},
|
|
607
|
+
"version": {
|
|
608
|
+
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
609
|
+
"default": None,
|
|
610
|
+
},
|
|
611
|
+
"record_locator": {
|
|
612
|
+
"anyOf": [
|
|
613
|
+
{
|
|
614
|
+
"type": "object",
|
|
615
|
+
"items": {"key": {"type": "string"}, "value": {}},
|
|
616
|
+
},
|
|
617
|
+
{"type": "null"},
|
|
618
|
+
],
|
|
619
|
+
"default": None,
|
|
620
|
+
},
|
|
621
|
+
"date_created": {
|
|
622
|
+
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
623
|
+
"default": None,
|
|
624
|
+
},
|
|
625
|
+
"date_modified": {
|
|
626
|
+
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
627
|
+
"default": None,
|
|
628
|
+
},
|
|
629
|
+
"date_processed": {
|
|
630
|
+
"anyOf": [{"type": "string"}, {"type": "null"}],
|
|
631
|
+
"default": None,
|
|
632
|
+
},
|
|
633
|
+
"permissions_data": {
|
|
634
|
+
"anyOf": [
|
|
635
|
+
{
|
|
636
|
+
"type": "array",
|
|
637
|
+
"items": {
|
|
638
|
+
"type": "object",
|
|
639
|
+
"items": {"key": {"type": "string"}, "value": {}},
|
|
640
|
+
},
|
|
641
|
+
},
|
|
642
|
+
{"type": "null"},
|
|
643
|
+
],
|
|
644
|
+
"default": None,
|
|
645
|
+
},
|
|
646
|
+
},
|
|
647
|
+
"required": [],
|
|
648
|
+
},
|
|
649
|
+
"additional_metadata": {
|
|
650
|
+
"type": "object",
|
|
651
|
+
"items": {"key": {"type": "string"}, "value": {}},
|
|
652
|
+
},
|
|
653
|
+
"reprocess": {"type": "boolean", "default": False},
|
|
654
|
+
},
|
|
655
|
+
"required": ["identifier", "connector_type", "metadata", "additional_metadata"],
|
|
656
|
+
},
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
assert output_schema == expected_output_schema
|
|
660
|
+
assert is_valid_response_dict(output_schema)
|