@@ -329,67 +329,6 @@ traditionally typed ``**kwargs`` aren't checked for keyword names.
329329To summarize, function parameters should behave contravariantly and function
330330return types should behave covariantly.
331331
332- Passing kwargs inside a function to another function
333- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
334-
335- :ref: `A previous point <PEP 692 assignment dest no kwargs >`
336- mentions the problem of possibly passing additional keyword arguments by
337- assigning a subclass instance to a variable that has a base class type. Let's
338- consider the following example::
339-
340- class Animal(TypedDict):
341- name: str
342-
343- class Dog(Animal):
344- breed: str
345-
346- def takes_name(name: str): ...
347-
348- dog: Dog = {"name": "Daisy", "breed": "Labrador"}
349- animal: Animal = dog
350-
351- def foo(**kwargs: Unpack[Animal]):
352- print(kwargs["name"].capitalize())
353-
354- def bar(**kwargs: Unpack[Animal]):
355- takes_name(**kwargs)
356-
357- def baz(animal: Animal):
358- takes_name(**animal)
359-
360- def spam(**kwargs: Unpack[Animal]):
361- baz(kwargs)
362-
363- foo(**animal) # OK! foo only expects and uses keywords of 'Animal'.
364-
365- bar(**animal) # WRONG! This will fail at runtime because 'breed' keyword
366- # will be passed to 'takes_name' as well.
367-
368- spam(**animal) # WRONG! Again, 'breed' keyword will be eventually passed
369- # to 'takes_name'.
370-
371- In the example above, the call to ``foo `` will not cause any issues at
372- runtime. Even though ``foo `` expects ``kwargs `` of type ``Animal `` it doesn't
373- matter if it receives additional arguments because it only reads and uses what
374- it needs completely ignoring any additional values.
375-
376- The calls to ``bar `` and ``spam `` will fail because an unexpected keyword
377- argument will be passed to the ``takes_name `` function.
378-
379- Therefore, ``kwargs `` hinted with an unpacked ``TypedDict `` can only be passed
380- to another function if the function to which unpacked kwargs are being passed
381- to has ``**kwargs `` in its signature as well, because then additional keywords
382- would not cause errors at runtime during function invocation. Otherwise, the
383- type checker should generate an error.
384-
385- In cases similar to the ``bar `` function above the problem could be worked
386- around by explicitly dereferencing desired fields and using them as arguments
387- to perform the function call::
388-
389- def bar(**kwargs: Unpack[Animal]):
390- name = kwargs["name"]
391- takes_name(name)
392-
393332Using ``Unpack `` with types other than ``TypedDict ``
394333^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
395334
0 commit comments