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

Consider reintroducing types.EllipsisType for the sake of typing #85976

Closed
BvB93 mannequin opened this issue Sep 18, 2020 · 24 comments
Closed

Consider reintroducing types.EllipsisType for the sake of typing #85976

BvB93 mannequin opened this issue Sep 18, 2020 · 24 comments
Labels
3.10 only security fixes stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@BvB93
Copy link
Mannequin

BvB93 mannequin commented Sep 18, 2020

BPO 41810
Nosy @gvanrossum, @rhettinger, @ericvsmith, @markshannon, @serhiy-storchaka, @ilevkivskyi, @SamuelMarks, @BvB93, @joshbode
PRs
  • bpo-41810: Reintroduce types.EllipsisType, .NoneType & .NotImplementedType #22336
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2020-09-22.15:55:57.057>
    created_at = <Date 2020-09-18.19:29:00.494>
    labels = ['type-feature', 'library', '3.10']
    title = 'Consider reintroducing `types.EllipsisType` for the sake of typing'
    updated_at = <Date 2020-11-05.09:51:11.541>
    user = 'https://github.com/BvB93'

    bugs.python.org fields:

    activity = <Date 2020-11-05.09:51:11.541>
    actor = 'eric.smith'
    assignee = 'none'
    closed = True
    closed_date = <Date 2020-09-22.15:55:57.057>
    closer = 'gvanrossum'
    components = ['Library (Lib)']
    creation = <Date 2020-09-18.19:29:00.494>
    creator = 'BvB93'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 41810
    keywords = ['patch']
    message_count = 22.0
    messages = ['377135', '377154', '377165', '377167', '377169', '377178', '377248', '377250', '377255', '377259', '377264', '377267', '377269', '377274', '377275', '377277', '377280', '377281', '377282', '377340', '380400', '380401']
    nosy_count = 9.0
    nosy_names = ['gvanrossum', 'rhettinger', 'eric.smith', 'Mark.Shannon', 'serhiy.storchaka', 'levkivskyi', 'samuelmarks', 'BvB93', 'joshbode']
    pr_nums = ['22336']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue41810'
    versions = ['Python 3.10']

    @BvB93
    Copy link
    Mannequin Author

    BvB93 mannequin commented Sep 18, 2020

    Ellipsis is one of the few builtin objects whose type is not exposed via the types module.
    This is not really an issue during runtime, as you can always call type(Ellipsis), but for the purpose of typing it is detrimental; the lack of suitable type means that it is impossible to properly annotate a function which takes or returns Ellipsis (unless one is willing to resort to the use of non-public types: python/typeshed#3556).

    In order to resolve this issue I propose to reintroduce types.EllipsisType. This should be a fairly simple process, so if there are no objections I'd be willing to give it a shot.

    @BvB93 BvB93 mannequin added 3.10 only security fixes stdlib Python modules in the Lib dir type-feature A feature request or enhancement labels Sep 18, 2020
    @serhiy-storchaka
    Copy link
    Member

    Can not type(Ellipsis) be used for typing too?

    @BvB93
    Copy link
    Mannequin Author

    BvB93 mannequin commented Sep 19, 2020

    If you're asking whether or not one can infer the return type of type(Ellipsis) then yes.
    In such case the inferred type is builtins.ellipsis, which is a private stub-only class (see the referenced typeshed issue in my original post).

    If you're asking if a valid annotation can be constructed from type(Ellipsis) then the answer is unfortunately no (see below for a few examples).

    EllipsisType = type(Ellipsis)
    
    # Both examples are considered invalid
    def func1(a: type(Ellipsis): ...
    def func2(a: EllipsisType): ...
    
    

    @gvanrossum
    Copy link
    Member

    Let’s do this.

    @serhiy-storchaka
    Copy link
    Member

    Would not be better to make MyPy supporting type(Ellipsis)? It would work also on Python versions older than 3.10.

    Also, could not Literal[Ellipsis] be used as annotation?

    @gvanrossum
    Copy link
    Member

    Would not be better to make MyPy supporting type(Ellipsis)? It would work also on Python versions older than 3.10.

    That would be quite complicated. There is no place in annotations where a function call is currently supported, so I'd prefer not to go there.

    Also, could not Literal[Ellipsis] be used as annotation?

    Alas, it currently doesn't work (PEP-586 only allows specific types, and type checkers have implemented it exactly). Making it work would be more complicated than the proposal -- once it exists in types.py, it's trivial to add support to mypy.

    IMO ideally, eventually, all "hidden" built-in types ought to be exposed somewhere, unless they are truly implementation details -- but since Ellipsis is a first-class singleton object, I don't see how its type could be an implementation detail. (Its name is actually clearly visible in repr(type(Ellipsis)).)

    Note that we have started exporting the types of other constructs through types.py, e.g. type(int|str) is types.Union, and type(list[str]) is types.GenericAlias. This is revealed in their repr().

    @BvB93
    Copy link
    Mannequin Author

    BvB93 mannequin commented Sep 21, 2020

    If we're going ahead with this: PR #22336 contains a concrete implementation of the proposed changes.

    @markshannon
    Copy link
    Member

    I can't resist the pun on typing.
    type(...) is the least typing :)

    More seriously,

    From a general consistency point of view,
    if this is to be added, shouldn't types.NoneType and types.NotImplementedType be added as well?

    @gvanrossum
    Copy link
    Member

    I’m okay with adding those (even though NoneType might not work in mypy, given the special-casing for None, per PEP-484).

    @BvB93
    Copy link
    Mannequin Author

    BvB93 mannequin commented Sep 21, 2020

    Apparently pyright has some interest in NoneType (python/typeshed#4519), so it seems there are already some actual use cases.

    In any case, I'm ok with adding NoneType and NotImplementedType to the PR.

    @gvanrossum
    Copy link
    Member

    In any case, I'm ok with adding NoneType and NotImplementedType to the PR.

    Please do.

    @BvB93
    Copy link
    Mannequin Author

    BvB93 mannequin commented Sep 21, 2020

    NoneType and NotImplementedType have been added to the PR as of the latest set of pushes.

    @ericvsmith
    Copy link
    Member

    Does anyone know why types.EllipsisType was removed to begin with? I just want to make sure we're not repeating some mistake of the past.

    @gvanrossum
    Copy link
    Member

    Bas can you do some research to answer Eric's question? In theory it should be possible to use git bisect to find it. I see it in 2.7 but not in 3.4. That's a fairly large interval, alas.

    @BvB93
    Copy link
    Mannequin Author

    BvB93 mannequin commented Sep 21, 2020

    According to the relevant commit (c9543e4):
    "Removed all types from the 'types' module that are easily accessible through builtins."

    @gvanrossum
    Copy link
    Member

    Thanks! Most of the deleted types *are* builtins (e.g. object, int). I assume the reasoning was just that if you wanted the type you could just write type(Ellipsis), type(None) etc.

    But that's too dynamic for static checkers, so we want *some* stable name for those back. Do any of the other deleted types strike you as possibly needing to come back?

    @BvB93
    Copy link
    Mannequin Author

    BvB93 mannequin commented Sep 21, 2020

    Do any of the other deleted types strike you as possibly needing to come back?

    I don't think so, no. The only other one that stands out to me is DictProxyType, which has already been reintroduced as MappingProxyType.

    @ericvsmith
    Copy link
    Member

    Thanks for doing the research, Bas! It sounds like adding back in NoneType, NotImplementedType, and EllipsisType is appropriate, then.

    +1

    The commit should have a comment about the reason: for type checkers which can't use type(Ellipsis), etc. I'll add a comment on the PR about adding a similar note to the blurb.

    @rhettinger
    Copy link
    Contributor

    Do any of the other deleted types strike you as possibly
    needing to come back?

    Yes. NoneType would be useful.

    @gvanrossum
    Copy link
    Member

    New changeset 0d0e9fe by Bas van Beek in branch 'master':
    bpo-41810: Reintroduce types.EllipsisType, .NoneType & .NotImplementedType (GH-22336)
    0d0e9fe

    @SamuelMarks
    Copy link
    Mannequin

    SamuelMarks mannequin commented Nov 5, 2020

    Since we're bringing these back, would you accept a backport of these types?

    [I'm writing a bunch of parsers/emitters—and starting to maintain an old runtime type-checker—for 3.6+]

    @ericvsmith
    Copy link
    Member

    I don't think we should backport them. It's definitely a new feature, and our policy is no new features in micro versions.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    @tsibley
    Copy link

    tsibley commented Aug 30, 2023

    How does one get access to the type of Ellipsis (for type annotation purposes, not at runtime) on Pythons older than 3.10, i.e. where the types.EllipsisType introduced here isn't available? There's typing_extensions for backported typing features, but no equivalent for types?

    (The "right" place to raise this sort of issue/question isn't clear to me, so if this isn't the right place, please let me know or point me elsewhere.)

    @gvanrossum
    Copy link
    Member

    try the typing category on discuss.python.org?

    tsibley added a commit to nextstrain/cli that referenced this issue Aug 30, 2023
    pyright 1.1.325 (released yesterday) added support for @type_check_only
    decorators¹, which were added (a year ago) to the builtins.ellipsis type
    of the stdlib typeshed².  This type is available only during
    type-checking and doesn't actually exist at runtime, but previously
    pyright didn't care about that (and mypy still doesn't).  Now it does,
    noticed thanks to scheduled CI, and throws an error like:
    
        "ellipsis" is marked as @type_check_only and can be used only in
        type annotations (reportGeneralTypeIssues)
    
    Explicitly clarify to pyright that our variable is a type alias³ and not
    a value also used at runtime so it knows its ok to use the type of
    Ellipsis (via a forward reference to the now-you-see-it, now-you-don't
    builtins.ellipsis).
    
    Relatedly, we can switch from 'builtins.ellipsis' → types.EllipsisType
    on Python ≥3.10⁴ and stop using the private/internal type for Ellipsis.
    I'll do that in the subsequent commit.
    
    ¹ <microsoft/pyright#5817>
    
    ² <python/typeshed@a92da58>
      <python/typeshed#8531>
    
    ³ <https://docs.python.org/3/library/typing.html#typing.TypeAlias>
      <https://peps.python.org/pep-0613/>
    
    ⁴ <https://docs.python.org/3/library/types.html#types.EllipsisType>
      <python/cpython#85976>
    tsibley added a commit to nextstrain/cli that referenced this issue Aug 30, 2023
    The former is preferable as its not a private/internal type¹, but it's
    only available on on Python ≥3.10.²
    
    ¹ <python/cpython#85976>
    ² <https://docs.python.org/3/library/types.html#types.EllipsisType>
    tsibley added a commit to nextstrain/cli that referenced this issue Aug 31, 2023
    The former is preferable as its not a private/internal type¹, but it's
    only available on on Python ≥3.10.²
    
    ¹ <python/cpython#85976>
    ² <https://docs.python.org/3/library/types.html#types.EllipsisType>
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.10 only security fixes stdlib Python modules in the Lib dir type-feature A feature request or enhancement
    Projects
    None yet
    Development

    No branches or pull requests

    6 participants