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 — bpo-44801: Check arguments in substitution of ParamSpec in Callable by serhiy-storchaka · Pull Request #27585 · python/cpython

Conversation

@serhiy-storchaka

@serhiy-storchaka serhiy-storchaka commented Aug 3, 2021 •
edited by bedevere-bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

https://bugs.python.org/issue44801

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@serhiy-storchaka
bpo-44801: Check arguments in substitution of ParamSpec in Callable
cd2ccff
@serhiy-storchaka serhiy-storchaka added type-bug An unexpected behavior, bug, or error needs backport to 3.10 labels Aug 3, 2021
@serhiy-storchaka
serhiy-storchaka requested a review from Fidget-Spinner August 3, 2021 18:12
@serhiy-storchaka
serhiy-storchaka requested review from gvanrossum and rhettinger as code owners August 3, 2021 18:12
@bedevere-bot bedevere-bot added the awaiting core review label Aug 3, 2021
@the-knights-who-say-ni the-knights-who-say-ni added the CLA signed label Aug 3, 2021
Fidget-Spinner
Fidget-Spinner approved these changes Aug 4, 2021
View reviewed changes

@Fidget-Spinner Fidget-Spinner left a comment

Copy link
Copy Markdown
Member

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.

Phew, that was harder than I expected to review 😉 .

Thanks for fixing this Serhiy, it looks good to me (and also seems like it follows the PEP more closely now :).

We might not be able to backport this until 3.10.1. I don't think such a huge change can land in rc2.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/_collections_abc.py
for arg in self.__args__:
if _is_typevarlike(arg):
arg = subst[arg]
if _is_param_expr(arg):

@Fidget-Spinner Fidget-Spinner Aug 4, 2021

Copy link
Copy Markdown
Member

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.

Checking for something like _is_paramspec would be clearer IMO, but we don't have that function and it's kind of a waste to make a function just for this one-time use.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@serhiy-storchaka serhiy-storchaka Aug 4, 2021

Copy link
Copy Markdown
Member Author

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.

This code will gone after moving the logic in ParamSpec.__getitem__ in #27511.

I am planning first to fix most bugs and to cover more cases by tests, and only then apply #27511, so we may not need to backport it.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/test/test_typing.py
C1 = Callable[P, T]
# substitution
self.assertEqual(C1[int, str], Callable[[int], str])
self.assertEqual(C1[[int], str], Callable[[int], str])

@Fidget-Spinner Fidget-Spinner Aug 4, 2021

Copy link
Copy Markdown
Member

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.

Hmm I feel a little strange about this. I feel that the new form is correct, but I also feel the old form should work. There's not much ambiguity in using the old form.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@serhiy-storchaka serhiy-storchaka Aug 4, 2021

Copy link
Copy Markdown
Member Author

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.

The PEP explicitly claim that only substituting ParamSpec with the parameters expression should be accepted. It will also simplify the future code.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@Fidget-Spinner Fidget-Spinner Aug 4, 2021

Copy link
Copy Markdown
Member

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.

Ah ok I see it now:

def f(x: X[int, int]) -> str: ...                    # Rejected

Thanks for the reminder.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/test/test_typing.py
self.assertEqual(C1[int, str], Callable[[int], str])
self.assertEqual(C1[[int], str], Callable[[int], str])
self.assertEqual(C1[[int, str], str], Callable[[int, str], str])
self.assertEqual(C1[[], str], Callable[[], str])

@Fidget-Spinner Fidget-Spinner Aug 4, 2021

Copy link
Copy Markdown
Member

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.

Good test! 👍

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/test/test_typing.py
self.assertEqual(G5, G6)

G7 = Z[int]
self.assertEqual(G7.__args__, ((int,),))

@Fidget-Spinner Fidget-Spinner Aug 4, 2021

Copy link
Copy Markdown
Member

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.

This isn't a critique of your PR, but a minor regret of mine: Looking at G5, G6, G7, I realized their __args__ should be (int, str, bool) or (int, ), etc.; not nested tuple with types. Nested tuple makes repr weird, and also nested tuple means any nested TypeVar or ParamSpec won't appear in __parameters__ and so can't be substituted.

I don't remember what made me code it like that back then, but it could be me not wanting to make the _GenericAlias.__getitem__ code complicated just for ParamSpec.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@serhiy-storchaka serhiy-storchaka Aug 4, 2021

Copy link
Copy Markdown
Member Author

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.

It does not work for user generics because they can have more than one ParamSpec. For example:

class X(Generic[P1, P2]):
    f: Callable[P1, int]
    g: Callable[P2, str]
G1 = X[[int, str], [bytes]]
G2 = X[int, [str, bytes]]
assert G1.__args__ == ((int, str), (bytes,))
assert G2.__args__ == ((int,) (str, bytes))

If flatten arguments, __args__ of G1 and G2 would be the same ((int, str, bytes)). But they are clearly different types.

I'll add a special test for this.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@Fidget-Spinner Fidget-Spinner Aug 4, 2021

Copy link
Copy Markdown
Member

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.

Right, thanks for pointing that out! I forgot there was ambiguity with multiple ParamSpec. Hopefully some future PEP makes this clearer.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@serhiy-storchaka
Merge branch 'main' into callable-paramspec-subst
7583789
Fidget-Spinner
Fidget-Spinner approved these changes Aug 4, 2021
View reviewed changes

@Fidget-Spinner Fidget-Spinner left a comment

Copy link
Copy Markdown
Member

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.

Again, LGTM. Thanks for patiently addressing my questions Serhiy :).

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@serhiy-storchaka
Add a test for multiple paramspecs in user generics.
6770ca9
@ambv
ambv merged commit 3875a69 into python:main Aug 4, 2021
@miss-islington

miss-islington commented Aug 4, 2021

Copy link
Copy Markdown
Contributor

Thanks @serhiy-storchaka for the PR, and @ambv for merging it 🌮🎉.. I'm working now to backport this PR to: 3.10.
🐍🍒⛏🤖

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-bot bedevere-bot removed the awaiting core review label Aug 4, 2021
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Aug 4, 2021
@serhiy-storchaka @miss-islington
bpo-44801: Check arguments in substitution of ParamSpec in Callable (p…
89971f3
…ythonGH-27585)

(cherry picked from commit 3875a69)

Co-authored-by: Serhiy Storchaka <[email protected]>
@bedevere-bot bedevere-bot removed the needs backport to 3.10 label Aug 4, 2021
@bedevere-bot

bedevere-bot commented Aug 4, 2021

Copy link
Copy Markdown

GH-27598 is a backport of this pull request to the 3.10 branch.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

miss-islington added a commit that referenced this pull request Aug 4, 2021
@miss-islington @serhiy-storchaka
bpo-44801: Check arguments in substitution of ParamSpec in Callable (G…
536e35a
…H-27585)

(cherry picked from commit 3875a69)

Co-authored-by: Serhiy Storchaka <[email protected]>
@serhiy-storchaka
serhiy-storchaka deleted the callable-paramspec-subst branch July 1, 2026 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@Fidget-Spinner Fidget-Spinner Fidget-Spinner approved these changes
@gvanrossum gvanrossum Awaiting requested review from gvanrossum
@rhettinger rhettinger Awaiting requested review from rhettinger rhettinger is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

type-bug An unexpected behavior, bug, or error

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

6 participants

@serhiy-storchaka @miss-islington @bedevere-bot @Fidget-Spinner @ambv @the-knights-who-say-ni
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.
You are visitor 01402520 — 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.