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-44975: [typing] Support issubclass for ClassVar data members by Fidget-Spinner · Pull Request #27883 · python/cpython

Conversation

@Fidget-Spinner

@Fidget-Spinner Fidget-Spinner commented Aug 22, 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/issue44975

Sorry, something went wrong.

Uh oh!

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

All reactions
@Fidget-Spinner
Support issubclass for ClassVar data members
a613af6
@Fidget-Spinner
Fidget-Spinner requested a review from gvanrossum as a code owner August 22, 2021 09:01
@the-knights-who-say-ni the-knights-who-say-ni added the CLA signed label Aug 22, 2021
@bedevere-bot bedevere-bot added the awaiting review label Aug 22, 2021
@Fidget-Spinner

Fidget-Spinner commented Aug 22, 2021

Copy link
Copy Markdown
Member Author

CC @uriyyo please take a look. Thank you.

All reactions

Sorry, something went wrong.

Uh oh!

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

@Fidget-Spinner Fidget-Spinner mentioned this pull request Aug 22, 2021
Allow issubclass for protocols with class variables python/typing#822
Open
@Fidget-Spinner Fidget-Spinner added the type-feature A feature request or enhancement label Aug 22, 2021
uriyyo
uriyyo reviewed Aug 22, 2021
View reviewed changes

@uriyyo uriyyo 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.

LGTM💫

I have few minor questions

Sorry, something went wrong.

Uh oh!

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

All reactions
Comment thread Lib/typing.py

def _is_callable_members_only(cls):
attr_names = _get_protocol_attrs(cls)
annotations = getattr(cls, '__annotations__', {})

@uriyyo uriyyo Aug 22, 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.

What about using typing.get_type_hints to resolve annotations for a class?

It will allow having ClassVar annotated as str:

@runtime_checkable
class P(Protocol):
    x: 'ClassVar[int]' = 1
Suggested change
annotations = getattr(cls, '__annotations__', {})
annotations = get_type_hints(cls)

Sorry, something went wrong.

Uh oh!

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

All reactions

@Fidget-Spinner Fidget-Spinner Aug 23, 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.

Good question! I'd considered that too but decided against it for two main reasons:

  1. get_type_hints is slow
  2. get_type_hints won't work with forward references/ PEP 563 if ClassVar is not defined in the caller's namespace

Consider the following:

# foo.py
from __future__ import annotations
from typing import *

@runtime_checkable
class X(Protocol):
 x: ClassVar[int] = 1
 y: SomeUndeclaredType = None
# bar.py
from .foo import X
class Y: ...

# Error! get_type_hints cannot resolve 'ClassVar' and 'SomeUndeclaredType'
issubclass(X, Y)

Nonetheless, your suggestion has reminded me of a basic workaround for string annotations. Thanks.

Sorry, something went wrong.

Uh oh!

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

uriyyo reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
Comment thread Lib/typing.py Resolved

Uh oh!

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

@Fidget-Spinner
make it work with string annotations and PEP 563
f045d2e
uriyyo
uriyyo approved these changes Aug 23, 2021
View reviewed changes

@uriyyo uriyyo left a comment •
edited
Loading

Uh oh!

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

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.

LGTM💫

Sorry, something went wrong.

Uh oh!

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

All reactions
@bedevere-bot bedevere-bot added awaiting core review and removed awaiting review labels Aug 23, 2021
ambv
ambv reviewed Aug 23, 2021
View reviewed changes
Comment thread Lib/typing.py Resolved

Uh oh!

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

Comment thread Lib/typing.py Resolved

Uh oh!

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

Fidget-Spinner and others added 3 commits August 24, 2021 21:14
@Fidget-Spinner
Apply Lukasz' suggestions
58c69e1
@Fidget-Spinner
fix test
2ed2ee5
@Fidget-Spinner @ambv
Use identity check instead of equality
c842370
Co-authored-by: Łukasz Langa <[email protected]>
sobolevn
sobolevn reviewed Sep 23, 2021
View reviewed changes

@sobolevn sobolevn 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.

👍

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

class C: pass

class D:

@sobolevn sobolevn Sep 23, 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.

Let's also add a case with the same class prop, but different value. Example:

class E:
    x = 2

Because right now all names / values always match. It is not clear whether value is a part of the protocol or not.

Sorry, something went wrong.

Uh oh!

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

All reactions

@Fidget-Spinner Fidget-Spinner Dec 5, 2021 •
edited
Loading

Uh oh!

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

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.

Agreed.

It is not clear whether value is a part of the protocol or not.

It shouldn't be. IMO, we should only care about the "shape". Trying to runtime-check the value is difficult and should be left to third-party libs to do.

Nevermind, I changed my mind. Let's do 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 Resolved

Uh oh!

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

Comment thread Lib/test/test_typing.py
x = 1
self.assertNotIsSubclass(C, P)
self.assertIsSubclass(D, P)

@sobolevn sobolevn Sep 23, 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.

Let's also test these classes:

class G:
   x: ClassVar[int] = 1
class H:
   x: 'ClassVar[int]' = 1

Sorry, something went wrong.

Uh oh!

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

All reactions

@Fidget-Spinner Fidget-Spinner Dec 5, 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.

These aren't testing more code paths, the code doesn't look at the annotations of the first class argument in issubclass.

Sorry, something went wrong.

Uh oh!

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

All reactions
Comment thread Lib/typing.py Resolved

Uh oh!

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

Fidget-Spinner added 4 commits December 5, 2021 22:39
@Fidget-Spinner
Merge remote-tracking branch 'upstream/main' into issubclass_data_pro…
f44d3b6
…tocols
@Fidget-Spinner
fix merge issues
9278a34
@Fidget-Spinner
Add more tests and comments
ba57bb1
@Fidget-Spinner
support value checking classvars
43ec2ea
@Fidget-Spinner

Fidget-Spinner commented Dec 5, 2021

Copy link
Copy Markdown
Member Author

TODO: Docs need updating.

All reactions

Sorry, something went wrong.

Uh oh!

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

JelleZijlstra
JelleZijlstra reviewed Jan 21, 2022
View reviewed changes
Comment thread Lib/typing.py
instance_attr = getattr(instance, attr_name, None)
if (instance_attr is not None
and attr is not None
and type(instance_attr) != type(attr)):

@JelleZijlstra JelleZijlstra Jan 21, 2022

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 is incorrect. Consider this example:

class P(Protocol):
     x: ClassVar[object] = object()

class Y:
     x: ClassVar[object] = 1

Y implements protocol P, but your code rejects it. There are also problems with None here that could produce an incorrect result.

I'd recommend removing this whole check, and just checking that the attribute exists. Full runtime type checking is hard and the standard library shouldn't try to do it.

Sorry, something went wrong.

Uh oh!

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

All reactions
@JelleZijlstra

JelleZijlstra commented Apr 13, 2022

Copy link
Copy Markdown
Member

@Fidget-Spinner are you still interested in this PR?

All reactions

Sorry, something went wrong.

Uh oh!

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

@Fidget-Spinner

Fidget-Spinner commented Apr 13, 2022

Copy link
Copy Markdown
Member Author

@JelleZijlstra hmm not really. I'm not too inclined on runtime checking in the standard library. IMO it's something we should leave to expert 3rd party libs.

All reactions

Sorry, something went wrong.

Uh oh!

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

@AlexWaygood AlexWaygood added the topic-typing label Apr 13, 2022
@ezio-melotti ezio-melotti removed the CLA signed label Jul 13, 2022
@Fidget-Spinner Fidget-Spinner mentioned this pull request Oct 10, 2022
[typing] Runtime protocols with ClassVar data members should support issubclass #89138
Closed
@gvanrossum

gvanrossum commented Oct 10, 2022

Copy link
Copy Markdown
Member

See #89138 -- maybe we should just abandon this?

All reactions

Sorry, something went wrong.

Uh oh!

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

@hauntsaninja hauntsaninja closed this Oct 11, 2022
@Fidget-Spinner
Fidget-Spinner deleted the issubclass_data_protocols branch October 11, 2022 05:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@ambv ambv ambv left review comments
@JelleZijlstra JelleZijlstra JelleZijlstra left review comments
@sobolevn sobolevn sobolevn left review comments
@uriyyo uriyyo uriyyo approved these changes
@gvanrossum gvanrossum Awaiting requested review from gvanrossum

Uh oh!

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

Assignees

No one assigned

Labels

awaiting core review topic-typing type-feature A feature request or enhancement

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.

11 participants

@Fidget-Spinner @JelleZijlstra @gvanrossum @ambv @sobolevn @uriyyo @hauntsaninja @the-knights-who-say-ni @ezio-melotti @bedevere-bot @AlexWaygood
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 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.