python / python/typeshed

Using typing.NoDefault instead of Ellipsis [3.13]

Open
#12,102 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
5.1k
Forks
2.1k
Avg merge
1d 19h
Merged PRs (30d)
82

Description

ParamSpec, TypeVar, TypeVarTuple have a __default__ attribute, which is evaluated to NoDefault, when no default is provided in constructor :

from typing import ParamSpec, TypeVar, TypeVarTuple, Any

print(f'{TypeVar("Plop").__default__ = }')
...

# ❯ python3.13 /tmp/tmpe9xlgjg8.py
TypeVar("Plop").__default__ = typing.NoDefault
TypeVarTuple("Plop").__default__ = typing.NoDefault
ParamSpec("Plop").__default__ = typing.NoDefault

TypeVar("Plop", default=Any).__default__ = typing.Any
TypeVarTuple("Plop", default=Any).__default__ = typing.Any
ParamSpec("Plop", default=Any).__default__ = typing.Any

But this behaviour is not implemented in stubs, Ellipsis is used instead of typing.NoDefault which is already in stubs. I guess it could be fixed without breaking risks.

diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi
index f04b2d858..a84a517cc 100644
--- a/stdlib/typing.pyi
+++ b/stdlib/typing.pyi
@@ -161,7 +161,7 @@ class TypeVar:
             contravariant: bool = False,
             covariant: bool = False,
             infer_variance: bool = False,
-            default: Any = ...,
+            default: Any = NoDefault,
         ) -> None: ...
     elif sys.version_info >= (3, 12):
         def __init__(
@@ -231,7 +231,7 @@ if sys.version_info >= (3, 11):
             def __default__(self) -> Any: ...
             def has_default(self) -> bool: ...
         if sys.version_info >= (3, 13):
-            def __init__(self, name: str, *, default: Any = ...) -> None: ...
+            def __init__(self, name: str, *, default: Any = NoDefault) -> None: ...
         else:
             def __init__(self, name: str) -> None: ...
 
@@ -279,7 +279,7 @@ if sys.version_info >= (3, 10):
                 contravariant: bool = False,
                 covariant: bool = False,
                 infer_variance: bool = False,
-                default: Any = ...,
+                default: Any = NoDefault,
             ) -> None: ...
         elif sys.version_info >= (3, 12):
             def __init__(

Ps :

print(f'{TypeVar("Plop").__default__ is TypeVarTuple("Plop").__default__ is ParamSpec("Plop").__default__ = }')
❯ python3.13 /tmp/tmpe9xlgjg8.py
TypeVar("Plop").__default__ is TypeVarTuple("Plop").__default__ is ParamSpec("Plop").__default__ = True
TypeVar("Plop").__default__ is Ellipsis = False

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Review the TypeVar, TypeVarTuple, and ParamSpec definitions in stdlib/typing.pyi, focusing on their default parameters and the existing NoDefault stub. Update the Python 3.13 signatures so omitted defaults correspond to typing.NoDefault, and confirm the stub no longer represents them as Ellipsis.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
tooling
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.