Repository: twisted/towncrier
Pull request #612 (2024-06-13 04:19:57)

Orphans in non showcontent categories
# Description
Currently, orphans (newsfragments without an issue number) don't display correctly in a non "showcontent" category, such as the "misc" category.

These fragments don't have an issue number, but if they were important enough to have a fragment, I still think their content should then be shown.

# Checklist
<!-- add a "X" inside the brackets to confirm -->
* [x] Make sure changes are covered by existing or new tests.
* [x] For at least one Python version, make sure local test run is green.
* [x] Create a file in `src/towncrier/newsfragments/`. Describe your
  change and include important information. Your change will be included in the public release notes.
* [x] Make sure all GitHub Actions checks are green (they are automatically checking all of the above).
* [x] Ensure documentation is still up-to-date.



Patch:
diff --git a/docs/configuration.rst b/docs/configuration.rst
index 0a35069..9841b1e 100644
--- a/docs/configuration.rst
+++ b/docs/configuration.rst
@@ -216,6 +216,11 @@ These may include the following optional keys:
 
     ``true`` by default.
 
+    .. note::
+
+        Orphan fragments (those without an issue number) always have their content included.
+        If a fragment was created, it means that information is important for end users.
+
 For example, if you want your custom fragment types to be ``["feat", "fix", "chore",]`` and you want all of them to use the default configuration except ``"chore"`` you can do it as follows:
 
 .. code-block:: toml
@@ -257,6 +262,11 @@ Each table within this array has the following mandatory keys:
 
     ``true`` by default.
 
+    .. note::
+
+        Orphan fragments (those without an issue number) always have their content included.
+        If a fragment was created, it means that information is important for end users.
+
 For example:
 
 .. code-block:: toml
diff --git a/src/towncrier/_builder.py b/src/towncrier/_builder.py
index bfb0522..91a6323 100644
--- a/src/towncrier/_builder.py
+++ b/src/towncrier/_builder.py
@@ -191,7 +191,11 @@ def split_fragments(
                 # Assume the text is formatted correctly
                 content = content.rstrip()
 
-            if definitions[category]["showcontent"] is False:
+            if definitions[category]["showcontent"] is False and issue:
+                # If this category is not supposed to show content (and we have an
+                # issue) then we should just add the issue to the section rather than
+                # the content. If there isn't an issue, still add the content so that
+                # it's recorded.
                 content = ""
 
             texts = section.setdefault(category, {})
diff --git a/src/towncrier/newsfragments/612.bugfix.rst b/src/towncrier/newsfragments/612.bugfix.rst
new file mode 100644
index 0000000..577a9c4
--- /dev/null
+++ b/src/towncrier/newsfragments/612.bugfix.rst
@@ -0,0 +1,1 @@
+Orphan news fragments, fragments not associated with an issue, will now still show in categories that are marked to not show content, since they do not have an issue number to show.
diff --git a/src/towncrier/templates/default.md b/src/towncrier/templates/default.md
index cc894f6..0aa7262 100644
--- a/src/towncrier/templates/default.md
+++ b/src/towncrier/templates/default.md
@@ -15,7 +15,6 @@
 {% for category, val in definitions.items() if category in sections[section] %}
 ### {{ definitions[category]['name'] }}
 
-{% if definitions[category]['showcontent'] %}
 {% for text, values in sections[section][category].items() %}
 - {{ text }}
 {%- if values %}
@@ -24,24 +23,18 @@
 
   (
 {%- else %}
- (
+{% if text %} ({% endif %}
 {%- endif -%}
 {%- for issue in values %}
 {{ issue.split(": ", 1)[0] }}{% if not loop.last %}, {% endif %}
 {%- endfor %}
-)
+{% if text %}){% endif %}
+
 {% else %}
 
 {% endif %}
 {% endfor %}
 
-{% else %}
-- {% for issue in sections[section][category][''] %}
-{{ issue.split(": ", 1)[0] }}{% if not loop.last %}, {% endif %}
-{% endfor %}
-
-
-{% endif %}
 {% if issues_by_category[section][category] and "]: " in issues_by_category[section][category][0] %}
 {% for issue in issues_by_category[section][category] %}
 {{ issue }}
diff --git a/src/towncrier/templates/default.rst b/src/towncrier/templates/default.rst
index f494036..bee1572 100644
--- a/src/towncrier/templates/default.rst
+++ b/src/towncrier/templates/default.rst
@@ -18,16 +18,11 @@
 {{ definitions[category]['name'] }}
 {{ underline * definitions[category]['name']|length }}
 
-{% if definitions[category]['showcontent'] %}
 {% for text, values in sections[section][category].items() %}
-- {{ text }}{% if values %} ({{ values|join(', ') }}){% endif %}
+- {% if text %}{{ text }}{% if values %} ({{ values|join(', ') }}){% endif %}{% else %}{{ values|join(', ') }}{% endif  %}
 
 {% endfor %}
 
-{% else %}
-- {{ sections[section][category]['']|join(', ') }}
-
-{% endif %}
 {% if sections[section][category]|length == 0 %}
 No significant changes.
 


Test patch:
diff --git a/src/towncrier/test/test_build.py b/src/towncrier/test/test_build.py
index 85a21bd..5da7d82 100644
--- a/src/towncrier/test/test_build.py
+++ b/src/towncrier/test/test_build.py
@@ -1416,6 +1416,115 @@ class TestCli(TestCase):
             - Adds levitation
 
 
+        """
+        )
+
+        self.assertEqual(0, result.exit_code, result.output)
+        self.assertEqual(expected_output, result.output)
+
+    @with_project(
+        config="""
+        [tool.towncrier]
+        """
+    )
+    def test_orphans_in_non_showcontent(self, runner):
+        """
+        When ``showcontent`` is false (like in the ``misc`` category by default),
+        orphans are still rendered because they don't have an issue number to display.
+        """
+        os.mkdir("newsfragments")
+        with open("newsfragments/123.misc", "w") as f:
+            f.write("Misc")
+        with open("newsfragments/345.misc", "w") as f:
+            f.write("Another misc")
+        with open("newsfragments/+.misc", "w") as f:
+            f.write("Orphan misc still displayed!")
+        with open("newsfragments/+2.misc", "w") as f:
+            f.write("Another orphan misc still displayed!")
+
+        result = runner.invoke(
+            _main,
+            [
+                "--version=7.8.9",
+                "--date=20-01-2001",
+                "--draft",
+            ],
+        )
+
+        expected_output = dedent(
+            """\
+            Loading template...
+            Finding news fragments...
+            Rendering news fragments...
+            Draft only -- nothing has been written.
+            What is seen below is what would be written.
+
+            7.8.9 (20-01-2001)
+            ==================
+
+            Misc
+            ----
+
+            - #123, #345
+            - Another orphan misc still displayed!
+            - Orphan misc still displayed!
+
+
+
+        """
+        )
+
+        self.assertEqual(0, result.exit_code, result.output)
+        self.assertEqual(expected_output, result.output)
+
+    @with_project(
+        config="""
+        [tool.towncrier]
+        filename = "CHANGES.md"
+        """
+    )
+    def test_orphans_in_non_showcontent_markdown(self, runner):
+        """
+        When ``showcontent`` is false (like in the ``misc`` category by default),
+        orphans are still rendered because they don't have an issue number to display.
+        """
+        os.mkdir("newsfragments")
+        with open("newsfragments/123.misc", "w") as f:
+            f.write("Misc")
+        with open("newsfragments/345.misc", "w") as f:
+            f.write("Another misc")
+        with open("newsfragments/+.misc", "w") as f:
+            f.write("Orphan misc still displayed!")
+        with open("newsfragments/+2.misc", "w") as f:
+            f.write("Another orphan misc still displayed!")
+
+        result = runner.invoke(
+            _main,
+            [
+                "--version=7.8.9",
+                "--date=20-01-2001",
+                "--draft",
+            ],
+        )
+
+        expected_output = dedent(
+            """\
+            Loading template...
+            Finding news fragments...
+            Rendering news fragments...
+            Draft only -- nothing has been written.
+            What is seen below is what would be written.
+
+            # 7.8.9 (20-01-2001)
+
+            ### Misc
+
+            - #123, #345
+            - Another orphan misc still displayed!
+            - Orphan misc still displayed!
+
+
+
         """
         )