fix(deps): update dependency beartype to >=0.20.0,<0.21.0 #21
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.
This PR contains the following updates:
>=0.19.0,<0.20.0
->>=0.20.0,<0.21.0
Release Notes
beartype/beartype (beartype)
v0.20.0
: Beartype 0.20.0: The Balding Bears Are Back in QA TownCompare Source
Beartype 0.20.0 catapults out of your CRT monitor from the 90's that contains only four pounds of lead, across your mechanical keyboard with the clacky keys and vibrant crumb trails, and into your lap. Startled, you shriek in fear. Then astonishment. Then back to fear. Trembling, your fingers reach for...
pip install --upgrade beartype # <-- bugger the bugs
@beartype
0.20.0
gurgles contentedly as you wipe the birthing fluids from its forehead. You choke back tears. In a moment of madness that borders on the divine, you pull the trigger. You update. You're in too deep now. The sunk cost fallacy you feel is real. Your devbox shudders. Your mechanical keyboard spills sugary soda all over itself. Your RSI-wracked mouse hand pulsates with the pre-install jitters. Surely the second coming of QA is at hand.0.20.0
: and you thought Gymnastics Turtle was weird@beartype
0.20.0
is brought to you by...GitHub Sponsors: When You Befriend the Bear, You've got a Bear for Life
This release comes courtesy these proud GitHub Sponsors, without whom @leycec's cats would currently be eating grasshoppers:
https://sescollc.com
https://dylanmodesitt.com
https://metrolo.gy imagine if this domain actually worked. how cool would that be!?
Thanks so much, masters of fintech and metrology.
And now for something fishy.
Did You Do Anything Except Break Everything?
Absolutely! Well, surely. Well, probably. Well, possibly. Well, maybe.
@beartype
0.20.0
brings to bear a whole new lineup of QA goodies. You never knew you needed these QA goodies until a small voice inside of you whispered:Before we get to some actual meaningful content in this changelog, though...
Tell @leycec What to Do in This Thrilling GitHub Poll 😮
Left to my own devices, I just play video games and obsessively rummage around in the bike shed with PEP standards nobody cares about. This is why...
I implore you to vote in this GitHub forum poll. Yes. It's all true. User opinions always mattered, but now user opinions really matter. I can't pretend they don't exist anymore. For the first time ever, you can force me to do your questionable and unsavoury bidding. Tell me what to do this summer. Vote now. Vote often. Vote hard. But for the sake of the bugs crushing your workload, vote. 🌝
Iterable[...]
+Container[...]
= BBFFLs (Best Bear Friends for Life)@beartype now deeply type-checks the last remaining PEP 484- and 585-compliant container type hints in
O(1)
constant time, including:collections.abc.Container[...]
type hints.collections.abc.Iterable[...]
type hints.collections.abc.Reversible[...]
type hints.typing.Container[...]
type hints.typing.Iterable[...]
type hints.typing.Reversible[...]
type hints.@beartype now type-checks exactly one item of containers annotated with general-purpose container type hints like
Iterable[...]
andContainer[...]
inO(1)
constant time. How? Smarty bear pants. @beartype intelligently detects whether a container is:list[str]
), in which case a pseudorandom item of thatsequence is type-checked.
set[int]
), in which case only the first item of thatcollection is type-checked.
0.20.0
isn't laughing. beartype0.20.0
doesn't even know what's happening anymore...Type Variables: More Typing, More Variables
@beartype now deeply type-checks PEP 484-compliant type variables (e.g.,
T = typing.TypeVar('T')
) for a variety of common use cases. Mostly, this means type variables whose type-checking can be entirely decided at decoration time by the@beartype
decorator.Since deciding type-checking at decoration time is really fast, deeply type-checking type variables in these use cases is really fast as well. Like,
O(1)
fast. Like everything @beartype does, these type variables are cost-free. They don't cost anything, so you'd might as well use them. This probably marks the first serious attempt by any package to tackle type variables at runtime.This support fully covers these common use cases:
MuhList[int]
given the typeclass MuhList[T](list[T]): ...
).MuhAlias[int]
given the type aliastype MuhAlias[T] = list[T] | T | int
).Let's take a swan dive into the deep end of...
Subscripted Generics: Knock-offs You Can Depend On
@beartype now propagates child hints up generic type hierarchies. Because @beartype values the cooperation of coworkers you barely convinced to use @beartype in the first place, @beartype propagates child hints efficiently, recursively, and (most importantly) safely. No generics are harmed in the propagation of child hints.
The proof is in the syntactically highlighted rainbow pudding. In this example, we bring the swift fist of justice to Python QA. First, we define a generic parametrized by a type variable
T
. Next, we annotate a function with a type hint created by subscripting that generic with the child hintint
. Finally, @beartype does the rest by propagating that child hintint
into that type variableT
up the type hierarchy of that generic.Behold! Boredom personified, yet you can't turn your lidded eyes away:
...which raises the expected type-checking violation:
In other words, @beartype now "knows" that any object typed as
SoDumbSoDelicious[int]
should be an iterable container whose items are all integers. Under the furry hood, @beartype "knows" this by recursively replacing each instance of the type variableT
with the child hintint
within the generic type hierarchy ofSoDumbSoDelicious
.In other words, @beartype now correctly propagates mappings from type variables parametrizing generic declarations (e.g., the
T
inclass SoDumbSoDelicious[T](Iterable[T], Container[T]):
) to the child hints subscripting usage of those generics (e.g., theint
inSoDumbSoDelicious[int]
). @beartype does this recursively for arbitrarily complex generic type hierarchies.This broke my brain and took two full months of mostly unpaid volunteerism. That's why I still beg for money on GitHub Sponsors like that hobo chugging Duck wine out of a cardboard box on your commute to work every day. Like the hobo, I had fun. Like the hobo, I had the urge to sleep in the gutter. This feature was so hard I had to refactor the entire @beartype codebase to support it – including @beartype's totally-not-fragile dynamic type-checking code generator that I avoid touching at all costs. That's how totally-not-fragile it is. It's the sort of poorly documented 10,074-line code dump you see prefixed with stultifying ASCII art banners like:
It's likely there are unresolved edge cases I'm blissfully unaware of. If you hit one of these golden landmines, please submit an issue. I'll promptly resolve everything or collapse on my keyboard trying. 😰
Subscripted Type Aliases: Not Just for QA Violators Anymore
@beartype now propagates child hints up generic
type
aliases, too. This is genuinely cool. Like, "cool kids" cool. Generictype
aliases are kinda like functions or a full-blown templating engine – except for type hints. If you've ever found yourself copy-pasting one stupidly long type hint into another, you've realized you're violating the Don't Repeat Yourself (DRY) principle and are now off the deep end of QA. Thus:In this example,
PygmentsToken
may not look like a function – but it pretty much is. It's a "function" that generates a new type hint from a standardized template every time you subscript it with a new child hint.So what's the catch? We hope you don't mind requiring Python ≥ 3.12 by dropping support for Python ≤ 3.11. Because... that's the catch. If you try to define even a single
type
alias in a single submodule of your package under Python ≤ 3.11, your entire app unceremoniously blows up with a fatalSyntaxError: invalid syntax
exception. Good luck with that.@beartype
0.20.0
: because your users hate Python ≤ 3.11, too.Subscripted Generics + Type Aliases = Power Untold Thrums Through You
I don't even know what "thrumming" is, but I'm pretty sure that's what happens to your sinews when you combine the fearsome power of subscripted generics and subscripted
type
aliases. The coworker to your right is already cowering. Good. That feeling is good. Soon, they will all kneel!</muhaha— *choking*>
Behold! A subscripted type alias propagating its child hint onto a subscripted generic. Why? Because your QA pipeline wasn't complicated enough and you now need to justify your position to those new
bastards in suitsnice HR spokespeople:...which raises the expected type-checking violation:
...which only goes to show that @beartype now knows everything. Lo! It is known.
Subscripted Generics: Gotta Compare Them All
One ill-fated morning, you realise with a gnawing horror... You've run out of coffee. The Pop-Tarts® box is empty. There's no reason to get up anymore. You greet the watery Sun with a thousand-yard stare half-baked beyond the void of space. Yet, through crusty eyes, you think to yourself:
I don't know why, but unspecified people okay, it's @patrick-kidger and @wesselb want to compare subscripted generics. I smell academia and a burgeoning career built on the shuddering back of @beartype. You might be one of these people or a person like these people. But, let's be honest... you're probably not. You're wondering why you're still reading this and rapidly realizing there's no good answer to that question. Some questions are bad.
Let's pretend you're one of these people. Rejoice! @beartype now decides the least trivial computational puzzle in the field of type systems, because @leycec couldn't bear to see that unresolved
[Bug]
status for another year:I'm confident you could profitably author multiple doctoral theses strung out across multiple poorly remunerated grad students who hate themselves almost as much as you do by just addressing, redressing, and endlessly rehashing this single issue. Papermill careers are built on the boneless backs of issues like this.
Originally, I wanted to bludgeon everyone in attendance with a tiresome essay doing just that. In the bitter end, even the mere thought of tiring everyone tires me beyond the event horizon of exhaustion.
Still, boredom is its own reward. I'll say that @beartype has probably invented the optimally efficient algorithm for deciding this problem. Nobody cares, of course. Even I am lacklustre about this whole thing.
But a non-recursive depth-first search (DFS) is a glorious self-flagellation that few ever attempt and even fewer survive. This DFS exhibits:
O(1)
constant time complexity. Pump that fist!O(jk)
quadratic time complexity, where:j
is the largest number of child type hints transitively subscripting an unerased pseudo-superclass of the first generic passed tois_subhint()
. You don't even want to know what "unerased pseudo-superclass" means.k
is the total number of transitive pseudo-superclasses of the same generic. Ditto.Because the DFS is non-recursive, it's stupidly fast, unreadable, undebuggable, and unmaintainable. This is why we @beartype:
Type Variables: Still Unchecked at Call Time after All These Years
Of course, @leycec is lazy. @beartype still lacks general-purpose support for type-checking type variables at call time. This means @beartype still ignores type-checking violations involving mismatching types across type variables like:
@beartype
0.20.0
: shrugging apathetically while your code burns@beartype-Hostile Packages: @beartype Tolerates You, Barely
@beartype now tolerates these extremely popular third-party packages that hate @beartype ≤ 0.19.0 (and other runtime type-checkers, too):
urllib3
.xarray
.Yes, these packages hate @beartype (and other runtime type-checkers, too). The irony is especially rich in Pydantic's case, because Pydantic itself is a runtime type-checker. This must be what happens when you go full-Rust.
These packages all doubled down on the
typing.TYPE_CHECKING
forward reference antipattern, which @beartype 0.21.0 will have a lot to say about. Until then, this is "Leycec's Abbreviated Notes on the Antipattern That Destroys True Goodness and Heroism":Those two approaches may look identical. From the runtime perspective, those two approaches share nothing in common. They hate one other.
TYPE_CHECKING
evaluates toFalse
at runtime, so @beartype (and other runtime type-checkers) can't see the imports hidden inside thoseif
conditionals. All @beartype sees is:'some_package.some_submodule.SomeType'
in the former case. @beartype can fully resolve theSomeType
type from this. @beartype is pleased and growls contentedly while rubbing its belly for scritches.'SomeType'
in the latter case. That's... just not enough information. Like, at all. Throw @beartype a friggin' bone. @beartype can't resolve anything from that! @beartype growls and throws up.@beartype 0.21.0 will explicitly detect, warn about, and repair this antipattern across all
beartype.claw
import hooks. That's the glorious future. For now, @beartype 0.20.0 contents itself with just silently ignoring these problematic packages inbeartype.claw
import hooks. We do what we can. Sometimes, it isn't much.@beartype doesn't hate these packages. We try to be tolerant of everyone's misinformed and bad opinions. In this case, we tolerate these packages by internally blacklisting them. We don't bother trying to subject their modules, types, or callables to runtime type-checking, because we can't. Their modules, types, and callables despise type-checking. What can you do? Nuthin'. We didn't make crazy; we can't control crazy; we just put crazy in a head lock and roll over it multiple times with our adipose-laden bodies until it stops moving.
Blacklisting these packages really improves the real-world usability of the
beartype.claw.beartype_all()
import hook in particular, which previously choked on imports from these packages. Since @beartype now automatically blacklists these packages, you no longer need to manually blacklist them yourself by listing these packages under theBeartypeConf(claw_skip_package_names=...)
configuration option: e.g.,@beartype
0.20.0
: make all the bad stuff go away, QA daddy.Python 3.8: It Died Quietly in the Corner While No One Shed a Tear
@beartype
0.20.0
officially drops support for Python 3.8. Python 3.8 "recently" hits its official End-of-Life (EOL). Alright. Okay. It was ages ago, wasn't it? I still remember when Python 3.8 was the cool new kid who just wanted to come over and show you his $1,000 LEGO Millennium Falcon constructed entirely from deprecated type hints. Now, it's dead. Only my baldness remains. Python makin' me feel old over here.This means that Python 3.8 now constitutes a security risk. More importantly, @beartype hates Python 3.8. Due to the Transitivity of Loathsomeness Principle (probably discovered by Pythagoras the Pythonic, the little-known balding stepchild of Pythagoras the Elder) your codebase now hates Python 3.8 too. Like a bad dream, feature loss is contagious.
Our New Motto: "We Promise the World and Deliver Less"
@beartype
0.20.0
delivers less bugs – a lot less bugs. Turns out @beartype has been buggy for years. If nobody hits a bug for a decade but that bug still exists, does it make a sound when it crushes your codebase at 4:23AM on an icy Sunday? The answer is: "That sound is your dev team screaming in shared anguish."@beartype
0.20.0
specifically:from __future__ import annotations
) with PEP 695 implicit type parameter instantiation (e.g.,def muh_func[T](muh_arg: T) -> T: ...
). Against all sanity, this somehow now works:type
aliases like you just don't care:The above function signature is equivalent to this simpler, more readable, more maintainable, more debuggable, and yet somehow more boring signature:
Boring is bad, though. That's clear. Simplicity doesn't count for much if you're bored all the time. Maximize non-boring even if it costs you your codebase, your career, and your future prospects of a happy family. Do what @leycec would do.
@beartype
0.20.0
: because @beartype has to do what you say, even when it no longer wants toLastly but Beastly (but not Leastly)...
...to financially feed @leycec and his friendly @beartype through our ancient GitHub Sponsors profile that predates the existence of dinosaur-like AI chatbots. 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.
🎵 🎹 🎶
Bear Beta Fan Club: Nobody Asked to Join...
...but nobody asked to leave, either. The Bear Beta Fan Club is GitHub's own Hotel California. The "Exit!" sign is poorly labelled. You keep getting roped back in with dubious reassurances that "things will be better this time."
This is that time.
@posita, @wesselb, @iamrecursion, @patrick-kidger, @langfield, @JelleZijlstra, @RobPasMue, @GithubCamouflaged, @kloczek, @uriyasama, @danielgafni, @JWCS, @rbroderi, @AlanCoding, @tvdboom, @crypdick, @jvesely, @komodovaran, @kaparoo, @MaximilienLC, @fleimgruber, @EtaoinWu, @alexoshin, @gabrieldemarmiesse, @James4Ever0, @NLPShenanigans, @rtbs-dev, @yurivict, @st--, @murphyk, @dosisod, @Rogdham, @alisaifee, @denisrosset, @damarro3, @ruancomelli, @jondequinor, @harshita-gupta, @jakebailey, @denballakh, @jaanli, @creatorrr, @msvensson222, @avolchek, @femtomc, @AdrienPensart, @jakelongo, @Artur-Galstyan, @ArneBachmann, @danielward27, @WeepingClown13, @rbnhd, @radomirgr, @rwiegan, @brettc, @spagdoon0411, @helderco, @paulwouters, @jamesbraza, @dcharatan, @kasium, @AdrienPensart, @sunildkumar, @peske, @mentalisttraceur, @awf, @PhilipVinc, @dcharatan, @empyrealapp, @rlkelly, @KyleKing, @skeggse, @RomainBrault, @deepyaman, @mzealey, @adamtheturtle, @Moosems, @minmax, @jedie, @pablovela5620, @thiswillbeyourgithub, @Logan-Pageler, @knyazer, @ilyapoz, @yuzhichang, @Fedezzab, @antonioan, @im-Kitsch, @mthramann, @fbartolic, @rgallardone, @frrad, @jonnyhyman, @jennydaman, @likewei92, @acec2127, @Glinte, @rudimichal, @woutdenolf, @PauloHMTeixeira
Configuration
📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.