Repository: python-babel/babel
Pull request #1130 (2024-09-22 13:49:12)

Replace `str.index` with `str.find`
`str.index` raises a `ValueError` when the substring is not found so there is no way to even check the return value as the code currently tries to do. Replacing it with `str.find` makes the code work as intended.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/python-babel/babel/pull/1130?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 90.19%. Comparing base [(`f91754b`)](https://app.codecov.io/gh/python-babel/babel/commit/f91754b01cb9f32b83aeaa80b74ed10b5dfccb6a?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) to head [(`be2709c`)](https://app.codecov.io/gh/python-babel/babel/commit/be2709cb3f7f8443e5de1863597d5572fbb01abc?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #1130      +/-   ##
==========================================
- Coverage   91.26%   90.19%   -1.07%     
==========================================
  Files          27       27              
  Lines        4602     4602              
==========================================
- Hits         4200     4151      -49     
- Misses        402      451      +49     
```

| [Flag](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | Coverage Δ | |
|---|---|---|
| [macos-12-3.10](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [macos-12-3.11](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [macos-12-3.12](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [macos-12-3.13-dev](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [macos-12-3.8](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [macos-12-3.9](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [macos-12-pypy3.10](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [ubuntu-22.04-3.10](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `90.11% <100.00%> (+0.02%)` | :arrow_up: |
| [ubuntu-22.04-3.11](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [ubuntu-22.04-3.12](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [ubuntu-22.04-3.13-dev](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [ubuntu-22.04-3.8](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [ubuntu-22.04-3.9](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `90.04% <100.00%> (+0.02%)` | :arrow_up: |
| [ubuntu-22.04-pypy3.10](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [windows-2022-3.10](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [windows-2022-3.11](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [windows-2022-3.12](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [windows-2022-3.13-dev](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [windows-2022-3.8](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [windows-2022-3.9](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |
| [windows-2022-pypy3.10](https://app.codecov.io/gh/python-babel/babel/pull/1130/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel) | `?` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/python-babel/babel/pull/1130?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=python-babel).


Patch:
diff --git a/babel/dates.py b/babel/dates.py
index 3373e06..4b2cad6 100644
--- a/babel/dates.py
+++ b/babel/dates.py
@@ -1232,7 +1232,7 @@ def parse_date(
 
     format_str = get_date_format(format=format, locale=locale).pattern.lower()
     year_idx = format_str.index('y')
-    month_idx = format_str.index('m')
+    month_idx = format_str.find('m')
     if month_idx < 0:
         month_idx = format_str.index('l')
     day_idx = format_str.index('d')
@@ -1277,7 +1277,7 @@ def parse_time(
 
     # TODO: try ISO format first?
     format_str = get_time_format(format=format, locale=locale).pattern.lower()
-    hour_idx = format_str.index('h')
+    hour_idx = format_str.find('h')
     if hour_idx < 0:
         hour_idx = format_str.index('k')
     min_idx = format_str.index('m')


Test patch:
diff --git a/tests/test_dates.py b/tests/test_dates.py
index 31ac782..58e82ad 100644
--- a/tests/test_dates.py
+++ b/tests/test_dates.py
@@ -17,7 +17,7 @@ import freezegun
 import pytest
 
 from babel import Locale, dates
-from babel.dates import NO_INHERITANCE_MARKER, UTC, _localize
+from babel.dates import NO_INHERITANCE_MARKER, UTC, _localize, parse_pattern
 from babel.util import FixedOffsetTimezone
 
 
@@ -666,6 +666,24 @@ def test_parse_time(input, expected):
     assert dates.parse_time(input, locale='en_US') == expected
 
 
+def test_parse_time_alternate_characters(monkeypatch):
+    # 'K' can be used as an alternative to 'H'
+    def get_time_format(*args, **kwargs):
+        return parse_pattern('KK:mm:ss')
+    monkeypatch.setattr(dates, 'get_time_format', get_time_format)
+
+    assert dates.parse_time('9:30') == time(9, 30)
+
+
+def test_parse_date_alternate_characters(monkeypatch):
+    # 'l' can be used as an alternative to 'm'
+    def get_date_format(*args, **kwargs):
+        return parse_pattern('yyyy-ll-dd')
+    monkeypatch.setattr(dates, 'get_time_format', get_date_format)
+
+    assert dates.parse_date('2024-10-20') == date(2024, 10, 20)
+
+
 @pytest.mark.parametrize('case', ['', 'a', 'aaa'])
 @pytest.mark.parametrize('func', [dates.parse_date, dates.parse_time])
 def test_parse_errors(case, func):