From: Aarni Koskela Date: Wed, 8 Jan 2025 13:37:19 +0000 (+0200) Subject: Raise a more specific error if `Locale.parse()` is passed an empty value X-Git-Tag: v2.17.0~11^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ed4595bb6a60dec283491d3176f1e4c8c3a892ba;p=thirdparty%2Fbabel.git Raise a more specific error if `Locale.parse()` is passed an empty value --- diff --git a/babel/core.py b/babel/core.py index a2e1e1de..e3fb7c8f 100644 --- a/babel/core.py +++ b/babel/core.py @@ -286,8 +286,8 @@ class Locale: Locale('de', territory='DE') If the `identifier` parameter is neither of these, such as `None` - e.g. because a default locale identifier could not be determined, - a `TypeError` is raised: + or an empty string, e.g. because a default locale identifier + could not be determined, a `TypeError` is raised: >>> Locale.parse(None) Traceback (most recent call last): @@ -325,10 +325,23 @@ class Locale: :raise `UnknownLocaleError`: if no locale data is available for the requested locale :raise `TypeError`: if the identifier is not a string or a `Locale` + :raise `ValueError`: if the identifier is not a valid string """ if isinstance(identifier, Locale): return identifier - elif not isinstance(identifier, str): + + if not identifier: + msg = ( + f"Empty locale identifier value: {identifier!r}\n\n" + f"If you didn't explicitly pass an empty value to a Babel function, " + f"this could be caused by there being no suitable locale environment " + f"variables for the API you tried to use.", + ) + if isinstance(identifier, str): + raise ValueError(msg) # `parse_locale` would raise a ValueError, so let's do that here + raise TypeError(msg) + + if not isinstance(identifier, str): raise TypeError(f"Unexpected value for identifier: {identifier!r}") parts = parse_locale(identifier, sep=sep) @@ -1235,6 +1248,8 @@ def parse_locale( :raise `ValueError`: if the string does not appear to be a valid locale identifier """ + if not identifier: + raise ValueError("empty locale identifier") identifier, _, modifier = identifier.partition('@') if '.' in identifier: # this is probably the charset/encoding, which we don't care about diff --git a/tests/test_core.py b/tests/test_core.py index 21debf6c..2dc571f5 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -308,6 +308,9 @@ def test_parse_locale(): assert (core.parse_locale('de_DE.iso885915@euro') == ('de', 'DE', None, None, 'euro')) + with pytest.raises(ValueError, match="empty"): + core.parse_locale("") + @pytest.mark.parametrize('filename', [ 'babel/global.dat', @@ -375,3 +378,12 @@ def test_language_alt_official_not_used(): locale = Locale('mus') assert locale.get_display_name() == 'Mvskoke' assert locale.get_display_name(Locale('en')) == 'Muscogee' + + +def test_locale_parse_empty(): + with pytest.raises(ValueError, match="Empty"): + Locale.parse("") + with pytest.raises(TypeError, match="Empty"): + Locale.parse(None) + with pytest.raises(TypeError, match="Empty"): + Locale.parse(False) # weird...! diff --git a/tests/test_numbers.py b/tests/test_numbers.py index 6828d243..9787afd1 100644 --- a/tests/test_numbers.py +++ b/tests/test_numbers.py @@ -492,6 +492,13 @@ def test_format_currency_with_none_locale_with_default(monkeypatch): assert numbers.format_currency(0, "USD", locale=None) == "0,00\xa0$" +def test_format_currency_with_none_locale(monkeypatch): + """Test that the API raises the "Empty locale identifier" error when locale is None, and the default is too.""" + monkeypatch.setattr(numbers, "LC_NUMERIC", None) # Pretend we couldn't find any locale when importing the module + with pytest.raises(TypeError, match="Empty"): + numbers.format_currency(0, "USD", locale=None) + + def test_format_currency_format_type(): assert (numbers.format_currency(1099.98, 'USD', locale='en_US', format_type="standard")