Skip to content

Commit ed4595b

Browse files
committed
Raise a more specific error if Locale.parse() is passed an empty value
1 parent 4d1c882 commit ed4595b

3 files changed

Lines changed: 37 additions & 3 deletions

File tree

babel/core.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,8 @@ def parse(
286286
Locale('de', territory='DE')
287287
288288
If the `identifier` parameter is neither of these, such as `None`
289-
e.g. because a default locale identifier could not be determined,
290-
a `TypeError` is raised:
289+
or an empty string, e.g. because a default locale identifier
290+
could not be determined, a `TypeError` is raised:
291291
292292
>>> Locale.parse(None)
293293
Traceback (most recent call last):
@@ -325,10 +325,23 @@ def parse(
325325
:raise `UnknownLocaleError`: if no locale data is available for the
326326
requested locale
327327
:raise `TypeError`: if the identifier is not a string or a `Locale`
328+
:raise `ValueError`: if the identifier is not a valid string
328329
"""
329330
if isinstance(identifier, Locale):
330331
return identifier
331-
elif not isinstance(identifier, str):
332+
333+
if not identifier:
334+
msg = (
335+
f"Empty locale identifier value: {identifier!r}\n\n"
336+
f"If you didn't explicitly pass an empty value to a Babel function, "
337+
f"this could be caused by there being no suitable locale environment "
338+
f"variables for the API you tried to use.",
339+
)
340+
if isinstance(identifier, str):
341+
raise ValueError(msg) # `parse_locale` would raise a ValueError, so let's do that here
342+
raise TypeError(msg)
343+
344+
if not isinstance(identifier, str):
332345
raise TypeError(f"Unexpected value for identifier: {identifier!r}")
333346

334347
parts = parse_locale(identifier, sep=sep)
@@ -1235,6 +1248,8 @@ def parse_locale(
12351248
:raise `ValueError`: if the string does not appear to be a valid locale
12361249
identifier
12371250
"""
1251+
if not identifier:
1252+
raise ValueError("empty locale identifier")
12381253
identifier, _, modifier = identifier.partition('@')
12391254
if '.' in identifier:
12401255
# this is probably the charset/encoding, which we don't care about

tests/test_core.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ def test_parse_locale():
308308
assert (core.parse_locale('de_DE.iso885915@euro') ==
309309
('de', 'DE', None, None, 'euro'))
310310

311+
with pytest.raises(ValueError, match="empty"):
312+
core.parse_locale("")
313+
311314

312315
@pytest.mark.parametrize('filename', [
313316
'babel/global.dat',
@@ -375,3 +378,12 @@ def test_language_alt_official_not_used():
375378
locale = Locale('mus')
376379
assert locale.get_display_name() == 'Mvskoke'
377380
assert locale.get_display_name(Locale('en')) == 'Muscogee'
381+
382+
383+
def test_locale_parse_empty():
384+
with pytest.raises(ValueError, match="Empty"):
385+
Locale.parse("")
386+
with pytest.raises(TypeError, match="Empty"):
387+
Locale.parse(None)
388+
with pytest.raises(TypeError, match="Empty"):
389+
Locale.parse(False) # weird...!

tests/test_numbers.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,13 @@ def test_format_currency_with_none_locale_with_default(monkeypatch):
492492
assert numbers.format_currency(0, "USD", locale=None) == "0,00\xa0$"
493493

494494

495+
def test_format_currency_with_none_locale(monkeypatch):
496+
"""Test that the API raises the "Empty locale identifier" error when locale is None, and the default is too."""
497+
monkeypatch.setattr(numbers, "LC_NUMERIC", None) # Pretend we couldn't find any locale when importing the module
498+
with pytest.raises(TypeError, match="Empty"):
499+
numbers.format_currency(0, "USD", locale=None)
500+
501+
495502
def test_format_currency_format_type():
496503
assert (numbers.format_currency(1099.98, 'USD', locale='en_US',
497504
format_type="standard")

0 commit comments

Comments
 (0)