-
-
Notifications
You must be signed in to change notification settings - Fork 50
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
How to use beartype with boto3? #68
Comments
ohnoes
Oh. Oh, yes.
ohnoes x 2: The Revenge of ohnoes
Oh. Oh, even more yes.
"Why, Bezos. Why are we cursed with your dark legacy?", I screech to the uncaring skies. No reply is heard.
Absolutely. When you start pushing past a million lines, That's why we're here... is what I'd be saying if I had any experience whatsoever with Boto3. Instead, I have none. Therefore, please take everything that follows with a generous pinch of salt to avoid additional salty tears of dismay and anguish from coworkers. According to StackOverflow, PEP 484-style forward references might be of some assistance here (citation, citation). Anonymous Internet strangers (who stridently assure us we can trust them with our Q4 profit margins) claim that types dynamically fabricated by abstruse Boto3 factories actually do exist at some indefinite point in time: e.g., # Supposedly, this works. I unconditionally trust Internet
# strangers with my cats. Would You?
dynamo: 'boto3.resources.factory.dynamodb.Table' = (
boto3
.resource('dynamodb')
.Table(os.environ['DYNAMODB_TABLE']))
# Supposedly, this works too. I believe what I am told.
def get_object(s3_client: 'botocore.client.S3') -> str:
pass The latter example suggests from beartype import beartype
import boto3
# Forward references for value. Because we care.
S3Client = 'botocore.client.S3'
S3ServiceResource = 'kinda.have.no.idea.what.the.type.of.S3ServiceResource.actually.is'
Bucket = 's3.Bucket'
Table = 'boto3.resources.factory.dynamodb.Table'
@beartype
def example(s3: S3ServiceResource) -> Bucket:
return s3.Bucket('example')
if __name__ == "__main__":
s3 = boto3.resource('s3')
bucket = example(s3) That's Not Gonna Work...yeah. I know. If that actually worked as advertised, I'm a bit surprised there's no sane public well-defined way to either:
Or is there? Neither project really name-drops runtime type-checkers like Map Types for the Good of the Amazon
This is a fascinating idea. In theory, it might be feasible for us to doctor up a new public
In practice, that's probably the wrong thing to do. Upstream is aware this is a pressing concern and will probably begin offically type-hinting Boto3 sometime this century. Obviously, no one wants to wait for the clone of Bezos to resolve this... but maybe we should? Of course, I would say this. I just spent three weeks wrestling with Sphinx My bear sense is tingling. This can only mean that absolutely nothing will work and we are doomed to abandon sanity-preserving intellisense for Boto3 types on excessively big codebases that make even VSCode Pylance weep. ohnoes x 3: The Final Legend of ohnoes |
Eureka! Ignore everything above, because it was bad. I have something better – nay, something ingenious – nay, something cruel and malicious that eats at the very beating heart of static type-checking like Lyme disease in PEP-compliant form. So. There's something awful and amazing called import boto3
from beartype import beartype
from typing import TYPE_CHECKING
# If performing static type-checking (e.g., mypy, pyright),
# conditionally import Boto3 type hint stubs that are
# safely usable *ONLY* at static type-checking time.
if TYPE_CHECKING:
from mypy_boto3_s3.service_resource import S3ServiceResource, Bucket
# Else, @beartime-based runtime type-checking is
# being performed. In this case, alias the same
# Boto3 type hint stub names imported above to their
# semantically equivalent beartype validators that are
# safely usable *ONLY* at runtime type-checking time.
else:
from typing import Annotated
from beartype.vale import Is
# Suck it, intellisense IDE. Suck it.
S3ServiceResource = Annotated[object, Is[
lambda obj: obj.__class__.__name__ == "s3.ServiceResourceOrSmthng"]]
Bucket = Annotated[object, Is[
lambda obj: obj.__class__.__name__ == "s3.Bucket"]]
# Do this for the good of the gross domestic product, @beartype.
@beartype
def example(s3: S3ServiceResource) -> Bucket:
return s3.Bucket('example')
if __name__ == "__main__":
s3 = boto3.resource('s3')
bucket = example(s3) Lastly, if you care about efficiency, ...you do care about efficiency, don't you you can optimize away the additional stack frame imposed by each lambda function defined above with semantically equivalent but much faster ...
else:
from typing import Annotated
from beartype.vale import IsAttr, IsEqual
# Suck it even faster, intellisense IDE. Suck it.
S3ServiceResource = Annotated[object,
IsAttr['__class__', IsAttr['__name__', IsEqual["s3.ServiceResourceOrSmthng"]]]]
Bucket = Annotated[object,
IsAttr['__class__', IsAttr['__name__', IsEqual["s3.Bucket"]]]]
... If that doesn't work, I will graffittii my next GitHub comment with 10,000 soul-destroying repetitions of the sparkly heart emoji. We pray it never comes to that. 💖 💖 💖 💖 💖 💖 💖 💖 💖 💖 💖 💖 💖 💖 💖 💖 |
@leycec Dude...you are amazing. Not only did you manage to figure something out for an issue I thought was going to be unsolvable (at least as far as the whole "have your types and intellisense too" goes), you did this within...(checks timestamp)... like a couple of hours from me posting. Looking back, In all seriousness, how may I express my thanks to you and the project for helping solve the missing piece of this puzzle? I can make a PR to add this to the documentation so that others who may come across in the future won't have to scratch their heads. |
This commit adds a new entry to the *Frequently Asked Questions (FAQ)* section of our front-facing `README.rst` file documenting how to type-hint types dynamically fabricated at runtime by Boto3 (i.e., the official Amazon Web Services (AWS) Software Development Kit (SDK) for Python), resolving issue #68 kindly submitted by Paul Hutchings (@paulhutchings) – the supremely skilled sloth rockin' big shades and ever bigger enthusiasm for well-typed Python web apps. (*Hedged sedge!*)
Awwwwwww. You so nice, Paul. As a supremely skilled sloth that rocks shades, I'm kinda concerned about hurting you if I emoji you too fast over here. Oh, God – here goes! 🤗
Bwa-hah. I accidentally got there first ahead of you. Let me know how that reads for you. Must be rough being a sloth. I sympathize. My beautiful wifey ←you just know she's gonna see this calls me a sloth all the time. Metaphorically speaking, she's not wrong. This issue is everything I did tonight. 😅
Why, I'm so glad you asked. The answer is money. Just kidding! Yikes. Tough crowd tonight. Seriously, though. If you find any available volunteer time for open source, yup so never I'm certain we'd all love a package from Paul that is either:
Thanks again for all this voluminous interest! Don't hesitate to drop me a line anywhere you need a helping hand with @beartype and/or Python type-checking in general. |
I love it! Could not have done a beartype style write-up better myself.
Indeed, I was already thinking of doing this :) I'm afraid midi-nn will have to wait (hopefully not for long). I'm afraid my musical knowledge outstrips my ML knowledge at the moment, but rest assured it is not an intersection of interests that I will abandon. |
This release titillates with scintillating support for **[PEP 557 -- Data Classes][PEP 557]**, **[PEP 570 -- Python Positional-Only Parameters][PEP 570]**, and **[PEP 604 -- Allow writing union types as X | Y][PEP 604]**. This release resolves a bone-crushing **30 issues** (mostly shameless dupes of one another, admittedly) and merges **3 pull requests.** World-girdling changes include: ## Compatibility Added * **[PEP 557 -- Data Classes][PEP 557].** `@beartype` now supports **dataclasses** (i.e., types decorated by the standard `@dataclasses.dataclass` decorator), resolving issue #56 kindly submitted by @JulesGM (Jules Gagnon-Marchand) the Big Brain NLP researcher. Specifically, `@beartype` now transparently type-checks: * **Dataclass-specific initialization-only instance variable type hints** (i.e., `dataclasses.InitVar[...]`). * The implicit `__init__()` method generated by `@dataclass` for dataclasses through a clever one-liner employed by @antonagestam (Anton Agestam) the ageless Swede that I stan for. * **[PEP 570 -- Python Positional-Only Parameters][PEP 570].** `@beartype` now supports positional-only arguments and no one cares. Given the triviality, the rear view mirror of regret suggests we kinda should've implemented this sooner. Better late than never, best @beartype friends for life (BBFFL). * **[PEP 604 -- Allow writing union types as X | Y][PEP 604].** `@beartype` now supports new-style set unions (e.g., `int | float`), resolving issue #71 kindly submitted by pro typing aficionado Derek Wan (@dycw). Thanks to Derek for the helpful heads up that @beartype was headed straight for typing disaster under Python ≥ 3.10. Since we dodged another bullet there, this must mean we have now activated bullet time. Goooooo, slomo! ## Compatibility Improved * **[PEP 484 -- Type Hints][PEP 484],** including: * **`typing.{Binary,Text,}IO[...]` deep type-checking.** `@beartype` now deeply type-checks subscripted `typing.{Binary,Text,}IO[...]` type hints, resolving issue #75 kindly submitted by Niklas "If I had a nickel for every lass..." Rosenstein. Notably: * Since the `typing.BinaryIO` protocol and its `typing.IO` superclass share the exact same API, the `typing.BinaryIO` protocol is lamentably useless for *all* practical purposes. This protocol *cannot* be leveraged to detect binary file handles. Can binary file handles be detected at runtime then? Yes, we can! A binary file handle is any object satisfying the `typing.IO` protocol but *not* the `typing.TextIO` protocol. To implement this distinction, `@beartype` necessarily invented a novel form of type-checking and a new variant of type elision: **anti-structural subtyping.** Whereas structural subtyping checks that one class matches the API of another class (referred to as a "protocol"), anti-structural subtyping checks that one class does *not* match the API of another class (referred to as an "anti-protocol"). `@beartype` public exposes this functionality via the new `beartype.vale.IsInstance[...]` validator, enabling *anyone* to trivially perform anti-structural subtyping. In this case, `@beartype` internally reduces all useless `typing.BinaryIO` type hints to substantially more useful `typing.Annotated[typing.IO, ~beartype.vale.IsInstance[typing.TextIO]]` type hints. * **Unsubscripted NumPy type hints.** `@beartype` now supports **untyped NumPy array type hints** (i.e., the unsubscripted `numpy.typing.NDArray` and subscripted `numpy.typing.NDArray[typing.Any]` type hints), resolving issue #69 kindly submitted by @Jasha10, the stylish boy wonder dual-wielding the double thumbs-up and coke-bottle glasses that signify elementary genius. Specifically, this commit now detects and reduces these hints to the equivalent `numpy.ndarray` type. * **Mypy ≥ 0.920.** `@beartype` now squelches ignorable mypy complaints first introduced by mypy 0.920, including: * **Explicit reexport errors.** `beartype` now squelches implicit reexport complaints from mypy with respect to public attributes published by the `beartype.cave` subpackage, resolving issue #57 kindly reopened by Göteborg melodic death metal protégé and brightest academic luminary @antonagestam. This subpackage is now compatible with both the `--no-implicit-reexport` mypy CLI option and equivalent `no_implicit_reexport = True` configuration setting in `.mypy.ini`. * **Version-dependent errors.** Previously, mypy permitted imports against standard library modules introduced in newer CPython versions to be squelched with the usual ``"# type: ignore[attr-defined]"`` pragma. Since mypy now ignores these pragmas, `@beartype` now silences its complaints through... *unconventional* means. A bear do wut a bear gotta do. ## Features Added * **Compatibility API.** `beartype` now publishes a new `beartype.typing` API as a `typing` compatibility layer improving forward compatibility with future Python releases, resolving issue #81 kindly submitted by the honorable @qiujiangkun (Qiu Jiangkun). Consider resolving [PEP 585][PEP 585] deprecations by importing from our new `beartype.typing` API rather than the standard `typing` API. A battery of new unit tests ensure conformance: * Between `beartype.typing` and `typing` across all Python versions. * With mypy when importing from `beartype.typing`. * **Configuration API** (i.e., public attributes of the `beartype` package enabling end users to configure the `@beartype` decorator, including configuring alternative type-checking strategies *other* than constant-time runtime type-checking). Specifically, `beartype` now publishes: * `beartype.BeartypeStrategy`, an enumeration of all type-checking strategies to *eventually* be fully supported by future beartype releases – including: * `BeartypeStrategy.O0`, disabling type-checking for a callable by reducing `@beartype` to the identity decorator for that callable. Although currently useless, this strategy will usefully allow end users to selectively prevent callables from being type-checked by our as-yet-unimplemented import hook. When implemented, that hook will type-check *all* callables in a given package by default. Some means is needed to prevent that from happening for select callables. This is that means. * `BeartypeStrategy.O1`, our default `O(1)` constant-time strategy type-checking a single randomly selected item of a container that you currently enjoy. Since this is the default, this strategy need *not* be explicitly configured. Of course, you're going to do that anyway, aren't you? `</sigh>` * `BeartypeStrategy.Ologn`, a new `O(lgn)` logarithmic strategy type-checking a randomly selected number of items `j` of a container `obj` such that `j = len(obj)`. This strategy is **currently unimplemented** (but will be implemented by a future beartype release). * `BeartypeStrategy.On`, a new `O(n)` linear strategy deterministically type-checking *all* items of a container. This strategy is **currently unimplemented** (but will be implemented by a future beartype release). * `beartype.BeartypeConf`, a simple dataclass encapsulating all flags, options, settings, and other metadata configuring the current decoration of the decorated callable or class. For efficiency, this dataclass internally self-caches itself (i.e., `BeartypeConf(*args, **kwargs) is BeartypeConf(*args, **kwargs)`). The `__init__()` method of this dataclass currently accepts these optional parameters: * An `is_debug` boolean instance variable. When enabled, `@beartype` emits debugging information for the decorated callable – including the code for the wrapper function dynamically generated by `@beartype` that type-checks that callable. * A `strategy` instance variable whose value must be a `BeartypeStrategy` enumeration member. This is how you notify `@beartype` of which strategy to apply to each callable. * **Wrapper function debuggability.** Enabling the `is_debug` parameter to the `BeartypeConf.__init__` method significantly improves the debuggability of type-checking wrapper functions generated by `@beartype`. This configuration option is entirely thanks to @posita the positive Numenorean, who pined longingly for debuggable wrapper functions and now receives proportionately. Praise be to @posita! He makes bears better. Specifically, enabling this option enables developer-friendly logic like: * Pretty-printing to stdout (standard output) the definitions of those functions, including line number prefixes for readability. * Enabling those functions to be debugged. Thanks to a phenomenal pull request by the dynamic dual threat that is @posita **+** @TeamSpen210, `@beartype` now conditionally caches the bodies of type-checking wrapper functions with the standard (albeit poorly documented) `linecache` module. Thanks so much! Bear Clan 2022!!! * Suffixing the declarations of `@beartype`-specific hidden private "special" parameters passed to those functions with comments embedding their human-readable representations. Safely generating these comments consumes non-trivial wall clock at decoration time and is thus conditionally enabled for external callers requesting `@beartype` debugging. For example, note the `"# is"`-prefixed comments in the following signature of a `@beartype`-generated wrapper function for an asynchronous callable with signature `async def control_the_car(said_the: Union[str, int], biggest_greenest_bat: Union[str, float]) -> Union[str, float]:` ``` python (line 0001) async def control_the_car( (line 0002) *args, (line 0003) __beartype_func=__beartype_func, # is <function test_decor_async_coroutine.<locals>.control_the_car at 0x7> (line 0004) __beartype_raise_exception=__beartype_raise_exception, # is <function raise_pep_call_exception at 0x7fa13d> (line 0005) __beartype_object_140328307018000=__beartype_object_140328307018000, # is (<class 'int'>, <class 'str'>) (line 0006) __beartype_object_140328306652816=__beartype_object_140328306652816, # is (<class 'float'>, <class 'str'>) (line 0007) **kwargs (line 0008) ): ``` * **Decorator modality.** `@beartype` now supports two orthogonal modes of operation: * **Decoration mode** (i.e., the standard mode where `@beartype` directly decorates a callable *without* being passed parameters). In this mode, `@beartype` reverts to the default configuration of constant-time runtime type-checking and *no* debugging behaviour. * **Configuration mode** (i.e., the new mode where `@beartype` is called as a function passed a `BeartypeConf` object via the keyword-only `conf` parameter). In this mode, `@beartype` efficiently creates, caches, and returns a memoized decorator encapsulating the passed configuration: e.g., ``` python from beartype import beartype, BeartypeConf, BeartypeStrategy @beartype(conf=BeartypeConf(strategy=BeartypeStrategy.On)) def muh_func(list_checked_in_linear_time: list[int]) -> int: return len(list_checked_in_linear_time) ``` * Specifically, this commit extricates our core `@beartype` decorator into a new private `beartype._decor._core` submodule in preparation for subsequently memoizing closures encapsulating that decorator returned by invocations of the form `@beartype.beartype(conf=BeartypeConf(...))` * **Declarative instance validator.** `beartype` now publishes a new `beartype.vale.IsInstance[...]` validator enforcing instancing of one or more classes, generalizing **isinstanceable type hints** (i.e., normal pure-Python or C-based classes that can be passed as the second parameter to the ``isinstance()`` builtin). Unlike standard isinstanceable type hints, `beartype.vale.IsInstance[...]` supports various set theoretic operators. Critically, this includes negation. Instance validators prefixed by the negation operator `~` match all objects that are *not* instances of the classes subscripting those validators. Wait. Wait just a hot minute there. Doesn't a typing.Annotated_ type hint necessarily match instances of the class subscripting that type hint? Yup. This means type hints of the form `typing.Annotated[{superclass}, ~IsInstance[{subclass}]` match all instances of a superclass that are *not* also instances of a subclass. And... pretty sure we just invented type hint arithmetic right there. That sounded intellectual and thus boring. Yet, the disturbing fact that Python booleans are integers <sup>yup</sup> while Python strings are infinitely recursive sequences of strings <sup>yup</sup> means that type hint arithmetic can save your codebase from Guido's younger self. Consider this instance validator matching only non-boolean integers, which *cannot* be expressed with any isinstanceable type hint (e.g., ``int``) or other combination of standard off-the-shelf type hints (e.g., unions): `Annotated[int, ~IsInstance[bool]]`. ← *bruh* * **Functional API.** `beartype` now publishes a new public `beartype.abby` subpackage enabling users to type-check *anything* *anytime* against *any* PEP-compliant type hints, resolving feature request #79 kindly submitted by (*...wait for it*) typing Kung Fu master @qiujiangkun (Qiu Jiangkun). This subpackage is largely thanks to @qiujiangkuni, whose impeccable code snippets drive our initial implementation. This subpackage provides these utility functions: * `beartype.abby.is_bearable()`, strictly returning a boolean signifying whether the passed arbitrary object satisfies the passed type hint or not (e.g., `is_bearable(['the', 'centre', 'cannot', 'hold;'], list[int]) is False`). * `beartype.abby.die_if_unbearable()`, raising the new `beartype.roar.BeartypeAbbyHintViolation` exception when the passed arbitrary object violates the passed type hint. ## Features Improved * **Exception message granularity,** including exceptions raised for: * **Disordered builtin decorators.** `@beartype` now raises instructive exceptions when decorating an uncallable descriptor created by a builtin decorator (i.e., `@property`, `@classmethod`, `@staticmethod`) due to the caller incorrectly ordering `@beartype` above rather than below that decorator, resolving issue #80 kindly submitted by typing academician @qiujiangkun (Qiu Jiangkun). Specifically, `@beartype` now raises human-readable exceptions suffixed by examples instructing callers to reverse decoration ordering. * **Beartype validators.** `@beartype` now appends a detailed pretty-printed diagnosis of how any object either satisfies or fails to satisfy any beartype validator to exception messages raised by high-level validators synthesized from lower-level validators (e.g., via overloaded set theoretic operators like `|`, `&`, and `~`), resolving issue #72 kindly submitted by the unwreckable type-hinting guru Derek Wan (@dycw). This diagnostic trivializes validation failures in non-trivial use cases involving multiple nested conjunctions, disjunctions, and/or negations. ## Features Optimized * **`@beartype` call-time performance.** `@beartype` now generates faster type-checking wrapper functions with a vast and undocumented arsenal of absolutely "legal" weaponry, including: * **`typing.{Generic,Protocol}` deduplication.** `@beartype` now microoptimizes away redundant `isinstance()` checks in wrapper functions checking `@beartype`-decorated callables annotated by **PEP 484-compliant subgenerics or PEP 585-compliant subprotocols** (i.e., user-defined classes subclassing user-defined classes subclassing `typing.{Generic, Protocol}`), resolving issue #76 kindly submitted by @posita the positive numerics QA guru and restoring the third-party `numerary` package to its glory. Our generics workflow has been refactored from the ground-up to stop behaving insane. `@beartype` now performs an inner breadth-first search (BFS) across generic pseudo-superclasses in its existing outer BFS that generates type-checking code. When you're nesting a BFS-in-a-BFS, your code went full-send. There's no going back from that. * **Worst-case nested data structures.** `@beartype` now resolves a performance regression in type-checking wrapper functions passed worst-case nested data structures violating PEP-compliant type hints, resolving issue #91 kindly submitted by Cuban type-checking revolutionary @mvaled (Manuel Vázquez Acosta). Specifically, this commit safeguards our low-level `represent_object()` function stringifying objects embedded in exception messages describing type-checking violations against worst-case behaviour. A new unit test shieldwalls against further performance regressions. All our gratitude to @mvaled for unveiling the darkness in the bear's heart. * **`@beartype` decoration-time performance.** The `@beartype` decorator has been restored to its prior speed, resolving performance regressions present throughout our [0.8.0, 0.10.0) release cycles. Significant decoration-time optimizations include: * **Code objects.** `@beartype` now directly accesses the code object underlying the possibly unwrapped callable being decorated via a temporary cache rather than indirectly accessing that code object by repeatedly (and expensively) unwrapping that callable, dramatically optimizing low-level utility functions operating on code objects. * **Exception messages.** `@beartype` now defers calling expensive exception handling-specific functions until an exception is raised, dramatically restoring our decoration-time performance to the pre-0.8.0 era – which isn't that great, honestly. But we'll take anything. Substantial optimizations remain, but we are dog-tired. Moreover, DQXIS:EofaEA (...that's some catchy name right there) ain't gonna play itself – *OR IS IT!?!* Cue creepy AI. * **Fixed lists.** `@beartype` now internally lelaxes inapplicable safety measures previously imposed by our internal `FixedList` container type. Notably, this type previously detected erroneous attempts to extend the length of a fixed list by subversively assigning a slice of that fixed list to a container whose length differs from that of that slice. While advisable in theory, `@beartype` *never* actually sliced any fixed list -- let alone used such a slice as the left-hand side (LHS) of an assignment. Disabling this detection measurably improves the efficiency of fixed lists across the codebase -- which is, after all, the entire raison d'etre for fixed lists in the first place. `</shaking_my_head>` * **Parameter introspection.** `@beartype` now introspects callable signatures using a homegrown lightweight parameter parsing API. `@beartype` previously introspected signatures using the standard heavyweight `inspect` module, which proved... *inadvisable.* All references to that module have been removed from timing-critical code paths. All remaining references reside only in timing-agnostic code paths (e.g., raising human-readable exceptions for beartype validators defined as anonymous lambda functions). * **`@beartype` importation-time performance.** The `beartype` package now avoids unconditionally importing optional first- and third-party subpackages, improving the efficiency of the initial ``from beartype import beartype`` statement in particular. `beartype` now intentionally defers these imports from global module scope to the local callable scope that requires them. A new functional test guarantees this to be the case. ## Features Deprecated * **Badly named exception classes,** to be removed in `beartype` 0.1.0. This includes: * `beartype.roar.BeartypeCallHintPepException`, deprecated by `beartype.roar.BeartypeCallHintViolation`. * `beartype.roar.BeartypeCallHintPepParamException`, deprecated by `beartype.roar.BeartypeCallHintParamViolation`. * `beartype.roar.BeartypeCallHintPepReturnException`, deprecated by `beartype.roar.BeartypeCallHintReturnViolation`. ## Documentation Revised * The *Frequently Asked Questions (FAQ)* section of our front-facing `README.rst` documentation now sports a medley of new entries, including instructions on: * **Boto3 integration,** enabling end users to type-check runtime types dynamically fabricated by Boto3 (i.e., the official Amazon Web Services (AWS) Software Development Kit (SDK) for Python), resolving issue #68 kindly submitted by Paul Hutchings (@paulhutchings) – the supremely skilled sloth rockin' big shades and ever bigger enthusiasm for well-typed Python web apps. Relatedly, the @beartype organization now officially hosts [`bearboto3`, Boto3 @beartype bindings by (*wait for it*) @paulhutchings](https: //github.com/beartype/bearboto3). * **Mock type type-checking,** resolving issue #92 kindly submitted by @Masoudas (Masoud Aghamohamadian-Sharbaf – wish I had an awesome name like that). Gratuitous shoutouts to @TeamSpen210 for the quick save with a ludicrous two-liner solving everything. [PEP 484]: https://www.python.org/dev/peps/pep-0484 [PEP 557]: https://www.python.org/dev/peps/pep-0557 [PEP 570]: https://www.python.org/dev/peps/pep-0570 [PEP 585]: https://www.python.org/dev/peps/pep-0585 [PEP 604]: https://www.python.org/dev/peps/pep-0604 The hype train is now boarding. All aboooooooard! (*Classless masterless masterclass!*)
Recently discovered beartype and have been loving it, especially love the humor and lighthearted nature of the project!
I'm working with boto3 (the AWS Python SDK) and disocvered that it uses a factory to dynamically create the various class types at runtime, meaning that by default, you cannot annotate them. I discovered the boto3-stubs package exists as a way to provide both types to annotate with, as well as allowing various IDE auto-complete features to work.
However...(you might already see where this is going), because the types provided by
boto3-stubs
and the actual type thatboto3
creates are not identical (even though they represent the same object/schema), the type validation fails when decorating a function that accepts/returns boto3 types as arguments withbeartype
. Below is a simple example:I've also made a small example project for this so that people can play around with it/reproduce it.
Now poking around, I discovered validators and I assume this is the appropriate way to handle situations like this. However, after playing around a bit, while I can create a custom type (see example below) that works with beartype, I lose the other features that the
boto3-stubs
library provides such as the autocomplete/suggest features. Granted, those are not the most important things in the world, but they certainly help, especially when working in a larger project.What I'm really after I suppose is a way to "map" types, or basically tell beartype, "hey, these types are the same" or something along those lines. Is it possible to have my salmon and eat it too?
The text was updated successfully, but these errors were encountered: