Repository: python/peps

Issue:
Discourage using References?
Many PEPs have a "References" section containing hyperlinks to various things. The main text then has a "reference"[1]. For the most part, this feels an outdated mechanism. In particular, when reading a PEP, if there's a link in the text, I want clicking on the link to go directly to the hyperlinked document, not to the References section. The markup to do that exists, it's just that most PEP authors follow the example of older PEPs that make all (or most) links go through the References section.

Perhaps we can encourage placing direct links in the text, and reserve the References section for either books or journal articles, or abandon it altogether?


Discussion:
I've been ignoring this suggestion for a while because it's extra work, so I definitely support dropping the section.
> For the most part, this feels an outdated mechanism. In particular, when reading a PEP, if there's a link in the text, I want clicking on the link to go directly to the hyperlinked document, not to the References section.

For what its worth, as an run of the mill Python developer, that gave me the exact same impression. It made sense back when PEPs where plain text and shared on email lists, but aside from feeling a bit archaic nowadays, it has significant usability impacts, requiring an extra layer of indirection to open links (or even see where they point to); in particular, I frequently <kbd>Ctrl</kbd>-click links as I'm reading to open them in new tabs to read later or after I've skimmed/read the PEP, only to be frustrated when I come back to them and realized that all I've done is open lots of duplicate pages to the references section, and have to look carefully in each tab to see what link I actually intended to click (if I even remember that was my intent at all). 

There are some cases where the are used for more than just references, particularly on older or long-established PEPs and meta-PEPs, e.g. [PEP 1](https://www.python.org/dev/peps/pep-0001/#references-and-footnotes), [PEP 465](https://www.python.org/dev/peps/pep-0465/#references), etc, along with that of non-web media/journal articles, etc. These cases could be accommodated by renaming the references section "footnotes" (as it is already named in PEP 1 and others that use it for this purpose) and using it as such, and updating the description (PEP 1) and the template (PEP 12) accordingly.

So, some proposed concrete steps to implement this issue:

* [ ] PEP 0
    * [ ] [References section](https://www.python.org/dev/peps/#references-1) Inline the (only two) links and elide section, for consistency 
* [ ] PEP 1
    * [ ] [What belongs in a successful PEP section](https://www.python.org/dev/peps/pep-0001/#what-belongs-in-a-successful-pep): Rename References -> Footnotes and update short description accordingly
    * [ ] [References and Footnotes section](https://www.python.org/dev/peps/pep-0001/#references-and-footnotes): Update title to just "Footnotes" and inline links
* [ ] PEP 12
    * [ ] [Hyperlinks section](https://www.python.org/dev/peps/pep-0012/#hyperlinks): Revise it to refer to only inline links, aside from perhaps explicitly mentioning the prior practice of a reference section as deprecated for new PEPs
    * [ ] [Footnotes section](https://www.python.org/dev/peps/pep-0012/#footnotes): Elide the portions only relevant to link references, and perhaps more explicitly describe the intended purpose of footnotes, for notes and non-link references
    * [ ] [Suggested Sections section](https://www.python.org/dev/peps/pep-0012/#suggested-sections): Rename "References" -> "Footnotes" and update short description accordingly
    * [ ] [References section](https://www.python.org/dev/peps/pep-0012/#references): Rename it to Footnotes, inline the links in the PEP, and add a few appropriate example footnotes linked from the footnote section, e.g. a note, a book reference, etc

Additionally, the [footer transform](https://github.com/python/peps/blob/master/pep_sphinx_extensions/pep_processor/transforms/pep_footer.py) could potentially be tweaked to not inject automatically generated links into the References section and add superfluous footnotes, while preserving the inline links, and not having any effect on any manually-created footnotes. For PEPs using just link references rather than manual footnotes, this would elide the section entirely, while those using a mix of both would only show the more-useful manual footnotes in that section, while direct-linking the rest. This would also allow use of non-inline references (e.g. referencing the same line multiple times) without the undesired addition of/into a References section.

Finally, we could consider updating the rest of the active [meta-PEPs](https://www.python.org/dev/peps/#meta-peps-peps-about-peps-or-processes) to use inline links, as these tend to be the most frequently read, updated, and likely used as exemplars (could include others as well, if desired, but probably best to keep things limited in scope if we do this at all):
* [ ] PEP 7, PEP 8, PEP 10, PEP 11, PEP 387, and PEP 609 all are up to date, long-lived, relatively higher-traffic (especially over the long term), and have only 2-3 references (except 609), all links, so conversion would be quick
* [ ] PEP 6 Meets all the criteria above, except "up to date" (see PEP 6 Note) `*` 
* [ ] PEP 4 and PEP 5 (and PEP 13) don't have any link references to begin with

`*` PEP 6 Note:  <details>Unlike the other meta-PEPs, [PEP 6](https://www.python.org/dev/peps/pep-0006/) , much of the content is 1-2 decades outdated (talking about things like CVS, SourceForge, the Patch Czar, the the pre-pre-PEP 602 release process, Python 2.x, BDFL, etc) and hasn't been updated since Python 2.3, and also has some overlap with other commonly referenced PEPs, including [PEP 387](https://www.python.org/dev/peps/pep-0387/) [PEP 602](https://www.python.org/dev/peps/pep-0602/), and possibly others. As such, it might make sense to either update it or subsume the remaining into other PEP(s). However, that's obviously an issue for another...issue.</details>

Particularly given the core devs have better things to do than this sort of stuff, I offer my help here on the above. Thanks!
Hi CAM, are you interested in submitting a series of PRs (or perhaps one big one) to make this happen? I don't think any of the other PEP editors would be opposed (@JelleZijlstra, @warsaw, @Rosuav -- I don't recall who else besides @brettcannon and me is a PEP editor :-).
I support this change in principle, but don't want to be the one to do the work of rewriting everything, so yes, absolutely in favour of seeing a PR if you're willing, CAM :)
Agree with everything @Rosuav said. Thanks for offering to help @CAM-Gerlach!
Thanks so much @gvanrossum @Rosuav @JelleZijlstra ! Sorry for the delay; I've been busy working on what ended up being a thorough overhaul of PEP 639 to implement several major changes and additions after discussion and consensus by the community, as well as update it to reflect all the ecosystem/tool/standard changes in the 1-2 years since its initial drafting plus copyediting and various fixes. I hope to have that ready for final review and PR by tomorrow, after which I'll be able to work on this one.

Based on your feedback, my tentative plan is to do two PRs split down the lines of the checklists above, with one proposing the documentation modifications to PEP 1 and PEP 12 along with the build tweak to not automatically make footnotes out of inline links (links that are just footnotes would stay as they are, to preserve backwards-compatibility and keep things in scope), and the second implementing the change on the active, core meta/process-PEPs listed that don't already have their links inline (like PEP 609, which the previous PR will fix automatically).

Also, should I open a new issue following up on my above footnote about PEP 6 (being an active meta-/process-PEP that contains a large amount of no-longer-accurate/very outdated content)? Or, is it worth bringing it up in a wider venue, like Discourse (if so, any suggestions on which section)?
I don't know if going back and updating PEPs that use references is worth it, but updating the PEPs that suggest/say to use references are definitely worth updating.
Yeah; for the PEPs that already use inline links the build changes needed (to get references to not get added automatically even for inline links) will fix it for free, but it would require a fair amount of manual effort to do on old PEPs, principally because it can't be really scripted due to the need to determine what prose text to actually link, and create a lot of low-SNR churn.

The one place I think it might be valuable is on the relatively small number of links (no more than a dozen or so total) on the most popular, active meta/process PEPs (as listed above), which (particularly PEPs like PEP 8) likely get a high amount of user and developer traffic relative to the others, which would both benefit users from the standpoint of accessibility, simplicity and concision, and help avoid potential PEP authors picking up on the old practice.

As it stands now, I propose submitting three PRs in sequence: One with the build tweaks to not always auto-generate references for inline links (assuming that ends up being doable without any unintended side effects); one with the PEP 0/1/12 changes that say to use references, and one to update the ~dozen or so references on the activate core meta/process PEPs.
> One with the build tweaks to not always auto-generate references for inline links (assuming that ends up being doable without any unintended side effects);

Wow. I didn't even know that that feature existed. I thought that all References were put in there manually -- like they often are, e.g. in PEP 8 there are 5 of these. Do you have an example (i.e., a PEP which uses inline links in the source that are converted to indirect links on the website)?

+1 on the general plan BTW.
Wait, did I just teach *@gvanrossum* something (vaguely) Python-related? :open_mouth: 

Actually, its even more complicated than that—there are no less than _four_ different ways link/references are done in the PEPs sources, three of which create a footnote and three of which render differently (times the two different build systems, docutils and Sphinx, which each have different code handling this, which are mostly equivalent but with some edge-case differences). In fact, some PEPs, like [PEP 1](https://github.com/python/peps/blob/c088d64ecb829ec596b6c6d7d098cf752c491535/pep-0001.txt#L773), use different ones within the very the same file, sometimes even in the very same line; in fact, the [PEP Formats and Templates](https://www.python.org/dev/peps/pep-0001/#pep-formats-and-templates) section uses three of the four in the span of a mere two sentences, all of which render visibly differently, and which creates a [minor rendering issue](https://python.github.io/peps/pep-0001/#references-and-footnotes) in the footnotes with a visible gap and double vertical rule between them.

* **Numbered Footnote**: Adding numbered references in the text (`[1]_`) and manually listing them in the References section, which renders as a linked footnote, e.g. as in PEP 8 ([Source](https://github.com/python/peps/blob/c088d64ecb829ec596b6c6d7d098cf752c491535/pep-0008.txt#L1446) | [Rendered](https://www.python.org/dev/peps/pep-0008/#references) and many older PEPs. 
* **Named Footnote**: Adding named footnote references in the text (`[#footnotename]`_) and listing the reference name and link in the References section, which render the same as the previous, e.g. PEP 639 ([Source](https://github.com/python/peps/blob/c088d64ecb829ec596b6c6d7d098cf752c491535/pep-0639.rst?plain=1#L796) | [Rendered](https://www.python.org/dev/peps/pep-0639/#references)) and a smattering of PEPs.
* **Inline references**: Adding named inline references in the text (``you can find it on `GitHub`_``) and listing the link targets separately (such as in the References section), which both links the text directly and automatically adds a (redundant) linked and numbered footnote, e.g. PEP 1 ([Source](https://github.com/python/peps/blob/c088d64ecb829ec596b6c6d7d098cf752c491535/pep-0001.txt?plain=1#L799) | [Rendered](https://www.python.org/dev/peps/pep-0001/#pep-formats-and-templates) ) and many newer PEPs
* **Inline links**: Adding the URL directly inline with the link text (`` `GitHub<https://github.com>`_``) with no separate link reference, which just links the text, _without_ creating a footnote, e.g. PEP 1 ([Source](https://github.com/python/peps/blob/c088d64ecb829ec596b6c6d7d098cf752c491535/pep-0001.txt?plain=1#L514) | [Rendered](https://www.python.org/dev/peps/pep-0001/#pep-formats-and-templates) ), and many other newer PEPs

But wait, there's more! For the first and second approach, if the actual footnote isn't in the footnote section, the rendered location and number of the footnote in the output moves with it, but the same is _not_ true of the third type of footnote (using regular inline links); it always gets rendered in the references section no matter its physical location, and only its order/number is changed. However, regardless, inline references are always listed after manual footnotes in the output, no matter where they are listed in the source.

So, not exactly the "only one (obvious) way to do it" ideal :)
Now for some good news... TL;DR, it ended up being nearly as straightforward as I could have hoped to implement the build changes in both the Sphinx and Docutils build process to support this, and I can go ahead with a PR on that shortly to get things moving.

For the Sphinx version of the build process, as I'd hoped, simply commenting out [lines 53 - 68](https://github.com/python/peps/blob/c088d64ecb829ec596b6c6d7d098cf752c491535/pep_sphinx_extensions/pep_processor/transforms/pep_footer.py#L53) of the footer transform (which is what adds the redundant footnotes in Case 3) makes them render as normal inline lines, just like in Case 4. With just a few small tweaks to the existing cleanup code that already does this, it also removes ``References`` sections that contain only link references and would otherwise render as empty (e.g. contained all normal link targets, no footnotes, as in e.g. [PEP 609](https://github.com/python/peps/blob/c088d64ecb829ec596b6c6d7d098cf752c491535/pep-0609.rst?plain=1#L260) and a number of others). This allows both existing and new PEPs to still list all their link targets under a references/footnotes section in the source (to make it easier to track and update links referenced multiple times), while only having it actually appear in the rendered output if it actually contains footnotes, offline references, etc.

The legacy docutils version took somewhat more work; removing `pep.TargetNotes` from the list of transforms on [line 456](https://github.com/python/peps/blob/c088d64ecb829ec596b6c6d7d098cf752c491535/pep2html.py#L456) skips generating the redundant links, though I had to port over the relevant bits of the `PEPFooter` transform to cleans up the resultant empty footers.

So, I already have the first PR pretty much ready to go, in spite of myself.
Amazing! Thanks for the detailed examples. There are definitely too many ways to do links in ReST…
Opened the first step as PR #2155 

Resolving patch:
diff --git a/pep0/constants.py b/pep0/constants.py
--- a/pep0/constants.py
+++ b/pep0/constants.py
@@ -21,14 +21,14 @@
 
 intro = """\
 This PEP contains the index of all Python Enhancement Proposals,
-known as PEPs.  PEP numbers are assigned by the PEP editors[1_], and
-once assigned are never changed.  The version control history [2_] of
-the PEP texts represent their historical record.
+known as PEPs.  PEP numbers are :pep:`assigned <1#pep-editors>` by the
+PEP editors, and once assigned are never changed.
+The `version control history`_ of the PEP texts represent
+their historical record.
 """
 
 references = """\
-.. [1] PEP 1: PEP Purpose and Guidelines
-.. [2] View PEP history online: https://github.com/python/peps
+.. _version control history: https://github.com/python/peps
 """
 
 footer = """\
diff --git a/pep2html.py b/pep2html.py
--- a/pep2html.py
+++ b/pep2html.py
@@ -496,7 +496,7 @@ def apply(self):
 
 
 class PEPFooter(Transform):
-    """Remove the References section if it is empty when rendered."""
+    """Remove the References/Footnotes section if it is empty when rendered."""
 
     # Set low priority so ref targets aren't removed before they are needed
     default_priority = 999
@@ -510,14 +510,13 @@ def apply(self):
         for section in reversed(self.document):
             if not isinstance(section, nodes.section):
                 continue
-            title_words = section[0].astext().lower().split()
-            if 'references' in title_words:
-                # Remove references section if there are no displayed
-                # footnotes (it only has title & link target nodes)
+            title_words = {*section[0].astext().lower().split()}
+            if {"references", "footnotes"} & title_words:
+                # Remove references/footnotes sections if there is no displayed
+                # content (i.e. they only have title & link target nodes)
                 if all(isinstance(ref_node, (nodes.title, nodes.target))
                        for ref_node in section):
                     section.parent.remove(section)
-                break
 
 
 class PEPReader(standalone.Reader):
diff --git a/pep_sphinx_extensions/pep_processor/transforms/pep_footer.py b/pep_sphinx_extensions/pep_processor/transforms/pep_footer.py
--- a/pep_sphinx_extensions/pep_processor/transforms/pep_footer.py
+++ b/pep_sphinx_extensions/pep_processor/transforms/pep_footer.py
@@ -9,8 +9,8 @@
 class PEPFooter(transforms.Transform):
     """Footer transforms for PEPs.
 
-     - Removes the References section if it is empty when rendered.
-     - Creates a link to the (GitHub) source text.
+     - Remove the References/Footnotes section if it is empty when rendered.
+     - Create a link to the (GitHub) source text.
 
     Source Link:
         Create the link to the source file from the document source path,
@@ -30,10 +30,10 @@ def apply(self) -> None:
         for section in reversed(self.document[0]):
             if not isinstance(section, nodes.section):
                 continue
-            title_words = section[0].astext().lower().split()
-            if "references" in title_words:
-                # Remove references section if there are no displayed
-                # footnotes (it only has title & link target nodes)
+            title_words = {*section[0].astext().lower().split()}
+            if {"references", "footnotes"} & title_words:
+                # Remove references/footnotes sections if there is no displayed
+                # content (i.e. they only have title & link target nodes)
                 to_hoist = []
                 types = set()
                 for node in section:
@@ -43,7 +43,6 @@ def apply(self) -> None:
                 if types <= {nodes.title, nodes.target}:
                     section.parent.extend(to_hoist)
                     section.parent.remove(section)
-                break
 
         # Add link to source text and last modified date
         if pep_source_path.stem != "pep-0000":


Test patch: