|
13 | 13 | between "I'd like it to be faster" and "doesn't finish at all".
|
14 | 14 | """
|
15 | 15 |
|
| 16 | +import itertools |
16 | 17 | import json
|
17 | 18 | import math
|
18 | 19 | import re
|
@@ -298,7 +299,7 @@ def canonicalish(schema: JSONType) -> Dict[str, Any]:
|
298 | 299 | elif isinstance(schema.get(key), (bool, dict)):
|
299 | 300 | schema[key] = canonicalish(schema[key])
|
300 | 301 | else:
|
301 |
| - assert key not in schema |
| 302 | + assert key not in schema, (key, schema[key]) |
302 | 303 | for key in SCHEMA_OBJECT_KEYS:
|
303 | 304 | if key in schema:
|
304 | 305 | schema[key] = {
|
@@ -831,8 +832,42 @@ def merged(schemas: List[Any]) -> Optional[Schema]:
|
831 | 832 | return None
|
832 | 833 | odeps[k] = m
|
833 | 834 | odeps.update(s.pop("dependencies"))
|
834 |
| - |
835 |
| - # TODO: merge `items` schemas or lists-of-schemas |
| 835 | + if "items" in out or "items" in s: |
| 836 | + oitems = out.pop("items", TRUTHY) |
| 837 | + sitems = s.pop("items", TRUTHY) |
| 838 | + if isinstance(oitems, list) and isinstance(sitems, list): |
| 839 | + out["items"] = [] |
| 840 | + out["additionalItems"] = merged( |
| 841 | + [ |
| 842 | + out.get("additionalItems", TRUTHY), |
| 843 | + s.get("additionalItems", TRUTHY), |
| 844 | + ] |
| 845 | + ) |
| 846 | + for a, b in itertools.zip_longest(oitems, sitems): |
| 847 | + if a is None: |
| 848 | + a = out.get("additionalItems", TRUTHY) |
| 849 | + elif b is None: |
| 850 | + b = s.get("additionalItems", TRUTHY) |
| 851 | + out["items"].append(merged([a, b])) |
| 852 | + elif isinstance(oitems, list): |
| 853 | + out["items"] = [merged([x, sitems]) for x in oitems] |
| 854 | + out["additionalItems"] = merged( |
| 855 | + [out.get("additionalItems", TRUTHY), sitems] |
| 856 | + ) |
| 857 | + elif isinstance(sitems, list): |
| 858 | + out["items"] = [merged([x, oitems]) for x in sitems] |
| 859 | + out["additionalItems"] = merged( |
| 860 | + [s.get("additionalItems", TRUTHY), oitems] |
| 861 | + ) |
| 862 | + else: |
| 863 | + out["items"] = merged([oitems, sitems]) |
| 864 | + if out["items"] is None: |
| 865 | + return None |
| 866 | + if isinstance(out["items"], list) and None in out["items"]: |
| 867 | + return None |
| 868 | + if out.get("additionalItems", TRUTHY) is None: |
| 869 | + return None |
| 870 | + s.pop("additionalItems", None) |
836 | 871 |
|
837 | 872 | # This loop handles the remaining cases. Notably, we do not attempt to
|
838 | 873 | # merge distinct values for:
|
|
0 commit comments