-
-
Notifications
You must be signed in to change notification settings - Fork 49
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
Ruh-roh! CACHING protocols? More like CRASHING protocols (in 3.7)! Amirite? #109
Comments
Okay. We're gonna dig deep into the fetid bowels of the The above exception means that
A few pithy examples, because I finally got to use the word "pithy": slam dunk >>> from beartype._util.hint.pep.utilpepget import get_hint_pep_sign_or_none
>>> get_hint_pep_sign_or_none(list[str])
HintSignList
>>> get_hint_pep_sign_or_none(str | int)
HintSignUnion
>>> get_hint_pep_sign_or_none(str)
None Simple types have no signs. Everything else supported by |
Also! This issue smells suspiciously like this conditional in # Protocol class to be passed as the "cls" parameter to the
# unwrapped superclass typing.Protocol.__class_getitem__()
# dunder method. There exist two unique cases corresponding to
# two unique branches of an "if" conditional in that method,
# depending on whether either this "Protocol" superclass or a
# user-defined subclass of this superclass is being
# subscripted. Specifically, this class is...
protocol_cls = (
# If this "Protocol" superclass is being directly
# subclassed by one or more type variables (e.g.,
# "Protocol[S, T]"), the non-caching "typing.Protocol"
# superclass underlying this caching protocol superclass.
# Since the aforementioned "if" conditional performs an
# explicit object identity test for the "typing.Protocol"
# superclass, we *MUST* pass that rather than this
# superclass to trigger that conditional appropriately.
_ProtocolSlow
if cls is Protocol else
# Else, a user-defined subclass of this "Protocol"
# superclass is being subclassed by one or more type
# variables *OR* types satisfying the type variables
# subscripting the superclass (e.g.,
# "UserDefinedProtocol[str]" for a user-defined subclass
# class UserDefinedProtocol(Protocol[AnyStr]). In this
# case, this subclass as is.
cls
) It's possible that the |
Oh no! 😬😢 I did not mean to ruin your Friday night. Those should be reserved for date night, or sipping hot tea by the wood pellet stove with a good book, or sipping luke warm tea from a thermos while freezing your butt off on some aluminum bleachers attending your kid's (or friend's kid's or other junior relative's or acquaintance's, but you know, like in a supportive way, not a super creepy way) extracurricular event, or feverishly trying to "just" finish that last minute herculean project for the boss who stopped by your desk at 4:30 p.m. before leaving you with a wink and a finger gun on his way out to "hit the slopes" this weekend for some "R&R". Wait. No. Scratch that last one. That doesn't belong. FWIW, I think you're onto something with
|
That's a funny way to spell "Mandatory Friday Afternoons at the Rick & Morty Matinee." Cottage country: you know we gets wild here. 😏
You know us well. Our 500-pound Main Coon cat Wolfie (so-named for good reason) rumbles contentedly. Your knowledge of the hidden life and hobbies of the average bottom-feeding Canadian cabin-dweller is... uncanny. I intended to insert additional quips here, but then got tired. Instead:
# Protocol class to be passed as the "cls" parameter to the
# unwrapped superclass typing.Protocol.__class_getitem__()
# dunder method. There exist two unique cases corresponding to
# two unique branches of an "if" conditional in that method,
# depending on whether either this "Protocol" superclass or a
# user-defined subclass of this superclass is being
# subscripted. Specifically, this class is...
protocol_cls = (
# If this "Protocol" superclass is being directly
# subclassed by one or more type variables (e.g.,
# "Protocol[S, T]"), the non-caching "typing.Protocol"
# superclass underlying this caching protocol superclass.
# Since the aforementioned "if" conditional performs an
# explicit object identity test for the "typing.Protocol"
# superclass, we *MUST* pass that rather than this
# superclass to trigger that conditional appropriately.
_ProtocolSlow
if cls is Protocol or IS_PYTHON_3_7 else
# Else, a user-defined subclass of this "Protocol"
# superclass is being subclassed by one or more type
# variables *OR* types satisfying the type variables
# subscripting the superclass (e.g.,
# "UserDefinedProtocol[str]" for a user-defined subclass
# class UserDefinedProtocol(Protocol[AnyStr]). In this
# case, this subclass as is.
cls
)
🦾
...heh. If it wasn't hard, Guido would have done it. This is why he didn't. We suffer that others may actually use protocols at runtime. We do this in remembrance of |
This commit is the next in a commit chain backporting PEP 544 (i.e., the `typing.Protocol` superclass) to Python 3.7 via our custom `beartype.typing.Protocol` superclass, driven under the hood by the third-party `typing_extensions.Protocol` superclass. Specifically, this commit streamlines unit tests exercising this functionality. Naturally, issue #109 remains unresolved. (*Streaming dreamlike beams like unhikeable seams!*)
lolbro. Against all semblance of sanity,
|
Woah. This is why we are not doing this again. Right? Right? Basically, Still, let's try to avoid
Surprisingly, this matters. @beartype internally detects subscripted protocols as subclassing |
My eye is twitching, bro. The only sane way to resolve this is to monkey-patch the hideous 500-line
|
Actually... I feel like a complete jerk, but I'm afraid this ain't gonna work. I ended up copy-and-pasting the entire friggin' Python 3.7-specific I'm kinda unsure anyone even cares about protocols under Python 3.7 besides us mice, either. Since With extreme apologies, I'm gonna judiciously rip out our caching Wouldn't blame if you feel hyper frustrated with some combination of me, |
This commit is the last in a commit chain reverting our sadly failed attempt to backport PEP 544 (i.e., the `typing.Protocol` superclass) to Python 3.7 via our custom `beartype.typing.Protocol` superclass, driven under the hood by the third-party `typing_extensions.Protocol` superclass. Since the third-party `typing_extensions.Protocol` superclass both fails to subclass `typing.Generic` *and* prohibits all subclasses from doing so, that superclass is not merely PEP 544-noncompliant; it's anti-PEP 544-compliant, because it actively obstructs downstream consumers from being PEP 544-compliant. Specifically, this commit gracefully undoes all of the prior commits of this chain to to preserve maintainability, portability, and usability -- technically "resolving" issue #109 (kindly submitted by ace typing expert @posita) in the worst way possible. Blame `typing_extensions`, for it deserves heckling and hurled peanuts. (*Subdued subnautical dues!*)
So. Our So. Here's what happened. What happened is that # Note the lack of all mention of "typing.Generic" here.
class Protocol(metaclass=_ProtocolMeta):
...
def __init_subclass__(cls, *args, **kwargs):
tvars = []
# *THIS IS INSANITY INCARNATE.* typing_extensions,
# why are you actively lobbing rocket-propelled
# grenades into our attempted workflow?
if '__orig_bases__' in cls.__dict__:
error = typing.Generic in cls.__orig_bases__
else:
error = typing.Generic in cls.__bases__
if error:
raise TypeError("Cannot inherit from plain Generic")
... If Altogether, these two Invisible Walls of Force mean that At 4:00 last night, I began asking myself why we were even doing this. And I realized, @posita, that I myself no longer knew. No one really cares about protocols under Python 3.7, because no one really cares about Python 3.7, because Python 3.7 is on the precipice of hitting its own End-of-Life (EOL) and becoming a raging security concern. Let's agree to never speak of this black day again. Black hole sun: rise from the depths and consume the third-party packages that assail us, we bid thee! ⚫ tl;dr
We support |
As a fellow festering nonsense aficionado, I actually loved your festering nonsense. It spoke to me. The burden of shame is entirely on My gears are being grinded, |
So here's a head-scratcher:
Using beartype @ 8da3ab4 in 3.8:
And now 3.7:
I'm scratching my head for two reasons: 1)
numerary
gets away with something nearly identical without breaking, even in 3.7; and 2) everything works as expected for 3.8.So I think I screwed up a translation somewhere (most likely in #103).
The text was updated successfully, but these errors were encountered: