GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — NamedTupleInterface · Issue #431 · python/typing

NamedTupleInterface #431

New issue
Copy link
New issue
Copy link
Closed
Closed
NamedTupleInterface#431
Copy link

Description

@zauddelig
zauddelig
opened on May 15, 2017
Issue body actions

Hello, I already wrote on python-ideas group, I frequently am in need to have abstract access to the NamedTuple API, here a very simple exapmple:

from typing import NamedTupleType

def test(
    arguments: NamedTupleType
) -> NamedTupleType:
    return SomeType(**NamedTupleType._asdict) 

At the moment I have two hotfix:
Overload the namedtuple factory, but somewhat breaking my IDE or creating a fake namedtuple but both of them are hacks.

If my proposal get accepted I'm willingly to do the coding part :)
Thanks

Reacted by Mitar

Activity

  1. ilevkivskyi commented on May 16, 2017

    @ilevkivskyi
    ilevkivskyi
    on May 16, 2017
    Member
    More actions

    Sorry, but it is still not clear what exactly do you need. If you just want to annotate a function parameter so that arbitrary named tuple can be passed there, then this will be solved by protocols, see #417 and PEP 544 (there are links to implementations for mypy and typeshed). For example something like this:

    T = TypeVar('T', bound='NamedTupleProto')
    
    class NamedTupleProto(Protocol):
        _source: str
        _fields: Tuple[str]
        def _asdict(self) -> Dict[str, Any]: ...
        @classmethod
        def _make(cls: Type[T], iterable: Iterable[Any], *,
                  new: Any = None, len: int = None) -> T: ...
        def __getitem__(self, item: int) -> Any: ...
    
    def f(arg: NamedTupleProto) -> Dict[str, Any]:
       arg[0]
       return arg._asdict()
    
    class A(NamedTuple):
        a: int
    class B(NamedTuple):
        b: int
    
    x: A
    y: B
    f(x) # OK
    f(y) # OK

    If you need only some part of the named tuple API, you could define a much simpler protocol.

    EDIT: If you need the full named tuple API, then NamedTupleProto should also subclass Sequence (to pull also __len__, __iter__, etc) and declare few other methods (like _replace).

  2. gvanrossum commented on May 16, 2017

    @gvanrossum
    gvanrossum
    on May 16, 2017 via email
    Member
    More actions
    Is there a workaround we can use before that PEP is ready? Or is Any the closest we can get without protocols?
    …
    On May 16, 2017 2:30 AM, "Ivan Levkivskyi" ***@***.***> wrote: Sorry, but it is still not clear what exactly do you need. If you just want to annotate a function parameter so that arbitrary named tuple can be passed there, then this will be solved by protocols, see #417 <#417> and PEP 544 (there are links to implementations for mypy and typeshed). For example something like this: T = TypeVar('T', bound='NamedTupleProto') class NamedTupleProto(Protocol): _source: str _fields: Tuple[str] def _asdict(self) -> Dict[str, Any]: ... @classmethod def _make(cls: Type[T], iterable: Iterable[Any], *, new: Any = None, len: int = None) -> T: ... def __getitem__(self, item: int) -> Any: ... def f(arg: NamedTupleProto) -> Dict[str, Any]: arg[0] return arg._asdict() class A(NamedTuple): a: intclass B(NamedTuple): b: int x: A y: B f(x) # OK f(y) # OK If you need only some part of the named tuple API, you could define a much simpler protocol. — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub <#431 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/ACwrMgybTgGVUKtr_8lDkkZ7ad4hV5Fvks5r6Wy7gaJpZM4NbwsB> .
  3. zauddelig commented on May 16, 2017

    @zauddelig
    zauddelig
    on May 16, 2017
    Author
    More actions

    I fear we are comparing an elephant and an ant here.. Anyway to require an user to define an implicit protocol to describe a core library interface does not make a lot of sense.

    At the moment I use various workarounds depending on the project, like creating the ABC myself and register my namedtuples manually, or use Any.

    What I want to archive is not hard conceptually, NamedTupleType would be used exactly like typing.Tuple, but exposing the NamedTuple API as well. Out of the obvious it would also be a nice place to document namedtuples API incode, and it would probably make the life easier to code checker when accessing namedtuples' public methods .

  4. gvanrossum commented on May 16, 2017

    @gvanrossum
    gvanrossum
    on May 16, 2017
    Member
    More actions

    What I want to archive is not hard conceptually

    OK, submit a PR and maybe we'll merge it.

  5. ilevkivskyi commented on May 16, 2017

    @ilevkivskyi
    ilevkivskyi
    on May 16, 2017
    Member
    More actions

    What I want to archive is not hard conceptually

    Note that implementing this in typing can be easy, but implementing this in mypy could be much harder. IIUC, essentially, you want a structural subtyping check, which would be just reimplementing protocols for a particular case (you could avoid this by injecting a "fake" nominal supertype during the semantic analysis of named tuples, but this could have other potential problems).

    In any case, as Guido mentioned, PRs are welcome.

  6. zauddelig commented on May 18, 2017

    @zauddelig
    zauddelig
    on May 18, 2017
    Author
    More actions

    Okey dokey, I'll work on it during the weekend :)
    @ilevkivski I actually was planning of doing that (injection) anyhow let's see.

  7. JukkaL commented on May 18, 2017

    @JukkaL
    JukkaL
    on May 18, 2017
    Contributor
    More actions

    @ilevkivskyi It may make sense to have NamedTupleProto also define __getattr__, for consistency with __getitem__.

    @zauddelig If something like NamedTupleProto is enough for you, you can just define this protocol once in some shared utility module and reuse it everywhere you need it. You can even publish it as a package on PyPI, and if it seems like many users find it useful, we can consider adding it to typing or mypy_extensions. Generally we are reluctant to add a feature (even a simple one) based on a request by a single user, especially if there is a workaround in sight that seems reasonable. Otherwise the static typing APIs will soon become very large and hard to learn, which is something we want to avoid. Each feature has a learning cost associated with it -- even if nobody needs some feature, most users will have to learn enough about the feature to at least be able to decide that it is something that they actually don't need.

  8. ilevkivskyi commented on May 18, 2017

    @ilevkivskyi
    ilevkivskyi
    on May 18, 2017
    Member
    More actions

    @JukkaL

    It may make sense to have NamedTupleProto also define __getattr__, for consistency with __getitem__.

    Probably. TBH I just picked some random attributes to illustrate the idea, but I rather think this is not the case where "one size fits all". At least it is not completely clear to me what is the "named tuple API".

  9. mitar commented on Sep 17, 2017

    @mitar
    mitar
    on Sep 17, 2017
    Contributor
    More actions

    Generally we are reluctant to add a feature (even a simple one) based on a request by a single user, especially if there is a workaround in sight that seems reasonable.

    I think there are at least three users until now who were surprised by this, see also python/mypy#3915.

    I think especially because in 3.6 NamedTuples have this nice class syntax. It then really looks like class and so it is surprising that one cannot just use it as a type.

  10. vnmabus commented on Jul 26, 2021

    @vnmabus
    vnmabus
    on Jul 26, 2021
    More actions
    _fields

    How can one access the _fields attribute from the namedtuple class itself instead of an instance of it? This protocol does not allow that, and using ClassVar does not seem to typecheck for me (maybe because _fields is read only somehow?).

  11. srittau commented on Nov 4, 2021

    @srittau
    srittau
    on Nov 4, 2021
    Collaborator
    More actions

    If this issue is still open, I think it should be reported to bugs.python.org.

  12. srittau
    closed this as completedon Nov 4, 2021
  13. sobolevn commented on Nov 4, 2021

    @sobolevn
    sobolevn
    on Nov 4, 2021
    Member
    More actions

    Related unmerged mypy PR: python/mypy#11162

    It allows to write:

        def deserialize_named_tuple(arg: NamedTuple) -> Dict[str, Any]:
            return arg._asdict()
    
        Point = namedtuple('Point', ['x', 'y'])
        Person = NamedTuple('Person', [('name', str), ('age', int)])
    
        deserialize_named_tuple(Point(x=1, y=2))  # ok
        deserialize_named_tuple(Person(name='Nikita', age=18))  # ok
    
        deserialize_named_tuple((1, 2))  
        # Argument 1 to "deserialize_named_tuple" has incompatible type "Tuple[int, int]"; expected "NamedTuple"

    Friendly ping to @JukkaL and @ilevkivskyi 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.