Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This bug-defying patch release adds official support for **hot module reloading,** **root superclass validators,** **forward reference `issubclass()` proxying,** **readable forward reference exceptions,** and **class redecoration eliding** as well as documenting a medley of topics and APIs first introduced with the `beartype.claw` subpackage under @beartype 0.15.0. Where did the time go? Probably playing vidya games, if I'm being openly honest with myself. @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. This includes: * **Hot reloading.** @beartype is now robust against **hot reloading** (i.e., re-importation of previously imported modules containing one or more @beartype-decorated classes), resolving issue #288 kindly submitted by awfully ingenious Cambridge researcher @awf (Andrew Fitzgibbon). The `@beartype` decorator now explicitly (in order): 1. Detects **class redefinition** (i.e., redefinition of a previously `@beartype`-decorated class with the same name in the same module, usually but *not* necessarily due to hot reloading). 1. On the first redefinition of *any* class, clears all **caches** (i.e., @beartype-specific internal caches that could possibly contain the prior definition of that redefined class). * **Root superclass validators.** The `@beartype` decorator now supports beartype validators of the form `typing(|_extensions).Annotated[object, beartype.vale.Is*, ...]` (i.e., PEP 593-compliant type hints annotating the otherwise ignorable root `object` superclass by one or more unignorable beartype validators), resolving both issues #290 kindly submitted by Plum maestro @wesselb (Wessel) *and* beartype/plum#120 kindly submitted by professional hodge-podger @hodgespodge. With the fearsome power of root superclass validators, validate that arbitrary objects satisfy various constraints regardless of the actual types of those objects. This is now a thing: ```python >>> from beartype.door import is_bearable >>> from beartype.typing import Annotated >>> from beartype.vale import Is >>> ICanHazAttr = Annotated[object, Is[ ... lambda value: hasattr(value, 'i_can_haz_attr')]] >>> is_bearable('hello', ICanHazAttr) False # <-- y u no got that attr, "str" class!? >>> class IHazAttr(object): ... i_can_haz_attr = 'Totally got this one, bro.' >>> is_bearable(IHazAttr, ICanHazAttr) True # <-- kk, you gots that attr ``` * **Forward reference `issubclass()` proxying.** The `@beartype` decorator now supports subscripted forward references (e.g., `"type[MuhClass]"`) to proxy both `isinstance()` *and* `issubclass()` type-checks, resolving issue #289 kindly submitted by Google X extraordinaire @patrick-kidger (Patrick Kidger). Previously, subscripted forward references erroneously proxied only `isinstance()` type-checks; this omission prevented these references from correctly resolving stringified type hints of the form `type[{UndefinedClass}]` (i.e., subscriptions of the PEP 585-compliant `type[...]` builtin by a forward reference to a class that has yet to be defined). Now, all is full of QA. Praise be to the Kidger: e.g., ```python from beartype import beartype # .-- this really hot ASCII art # | arrow means this works now @beartype # v def dance_beartype_dance(i_dont_wanna: 'type[YoullDanceAndLikeIt]'): pass class YoullDanceAndLikeIt(...): ... ``` * **Readable forward reference exceptions.** The `@beartype` decorator now raises human-readable exceptions involving forward references. Previously, forward reference proxies insanely presented themselves as unreadable private @beartype classes like `beartype._check.forward._fwdref._BeartypeForwardRefIndexable`. Now, forward reference proxies quietly pretend they're just the classes they proxy. They're not, but you're no longer supposed to know. Sure... okay. Look. This is a bald-faced lie, but @beartype is okay with lying to ~~your face~~ `git blame` when doing so is in your best interests. Specifically, forward reference proxies now additionally proxy both: * The fully-qualified names of the modules declaring the classes to which they refer. * The unqualified basenames of those classes. * **Class redecoration eliding.** The `@beartype` decorator now efficiently protects itself against redecoration. Previously, `@beartype` uselessly allowed classes already decorated by `@beartype` to be redecorated by `@beartype`. Now, `@beartype` usefully ignores attempts to redecorate classes: e.g., ```python @beartype # <-- this now reduces to a noop @beartype # <-- this still does nice stuff class MuhRedecoratedClass(...): ... ``` * **Documented stuff.** Read such risible, readily defensible, and easily digestible documentation as: * A [revised high-level introduction](https://beartype.readthedocs.io) to @beartype, which now promotes our principal `beartype.claw.beartype_this_package()` import hook. Ideally, this is what almost everyone should now be using. * A new [`beartype.claw` API page](https://beartype.readthedocs.io/en/latest/api_claw). Every beartype import hook has now been exhaustively documented. Okay, okay. We omitted the `beartype.claw.beartyping()` context manager, because we ran out of time and *Cyberpunk 2077* isn't going to hack its own neural link, is it? It might, actually. We were warned! * A new ["What does 'pure-Python' mean?" FAQ entry](https://beartype.readthedocs.io/en/latest/faq/#what-does-pure-python-mean). Reading is fun, even if you learn nothing and squander precious time that could have been better spent breathlessly watching Keanu Reeves do Keanu Reeves things. * A new ["What does 'hybrid runtime-static' mean?" FAQ entry](https://beartype.readthedocs.io/en/latest/faq/#what-does-hybrid-runtime-static-mean-pretty-sure-you-made-that-up-too). You will be bored to tears even as you gnash your teeth in mute frustration, which really cannot be good for your teeth. * A new ["What does 'third-generation type-checker' mean?" FAQ entry](https://beartype.readthedocs.io/en/latest/faq/#third-generation-type-checker-doesn-t-mean-anything-does-it). Fun with Tedious Historical Facts That Will Bore You and Were Probably Just Made Up By @leycec Anyway: *The Reckoning.* * Injects superfluous images illegally culled from *Akira* into this documentation, just because. If @beartype can do something, @beartype will do something. This is @beartype 0.16.3, the patch release best described as... When you strive for Mount Olympus, yet you're still in Hades. — @leycec, excerpts from "My Life with Beartype: A Sad Story" This is how the QA was won. Not with a whimper, but an exploding head emoji. (An explosive impulse detonates tons of decidedly pulsating lozenges!*)
- Loading branch information