Repository: bskinn/sphobjinv (language: python)

Issue:
Consider uploading source dist (aka. "sdist") to PyPI
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is. E.g., I'm always frustrated when [...] -->

I'm trying to create a conda package for this utility.  The recommended way to get this done is via [grayskull](https://github.com/conda-incubator/grayskull).  For that tool to correctly operate, it requires the sdist package to be uploaded to PyPI.

**Describe the solution you'd like**
<!-- A clear and concise description of what you want to happen. -->

Include the "sdist" source package when you do PyPI uploads of new releases.

**Describe alternatives you've considered**
<!-- A clear and concise description of any alternative solutions or features you've considered, if any. -->

Currently, I got away with conda-packaging using GitHub's archive for extracting the tarball of the latest release.  It works, but a cleaner cut would be to have the sdist regularly uploaded to PyPI.

**Additional context**
<!--
  Add any other context or screenshots about the feature request here. If there's a
  specific inventory file that helps demonstrate the behavior you want, attach it here.
-->

Consider uploading source dist (aka. "sdist") to PyPI
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is. E.g., I'm always frustrated when [...] -->

I'm trying to create a conda package for this utility.  The recommended way to get this done is via [grayskull](https://github.com/conda-incubator/grayskull).  For that tool to correctly operate, it requires the sdist package to be uploaded to PyPI.

**Describe the solution you'd like**
<!-- A clear and concise description of what you want to happen. -->

Include the "sdist" source package when you do PyPI uploads of new releases.

**Describe alternatives you've considered**
<!-- A clear and concise description of any alternative solutions or features you've considered, if any. -->

Currently, I got away with conda-packaging using GitHub's archive for extracting the tarball of the latest release.  It works, but a cleaner cut would be to have the sdist regularly uploaded to PyPI.

**Additional context**
<!--
  Add any other context or screenshots about the feature request here. If there's a
  specific inventory file that helps demonstrate the behavior you want, attach it here.
-->



Discussion / hints:
For that to be properly tested on conda-forge, both `tests/` and `conftest.py` must be included with the source distribution.
Very cool! Thanks for the work to get this up on conda -- I'd considered doing it myself, so I really appreciate you working on it.

Should be easy enough to do... I'll make sure that both `conftest.py` and `tests/` are in the dist, as you indicate.

Logistically, what's the best way to proceed to make sure that I've packaged everything you need into the sdists? Can I provide you with tarballs via a side channel (attaching them to this issue?) for you to test, or do they have to be mediated through PyPI?

Also, which versions would you like sdists for? v2.3 as the latest, obviously -- how far back would be good?

It looks like I stopped uploading sdists after v2.0.1 (which was the point where I realized that I'd been uploading broken sdists... hm, I should look into whether I can yank individual files...), so it would be pretty clean for me to go all the way back to v2.1.


Before I test the PyPI sdists, I'd like to get a functional build, including testing.  However, I'm stuck getting this package to test properly (in a conda-build environment):  I have a few pytest markers missing (`pytest.mark.api` and `pytest.mark.cli`).  Where are these coming from?

```
+ pytest -rsxX -Werror
============================= test session starts ==============================
platform darwin -- Python 3.11.0, pytest-7.2.0, pluggy-1.0.0
rootdir: $SRC_DIR
plugins: timeout-2.1.0, ordering-0.6
collected 291 items / 8 errors

==================================== ERRORS ====================================
___________________ ERROR collecting tests/test_api_fail.py ____________________
tests/test_api_fail.py:41: in <module>
    pytestmark = [pytest.mark.api, pytest.mark.local]
../_test_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_/lib/python3.11/site-packages/_pytest/mark/structures.py:544: in __getattr__
    warnings.warn(
E   pytest.PytestUnknownMarkWarning: Unknown pytest.mark.api - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/how-to/mark.html
```

Any ideas?
Mmm, those live in [`tox.ini`][tox_ini] -- I'll have to make sure that's in the manifest.

Ah: the `doc/source` directory, too -- the test suite requires a fresh build of the Sphinx docs (`cd doc; make html`) in order to function correctly.

Probably `requirements-(dev|flake8).txt`, too.


[tox_ini]: https://github.com/bskinn/sphobjinv/blob/1cce07bcbab45ace83c7c6e3c530bf4a44c57cde/tox.ini#L114-L125
I'm finishing the bskinn/stdio-mgr packaging, which is required to test this package (I took the liberty to add you as a maintainer, since you showed interest).  I'll upload that first in a bit.
Here, for your reference: https://github.com/conda-forge/staged-recipes/pull/21238
Cool! Hopefully that v1.0.1 sdist is functional, my packaging config was incorrect for a while.

The Azure pipelines seem content enough... though, oof -- not surprising that the logging got fouled up, what with how the `stdio-mgr` test suite mucks about with stdio. 
One thing to watch out for, potentially -- `sphobjinv` >=2.2 *does* have a vendored dependency, an old copy of fuzzywuzzy. [I *do* have the relevant LICENSE.txt in the source tree][fuzzywuzzy-src-tree]... I'll make sure that makes it into the sdist.


[fuzzywuzzy-src-tree]: https://github.com/bskinn/sphobjinv/tree/main/src/sphobjinv/_vendored/fuzzywuzzy
For that to be properly tested on conda-forge, both `tests/` and `conftest.py` must be included with the source distribution.
Very cool! Thanks for the work to get this up on conda -- I'd considered doing it myself, so I really appreciate you working on it.

Should be easy enough to do... I'll make sure that both `conftest.py` and `tests/` are in the dist, as you indicate.

Logistically, what's the best way to proceed to make sure that I've packaged everything you need into the sdists? Can I provide you with tarballs via a side channel (attaching them to this issue?) for you to test, or do they have to be mediated through PyPI?

Also, which versions would you like sdists for? v2.3 as the latest, obviously -- how far back would be good?

It looks like I stopped uploading sdists after v2.0.1 (which was the point where I realized that I'd been uploading broken sdists... hm, I should look into whether I can yank individual files...), so it would be pretty clean for me to go all the way back to v2.1.


Before I test the PyPI sdists, I'd like to get a functional build, including testing.  However, I'm stuck getting this package to test properly (in a conda-build environment):  I have a few pytest markers missing (`pytest.mark.api` and `pytest.mark.cli`).  Where are these coming from?

```
+ pytest -rsxX -Werror
============================= test session starts ==============================
platform darwin -- Python 3.11.0, pytest-7.2.0, pluggy-1.0.0
rootdir: $SRC_DIR
plugins: timeout-2.1.0, ordering-0.6
collected 291 items / 8 errors

==================================== ERRORS ====================================
___________________ ERROR collecting tests/test_api_fail.py ____________________
tests/test_api_fail.py:41: in <module>
    pytestmark = [pytest.mark.api, pytest.mark.local]
../_test_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_/lib/python3.11/site-packages/_pytest/mark/structures.py:544: in __getattr__
    warnings.warn(
E   pytest.PytestUnknownMarkWarning: Unknown pytest.mark.api - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/how-to/mark.html
```

Any ideas?
Mmm, those live in [`tox.ini`][tox_ini] -- I'll have to make sure that's in the manifest.

Ah: the `doc/source` directory, too -- the test suite requires a fresh build of the Sphinx docs (`cd doc; make html`) in order to function correctly.

Probably `requirements-(dev|flake8).txt`, too.


[tox_ini]: https://github.com/bskinn/sphobjinv/blob/1cce07bcbab45ace83c7c6e3c530bf4a44c57cde/tox.ini#L114-L125
I'm finishing the bskinn/stdio-mgr packaging, which is required to test this package (I took the liberty to add you as a maintainer, since you showed interest).  I'll upload that first in a bit.
Here, for your reference: https://github.com/conda-forge/staged-recipes/pull/21238
Cool! Hopefully that v1.0.1 sdist is functional, my packaging config was incorrect for a while.

The Azure pipelines seem content enough... though, oof -- not surprising that the logging got fouled up, what with how the `stdio-mgr` test suite mucks about with stdio. 
One thing to watch out for, potentially -- `sphobjinv` >=2.2 *does* have a vendored dependency, an old copy of fuzzywuzzy. [I *do* have the relevant LICENSE.txt in the source tree][fuzzywuzzy-src-tree]... I'll make sure that makes it into the sdist.


[fuzzywuzzy-src-tree]: https://github.com/bskinn/sphobjinv/tree/main/src/sphobjinv/_vendored/fuzzywuzzy

Fix patch:
diff --git a/.gitattributes b/.gitattributes
index 89af26e..c6f20db 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,2 @@
 tests/resource/objects_mkdoc_zlib0.inv binary
-
+tests/resource/objects_attrs.txt binary
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d941a96..2c26b9e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,12 @@ and this project strives to adhere to
   * The 'suggest' CLI mode output now includes dividers for improved
     readability.
 
+#### Tests
+
+  * The README doctests and shell tests have been removed from the default
+    pytest suite. They must be explicitly opted-in with the `--readme` and
+    `--doctest-glob="README.rst"` flags to pytest.
+
 #### Internal
 
   * The `sys.exit()` in the case of no objects falling above the 'suggest' search threshold was refactored into the main `do_suggest()` body, to minimize the surprise of an `exit()` call coming in a subfunction. ([#263](https://github.com/bskinn/sphobjinv/issues/263))
diff --git a/MANIFEST.in b/MANIFEST.in
index bf8e0a2..c7069e4 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,1 +1,15 @@
-include AUTHORS.md CHANGELOG.md CONTRIBUTING.md LICENSE.txt pyproject.toml README.rst
+include AUTHORS.md CHANGELOG.md CONTRIBUTING.md LICENSE.txt pyproject.toml
+include README.rst requirements-dev.txt requirements-flake8.txt tox.ini
+
+graft src/sphobjinv/_vendored/fuzzywuzzy
+
+graft doc/source
+include doc/make.bat doc/Makefile
+
+include conftest.py
+graft tests
+prune tests/resource
+include tests/resource/objects_attrs* tests/resource/objects_sarge*
+
+global-exclude __pycache__/*
+prune **/*.egg-info
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index a75333f..7bb542c 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -7,8 +7,12 @@ pr:
     - main
     - stable
 
+variables:
+  pip_cache_dir: $(Pipeline.Workspace)/.pip
+
 
 stages:
+
 - stage: code_quality
   displayName: Check code quality
 
@@ -18,11 +22,20 @@ stages:
 
     pool:
       vmImage: 'Ubuntu-latest'
+
     steps:
     - task: UsePythonVersion@0
       inputs:
         versionSpec: '3.10'
 
+    - task: Cache@2
+      inputs:
+        key: 'pip | "$(Agent.OS)" | requirements-dev.txt | requirements-flake8.txt'
+        restoreKeys: |
+          pip | "$(Agent.OS)"
+        path: $(pip_cache_dir)
+      displayName: Cache pip
+
     - script: pip install -U tox
       displayName: Install tox
 
@@ -35,16 +48,26 @@ stages:
     - script: tox -e flake8
       displayName: Lint the codebase
 
+
   - job: interrogate
     displayName: Run interrogate docstrings check
 
     pool:
       vmImage: 'Ubuntu-latest'
+
     steps:
     - task: UsePythonVersion@0
       inputs:
         versionSpec: '3.10'
 
+    - task: Cache@2
+      inputs:
+        key: 'pip | "$(Agent.OS)" | requirements-dev.txt | requirements-flake8.txt'
+        restoreKeys: |
+          pip | "$(Agent.OS)"
+        path: $(pip_cache_dir)
+      displayName: Cache pip
+
     - script: pip install interrogate
       displayName: Install interrogate
 
@@ -88,6 +111,8 @@ stages:
           spec: '3.11'
       platforms: [windows, macOs]
 
+  - template: azure-sdisttest.yml
+
 
 - stage: aux_tests
   displayName: Run auxiliary tests
@@ -104,6 +129,14 @@ stages:
       inputs:
         versionSpec: '3.10'
 
+    - task: Cache@2
+      inputs:
+        key: 'pip | "$(Agent.OS)" | requirements-dev.txt | requirements-flake8.txt'
+        restoreKeys: |
+          pip | "$(Agent.OS)"
+        path: $(pip_cache_dir)
+      displayName: Cache pip
+
     - script: pip install . -r requirements-rtd.txt
       displayName: Install project, plus docs requirements
 
@@ -122,12 +155,21 @@ stages:
       inputs:
         versionSpec: '3.10'
 
+    - task: Cache@2
+      inputs:
+        key: 'pip | "$(Agent.OS)" | requirements-dev.txt | requirements-flake8.txt'
+        restoreKeys: |
+          pip | "$(Agent.OS)"
+        path: $(pip_cache_dir)
+      displayName: Cache pip
+
     - script: pip install -r requirements-dev.txt
       displayName: Install full dev requirements
 
     - script: cd doc; make doctest
       displayName: Run doctests
 
+
   - job: readme
     displayName: Run README doctests/shell tests
 
@@ -142,12 +184,21 @@ stages:
     - script: pip install -r requirements-ci.txt
       displayName: Install CI requirements
 
+    - task: Cache@2
+      inputs:
+        key: 'pip | "$(Agent.OS)" | requirements-dev.txt | requirements-flake8.txt'
+        restoreKeys: |
+          pip | "$(Agent.OS)"
+        path: $(pip_cache_dir)
+      displayName: Cache pip
+
     - script: cd doc; make html
       displayName: Build docs
 
     - script: pytest -k readme --readme --doctest-glob="README.rst"
       displayName: Run README doc/shell tests
 
+
   - job: linkcheck
     displayName: Run docs link-check suite
 
@@ -159,6 +210,14 @@ stages:
       inputs:
         versionSpec: '3.10'
 
+    - task: Cache@2
+      inputs:
+        key: 'pip | "$(Agent.OS)" | requirements-dev.txt | requirements-flake8.txt'
+        restoreKeys: |
+          pip | "$(Agent.OS)"
+        path: $(pip_cache_dir)
+      displayName: Cache pip
+
     - script: pip install . -r requirements-rtd.txt
       displayName: Install doc requirements and local project
 
@@ -177,6 +236,14 @@ stages:
       inputs:
         versionSpec: '3.10'
 
+    - task: Cache@2
+      inputs:
+        key: 'pip | "$(Agent.OS)" | requirements-dev.txt | requirements-flake8.txt'
+        restoreKeys: |
+          pip | "$(Agent.OS)"
+        path: $(pip_cache_dir)
+      displayName: Cache pip
+
     - script: pip install -r requirements-dev.txt
       displayName: Install full dev requirements
 
@@ -189,6 +256,7 @@ stages:
     - script: coverage report --include="tests/*" --fail-under=100
       displayName: Check 100% test execution
 
+
   - job: contributing_toc
     displayName: Confirm CONTRIBUTING.md TOC is up to date
 
@@ -200,6 +268,14 @@ stages:
       inputs:
         versionSpec: '3.10'
 
+    - task: Cache@2
+      inputs:
+        key: 'pip | "$(Agent.OS)" | requirements-dev.txt | requirements-flake8.txt'
+        restoreKeys: |
+          pip | "$(Agent.OS)"
+        path: $(pip_cache_dir)
+      displayName: Cache pip
+
     - script: pip install -r requirements-ci.txt
       displayName: Install CI requirements
 
@@ -209,6 +285,7 @@ stages:
     - script: if [[ $( git status | grep modified | wc -l ) -ne 0 ]]; then exit 1; fi
       displayName: Fail if md-toc modified CONTRIBUTING
 
+
   - job: noqa_info
     displayName: Report flake8-noqa results for info (never fails)
 
@@ -220,6 +297,14 @@ stages:
       inputs:
         versionSpec: '3.10'
 
+    - task: Cache@2
+      inputs:
+        key: 'pip | "$(Agent.OS)" | requirements-dev.txt | requirements-flake8.txt'
+        restoreKeys: |
+          pip | "$(Agent.OS)"
+        path: $(pip_cache_dir)
+      displayName: Cache pip
+
     - script: pip install tox flake8-noqa -r requirements-flake8.txt
       displayName: Install requirements
 
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 678d1b7..4c8f13c 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -57,7 +57,7 @@ and package managers, including:
 
   * Gentoo: ``dev-python/sphobjinv`` (`info <https://gitweb.gentoo.org/repo/gentoo.git/tree/dev-python/sphobjinv>`__)
 
-  * Guix: ``python-sphobjinv`` (`info <https://guix.gnu.org/en/packages/python-sphobjinv-2.0.1/>`__)
+  * Guix: ``python-sphobjinv`` (`info <https://packages.guix.gnu.org/packages/python-sphobjinv/2.0.1/>`__)
 
   * Manjaro: ``python-sphobjinv``
 
diff --git a/src/sphobjinv/version.py b/src/sphobjinv/version.py
index 21e130e..311beb4 100644
--- a/src/sphobjinv/version.py
+++ b/src/sphobjinv/version.py
@@ -29,4 +29,4 @@
 
 """
 
-__version__ = "2.3.1.dev0"
+__version__ = "2.3.1.dev3"


Test patch:
diff --git a/azure-coretest.yml b/azure-coretest.yml
index eb1a3b7..9de7ca7 100644
--- a/azure-coretest.yml
+++ b/azure-coretest.yml
@@ -1,3 +1,6 @@
+# Caching implemented as per
+# https://stackoverflow.com/a/70297887/4376000
+
 parameters:
   pythons: []
   platforms: []
@@ -15,6 +18,7 @@ jobs:
           image: 'macOS-latest'
         ${{ if notIn(platform, 'macOs', 'linux', 'windows') }}:
           image: 'Ubuntu-latest'
+        pip_cache_dir: $(Pipeline.Workspace)/.pip
 
       pool:
         vmImage: $[ variables.image ]
@@ -26,6 +30,14 @@ jobs:
           architecture: 'x64'
         displayName: Use cached ${{ coalesce(python.value.name, python.key) }} for tests.
 
+      - task: Cache@2
+        inputs:
+          key: 'pip | "$(Agent.OS)" | requirements-dev.txt | requirements-flake8.txt'
+          restoreKeys: |
+            pip | "$(Agent.OS)"
+          path: $(pip_cache_dir)
+        displayName: Cache pip
+
       - script: pip install -U --force-reinstall -r requirements-ci.txt
         displayName: Install CI requirements
 
diff --git a/azure-sdisttest.yml b/azure-sdisttest.yml
new file mode 100644
index 0000000..422881b
--- /dev/null
+++ b/azure-sdisttest.yml
@@ -0,0 +1,73 @@
+jobs:
+- job: testable_sdist
+  displayName: Ensure sdist is testable
+
+  variables:
+    pip_cache_dir: $(Pipeline.Workspace)/.pip
+
+  pool:
+    vmImage: 'Ubuntu-latest'
+
+  steps:
+  - task: UsePythonVersion@0
+    inputs:
+      versionSpec: '3.10'
+
+  - task: Cache@2
+    inputs:
+      key: 'pip | "$(Agent.OS)" | requirements-dev.txt | requirements-flake8.txt'
+      restoreKeys: |
+        pip | "$(Agent.OS)"
+      path: $(pip_cache_dir)
+    displayName: Cache pip
+
+  - script: python -m pip install build
+    displayName: Install 'build' package
+
+  - script: |
+      python -m build -s
+      ls -lah dist
+    displayName: Build sdist
+
+  - script: |
+      mkdir sandbox
+    displayName: Create sandbox
+
+  - script: |
+      cp dist/*.gz sandbox/
+      cd sandbox
+      tar xvf *.gz
+    displayName: Unpack sdist in sandbox
+
+  - script: |
+      cd sandbox
+      python -m venv env
+    displayName: Create venv
+
+  # Only the dir of the unpacked sdist will have a digit in its name
+  - script: |
+      cd sandbox
+      echo $( find . -maxdepth 1 -type d -regex "./.+[0-9].+" )
+    displayName: Check unpack dir name
+
+  - script: |
+      cd sandbox
+      source env/bin/activate
+      cd $( find . -maxdepth 1 -type d -regex "./.+[0-9].+" )
+      python -m pip install -r requirements-dev.txt
+    displayName: Install dev req'ts to venv
+
+  - script: |
+      cd sandbox
+      source env/bin/activate
+      cd $( find . -maxdepth 1 -type d -regex "./.+[0-9].+" )
+      cd doc
+      O=-Ean make html
+    displayName: Build docs in sandbox
+
+  - script: |
+      cd sandbox
+      source env/bin/activate
+      cd $( find . -maxdepth 1 -type d -regex "./.+[0-9].+" )
+      pytest --nonloc
+    displayName: Run test suite in sandbox
diff --git a/conftest.py b/conftest.py
index 270bdf4..5c10462 100644
--- a/conftest.py
+++ b/conftest.py
@@ -36,7 +36,6 @@
 import shutil
 import sys
 from enum import Enum
-from filecmp import cmp
 from functools import partial
 from io import BytesIO
 from pathlib import Path
@@ -139,7 +138,7 @@ class Extensions(str, Enum):
 
 
 @pytest.fixture()
-def scratch_path(tmp_path, res_path, misc_info):
+def scratch_path(tmp_path, res_path, misc_info, is_win, unix2dos):
     """Provision pre-populated scratch directory, returned as Path."""
     res_base = misc_info.FNames.RES.value
     scr_base = misc_info.FNames.INIT.value
@@ -151,6 +150,13 @@ def scratch_path(tmp_path, res_path, misc_info):
             str(tmp_path / f"{scr_base}{ext}"),
         )
 
+    # With the conversion of resources/objects_attrs.txt to Unix EOLs in order to
+    # provide for a Unix-testable sdist, on Windows systems this resource needs
+    # to be converted to DOS EOLs for consistency.
+    if is_win:
+        win_path = tmp_path / f"{scr_base}{misc_info.Extensions.DEC.value}"
+        win_path.write_bytes(unix2dos(win_path.read_bytes()))
+
     yield tmp_path
 
 
@@ -260,13 +266,22 @@ def func(arglist, *, expect=0):  # , suffix=None):
 
 
 @pytest.fixture(scope="session")
-def decomp_cmp_test(misc_info):
+def decomp_cmp_test(misc_info, is_win, unix2dos):
     """Return function to confirm a decompressed file is identical to resource."""
 
     def func(path):
         """Perform the round-trip compress/decompress comparison test."""
         # The str() calls here are for Python 3.5 compat
-        assert cmp(str(misc_info.res_decomp_path), str(path), shallow=False)
+        res_bytes = Path(misc_info.res_decomp_path).read_bytes()
+        tgt_bytes = Path(path).read_bytes()  # .replace(b"\r\n", b"\n")
+
+        if is_win:
+            # Have to explicitly convert these newlines, now that the
+            # tests/resource/objects_attrs.txt file is marked 'binary' in
+            # .gitattributes
+            res_bytes = unix2dos(res_bytes)
+
+        assert res_bytes == tgt_bytes
 
     return func
 
diff --git a/tests/test_fixture.py b/tests/test_fixture.py
index 985e5a3..1e94d4a 100644
--- a/tests/test_fixture.py
+++ b/tests/test_fixture.py
@@ -63,11 +63,13 @@ def test_cli_invoke(run_cmdline_test):
     run_cmdline_test([])
 
 
-def test_decomp_comp_fixture(misc_info, decomp_cmp_test):
+def test_decomp_comp_fixture(misc_info, decomp_cmp_test, scratch_path):
     """Test decomp_cmp_test works in 'identity' case.
 
     Basically is telling filecmp.cmp to compare a reference inventory file
     with itself.
 
     """
-    decomp_cmp_test(misc_info.res_decomp_path)
+    decomp_cmp_test(
+        scratch_path / f"{misc_info.FNames.INIT.value}{misc_info.Extensions.DEC.value}"
+    )