Repository: omni-us/jsonargparse
Pull request #351 (2023-08-15 05:20:52)

New option in dump for including link targets
## Before submitting

- [x] Did you read the [contributing guideline](https://github.com/omni-us/jsonargparse/blob/main/CONTRIBUTING.rst)?
- [x] 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]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=omni-us_jsonargparse&pullRequest=351)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=351&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=351&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=351&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=351&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=351&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=351&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=omni-us_jsonargparse&pullRequest=351&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=omni-us_jsonargparse&pullRequest=351&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=omni-us_jsonargparse&pullRequest=351&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=351&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=351&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=omni-us_jsonargparse&pullRequest=351&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=omni-us_jsonargparse&pullRequest=351) No Coverage information  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=omni-us_jsonargparse&pullRequest=351&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=omni-us_jsonargparse&pullRequest=351&metric=new_duplicated_lines_density&view=list)


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/omni-us/jsonargparse/pull/351?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) Report
Patch coverage: **`100.00%`** and project coverage change: **`-0.11%`** :warning:
> Comparison is base [(`2de91b9`)](https://app.codecov.io/gh/omni-us/jsonargparse/commit/2de91b9209364b748e372a8e85c2d33cbe21a41d?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) 100.00% compared to head [(`65efc75`)](https://app.codecov.io/gh/omni-us/jsonargparse/pull/351?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) 99.89%.

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


```diff
@@             Coverage Diff             @@
##              main     #351      +/-   ##
===========================================
- Coverage   100.00%   99.89%   -0.11%     
===========================================
  Files           21       21              
  Lines         5548     5549       +1     
===========================================
- Hits          5548     5543       -5     
- Misses           0        6       +6     
```

| Flag | Coverage Δ | |
|---|---|---|
| py3.10 | `?` | |
| py3.10_all | `?` | |
| py3.10_types | `?` | |
| py3.11 | `?` | |
| py3.11_all | `?` | |
| py3.11_types | `?` | |
| py3.6 | `85.97% <100.00%> (+<0.01%)` | :arrow_up: |
| py3.6_all | `97.81% <100.00%> (+<0.01%)` | :arrow_up: |
| py3.7 | `87.95% <100.00%> (+<0.01%)` | :arrow_up: |
| py3.7_all | `99.47% <100.00%> (+<0.01%)` | :arrow_up: |
| py3.7_types | `99.45% <100.00%> (+<0.01%)` | :arrow_up: |
| py3.8 | `88.12% <100.00%> (+<0.01%)` | :arrow_up: |
| py3.8_all | `99.54% <100.00%> (+<0.01%)` | :arrow_up: |
| py3.8_types | `99.53% <100.00%> (+<0.01%)` | :arrow_up: |
| py3.9 | `88.05% <100.00%> (+<0.01%)` | :arrow_up: |
| py3.9_all | `?` | |
| py3.9_types | `?` | |

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.

| [Files Changed](https://app.codecov.io/gh/omni-us/jsonargparse/pull/351?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us) | Coverage Δ | |
|---|---|---|
| [jsonargparse/\_core.py](https://app.codecov.io/gh/omni-us/jsonargparse/pull/351?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us#diff-anNvbmFyZ3BhcnNlL19jb3JlLnB5) | `100.00% <100.00%> (ø)` | |

... and [3 files with indirect coverage changes](https://app.codecov.io/gh/omni-us/jsonargparse/pull/351/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=omni-us)


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/omni-us/jsonargparse/pull/351?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 bb1be3f..0c0b0a3 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -12,6 +12,14 @@ The semantic versioning only considers the public API as described in
 paths are considered internals and can change in minor and patch releases.
 
 
+v4.24.0 (2023-08-??)
+--------------------
+
+Added
+^^^^^
+- New option in ``dump`` for including link targets.
+
+
 v4.23.1 (2023-08-04)
 --------------------
 
diff --git a/jsonargparse/_core.py b/jsonargparse/_core.py
index 6a7bc92..8a1562f 100644
--- a/jsonargparse/_core.py
+++ b/jsonargparse/_core.py
@@ -677,6 +677,7 @@ class ArgumentParser(ParserDeprecations, ActionsContainer, ArgumentLinking, argp
         skip_default: bool = False,
         skip_check: bool = False,
         yaml_comments: bool = False,
+        skip_link_targets: bool = True,
     ) -> str:
         """Generates a yaml or json string for the given configuration object.
 
@@ -688,6 +689,7 @@ class ArgumentParser(ParserDeprecations, ActionsContainer, ArgumentLinking, argp
             skip_default: Whether to exclude entries whose value is the same as the default.
             skip_check: Whether to skip parser checking.
             yaml_comments: Whether to add help content as comments. ``yaml_comments=True`` implies ``format='yaml'``.
+            skip_link_targets: Whether to exclude link targets.
 
         Returns:
             The configuration in yaml or json format.
@@ -698,7 +700,8 @@ class ArgumentParser(ParserDeprecations, ActionsContainer, ArgumentLinking, argp
         check_valid_dump_format(format)
 
         cfg = strip_meta(cfg)
-        ActionLink.strip_link_target_keys(self, cfg)
+        if skip_link_targets:
+            ActionLink.strip_link_target_keys(self, cfg)
 
         with parser_context(load_value_mode=self.parser_mode):
             if not skip_check:


Test patch:
diff --git a/jsonargparse_tests/test_link_arguments.py b/jsonargparse_tests/test_link_arguments.py
index 6d7e300..37dc722 100644
--- a/jsonargparse_tests/test_link_arguments.py
+++ b/jsonargparse_tests/test_link_arguments.py
@@ -45,6 +45,10 @@ def test_on_parse_compute_fn_single_arguments(parser, subtests):
         dump = yaml.safe_load(parser.dump(cfg))
         assert dump == {"a": {"v1": 2, "v2": -5}}
 
+    with subtests.test("dump keep target"):
+        dump = yaml.safe_load(parser.dump(cfg, skip_link_targets=False))
+        assert dump == {"a": {"v1": 2, "v2": -5}, "b": {"v2": -10}}
+
     with subtests.test("invalid compute_fn result type"):
         with pytest.raises(ArgumentError) as ctx:
             parser.parse_args(["--a.v1=x"])
@@ -120,6 +124,11 @@ def test_on_parse_add_class_arguments(subtests):
         dump = yaml.safe_load(parser.dump(cfg))
         assert dump == {"a": {"v1": 11, "v2": 7}, "b": {"v3": 2}}
 
+    with subtests.test("dump keep targets"):
+        cfg = parser.parse_args(["--a.v1=11", "--a.v2=7"])
+        dump = yaml.safe_load(parser.dump(cfg, skip_link_targets=False))
+        assert dump == {"a": {"v1": 11, "v2": 7}, "b": {"v3": 2, "v1": 7, "v2": 18}}
+
     with subtests.test("argument error"):
         pytest.raises(ArgumentError, lambda: parser.parse_args(["--b.v1=5"]))
 
@@ -156,6 +165,10 @@ def test_on_parse_add_subclass_arguments(parser, subtests):
         dump = yaml.safe_load(parser.dump(cfg))
         assert dump["c"] == {"class_path": "calendar.Calendar"}
 
+    with subtests.test("dump keep target"):
+        dump = yaml.safe_load(parser.dump(cfg, skip_link_targets=False))
+        assert dump["c"] == {"class_path": "calendar.Calendar", "init_args": {"firstweekday": 4}}
+
     with subtests.test("compute_fn invalid result type"):
         s_value["init_args"] = {"v1": "a", "v2": "b"}
         with pytest.raises(ArgumentError):
@@ -227,6 +240,10 @@ def test_on_parse_add_subclass_arguments_with_instantiate_false(parser, subtests
         dump = yaml.safe_load(parser.dump(cfg))
         assert "c" not in dump["f"]["init_args"]
 
+    with subtests.test("dump keep target"):
+        dump = yaml.safe_load(parser.dump(cfg, skip_link_targets=False))
+        assert dump["f"]["init_args"]["c"] == {"class_path": "calendar.Calendar", "init_args": {"firstweekday": 3}}
+
 
 class ClassD:
     def __init__(