diff --git a/src/werkzeug/datastructures.py b/src/werkzeug/datastructures.py index 9cfa1eb132..89e8414e36 100644 --- a/src/werkzeug/datastructures.py +++ b/src/werkzeug/datastructures.py @@ -1849,6 +1849,19 @@ def _normalize(language): return item == "*" or _normalize(value) == _normalize(item) + def best_match(self, matches, default=None): + """Calls the super version of `best_match` and if it returns none, + attempts to fall back to language only matches. + + :param matches: a list of matches to check for + :param default: the value that is returned if none match + """ + result = super(LanguageAccept, self).best_match(matches) + if result is not None: + return result + fallback = Accept([(item[0][0:2], item[1]) for item in self]) + return fallback.best_match(matches, default=default) + class CharsetAccept(Accept): """Like :class:`Accept` but with normalization for charsets.""" diff --git a/tests/test_datastructures.py b/tests/test_datastructures.py index bf6b3f7ccf..836106c94d 100644 --- a/tests/test_datastructures.py +++ b/tests/test_datastructures.py @@ -1074,6 +1074,35 @@ def test_accept_wildcard_specificity(self): assert accept.best_match(["text/plain", "image/png"]) == "image/png" +class TestLanguageAccept(object): + storage_class = datastructures.LanguageAccept + + def test_best_match_fallback(self): + accept = self.storage_class([("en-us", 1)]) + assert accept.best_match(["en"]) == "en" + + accept = self.storage_class([("de_AT", 1), ("de", 0.9)]) + assert accept.best_match(["en"]) is None + + accept = self.storage_class([("de_AT", 1), ("de", 0.9), ("en-US", 0.8)]) + assert accept.best_match(["de", "en"]) == "de" + + accept = self.storage_class([("de_AT", 0.9), ("en-US", 1)]) + assert accept.best_match(["en"]) == "en" + + accept = self.storage_class([("en-us", 1)]) + assert accept.best_match(["en-us"]) == "en-us" + + accept = self.storage_class([("en-us", 1)]) + assert accept.best_match(["en-us", "en"]) == "en-us" + + accept = self.storage_class([("en-GB", 1)]) + assert accept.best_match(["en-US", "en"], default="en-US") == "en" + + accept = self.storage_class([("de-AT", 1)]) + assert accept.best_match(["en-US", "en"], default="en-US") == "en-US" + + class TestFileStorage(object): storage_class = datastructures.FileStorage