|
51 | 51 | # Note that in some cases ("dependencies"), the value may be a list of strings. |
52 | 52 | SCHEMA_OBJECT_KEYS = ("properties", "patternProperties", "dependencies") |
53 | 53 | ALL_KEYWORDS = tuple( |
54 | | - ["$schema", *SCHEMA_KEYS, *SCHEMA_OBJECT_KEYS] |
| 54 | + [*SCHEMA_KEYS, *SCHEMA_OBJECT_KEYS] |
55 | 55 | + sum((s.split() for _, s in TYPE_SPECIFIC_KEYS), []) |
56 | 56 | ) |
57 | 57 |
|
@@ -737,15 +737,26 @@ def merged(schemas: List[Any]) -> Optional[Schema]: |
737 | 737 | out["multipleOf"] = max(x, y) |
738 | 738 | else: |
739 | 739 | return None |
740 | | - |
| 740 | + # TODO: merge `contains` schemas when one is a subset of the other |
| 741 | + # TODO: merge `items` schemas or lists-of-schemas |
| 742 | + # TODO: merge `not` schemas as {not: anyOf: [not1, not2]} |
| 743 | + # TODO: merge if/then/else schemas to the chained form |
| 744 | + # or maybe canonicalise them to an anyOf instead? |
| 745 | + # TODO: merge dependencies |
| 746 | + |
| 747 | + # This loop handles the remaining cases. Notably, we do not attempt to |
| 748 | + # merge distinct values for: |
| 749 | + # - `pattern`; computing regex intersection is out of scope |
| 750 | + # - `contains`; requires allOf and thus enters an infinite loop |
| 751 | + # - `$ref`; if not already resolved we can't do that here |
| 752 | + # - `anyOf`; due to product-like explosion in worst case |
| 753 | + # - `oneOf`; which we plan to handle as an anyOf-not composition |
741 | 754 | for k, v in s.items(): |
742 | 755 | if k not in out: |
743 | 756 | out[k] = v |
744 | 757 | elif out[k] != v and k in ALL_KEYWORDS: |
745 | 758 | # If non-validation keys like `title` or `description` don't match, |
746 | 759 | # that doesn't really matter and we'll just go with first we saw. |
747 | | - known = "$ref $schema anyOf oneOf items if not pattern contains" |
748 | | - assert k in known.split(), (k, out[k], v) |
749 | 760 | return None |
750 | 761 | out = canonicalish(out) |
751 | 762 | if out == FALSEY: |
|
0 commit comments