Repository: omni-us/jsonargparse
Pull request #551 (2024-07-17 05:18:31)

Fixes related to transformers PreTrainedModel.from_pretrained
## 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)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=omni-us_jsonargparse&pullRequest=551) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=551&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=551&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=omni-us_jsonargparse&pullRequest=551&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=omni-us_jsonargparse&pullRequest=551&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=omni-us_jsonargparse&pullRequest=551&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=omni-us_jsonargparse&pullRequest=551)


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551?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 [(`45044f2`)](https://app.codecov.io/gh/omni-us/jsonargparse/commit/45044f23d3a13648aedb3305933e97e4349e846d?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) to head [(`6189fa5`)](https://app.codecov.io/gh/omni-us/jsonargparse/commit/6189fa5b9c1f1506eefab588c6f4a23b60249db7?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us).

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


```diff
@@            Coverage Diff            @@
##              main      #551   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           22        22           
  Lines         6428      6441   +13     
=========================================
+ Hits          6428      6441   +13     
```

| [Flag](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | Coverage Δ | |
|---|---|---|
| [py3.10](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `85.72% <100.00%> (+0.02%)` | :arrow_up: |
| [py3.10_all](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `98.69% <100.00%> (+<0.01%)` | :arrow_up: |
| [py3.10_pydantic1](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `48.61% <50.00%> (+0.08%)` | :arrow_up: |
| [py3.10_pydantic2](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `48.39% <50.00%> (+0.08%)` | :arrow_up: |
| [py3.10_types](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `98.71% <100.00%> (+<0.01%)` | :arrow_up: |
| [py3.11](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `85.71% <100.00%> (+0.02%)` | :arrow_up: |
| [py3.11_all](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `98.69% <100.00%> (+<0.01%)` | :arrow_up: |
| [py3.11_types](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `98.71% <100.00%> (+<0.01%)` | :arrow_up: |
| [py3.12](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `85.85% <100.00%> (+0.02%)` | :arrow_up: |
| [py3.12_all](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `98.69% <100.00%> (+<0.01%)` | :arrow_up: |
| [py3.12_types](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `98.71% <100.00%> (+<0.01%)` | :arrow_up: |
| [py3.7](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `86.17% <100.00%> (+0.02%)` | :arrow_up: |
| [py3.7_all](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `99.20% <100.00%> (+<0.01%)` | :arrow_up: |
| [py3.7_types](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `99.24% <100.00%> (+<0.01%)` | :arrow_up: |
| [py3.8](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `86.36% <100.00%> (+0.02%)` | :arrow_up: |
| [py3.8_all](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `99.36% <100.00%> (+<0.01%)` | :arrow_up: |
| [py3.8_types](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `99.39% <100.00%> (+<0.01%)` | :arrow_up: |
| [py3.9](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `86.25% <100.00%> (+0.02%)` | :arrow_up: |
| [py3.9_all](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `99.28% <100.00%> (+<0.01%)` | :arrow_up: |
| [py3.9_types](https://app.codecov.io/gh/omni-us/jsonargparse/pull/551/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | `99.30% <100.00%> (+<0.01%)` | :arrow_up: |

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=omni-us#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/omni-us/jsonargparse/pull/551?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).

sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=omni-us_jsonargparse&pullRequest=551) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=551&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=551&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=omni-us_jsonargparse&pullRequest=551&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=omni-us_jsonargparse&pullRequest=551&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=omni-us_jsonargparse&pullRequest=551&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=omni-us_jsonargparse&pullRequest=551)



Patch:
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 7b47285..d07f09b 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -34,9 +34,19 @@ Fixed
 - ``default_config_files`` making parse fail for subcommands and nested subclass
   types (`lightning-forums#5963
   <https://lightning.ai/forums/t/problem-lightningcli-with-default-config-files/5963>`__).
-- Import path of inherited classmethod not resolving correctly (`lightning#19863
-  comment
-  <https://github.com/Lightning-AI/pytorch-lightning/discussions/19863#discussioncomment-10010226>`__).
+- Fixes related to transformers ``PreTrainedModel.from_pretrained``
+  (`lightning#19863 comment
+  <https://github.com/Lightning-AI/pytorch-lightning/discussions/19863#discussioncomment-9821765>`__).
+  - Import path of inherited classmethod not resolving correctly (`#548
+    <https://github.com/omni-us/jsonargparse/pull/548>`__).
+  - Resolved parameters leading to multiple values for keyword argument (`#551
+    <https://github.com/omni-us/jsonargparse/pull/551>`__).
+  - Function with return type a class in ``class_path`` in some cases fails with
+    unexpected ``instantiate`` parameter error (`#551
+    <https://github.com/omni-us/jsonargparse/pull/551>`__).
+  - Ignore incorrectly resolved ``config_file_name`` parameter for transformers
+    model ``from_pretrained``(`#551
+    <https://github.com/omni-us/jsonargparse/pull/551>`__).
 
 
 v4.31.0 (2024-06-27)
diff --git a/jsonargparse/_parameter_resolvers.py b/jsonargparse/_parameter_resolvers.py
index 7ef82c3..29712ea 100644
--- a/jsonargparse/_parameter_resolvers.py
+++ b/jsonargparse/_parameter_resolvers.py
@@ -11,7 +11,7 @@ from copy import deepcopy
 from functools import partial
 from importlib import import_module
 from types import MethodType
-from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union
+from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union
 
 from ._common import (
     LoggerProperty,
@@ -52,6 +52,10 @@ kinds = inspect._ParameterKind
 ast_assign_type: Tuple[Type[ast.AST], ...] = (ast.AnnAssign, ast.Assign)
 param_kwargs_pop_or_get = "**.pop|get():"
 
+ignore_params = {
+    "transformers.BertModel.from_pretrained": {"config_file_name"},
+}
+
 
 class SourceNotAvailable(Exception):
     "Raised when the source code for some component is not available."
@@ -268,11 +272,14 @@ def ast_get_call_keyword_names(node):
     return [kw_node.arg for kw_node in node.keywords if kw_node.arg]
 
 
-def remove_given_parameters(node, params):
+def remove_given_parameters(node, params, removed_params: Optional[set] = None):
     given_args = set(ast_get_call_positional_indexes(node))
     given_kwargs = set(ast_get_call_keyword_names(node))
+    input_params = params
     params = [p for n, p in enumerate(params) if n not in given_args]
     params = [p for p in params if p.name not in given_kwargs]
+    if removed_params is not None and len(params) < len(input_params):
+        removed_params.update(p.name for p in input_params if p.name in given_kwargs)
     return params
 
 
@@ -745,6 +752,7 @@ class ParametersVisitor(LoggerProperty, ast.NodeVisitor):
             return [], []
 
         params_list = []
+        removed_params: Set[str] = set()
         kwargs_value = kwargs_name and values_to_find[kwargs_name]
         kwargs_value_dump = kwargs_value and ast.dump(kwargs_value)
         for node, source in [(v, s) for k, v, s in values_found if k == kwargs_name]:
@@ -768,7 +776,7 @@ class ParametersVisitor(LoggerProperty, ast.NodeVisitor):
                     get_param_args = self.get_node_component(node, source)
                     if get_param_args:
                         params = get_signature_parameters(*get_param_args, logger=self.logger)
-                params = remove_given_parameters(node, params)
+                params = remove_given_parameters(node, params, removed_params)
                 if params:
                     self.add_node_origins(params, node)
                     params_list.append(params)
@@ -783,6 +791,7 @@ class ParametersVisitor(LoggerProperty, ast.NodeVisitor):
                     self.log_debug(f"unsupported type of assign: {ast_str(node)}")
 
         params = group_parameters(params_list)
+        params = [p for p in params if p.name not in removed_params]
         return split_args_and_kwargs(params)
 
     def get_parameters_attr_use_in_members(self, attr_name) -> ParamList:
@@ -826,6 +835,12 @@ class ParametersVisitor(LoggerProperty, ast.NodeVisitor):
             matched = group_parameters(matched)
         return matched or None
 
+    def remove_ignore_parameters(self, params: ParamList) -> ParamList:
+        import_path = get_import_path(self.component)
+        if import_path in ignore_params:
+            params = [p for p in params if p.name not in ignore_params[import_path]]
+        return params
+
     def get_parameters(self) -> ParamList:
         if self.component is None:
             return []
@@ -839,6 +854,7 @@ class ParametersVisitor(LoggerProperty, ast.NodeVisitor):
                 args, kwargs = self.get_parameters_args_and_kwargs()
             params = replace_args_and_kwargs(params, args, kwargs)
         add_stub_types(stubs, params, self.component)
+        params = self.remove_ignore_parameters(params)
         return params
 
 
diff --git a/jsonargparse/_typehints.py b/jsonargparse/_typehints.py
index 19aeb9e..aec416d 100644
--- a/jsonargparse/_typehints.py
+++ b/jsonargparse/_typehints.py
@@ -620,6 +620,7 @@ class ActionTypeHint(Action):
         if inspect.isclass(val_class):
             parser.add_class_arguments(val_class, **kwargs)
         else:
+            kwargs = {k: v for k, v in kwargs.items() if k != "instantiate"}
             parser.add_function_arguments(val_class, **kwargs)
 
         if "linked_targets" in kwargs and parser.required_args:


Test patch:
diff --git a/jsonargparse_tests/test_parameter_resolvers.py b/jsonargparse_tests/test_parameter_resolvers.py
index 9cc6f80..f894eae 100644
--- a/jsonargparse_tests/test_parameter_resolvers.py
+++ b/jsonargparse_tests/test_parameter_resolvers.py
@@ -549,10 +549,11 @@ def function_optional_callable(p1: Optional[Callable] = None, **kw):
     function_no_args_no_kwargs(**kw)
 
 
-def assert_params(params, expected, origins={}):
+def assert_params(params, expected, origins={}, help=True):
     assert expected == [p.name for p in params]
-    docs = [f"help for {p.name}" for p in params] if docstring_parser_support else [None] * len(params)
-    assert docs == [p.doc for p in params]
+    if help:
+        docs = [f"help for {p.name}" for p in params] if docstring_parser_support else [None] * len(params)
+        assert docs == [p.doc for p in params]
     assert all(isinstance(params[n].default, ConditionalDefault) for n in origins.keys())
     param_origins = {
         n: [o.split(f"{__name__}.", 1)[1] for o in p.origin] for n, p in enumerate(params) if p.origin is not None
@@ -876,6 +877,28 @@ def test_get_params_optional_callable():
     assert_params(get_params(function_optional_callable), ["p1", "pk1", "k2"])
 
 
+def func_several_params(p1: int = 1, p2: int = 2, p3: int = 3, p4: int = 4):
+    pass
+
+
+def func_given_kwargs(p: int, **kwargs):
+    func_several_params(p2=0, **kwargs)
+    func_several_params(p4=0, **kwargs)
+
+
+def test_get_params_given_kwargs():
+    assert_params(get_params(func_given_kwargs), ["p", "p1", "p3"], help=False)
+
+
+def test_get_params_some_ignored():
+    with patch.dict(
+        "jsonargparse._parameter_resolvers.ignore_params", {f"{__name__}.func_several_params": {"p2", "p3"}}
+    ):
+        assert_params(get_params(func_several_params), ["p1", "p4"], help=False)
+    with patch.dict("jsonargparse._parameter_resolvers.ignore_params", {f"{__name__}.func_given_kwargs": {"p3"}}):
+        assert_params(get_params(func_given_kwargs), ["p", "p1"], help=False)
+
+
 # unsupported cases