python / cpython

The Python programming language
https://www.python.org
Other
63.4k stars 30.36k forks source link

Policy for removal of old `.. versionadded`|`.. versionchanged` ? #108514

Open Carreau opened 1 year ago

Carreau commented 1 year ago

A large number of .. versionadded, and .. versionchanged directive are from long-unmaintained version of Python, from a rough search through the codebase/docs (excluding whatsnew), of everything 3.5 and before:

   4 .. versionchanged:: 3.0
  33 .. versionchanged:: 3.1
  55 .. versionadded:: 3.1
 143 .. versionchanged:: 3.2
 152 .. versionadded:: 3.5
 159 .. versionchanged:: 3.4
 182 .. versionadded:: 3.4
 192 .. versionchanged:: 3.5
 209 .. versionchanged:: 3.3
 219 .. versionadded:: 3.2
 295 .. versionadded:: 3.3

I think that at some point it might be useful to remove those, and write the documentation as if what was changed/added has always be present.

Is there any policy as to when those can/should be removed/rephrased ?

Linked PRs

vstinner commented 1 year ago

It is an useful information to me. Why do you want to remove it?

Carreau commented 1 year ago

for say 3.6-3.12 I find it useful, but I find it adds cruft in some area.

For example:

Changed in version 3.4: Test discovery supports [namespace packages](https://docs.python.org/3/glossary.html#term-namespace-package) for the start directory. Note that you need to specify the top level directory too (e.g. python -m unittest discover -s root/namespace -t root).

Couldn't the Note that you need to specify the top level directory too (e.g. python -m unittest discover -s root/namespace -t root). part be in the normal doc instead of being in a .. version changed:: ?

But another

Skipping tests and expected failures

New in version 3.1.

At that point do the "new in version 3.1" really bring useful information as a first item to inform the use in the skipping test and expected failures ?

vstinner commented 1 year ago

I don't have a strong opinon about it, I will not block if you propose a change :-)

I'm not concerned by Changelog which goes up to Python 3.5.0! Maybe it's time to cut it :-) https://docs.python.org/dev/whatsnew/changelog.html#python-3-5-0-alpha-1

hugovk commented 1 year ago

It was discussed on the core dev Discord fairly recently.

To summarise:

terryjreedy commented 1 year ago

The current policy is that the Python x (3) manual should have a complete history of feature changes so that one can write and maintain code compatible with any minor x.y (3.y) version. The premise of this proposal seems to be that is that no one writes or maintains code for 3.5 or earlier. I doubt that this is true for the wider Python community. In any case, I think that this documentation policy change should be discussed on discourse, just as major code changes should be discussed on the Ideas channel. This issue could be closed and reopened later.

Note 1: AFAIK, no notices in the Python 2 manual were ever removed. On the other hand, there were just 8 Python 2 versions over a decade, at which point Python 2 and its manual were essentially feature frozen.

Note 2: When 3.0 came out, it was anticipated that we would be distributing Python 4 now, with a new manual tracking changes from 4.0. (Releasing 3.10 required removing the assumption in several places that 1 digit was enough for the minor version number.) Since that has not happened yet, I think revising the policy can be considered.

Note 3: PyPI searches in a browser do not seem directly useful for ongoing guidance as to what changes to make. Searches https://pypi.org/search/?q=&o=&c=Programming+Language+%3A%3A+Python+%3A%3A+3.0 (and .1, .2, .3) give 647, 1435, 5469, and 10000+ hits (and 10000+ up to 3.11). Dead packages tend to hang around, while we would be more interested in active projects that drop older versions.

CAM-Gerlach commented 1 year ago

I personally don't really mind seeing them at least back to Python 3.0 as they're not that numerous (relative to the size of the docs) or intrusive, and we of course certainly shouldn't spend valuable time mechanically removing semantically meaningful information from the source. Though, I don't feel too strongly about hiding annotations for Python <≈3.4-3.5 or so in the rendered output, if its agreed upon by others.

Whatever minimum version we agree on, 3.0, 3.6 or something in between, it would be trivial to implement this via via a Sphinx post-transform that checks for versionmodified nodes (of the desired types) that have a version older than that specified by a conf.py config value and removes them from the output. This could be easily adjusted in the future if our policy were to change, or upon the release of a new version, by changing a single config value.

I've opened a PR, #108522 , with a working implementation, if/when we agree on a minimum value, or we could specify 3.0 for starters as the status quo, and change it later if agreed.

One other point to note is that seeing an annotation for a version well older than anything than I support gives me affirmative confirmation that I can safety use an API, whereas not showing it adds a kernel of doubt that perhaps the annotation was simply omitted (of course, with reasonably complete annotations in the source and a couple additional bits of inline structured data, we avoid the latter concern by programmatically validate that all public APIs have the version they were added documented in their metadata, which is something I'm currently working on).


Summary of previous discussion/proposals For posterity, there has been previous recent discussions about this among the core devs; the main approach that was considered and generally seemed to be agreed upon at the time was to make old `versionmodified` annotations collapsed/hidden by default in the rendered docs, with a user-facing option (either a dropdown or a global toggle) to show them. To summarize, on the backend side, its pretty trivial do so; just add a `conf.py` config setting for the minimum version, and then either add a simple `NodeVisitor` for `versionmodified` nodes that adds a particular class that is set to `display: none` in CSS (for HTML-based docs, which would allow hiding/showing them in JS), and/or just straight remove the doctree nodes entirely (for other builders). The frontend side is simple in theory—add e.g. an HTMLTranslator to wrap marked `versionmodified` nodes in `
` blocks. However, in order to actually significantly reduce user-facing clutter, we need to group and re-order blocks of _multiple_ versionmodifieds applying to the same object and hide them as a unit, or we're just replacing a `versionmodified` line with a widget to show/hide it, which doesn't really gain us much if anything. And that in turn requires adding some additional options to `version*` directives to specify the additional bits of structured data required to do the grouping accurately. I am already actively working on both of those blockers because grouping and sorting the list has been requested and is potentially beneficial anyway, and it allows us to do a number of other things that have been requested (statically/programmatically exposing deprecation, etc. information, automatically collating changes/deprecations/removals in the What's New, a dedicated page, etc.). However, while a hide/show option the cases where it is potentially the most bothersome (long lists of changes for the same object over different versions), it doesn't really help for the ≈majority of such annotations that are standalone. Here's my detailed comments and design for how that can be implemented, from that discussion:
Detailed proposal for user-controlled hide/show > At the Sphinx level, we could add a NodeVisitor for verionmodified doctree nodes to emit a CSS class based on whether the extracted version compares less than the minimum version we set (e.g. in conf.py), and then just have display: none in for that in the custom CSS. > > Alternatively, it could be done in client-side JS instead as you suggest, with a snippit that looked for versionmodified-class DOM elements, extracted the version number, compared it with a set version (configured...somewhere), and added the class to the parent if too old. However, this wouldn't work on other builders (e.g. PDF, epub, etc.), whereas the Sphinx-level approach could be extended to do so if desired, and overall seems generally cleaner and more efficient, and doesn't require JS to work. > It definitely shouldn't be sorted manually as its a lot of churn (given oldest-first is the current convention); while you could potentially do it with JS, it should be easier at the Sphinx level, though still not trivial (especially if we re-use the version extraction logic of the marking as hidden). Each version* directive/node/element is independent and they may not be grouped appropriately in the source, with other version-based directives interspersed. > > The most comprehensive and easiest to implement approach would be to just group and order them by the nodes they document (i.e. are children of), like functions, classes, etc—though that assumes the doc source is structured correctly and may not handle special cases well, which we'd need to either fix or add the appropriate heuristics to handle them. However, this would make it easy to consistently order and group other things like platform availability, audit events, deprecated/removed, etc., so readers can find them more easily, while reducing or avoiding the need to worry about how to order them in the source. > > Grouping and ordering them should also allow us to fairly easily add older entries to an uncollapsable details HTML element via Sphinx (rather than hiding them), or adding a show/uncollapse button via a JS snippit. The latter would probably look a little nicer, but the former is more efficient, simper and doesn't require JS to work. With that, we could be a lot less conservative with the minimum version to show by default (e.g. back to the oldest version that's not EOL), as people could easily expand them if desired (of course, that wouldn't work for static non-HTML builders, but we could use the more conservative bound for them or just show everything). > It definitely shouldn't be sorted manually as its a lot of churn (given oldest-first is the current convention); while you could potentially do it with JS, it should be easier at the Sphinx level, though still not trivial (especially if we re-use the version extraction logic of the marking as hidden). Each version* directive/node/element is independent and they may not be grouped appropriately in the source, with other version-based directives interspersed. > > The most comprehensive and easiest to implement approach would be to just group and order them by the nodes they document (i.e. are children of), like functions, classes, etc—though that assumes the doc source is structured correctly and may not handle special cases well, which we'd need to either fix or add the appropriate heuristics to handle them. However, this would make it easy to consistently order and group other things like platform availability, audit events, deprecated/removed, etc., so readers can find them more easily, while reducing or avoiding the need to worry about how to order them in the source. > > Grouping and ordering them should also allow us to fairly easily add older entries to an uncollapsable details HTML element via Sphinx (rather than hiding them), or adding a show/uncollapse button via a JS snippit. The latter would probably look a little nicer, but the former is more efficient, simper and doesn't require JS to work. With that, we could be a lot less conservative with the minimum version to show by default (e.g. back to the oldest version that's not EOL), as people could easily expand them if desired (of course, that wouldn't work for static non-HTML builders, but we could use the more conservative bound for them or just show everything).
Carreau commented 1 year ago

Thanks, I'll use my best judgement if I see anything that could be written better or maybe remove. I just want to make sure there is no "keep everything" policy.

CAM-Gerlach commented 1 year ago

I just want to make sure there is no "keep everything" policy.

@Carreau To summarize my interpretation of the discussions here and elsewhere, the general consensus seems to be that older .. versionadded / .. versionchanged should generally, aside from special cases, be kept in the source at least, as they provide useful human and machine-readable semantic information, and can easily be hidden from the reader-facing output if desired and agreed upon, as the implementation in #108522 illustrates.

However, you bring up the good point that there are cases where significant information/explanation is contained within the versionchanged rather than in the prose proper and likely should be moved to the latter if it exists already or is still useful, or otherwise considered for removal from the message. Indeed, as @AA-Turner lists in detail on the PR, there seems to be a fair number of cases where this is so.

Therefore, for those it seems it would be of value to move such detailed information to the prose instead, leaving just a brief summary in the versionchanged, which is also a blocker to considering hiding the versionchanged itself. In the specific case of your example, the part you highlight can probably just be removed entirely for 3.11+, since as a following versionchanged mentions, it is no longer supported in Python 3.11.

davidism commented 1 year ago

I wrote a little Sphinx plugin years ago for Pallets/Flask for this exact case where we had years of changes that were interesting but noisy. The plugin ensures the change entries are sorted most recent first, then collapses everything but the previous version. https://pypi.org/project/sphinxcontrib-log-cabinet/ If you think that's useful, I wouldn't mind maintaining it if anything is needed.