-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
PEP 827: Split whether a param has a default out from "quals" #4979
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
Open
msullivan
wants to merge
1
commit into
python:main
Choose a base branch
from
msullivan:default
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+40
−26
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,7 @@ Status: Draft | |
| Type: Standards Track | ||
| Topic: Typing | ||
| Created: 27-Feb-2026 | ||
| Python-Version: 3.15 | ||
| Python-Version: 3.16 | ||
| Post-History: 02-Mar-2026 | ||
|
|
||
|
|
||
|
|
@@ -376,18 +376,37 @@ this PEP. | |
|
|
||
| We introduce a ``Param`` type that contains all the information about a function param:: | ||
|
|
||
| class Param[N: str | None, T, Q: ParamQuals = typing.Never]: | ||
| class Param[ | ||
| N: str | None, | ||
| T, | ||
| K: ParamKind = typing.Never, | ||
| D = typing.Never, | ||
| ]: | ||
| pass | ||
|
|
||
| ParamQuals = typing.Literal["*", "**", "default", "keyword"] | ||
| ParamKind = typing.Literal["*", "**", "keyword", "positional"] | ||
|
|
||
| type PosParam[N: str | None, T] = Param[N, T, Literal["positional"]] | ||
| type PosDefaultParam[N: str | None, T] = Param[N, T, Literal["positional", "default"]] | ||
| type DefaultParam[N: str, T] = Param[N, T, Literal["default"]] | ||
| type PosParam[T] = Param[None, T, Literal["positional"]] | ||
| type PosDefaultParam[T] = Param[None, T, Literal["positional"], T] | ||
| type DefaultParam[N: str, T] = Param[N, T, typing.Never, T] | ||
| type NamedParam[N: str, T] = Param[N, T, Literal["keyword"]] | ||
| type NamedDefaultParam[N: str, T] = Param[N, T, Literal["keyword", "default"]] | ||
| type ArgsParam[T] = Param[Literal[None], T, Literal["*"]] | ||
| type KwargsParam[T] = Param[Literal[None], T, Literal["**"]] | ||
| type NamedDefaultParam[N: str, T] = Param[N, T, Literal["keyword"], T] | ||
| type ArgsParam[T] = Param[None, T, Literal["*"]] | ||
| type KwargsParam[T] = Param[None, T, Literal["**"]] | ||
|
|
||
|
|
||
| The argument ``K``, of type ``ParamKind``, represents the parameter | ||
| kind of the parameter. The default "positional or named" kind of | ||
| argument is represented as ``Never``. It is an error to create | ||
| ``Callable`` with a ``Param`` containing multiple kinds unioned | ||
| together. | ||
|
|
||
| The argument ``D`` carries the type of the parameter's default, if one | ||
| exists, and is ``Never`` otherwise. When the default value is a | ||
| literal (e.g. ``None``, an int, a string, an enum member), ``D`` may | ||
| be a ``Literal`` carrying that value. (Having it be such a ``Literal`` | ||
| has no effect other than to make it available to introspection and | ||
| potentially for diagnostics.) | ||
|
|
||
| We also introduce a ``Params`` type that wraps a sequence of ``Param`` | ||
| types, serving as the first argument to ``Callable``:: | ||
|
|
@@ -419,17 +438,18 @@ as:: | |
| Params[ | ||
| Param[Literal["a"], int, Literal["positional"]], | ||
| Param[Literal["b"], int], | ||
| Param[Literal["c"], int, Literal["default"]], | ||
| Param[Literal["c"], int, typing.Never, Literal[0]], | ||
| Param[None, int, Literal["*"]], | ||
| Param[Literal["d"], int, Literal["keyword"]], | ||
| Param[Literal["e"], int, Literal["default", "keyword"]], | ||
| Param[Literal["e"], int, Literal["keyword"], Literal[0]], | ||
| Param[None, int, Literal["**"]], | ||
| ], | ||
| int, | ||
| ] | ||
|
|
||
|
|
||
| or, using the type abbreviations we provide:: | ||
| or, using the type abbreviations we provide (though this version will not track | ||
| specific values for the defaults):: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This wording is a bit confusing. Anyways, maybe we should just add the default as a param with |
||
|
|
||
| Callable[ | ||
| Params[ | ||
|
|
@@ -793,8 +813,9 @@ Callable inspection and creation | |
| ``Callable`` types always have their arguments exposed in the extended | ||
| Callable format discussed above. | ||
|
|
||
| The names, type, and qualifiers share associated type names with | ||
| ``Member`` (``.name``, ``.type``, and ``.quals``). | ||
| The name and type associated type names with ``Member`` (``.name`` and | ||
| ``.type``). ``Param`` also has a ``.kind`` associated type, which | ||
| exposes ``K`` and a ``.default`` associated type, which exposes ``D``. | ||
|
|
||
| .. _pep827-generic-callable: | ||
|
|
||
|
|
@@ -1101,13 +1122,10 @@ based on iterating over all attributes. | |
| p.name, | ||
| p.type, | ||
| # All arguments are keyword-only | ||
| # It takes a default if a default is specified in the class | ||
| Literal["keyword"] | ||
| if typing.IsAssignable[ | ||
| GetDefault[p.init], | ||
| Never, | ||
| ] | ||
| else Literal["keyword", "default"], | ||
| Literal["keyword"], | ||
| # GetDefault is Never when there's no default, so use it | ||
| # directly as D. | ||
| GetDefault[p.init], | ||
| ] | ||
| for p in typing.Iter[typing.Attrs[T]] | ||
| ], | ||
|
|
@@ -1343,7 +1361,7 @@ functions with explicit generic annotations. For old-style generics, | |
| we'll probably have to try to evaluate it and then raise an error when | ||
| we encounter a variable.) | ||
|
|
||
| With our real syntax, this look likes:: | ||
| With our real syntax, this looks like:: | ||
|
|
||
| type Foo = NewProtocol[ | ||
| Member[ | ||
|
|
@@ -1888,10 +1906,6 @@ Open Issues | |
| would be to mirror ``inspect.Signature`` more directly, and have an enum | ||
| with names like ``ParamKind.POSITIONAL_OR_KEYWORD``. Would that be better? | ||
|
|
||
| A related potential change would be to fully separate the kind from whether | ||
| there is a default, and have whether there is a default represented in | ||
| an ``init`` field, like we do for class member initializers with ``Member``. | ||
|
|
||
| * :ref:`Members <pep827-members>`: Should ``Members`` return all | ||
| methods, even those without annotations? We excluded them out of the | ||
| desire for some consistency with attributes, but it would not be | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like a strange use of Never. I would try to align these kinds with the ones in inspect: https://docs.python.org/3.15/library/inspect.html#inspect.Parameter.kind
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a planned follow-up to change the literals to actually be enums modeled directly after
Parameter.kindthat I wanted to keep separate from this. But I guess I can make t he default one "positional-or-named" now also while still strings