Skip to content

gh-106240: Add stdlib_deprecations module #106241

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

Closed
wants to merge 4 commits into from

Conversation

vstinner
Copy link
Member

@vstinner vstinner commented Jun 29, 2023

@vstinner
Copy link
Member Author

This PR is incomplete: I wrote it to propose the idea of a new "stdlib_deprecations" module: API to query if a function is deprecated or not. The API should be designed. So far, I only proposed a very basic API:

stdlib_deprecations.is_deprecated(name) returns True if a stdlib module or a stdlib module is deprecated.

stdlib_deprecations.is_capi_deprecated(name) returns True if a C API symbol is deprecated.

Internally, I wrote a dataclass which contains the following data:

  • Name
  • Version when the API is deprecated
  • Optional version when the API is removed
  • Optional message: usually explain how to replace the deprecate API

My current API doesn't provide all data. Maybe the API should be get_deprecated() instead: return the dataclass, or None if it's not deprecated.

TODO: enhance the API to support other deprecation kinds, like deprecation of a function parameter. I propose module.function:argument_name name. We already use such syntax in PyArg_ParseTuple() C API: :function_name suffix in the format string.

@vstinner
Copy link
Member Author

cc @hugovk

Copy link
Member

@sobolevn sobolevn left a comment

Choose a reason for hiding this comment

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

I like the idea! 👍

@vstinner vstinner force-pushed the stdlib_deprecations branch 2 times, most recently from ec8e571 to 50a6e53 Compare June 29, 2023 13:00
@vstinner
Copy link
Member Author

I changed the API to: get_deprecated(name) which returns a Deprecated object if the API is deprecated, or None if it's not.

_deprecate('asynchat', '3.6', remove='3.12', replace='asyncio'),
_deprecate('smtpd', '3.6', remove='3.12', replace='aiosmtp'),
_deprecate('ssl.RAND_pseudo_bytes', '3.6', remove='3.12',
replace='os.urandom()'),
Copy link
Member

Choose a reason for hiding this comment

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

Does this mean the exact call os.urandom() without args, or is it a reference to the function with parentheses added like in C documentation?

Being a Python dev and not a C dev, I take os.urandom to mean one thing and os.urandom() to mean another thing!

Copy link
Member Author

Choose a reason for hiding this comment

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

os.urandom() has no arguments. Adding parenthesis is a hint to show that it's a function

Copy link
Member

Choose a reason for hiding this comment

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

OK but my point is that it’s not a great doc convention for Python. I think the functions that follow need arguments but have () too, that’s misleading.

Copy link
Member

Choose a reason for hiding this comment

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

I presume that ssl.RAND_pseudo_bytes is the name of a function. The exact replacement is os.random, without (). I think it should be given than way.

Copy link
Member Author

Choose a reason for hiding this comment

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

In practice, I expect that the most usual usage of a function like ssl.RAND_pseudo_bytes is to call it: ssl.RAND_pseudo_bytes(). So I prefer to specify the replacement with parenthesis as well: os.urandom(). In my current implementation, Deprecation.message is an arbitrary string, it's not designed to automate replacement by a linter or a similar tool.

@vstinner vstinner force-pushed the stdlib_deprecations branch from 50a6e53 to b717488 Compare June 29, 2023 23:53
@vstinner
Copy link
Member Author

It seems like pylint would prefer a JSON file than a stdlib module. I'm not sure that this module is a good idea :-)

See: https://discuss.python.org/t/formalize-the-concept-of-soft-deprecation-dont-schedule-removal-in-pep-387-backwards-compatibility-policy/27957/61

@michaelfm1211
Copy link

Just from a quick look over the documentation preview, it looks like there's something wrong with the synatx. The name attribute heading for the stdlib_deprecations.Deprecated appears as .. attribute:: name in a code block. I'm unsure why though; the reST looks fine.

@vstinner
Copy link
Member Author

vstinner commented Jul 1, 2023

Oh right, it was because of Attributes:: syntax: fixed

@vstinner
Copy link
Member Author

vstinner commented Jul 1, 2023

I'm not sure about this approach. Linters developpers seem to prefer JSON files rather than an import.

@merwok
Copy link
Member

merwok commented Jul 2, 2023

Yea, the discussion thread seems to agree on a data file rather than a module.

@vstinner
Copy link
Member Author

vstinner commented Jul 3, 2023

Yea, the discussion thread seems to agree on a data file rather than a module.

Right. I close my issue and its PR.

@vstinner vstinner closed this Jul 3, 2023
@vstinner vstinner deleted the stdlib_deprecations branch July 3, 2023 23:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants