From 38be6085612bd9fb32685014d955b1009a6e4c71 Mon Sep 17 00:00:00 2001 From: Mauricio Villegas <5780272+mauvilsa@users.noreply.github.com> Date: Thu, 6 Aug 2026 05:26:12 +0200 Subject: [PATCH] Misc fixes --- CHANGELOG.rst | 2 + DOCUMENTATION.rst | 4 +- README.rst | 2 +- jsonargparse/_typehints.py | 22 +++++------ .../test_parameter_resolvers.py | 2 +- jsonargparse_tests/test_paths.py | 2 +- jsonargparse_tests/test_typehints.py | 37 +++++++++++++++++++ 7 files changed, 56 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 13dd1380..9fee7f57 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -80,6 +80,8 @@ Changed implementation are accepted. Parameter and return types must still match exactly, except when the protocol has no annotation or ``Any`` (`#941 `__). +- The default print config argument name will remain as ``--print_config`` in + v5.0.0, no longer changing as described in the deprecated section of v4.35.0. v4.50.0 (2026-07-22) diff --git a/DOCUMENTATION.rst b/DOCUMENTATION.rst index 49e2eb6f..f7461ec4 100644 --- a/DOCUMENTATION.rst +++ b/DOCUMENTATION.rst @@ -607,7 +607,9 @@ Some notes about this support are: names must be builtins, ``typing`` names or dot import paths. - ``TypeAliasType`` is supported with values parsed as the aliased type and the - alias shown as the argument type in help. + alias shown as the argument type in help. This includes aliases defined with + the `PEP 695 `__ ``type X = ...`` statement + (python 3.12+) and aliases created with ``typing_extensions.TypeAliasType``. .. _restricted-numbers: diff --git a/README.rst b/README.rst index b661bb95..9aa0dffa 100644 --- a/README.rst +++ b/README.rst @@ -4,7 +4,7 @@ :target: https://github.com/mauvilsa/jsonargparse/actions/workflows/tests.yaml .. image:: https://codecov.io/gh/mauvilsa/jsonargparse/branch/main/graph/badge.svg :target: https://codecov.io/gh/mauvilsa/jsonargparse -.. image:: https://sonarcloud.io/api/project_badges/measure?project=mauvilsa_jsonargparse&metric=alert_status +.. image:: https://sonarcloud.io/api/project_badges/measure?project=mauvilsa_jsonargparse&metric=alert_status&token=74f3ff0af709f6caa0544dfbcf823c49fb68cb46 :target: https://sonarcloud.io/dashboard?id=mauvilsa_jsonargparse .. image:: https://badge.fury.io/py/jsonargparse.svg :target: https://badge.fury.io/py/jsonargparse diff --git a/jsonargparse/_typehints.py b/jsonargparse/_typehints.py index ab940944..2e1d1293 100644 --- a/jsonargparse/_typehints.py +++ b/jsonargparse/_typehints.py @@ -1195,21 +1195,20 @@ def adapt_typehints( # Module elif typehint is ModuleType: - if serialize: - if isinstance(val, ModuleType): + if isinstance(val, ModuleType): + if serialize: val = val.__name__ - elif not isinstance(val, ModuleType): - if not is_importable_module_path(val): - raise_unexpected_value("Expected an import path corresponding to a module", val) - if instantiate_classes: - val = import_module(val) + elif not is_importable_module_path(val): + raise_unexpected_value("Expected an import path corresponding to a module", val) + elif instantiate_classes: + val = import_module(val) # UnionType and GenericAlias elif typehint in type_expression_types: - if serialize: - if isinstance(val, typehint): + if isinstance(val, typehint): + if serialize: val = str(val) - elif not isinstance(val, typehint): + else: expected = f"Expected a string with a {type_expression_types[typehint]} type expression" try: type_expression = str_to_type_expression(val) @@ -1217,7 +1216,8 @@ def adapt_typehints( raise_unexpected_value(expected, val, ex) if not isinstance(type_expression, typehint): raise_unexpected_value(expected, val) - val = type_expression + if not serialize: + val = type_expression # Union elif typehint_origin == Union: diff --git a/jsonargparse_tests/test_parameter_resolvers.py b/jsonargparse_tests/test_parameter_resolvers.py index 726649a2..c9f7e4fa 100644 --- a/jsonargparse_tests/test_parameter_resolvers.py +++ b/jsonargparse_tests/test_parameter_resolvers.py @@ -1037,7 +1037,7 @@ class _ConcreteImpl: """Implements _NonRTCheckableProtocol structurally.""" def execute(self) -> None: - pass + pass # pragma: no cover class _DoesNotImpl: diff --git a/jsonargparse_tests/test_paths.py b/jsonargparse_tests/test_paths.py index 414b8138..595656b6 100644 --- a/jsonargparse_tests/test_paths.py +++ b/jsonargparse_tests/test_paths.py @@ -611,7 +611,7 @@ def __init__(self, objects: List[ItemBase] = []): class ItemsDictMain: def __init__(self, objects: Optional[Dict[str, ItemBase]] = None): - self.objects = objects + self.objects = objects # pragma: no cover item1_spec = {"class_path": f"{__name__}.ItemSub", "init_args": {"x": 2, "y": "a"}} diff --git a/jsonargparse_tests/test_typehints.py b/jsonargparse_tests/test_typehints.py index a7e3f767..d2a88f21 100644 --- a/jsonargparse_tests/test_typehints.py +++ b/jsonargparse_tests/test_typehints.py @@ -922,6 +922,24 @@ def test_module_type_dump_module_object(parser): assert json_or_yaml_load(parser.dump(cfg)) == {"mod": "json"} +def test_module_type_union_with_callable_dump(parser): + parser.add_argument("--val", type=Union[ModuleType, Callable]) + cfg = parser.parse_args(["--val=uuid.uuid4"]) + assert json_or_yaml_load(parser.dump(cfg)) == {"val": "uuid.uuid4"} + + +class WithCallableDefault: + def __init__(self, cb: Callable = uuid.uuid4): + self.cb = cb + + +def test_module_type_union_with_class_dump(parser): + parser.add_argument("--val", type=Union[ModuleType, WithCallableDefault]) + cfg = parser.parse_args([f"--val={__name__}.WithCallableDefault"]) + expected = {"class_path": f"{__name__}.WithCallableDefault", "init_args": {"cb": "uuid.uuid4"}} + assert json_or_yaml_load(parser.dump(cfg)) == {"val": expected} + + def test_module_type_help(parser): parser.add_argument("--mod", type=ModuleType, help="Module to use.") help_str = get_parser_help(parser) @@ -995,6 +1013,19 @@ def test_union_type_optional(parser): assert parser.parse_args(["--type=int | str"]).type == int | str +def test_union_type_dump_type_expression_string(parser): + parser.add_argument("--type", type=UnionType) + cfg = parser.parse_args(["--type=int | str"]) + cfg.type = "int | str" + assert json_or_yaml_load(parser.dump(cfg)) == {"type": "int | str"} + + +def test_union_type_union_with_callable_dump(parser): + parser.add_argument("--val", type=Union[UnionType, Callable]) + cfg = parser.parse_args(["--val=uuid.uuid4"]) + assert json_or_yaml_load(parser.dump(cfg)) == {"val": "uuid.uuid4"} + + def test_union_type_help(parser): parser.add_argument("--type", type=UnionType, help="Type to use.") help_str = get_parser_help(parser) @@ -1025,6 +1056,12 @@ def test_generic_alias_dump(parser): assert json_or_yaml_load(parser.dump(cfg)) == {"type": "dict[str, int]"} +def test_generic_alias_union_with_callable_dump(parser): + parser.add_argument("--val", type=Union[GenericAlias, Callable]) + cfg = parser.parse_args(["--val=uuid.uuid4"]) + assert json_or_yaml_load(parser.dump(cfg)) == {"val": "uuid.uuid4"} + + def test_generic_alias_help(parser): parser.add_argument("--type", type=GenericAlias, help="Type to use.") help_str = get_parser_help(parser)