Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-126180: Remove getopt and optparse deprecation notices #126227

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

ncoghlan
Copy link
Contributor

@ncoghlan ncoghlan commented Oct 31, 2024

getopt and optparse are in no way at risk of being removed,
as they have genuinely valid use cases. Those use cases
(mimicing the C getopt API, implementing third party
command line argument processing libraries) are just
far less common than the ones that argparse addresses.

Relevant issue is #126180.


📚 Documentation preview 📚: https://cpython-previews--126227.org.readthedocs.build/

@ncoghlan ncoghlan changed the title gh-126225: Remove getopt and optparse deprecation notices gh-126180: Remove getopt and optparse deprecation notices Oct 31, 2024
more declarative style of command-line parsing: you create an instance of
:class:`OptionParser`, populate it with options, and parse the command
line. :mod:`optparse` allows users to specify options in the conventional
command-line options than the minimalist :mod:`getopt` module.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replacing old with minimalist is the only actual wording change here (the rest is just reflowing text)

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are focused on one particular peculiarity in argparse, but there are many others. The difference is fundamental in the way how optional and positional arguments are parsed.

@@ -15,7 +15,7 @@ recommended command-line parsing module in the Python standard library.

There are two other modules that fulfill the same task, namely
:mod:`getopt` (an equivalent for ``getopt()`` from the C
language) and the deprecated :mod:`optparse`.
language) and the lower level :mod:`optparse` module.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may create an impression that optparse is lower level than getopt.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll reorder it to make it clear the "lower level" comparison is relative to argparse

Comment on lines 23 to 24
conventions around the handling of option parameter values that start
with ``-`` is desired.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not only this. There are other peculiarities that make implementation of compatible interface with argparse impossible (unlike to getopt and optparse).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I had gotten the impression from the Discourse thread that this was the primary quirk, but I can reword these caveats to be less specific to that one issue.

@@ -11,6 +11,18 @@

**Source code:** :source:`Lib/argparse.py`

.. note::

While :mod:`argparse` is the recommended standard library module for
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not recommend it for now. You can use it on your own risk. optparse may need more work, but it works as expected. I would recommend it for beginners, which cannot distinguish their own errors from peculiarities of the library.

Copy link
Contributor Author

@ncoghlan ncoghlan Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this PR, I'd like to stick with the status quo as far as recommendations go (that is, only taking the step back from "argparse is the only non-deprecated argument processing option in the standard library").

Taking the extra step to saying "argparse is not recommended over optparse anymore, even for end user applications" would then be a separate follow up question.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. Keep the argparse recommendation. We're not going to dis-recommend the most widely used Python argument parsing library in the world (that causes churn and angst from users). Nor are we going to be adding yet another one to the stdlib in the future. argparse supports most users quite well, "warts" and all, with plenty of popular third party options for yet other behaviors beyond our stdlib options.

Comment on lines +15 to +16
argparse.rst
optparse.rst
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would place optparse above argparse.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If anything, this list sure be in purely alphabetical order. passive aggressive opinions via list ordering aren't helpful. 😄

Doc/library/getopt.rst Show resolved Hide resolved
opts, args = parser.parse_args()
process(args, output=opts.output, verbose=opts.verbose)

An equivalent command line interface for this simple case can also be produced
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even in this simple example this is not an exact equivalent. For example, -o -v and -o -- do not work, -o=foo works differently, you cannot interleave options and positional arguments. I said this is "a roughly equivalent".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if we elaborate on the discrepancies here, it may help lay the foundation for weakening the current recommendation to use argparse in a future PR. I'll incorporate more of your notes here tomorrow.

Comment on lines 169 to 170
# ... do something with args.output ...
# ... do something with args.verbose ..
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this to show the difference in the API between three modules

       parser.add_argument('rest', nargs='*')
       args = parser.parse_args()
       process(args.rest, output=args.output, verbose=args.verbose)

Comment on lines 174 to 175
``optparse`` versions due to the way ``argparse`` handles parameter
values that start with ``-``.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference is not only in this.

@ncoghlan
Copy link
Contributor Author

@serhiy-storchaka I think several of your suggestions are good improvements. I should have time to incorporate them tomorrow (Nov 1 AEST)

Comment on lines 33 to 44
.. seealso::

The :pypi:`"click" package <click>` is an ``optparse`` based third party
argument processing library which allows command line applications to be
developed as a set of appropriately decorated command implementation
functions.

.. seealso::

The :pypi:`"Typer" package <click>` is a ``click`` based third party
argument processing library which allows the use of annotated Python
type hints to define an application's command line interface.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might make sense to duplicate these seealso notes in Doc/library/argparse.rst and Doc/howto/argparse.rst.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wary of the potential for confusion for folks that are running through "My first command line application" style tutorials, so I'd like to avoid having too much "Should you be using this?" text at the start of the argparse docs.

Having an off-ramp from argparse to optparse and then from there to PyPI alternatives seems like it could be a reasonable middle ground.

@ncoghlan
Copy link
Contributor Author

ncoghlan commented Nov 1, 2024

@serhiy-storchaka I won't get back to this today, and this weekend isn't looking good either. Early next week will probably be the next update.

@ncoghlan
Copy link
Contributor Author

ncoghlan commented Nov 2, 2024

@serhiy-storchaka I ended up procrastinating on my assignment by working on this (amongst other things), so I've pushed some updates for you to take a look at when you're back at work.


Whether these differing behaviors in the ``argparse`` version are
considered desirable or a problem will depend on the specific command line
application use case.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@serhiy-storchaka ^^^ is the main reason I don't think we should walk back the default argparse recommendation. Many (probably even most) Python devs would consider argparse to be in the right for these 3 examples, and getopt/optparse the ones doing something dubious (even if what they're doing is the common Unix convention).

The discrepancies are valid reasons for reverting the soft deprecation (optparse can genuinely be used to define command line behaviours that argparse doesn't support), but it will take less arguable examples than these ones to make the case that optparse should be preferred over argparse in general.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to write about these peculiarities in the argparse module documentation. The getopt module documentation is not the place where users will search information about the argparse module.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed. I like that we're giving a list of differences in behavior, but I think it makes more sense to put this in a common section :ref:'d from all three of our command line parsing module docs. I don't expect anyone reading argparse (most likely) or optparse (likely) docs to find this in the getopt docs (presumed least likely to be read).

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not agree with some of these changes, but overall this is a step in the right direction. Let's not drag it in bikeshedding.

A roughly equivalent command line interface for this case can also be
produced by using the :mod:`argparse` module::

import argparse
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong indentation. Also, add .. testcode::.


Whether these differing behaviors in the ``argparse`` version are
considered desirable or a problem will depend on the specific command line
application use case.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to write about these peculiarities in the argparse module documentation. The getopt module documentation is not the place where users will search information about the argparse module.

``nargs=`` specifiers and better usage messages. When most everything in
:mod:`optparse` had either been copy-pasted over or monkey-patched, it no
longer seemed practical to try to maintain the backwards compatibility.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me try squinting at this from a slightly different angle, feel free to ignore...

:mod:argparse was originally created to address some needs that the design of :mod:optparse made difficult to implement. While initially the majority of the :mod:optparse interface was imported as a transitional aid, maintaining backwards compatibility was never a goal.

module (which may require more code to configure for a given application,
but also allows an application to request behaviors that ``argparse``
doesn't support), and the very low level :mod:`getopt` (which specifically
serves as an equivalent to :c:func:`!getopt` from the C language).
Copy link

@mwichmann mwichmann Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Python getopt provides behavior that combines the classic getopt and the GNU getopt_long, so the reference (I realize it was there in the original) is incomplete. And to be a little nitpicky, the ISO C standard says nothing about getopt (POSIX does, but only the single-char getopt) so From C could be mildly confusing. Maybe something like: (which specifically serves as an equivalent to the getopt family of functions familiar to C language programmers)?

based on it) may also be worth considering for applications where
``argparse`` doesn't support behaviors that the application requires
(such as entirely disabling support for interspersed options and
positional arguments, or stricter adherence to common Unix and Linux
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd editorialize a little less and elide "stricter" & "common Unix and Linux" and simplify this to "adherence to command line interface concentions related to the handling of values that start with -"

@@ -11,6 +11,18 @@

**Source code:** :source:`Lib/argparse.py`

.. note::

While :mod:`argparse` is the recommended standard library module for
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. Keep the argparse recommendation. We're not going to dis-recommend the most widely used Python argument parsing library in the world (that causes churn and angst from users). Nor are we going to be adding yet another one to the stdlib in the future. argparse supports most users quite well, "warts" and all, with plenty of popular third party options for yet other behaviors beyond our stdlib options.

Comment on lines +15 to +16
argparse.rst
optparse.rst
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If anything, this list sure be in purely alphabetical order. passive aggressive opinions via list ordering aren't helpful. 😄


Whether these differing behaviors in the ``argparse`` version are
considered desirable or a problem will depend on the specific command line
application use case.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed. I like that we're giving a list of differences in behavior, but I think it makes more sense to put this in a common section :ref:'d from all three of our command line parsing module docs. I don't expect anyone reading argparse (most likely) or optparse (likely) docs to find this in the getopt docs (presumed least likely to be read).

Module :mod:`argparse`
Alternative command line option and argument parsing library.
Module :mod:`optparse`
More object-oriented command line option parsing.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the salient feature of optparse over getopt is that it’s more convenient and automated! «more OO» is not a selling point

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Todo
Development

Successfully merging this pull request may close these issues.

6 participants