]> git.ipfire.org Git - thirdparty/babel.git/commitdiff
Raise a more specific error if `Locale.parse()` is passed an empty value
authorAarni Koskela <akx@iki.fi>
Wed, 8 Jan 2025 13:37:19 +0000 (15:37 +0200)
committerAarni Koskela <akx@iki.fi>
Thu, 9 Jan 2025 12:35:40 +0000 (14:35 +0200)
babel/core.py
tests/test_core.py
tests/test_numbers.py

index a2e1e1de507d94ebfd733246ead134fdedd5d780..e3fb7c8f732d1698c204cbe1ee7af5a14af949f7 100644 (file)
@@ -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
index 21debf6c9e0a08a07f80bda7f56034ec31435230..2dc571f5da1173d8c8add222402cc8ea405bf5bb 100644 (file)
@@ -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...!
index 6828d2434fa413c0826ac4b251b61796c998fe93..9787afd165dfb9ff6aeb13020f8d1a82eb482f6f 100644 (file)
@@ -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")