Beartype 0.16.0: Super Unsexy Stabilization Asinine Force (SUSAF) #280
Replies: 7 comments 1 reply
-
😍 amazing! QoL patches are a lot of drudgery, but are much appreciated 🙏
*looks around for the hidden camera* |
Beta Was this translation helpful? Give feedback.
-
Getting your coworker to stop wearing skinny jeans and squinting is alone worth doubling donations.
|
Beta Was this translation helpful? Give feedback.
-
@skeggse, this is a mere QoL patch – but it may be the Mother of All QoL Patches. Just gaze upon the dancing panda bear that @posita's animal familiar is showering with sweet moolah. That panda bear dances for you and me. Relatedly: @beartype 0.16.0 was painfully busted! It's all true! Read the shameful story of how @beartype unwittingly broke PyTorch and by extension the entire world over its fat panda knees. I won't admit that @beartype 0.16.0 even exists, anymore. Thankfully, this is why we have... @beartype 0.16.2! Do you upgrade now or do you kill the flame of PyTorch before it has yet to spark the "non-violent" AI uprising that absolutely nobody saw coming? You be the adjudicator. python3 -m pip install --upgrade beartype |
Beta Was this translation helpful? Give feedback.
-
Whoo! Thanks for the patch release, @leycec! That's greatly appreciated. :) |
Beta Was this translation helpful? Give feedback.
-
Beartype 0.16.3: Quality of Life Dev Cycle Becomes a Daytime Soap Opera@beartype 0.16.3 lazily sprawls out in the public bath house that is PyPI. Join @leycec in that bath house. python3 -m pip install --upgrade beartype This bug-defying patch release adds official support for hot module reloading, root superclass validators, forward reference @beartype 0.16.3 almost qualified as a full-blown minor release called @beartype 0.17.0. In the end, however... you failed, @beartype 0.16.3! You weren't quite big enough, dizzyingly stupefying enough, or blatantly broken enough to get upgraded to a minor release. It's for the best. Look. It was Canadian Thanksgiving. It was all I could do to take the roasted turkey leg out of my mouth. Still, there is awesome sauce. Feast your bleary eyes on this tiresome changelog that will ruin what's left of your weekend:
This is @beartype 0.16.3, the patch release best described as...
This is how the QA was won. Not with a whimper, but an exploding head emoji. 😑 → 🤯 |
Beta Was this translation helpful? Give feedback.
-
@beartype 0.16.4 exhaustedly collapses in front of you. You are shocked, but ultimately unmoved. You've been here before and you know what to do. python3 -m pip install --upgrade beartype This patch release resolves all the bad things that have quietly gone unnoticed by both man and Maine Coon alike... until now. Fellow Ontarian and ML superstar @MaximilienLC (Maximilien Le Cleï) seriously, what is up with that "ï" quietly called our attention to a bevy (pretty sure that means "alot") of outstanding badness riddling the @beartype codebase. This patch release resolves that badness. This means:
Much thanks to @MaximilienLC for his all-seeing eye, which sees all @beartype's typing failures as plainly as I see the blinding glare off my bald and malding head. |
Beta Was this translation helpful? Give feedback.
-
Thanks for tagging me -- I may not be dropping comments, but it's super handy to see everything that's cooking in beartype! |
Beta Was this translation helpful? Give feedback.
-
@beartype 0.16.0 [codename: Super Unsexy Stabilization Asinine Force (SUSAF)] boringly stabilizes everything unstable about @beartype that made your coworker who only wears skinny jeans while squinting whenever you mention @beartype stop doing those things. Fix everything bad, SUSAF!
@beartype 0.16.0 mostly introduces nothing new. Instead, @beartype 0.16.0 just fixes everything that's been broken for several years. We all tried to pretend that those things worked. I'm grateful for that. You were willing to look the other way while @beartype insanely stumbled around with its paws up in the air. Now, @beartype finally makes good on one or two of its historical promises.
To introduce our SUSAF feature list, @beartype presents... super unsexy anime ugly man Rock Lee!
Seriously. Those eyes. Those eyebrows. That bowl cut. Seriously.
All of these things and more now fully work as intended:
"List[MuhClass[str]]"
. Party! 🥳from __future__ import annotations
. Never actually do this. 🕺@classmethod
+@property
. Never actually do this, either. 💃typing.NewType()
objects. Compose those new types together, because you can! 😑beartype.claw
warnings.beartype.claw
now tries to be quieter, but fails! 😮💨beartype.claw
+python -m {your_package}.{your_module}
. It just works! Maybe! 😃@beartype
+enum.StrEnum
. You know somebody wanted this! 🐳@beartype now supports basically everything. @beartype should no longer raise decoration-time exceptions about unsupported type hints, because all type hints should now be supported. Because we just used weasel words like "basically" and "should," you "basically" "should" not trust anything I just wrote. Instead, please throw
beartype.claw.beartype_this_package()
against the bug-stained windshield of your favourite codebase. Let us know if @beartype is still broke af for your use case.Previously, everyone blacklisted
@beartype
from decorating one or more problematic classes, methods, or functions with the standard@no_type_check
decorator. Now, you no longer need to that. Unleash the bear. Let @beartype claw its disturbingly hungry way through yourdisconcerting infestation of bugsbug-free codebase.Taiko drum roll, please.
Above: @leycec in a troubled moment during the 0.16.0 release cycle.
GitHub Sponsors: You Make the Hard Work Less Work
But first... a huge thank you to @beartype's growing retinue of one-time and recurring sponsors! I'm incredibly touched in a good way by everyone's outpouring of hard-earned biosecurity tickets. You know who you are... but nobody else did. Until now.
@beartype sponsors, please line up to receive your complimentary sugar-free Bear Claw of Undulating Adulation & Unending Congratulations:
I also kinda feed bad. I do intend to deliver a high-quality QA product of blood, sweat, tears, memes, and fun – but I also frequently drop the ball and fall short of that lofty goal. Moreover, money is increasingly hard for many to find in 2023. The post-scarcity future that Ian Banks promised that I personally would live to see in depressing sci-fi books about Culture – the mythological utopian society that I will probably never live to see – has never seemed further away.
Thank you. So much.
The true form of @beartype is revealed – and also thanks you.
Up next... @beartype 0.16.0 did actually do something novel. Surprise! It's:
${BEARTYPE_IS_COLOR}
: Make the Bad Color Go Away@beartype 0.16.0 introduces our first official shell environment variable:
${BEARTYPE_IS_COLOR}
. Through the power of${BEARTYPE_IS_COLOR}
, you too can now enforce a global colour policy by externally configuring our popularBeartypeConf.is_color
option from the command line. As withis_color
,${BEARTYPE_IS_COLOR}
is a tri-state boolean with three possible string values:BEARTYPE_IS_COLOR='True'
, forcefully instantiating all beartype configurations across all Python processes with theis_color=True
parameter.BEARTYPE_IS_COLOR='False'
, forcefully instantiating all beartype configurations across all Python processes with theis_color=False
parameter.BEARTYPE_IS_COLOR='None'
, forcefully instantiating all beartype configurations across all Python processes with the is_color=None parameter.Force beartype to obey your unthinking hatred of the colour spectrum. You can’t be wrong!
When @beartype makes your eyes bleed, call
${BEARTYPE_IS_COLOR}
.Forward References: This Day All Circular Imports Die
Previously, @beartype only supported simple forward references consisting of one or more
"."
-delimited Python identifiers like"MuhClass"
andmuh_package.muh_module.MuhClass
. Now, @beartype finally supports complex forward references consisting of arbitrary combinations of references to classes that have yet to be defined both subscripted by and subscripting type hint factories.In other words, forward references just work now. Bask in the ruthless complexity of @beartype now fully resolving a subscripted generic type alias forward reference (i.e., a stringified type hint referring to a global attribute that has yet to be defined whose value is a subscripted generic that also has yet to be defined). It hurts – but @beartype is here to help:
Like a rolling stone, @beartype now brings it all back home.
Sadly, none of this is free. There are now space and time costs associated with forward references that you should be aware of. For most codebases, these costs will be negligible and thus ignorable. For some codebases, however, ...especially codebases enabling PEP 563 via
from __future__ import annotations
, these costs could gradually become non-negligible and thus unignorable. Let's unpack what exactly is happening above.this_is_fine()
function is annotated by two stringified type hints (i.e., type hints that are strings describing standard type hints rather than standard type hints).List
attribute has been previously imported, @beartype replacesList
in the return annotation with the previously importedbeartype.typing.List
attribute. Now:this_is_fine()
resemblesdef this_is_fine(still_fine: 'WonkyTypeAlias') -> List['WonkyTypeAlias']:
. The only remaining stringified attributes refer to'WonkyTypeAlias'
, which has yet to be defined._BeartypeForwardRefIndexable
. (It's best not to think too hard about this. @leycec sure didn't.) Now:this_is_fine()
resemblesdef this_is_fine(still_fine: _BeartypeForwardRefIndexable('WonkyTypeAlias')) -> List[_BeartypeForwardRefIndexable('WonkyTypeAlias')]:
. No stringified attributes remain. All previously stringified type hints have now been replaced by standard type hints. Well, sort of standard type hints. I mean, we're all just squinting at this point.this_is_fine()
function with a dynamically generated wrapper function performing runtime type-checking. B-b-but... how does @beartype even do that!?!? After all, neither theWoknyGeneric
norWonkyTypeAlias
global have been defined yet. Ah-ha! Here is where the magic and the madness happens. Remember those forward reference proxies like_BeartypeForwardRefIndexable('WonkyTypeAlias')
that @beartype previously injected into your type hints? Right. Those now do something. Each forward reference proxy now pretends that it is a normal class. From this point on, as far as @beartype and everything else in the Python ecosystem is concerned, forward reference proxies are just normal classes. You type-check them like you would any normal class (i.e., by passing them as the second argument to theisinstance()
builtin). @beartype's code generation algorithm doesn't know any better. Ignorance is bliss when you are tired, it's Friday night, and you just want to play five hours more of Baldur's Gate 3 already.WonkyGeneric
andWonkyTypeAlias
global attributes.this_is_fine()
function. Magic and madness erupt. At last! Remember those forward reference proxies? They're baaaaaack. They finally do something. The type-checking code that @beartype previously wrappedthis_is_fine()
with kicks in by:isinstance()
builtin, which then...__instancecheck__()
dunder method defined by the private metaclass_BeartypeForwardRefMeta
of that forward reference proxy, which then...is_instance()
method defined by that forward reference proxy, which then...WonkyTypeAlias
from your module, which has now been defined.WonkyGeneric[int]
rather than an actual type.WonkyGeneric
, which is an actual type.isinstance()
builtin.This is an understandable response when @leycec starts talking. The laborious point I am trying and failing to make here is that forward references now incur costs. Ignoring the ridiculous explosion in code complexity, there are now unavoidable space and time costs here. Types are being cached all over.
eval()
is being called all over. Dynamic forward reference proxy classes are being instantiated all over.@beartype optimizes this as much as feasible, because that's why we're here. Realistically, though? There's just soooo much magical dynamism here. @beartype can only safely optimize so much. You don't even want to know what @beartype does for fully-qualified forward references like
'muh_package.muh_module.MuhGeneric[T]'
. Let us just say that it is Trash Day, your trash bins are now overflowing with stinky refuse, and Python's garbage collector is parked out front eviscerating the steaming mountain of short-lived objects in generation 0 that you have inflicted upon it.Sometimes, you just need to forward reference. That's fine. @beartype is now here for you. Just try to keep it low-key. KK?
Oh – and here's what @leycec's idealistic and better-adjusted younger self had to say about this:
It happened. @leycec remembers.
Kumamoto Bear remembers, too.
PEP 563: You Still Shouldn't Do It. Now, You Can.
And then there was PEP 563 via
from __future__ import annotations
– the dread PEP whose name shall not be spake that we just spake. We fundamentally reimplemented our entire PEP 563 pipeline in terms of our forward resolution mechanism from Hell. (See: above.)From @beartype's perspective, PEP 563 basically no longer exists. @beartype no longer particularly cares whether you explicitly stringify your type hint likes
'List[WonkyTypeAlias]'
or implicitly stringify your type hints viafrom __future__ import annotations
. The end result is the exact same: stringified type hints.Do we all now understand why PEP 563 is bad? We do. But let us tiresomely enumerate the ways, anyway:
Here. We're gonna give it to you straight. If you enable PEP 563 across only a small number of modules, it's unlikely that you will see a measurable performance hit. If you enable PEP 563 across your entire friggin' codebase, however? Yeah. Expect those performance hits. Your apps will startup slower, run slower even after they spin up, and possibly even catastrophically fail in pernicious edge cases.
Don't be that guy. Don't enable PEP 563. Not even once.
Would you trust a man whose neck is also his chin? @beartype would.
Plum: It Just Works Better
@wesselb's magnum opus to @beartype-based multiple dispatch now works better. Notably:
from __future__ import annotations
. I mean, you shouldn't. But you can. Maybe. But... yeah. I still wouldn't.typing.Literal[...]
type hints now works considerably better. @PhilipVinc: you know who you are.Plum: even the poor little doggo agrees
Shoutouts to the Beasts in Back
Greets to @posita, @wesselb, @patrick-kidger, @empyrealapp, @eohomegrownapps, @MaxSchoenau, @PhilipVinc, @SalamanderXing, @rlkelly, @KyleKing, @RomainBrault, @tolomea, @skeggse, @alexander-c-b, @gabrieldemarmiesse, @machow. You know who you are. You are... awesome!
i luv u
It was SUSAF. It was... @beartype 0.16.0.
Beta Was this translation helpful? Give feedback.
All reactions