Repository: omni-us/jsonargparse
Pull request #674 (2025-02-10 05:40:41)

Fix string parsing regressions
## Before submitting

- [x] Did you read the [contributing guideline](https://github.com/omni-us/jsonargparse/blob/main/CONTRIBUTING.rst)?
- [n/a] Did you update **the documentation**? (readme and public docstrings)
- [x] Did you write **unit tests** such that there is 100% coverage on related code? (required for bug fixes and new features)
- [x] Did you verify that new and existing **tests pass locally**?
- [x] Did you make sure that all changes preserve **backward compatibility**?
- [x] Did you update **the CHANGELOG**? (not for typos, docs, test updates, or minor internal changes/refactors)


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/omni-us/jsonargparse/pull/674?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 100.00%. Comparing base [(`19d7f61`)](https://app.codecov.io/gh/omni-us/jsonargparse/commit/19d7f61daf3e4d1930dc3217462ce69953de013d?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) to head [(`9f200d0`)](https://app.codecov.io/gh/omni-us/jsonargparse/commit/9f200d02f0937cd55d2b3a742ee61da43b84bd57?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us).
> Report is 4 commits behind head on main.

:white_check_mark: All tests successful. No failed tests found.

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


```diff
@@            Coverage Diff            @@
##              main      #674   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           22        22           
  Lines         6678      6686    +8     
=========================================
+ Hits          6678      6686    +8     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/omni-us/jsonargparse/pull/674?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us).   
: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=omni-us).


Patch:
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 8aab1a3..58723e5 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -31,8 +31,9 @@ Fixed
   <https://github.com/omni-us/jsonargparse/pull/668>`__)
 - Functions that create types now have ``TypeAlias`` return type to avoid mypy
   errors (`#671 <https://github.com/omni-us/jsonargparse/pull/671>`__).
-- Bug when parsing strings with digits and a starting or ending 'e' (`#672
-  <https://github.com/omni-us/jsonargparse/pull/673>`__).
+- String parsing regressions (`#673
+  <https://github.com/omni-us/jsonargparse/pull/673>`__, `#674
+  <https://github.com/omni-us/jsonargparse/pull/674>`__).
 
 
 v4.36.0 (2025-01-17)
diff --git a/jsonargparse/_loaders_dumpers.py b/jsonargparse/_loaders_dumpers.py
index b8254be..c551684 100644
--- a/jsonargparse/_loaders_dumpers.py
+++ b/jsonargparse/_loaders_dumpers.py
@@ -28,15 +28,15 @@ def load_basic(value):
         return False
     if value == "null":
         return None
-    if value.isdigit() or (value.startswith("-") and value[1:].isdigit()):
-        return int(value)
-    if (
-        not value.startswith("e")
-        and not value.endswith("e")
-        and value.replace(".", "", 1).replace("e", "", 1).replace("-", "", 2).isdigit()
-        and ("e" in value or "." in value)
-    ):
-        return float(value)
+    try:
+        if value.isdigit() or (value.startswith("-") and value[1:].isdigit()):
+            return int(value)
+        if value.replace(".", "", 1).replace("e", "", 1).replace("-", "", 2).isdigit() and (
+            "e" in value or "." in value
+        ):
+            return float(value)
+    except ValueError:
+        pass
     return not_loaded
 
 
diff --git a/jsonargparse/_typehints.py b/jsonargparse/_typehints.py
index b3c72bf..e120f7a 100644
--- a/jsonargparse/_typehints.py
+++ b/jsonargparse/_typehints.py
@@ -602,11 +602,20 @@ class ActionTypeHint(Action):
                     val["__path__"] = config_path
                 value[num] = val
             except (TypeError, ValueError) as ex:
-                elem = "" if not islist else f" element {num+1}"
-                error = indent_text(str(ex))
-                raise TypeError(f'Parser key "{self.dest}"{elem}:\n{error}') from ex
+                if self._is_valid_string(val):
+                    value[num] = val
+                else:
+                    elem = "" if not islist else f" element {num+1}"
+                    error = indent_text(str(ex))
+                    raise TypeError(f'Parser key "{self.dest}"{elem}:\n{error}') from ex
         return value if islist else value[0]
 
+    def _is_valid_string(self, value):
+        typehint = self._typehint
+        return isinstance(value, str) and (
+            typehint is str or (get_typehint_origin(typehint) == Union and str in typehint.__args__)
+        )
+
     def instantiate_classes(self, value):
         islist = _is_action_value_list(self)
         if not islist:


Test patch:
diff --git a/jsonargparse_tests/test_loaders_dumpers.py b/jsonargparse_tests/test_loaders_dumpers.py
index 9ba357d..56c9e6b 100644
--- a/jsonargparse_tests/test_loaders_dumpers.py
+++ b/jsonargparse_tests/test_loaders_dumpers.py
@@ -91,12 +91,6 @@ def test_dump_header_invalid(parser):
         parser.dump_header = True
 
 
-def test_load_value_digits_and_e():
-    with parser_context(load_value_mode="yaml"):
-        assert "e123" == load_value("e123")
-        assert "123e" == load_value("123e")
-
-
 @skip_if_no_pyyaml
 def test_load_value_dash():
     with parser_context(load_value_mode="yaml"):
diff --git a/jsonargparse_tests/test_typehints.py b/jsonargparse_tests/test_typehints.py
index 87c5d8b..6181488 100644
--- a/jsonargparse_tests/test_typehints.py
+++ b/jsonargparse_tests/test_typehints.py
@@ -109,6 +109,15 @@ def test_str_yaml_constructor_error(parser):
     assert "{{something}}" == parser.parse_args(["--val={{something}}"]).val
 
 
+@parser_modes
+def test_str_edge_cases(parser):
+    parser.add_argument("--val", type=str)
+    assert parser.parse_args(["--val=e123"]).val == "e123"
+    assert parser.parse_args(["--val=123e"]).val == "123e"
+    val = "1" * 5000
+    assert parser.parse_args([f"--val={val}"]).val == val
+
+
 def test_bool_parse(parser):
     parser.add_argument("--val", type=bool)
     assert None is parser.get_defaults().val