Beartype 0.15.0: The Claw Goes Up #257
leycec
announced in
Announcements
Replies: 3 comments 1 reply
-
That's just amazing! |
Beta Was this translation helpful? Give feedback.
0 replies
-
Thanks so much for that awesome sauce, all. By the frightening power of QA friendship, we will change this world together. 1ed7c90 is the last commit in @beartype's 0.16.0 release cycle. Strap in, folks. We are cleared for launch. Beartype 0.16.0 – now better known as "Super Unsexy Stabilization Release (SUSR)" – is soon to be catapulted off the flight deck of PyPI and into the glorious cacophony of your crowded dependency list. Prepare for incoming. Arise, SUSR! |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
@beartype 0.15.0 arises from the ashes of our issue tracker. Now, so too will your codebase.
Like a cyberpunk phoenix whose intertube veins are made of pure honey and blueberry juice, @beartype 0.15.0 introduces the new
beartype.claw
API. Automate the@beartype
decorator away with magical import hooks frombeartype.claw
. Do it for the new guy that's sobbing quietly in his cubicle.When you call import hooks published by the
beartype.claw
API, you enable hybrid runtime-static type-checking. By "hybrid runtime-static," we mean thatbeartype.claw
performs both standard runtime type-checking (ala the@beartype
decorator) and standard static type-checking (ala mypy andpyright
) but at runtime – and that ain't standard.That's right. @beartype is now a tentacular cyberpunk horror like that mutant brain baby from Katsuhiro Otomo's dystopian 80's masterpiece "Akira." You can't look away!
May Neo-Tokyo have mercy on @beartype's soul.
Does this mean that you can now safely discard mypy,
pyright
, and every other pure-static type-checker that your enlightened IDE has unjustly subjected you to over the past several years? In general:type: ignore[...]
andpyright: ignore[...]
comment chatter throughout your once-pristine codebase, and fail to enforce anything at test- or runtime. In other words, they (mostly) suck; we should all stop using them, because they (mostly) fail at their core mandate.typing.LiteralString
type hint. That's critical.In either case,
beartype.claw
lies less,...in most cases, much much less requires no comment chatter, and enforces everything at test- and runtime. You do still want a real-time IDE linter to catch mundane mistakes like trivial syntactic errors and semantics concerns like obviously undeclared attributes, of course; allow me to now shill for @astral-sh's magnum opusruff
here. If it barks, it's eitherruff
or that neighbourhood mongrel harassing our Maine Coons again. Those are domesticated cats, fat doggo – not raccoons. Why won't you listen to a human's plea in the night? 😮💨tl;dr: Just Tell My Coworker What to Do, Daddy @leycec
For those who are about to code, we salute you with all you need to know:
That's it. That's
beartype.claw
in ten seconds (dyslexia notwithstanding). As the simplest of several import hooks published by thebeartype.claw
API, thebeartype_this_package()
function:{your_package}
by the@beartype
decorator. Rejoice, fellow mammals! You no longer need to explicitly decorate anything by@beartype
ever again. Of course, you still can if you want to – but there's no compelling reason to do so and many compelling reasons not to do so. You have probably just thought of five, but there are even more.muh_int: int = 'Pretty sure this isn't an integer.'
) to runtime type-checking via thebeartype.door.die_if_unbearable()
function. More below.Okay, that's not it. The
beartype.claw
rabbit hole goes so deep that we couldn't even document anything for this release. Because exhaustion defeated common sense, these release notes are all the documentation.This is what happens when we don't
beartype_this_package()
.Will The Real Import Hooks Stand Up?
beartype.claw
actually provides five vaguely related import hooks. In ascending order of scope, these are...beartyping
: The Context Manager That Does StuffThe
beartype.claw.beartyping
context manager is our most self-limiting import hook. When you want to temporarily type-check only a few packages and modules isolated to a single block of code, put thatbeartyping
on speed dial:As the above example suggests, all
beartype.claw
import hooks apply equally well to code you and your fearless team have authored, other people's third-party code, and Python's standard library. Whether they intended you to @beartype their stuff or not, do it anyway. Shove @beartype's snuffling snout into every hidden nook and cranny of the Python ecosystem. If it feels good, improves quality assurance, and impresses that weird management guy, could it be wrong?The journey of a thousand bugs begins with a single telekinetic leap.
beartype.claw.beartyping
: this is that leap.beartype_this_package
: It Does What It Says, Unlike @leycecThe
beartype.claw.beartype_this_package()
import hook isolates its bug-hunting action to the current package. This is what everyone wants to try first. Ifbeartype_this_package()
fails, there is little hope for your package. Even though it's probably @beartype's fault, @beartype will still blame you for its mistakes.Typically called as the first statement in your top-level
{your_package}.__init__
submodule,beartype_this_package()
extends the surprisingly sharp claws of @beartype to all callables, classes, and PEP 526-compliant annotated variable assignments defined across all submodules and subpackages of the current package – regardless of lexical or filesystem nesting depth. As the term "import hook" implies,beartype_this_package()
only applies to subsequent imports performed after that function is called; previously imported submodules and subpackages remain unaffected.beartype_this_package()
: it do be like that.beartype_package
: No One Expects GitHub BearThe
beartype.claw.beartype_package()
import hook isolates its bug-hunting action to the single package or module with the passed absolute name. Examples or it didn't happen:Of course, that's fairly worthless. Just call
beartype_this_package()
, right? But what if you wanted to confinebeartype.claw
to a single subpackage or submodule of your package (rather than your entire package)? In that case,beartype_this_package()
is over-bearing.badum ching Enterbeartype_package()
, the outer limits of QA where you control the horizontal and the vertical:beartype_package()
shows it true worth, however, in type-checking other people's code. Because thebeartype.claw
API is a permissive Sarlacc pit,beartype_package()
happily accepts the absolute name of any package or module – whether they wanted you to do that or not:Truer words were never spoken, wizened psychic baby lady.
beartype_packages
: When A Single Bear Just Won't DoThe
beartype.claw.beartype_packages()
import hook isolates its bug-hunting action to the one or more packages or modules with the passed absolute names. Whereasbeartype_package()
accepts only a single string,beartype_packages()
accepts an iterable of zero or more strings. One function to QA them all, and in the darkness of our implementation bind them:The end of the road is where
beartype_packages()
is just getting started.beartype_all
: You Will Be AssimilateThe
beartype.claw.beartype_all()
import hook doesn't isolate anything! It's the ultimate extroverted import hook, spasmodically unleashing a wave of bug-hunting action across the entire Python ecosystem. After callingbeartype_all()
, any package or module authored by anybody (including standard packages and modules in Python's standard library) will be subject to @beartype.This is the extreme QA nuclear option. Because this is the extreme QA nuclear option, most packages should not do this.
beartype_all()
forces possibly unwanted@beartype
-ing on all downstream consumers importing your package. The only packages that should do this are high-level applications run as hegemonic executables (rather than imported by other higher-level applications and packages).@beartype cannot be held responsible for the sudden rupture of normalcy, the space-time continuum, or your previously stable job. For those who are about to explode their codebases, we duck inside a bomb shelter:
The
beartype_all()
lifestyle is short but sweet, just like @leycec.PEP 526: What Do These Ineffable Numbers Even Mean?
This is PEP 526:
Previously, PEP 526-compliant annotated variable assignments were beyond the feeble reach of the Bear. Now, the Bear lovingly fondles those assignments with runtime type-checking fuelled by our
beartype.door.die_if_unbearable()
function. Specifically, for each assignment of the formvar_name: type_hint = new_value
at any lexical scope of any module imported under an import hook described above,beartype.claw
appends that assignment by a statement of the formdie_if_unbearable(var_name, type_hint)
type-checking that assignment against that type hint at runtime.beartype.claw
thus silently expands the above single-line assignment to: e.g.,Since the above assignment violates that type hint,
beartype.claw
will now raise abeartype.roar.BeartypeDoorHintViolation
exception at the point of that assignment.beartype.claw
ignores all variable assignments that are not annotated by type hints: e.g.,If you hate this, you'll just love our new
BeartypeConf.claw_is_pep526
configuration option. Which leads us directly to...Unhappy people forgot to annotate their variable assignments, I see.
BeartypeConf
: Now With More Umph in its ConfWe didn't tell you this, because we save the best for last. But all of the import hooks described above accept an optional keyword-only
conf: BeartypeConf = BeartypeConf()
parameter (i.e., user-defined beartype configuration, defaulting to the default beartype configuration). Unsurprisingly, that configuration configures all actions performed by thebeartype.claw
API under that import hook:Equally unsurprisingly, our existing
beartype.BeartypeConf
dataclass has been augmented with newbeartype.claw
-aware super powers. Fine-tune the behaviour of our import hooks for your exact needs, including:BeartypeConf(claw_is_pep526: bool = True)
. By default,beartype.claw
type-checks PEP 526-compliant annotated variable assignments likemuh_int: int = 'Pretty sure this isn't an integer.'
. Although this is usually what everyone wants, this may not be what someone suspicious dressed in black leather, a red "velvet" cape, and aviator goggles wants in an edge case too unfathomable to even contemplate. If you are such a person, consider disabling this option to reduce runtime safety and destroy your code like Neo-Tokyo vs. Mecha-Baby-Godzilla: ...who will win!?!?BeartypeConf(warning_cls_on_decorator_exception: Optional[Type[Warning]] = None)
. By default,beartype.claw
emits non-fatal warnings rather than fatal exceptions raised by the @beartype decorator at decoration time. This is usually what everyone wants, because the @beartype decorator currently fails to support all possible edge cases and is thus likely to raise at least one exception while decorating your entire package. To improve the resilience ofbeartype.claw
against those edge cases, @beartype emits one warning for each decoration exception and then simply continues to the next decoratable callable or class. This is occasionally unhelpful. What if you really do wantbeartype.claw
to raise a fatal exception on the first such edge case in your codebase – perhaps because you either want to see the full exception traceback or to punish your coworkers who are violating typing standards by trying to use an imported module as a type hint?...this actually happened. In this case, consider passingNone
as the value of this parameter; doing so forcesbeartype.claw
to act strictly, inflexibly, and angrily with maximal roaring and blood-flecked claws:Crack commando Bear-Team: Assemble!
Lastly but not Leastly...
...to financially feed @leycec and his friendly @beartype through our new GitHub Sponsors profile. Come for the candid insider photos of a sordid and disreputable life in the Canadian interior; stay for the GitHub badge and warm feelings of general goodwill.
Cue hypnagogic rave music that encourages fiscal irresponsibility. 🎵 🎹 🎶
Shoutouts to the Beasts in Back
Greets to:
beartype.claw
. @gabrieldemarmiesse went above the call of the wild, relentlessly previewing live unstable commits to thebeartype.claw
API against both open-source and proprietary projects. Two paws in the air, 'cause you know Gabriel care! 🐾beartype.claw
breakage against real-world use cases – including @qutebrowser itself. This is the stuff dream teams are made of. High fives for the glory of Python. ✋ ✋awfulless than ideal it still is: @jklaise, @skeggse, @yurivict, @rsokl, @KyleKing, @kloczek, @justinchuby, @alexander-c-b, @machow, @JWCS, @Skylion007, @eohomegrownapps, @BowenBao, @k4ml, @tolomea, and @ZeevoX.And... I'm spent. Clearly, our old mega-issue is also spent. Fifteen million meme images and dissertation-length monologuing have clogged the Intertubes beyond repair. With an appreciable sigh of relief as we move into the new age of
beartype.claw
, let's close that venerable thread. All newer release announcements will be posted to our peanut gallery.Goodbye, Future Sound of Beartype. Thanks for all the salmon.
beartype.claw
rises with the paw of quality. Will you high-five that paw?Beta Was this translation helpful? Give feedback.
All reactions