@@ -223,10 +223,68 @@ def get_form_media_one_of_match(
223223 if self .schema is None or "oneOf" not in self .schema :
224224 return None
225225
226+ matches : list [FormMediaSchemaMatch ] = []
226227 for subschema in self .schema / "oneOf" :
227228 match = self .get_form_media_schema_match (subschema , location )
228229 if match is not None :
229- return match
230+ matches .append (match )
231+
232+ if len (matches ) == 1 :
233+ return matches [0 ]
234+
235+ return self .get_preferred_form_media_one_of_match (matches )
236+
237+ def get_preferred_form_media_one_of_match (
238+ self ,
239+ matches : list [FormMediaSchemaMatch ],
240+ ) -> Optional [FormMediaSchemaMatch ]:
241+ if len (matches ) < 2 :
242+ return None
243+
244+ preferred_match = matches [0 ]
245+ for match in matches [1 :]:
246+ preferred_match = self .prefer_form_media_one_of_match (
247+ preferred_match ,
248+ match ,
249+ )
250+ if preferred_match is None :
251+ return None
252+
253+ return preferred_match
254+
255+ def prefer_form_media_one_of_match (
256+ self ,
257+ current : FormMediaSchemaMatch ,
258+ new : FormMediaSchemaMatch ,
259+ ) -> Optional [FormMediaSchemaMatch ]:
260+ current_keys = set (current .decoded_candidate )
261+ new_keys = set (new .decoded_candidate )
262+ if current_keys != new_keys :
263+ return None
264+
265+ preferred = current
266+ preferred_has_binary = False
267+
268+ for prop_name in current_keys :
269+ current_value = current .decoded_candidate [prop_name ]
270+ new_value = new .decoded_candidate [prop_name ]
271+
272+ if current_value == new_value :
273+ continue
274+
275+ if isinstance (current_value , bytes ) and isinstance (new_value , str ):
276+ preferred_has_binary = True
277+ continue
278+
279+ if isinstance (current_value , str ) and isinstance (new_value , bytes ):
280+ preferred = new
281+ preferred_has_binary = True
282+ continue
283+
284+ return None
285+
286+ if preferred_has_binary :
287+ return preferred
230288
231289 return None
232290
0 commit comments