Skip to content
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

TypeError: TypedDict does not support instance and class checks #55

Closed
KyleKing opened this issue Oct 6, 2021 · 5 comments
Closed

TypeError: TypedDict does not support instance and class checks #55

KyleKing opened this issue Oct 6, 2021 · 5 comments

Comments

@KyleKing
Copy link

KyleKing commented Oct 6, 2021

I saw in #7 that TypedDict should be supported from 0.7.0 and partial support has been in beartype since 0.1.0, but I'm running into errors with Python 3.7.12 and 3.9.7, so I'm not sure if this snippet should be working:

# beartype==0.8.1

from beartype import beartype

try:
    from typing import TypedDict
except ImportError:  # For Python < 3.8
    from typing_extensions import TypedDict  # typing-extensions = "^3.10.0"

class Point2D(TypedDict):
    x: int
    y: int
    label: str

@beartype
def convert(point: Point2D) -> Point2D:
    return point

convert({'x': 1, 'y': 2, 'label': 'good'})
> python tmp.py                                                                                                                    ─╯
Traceback (most recent call last):
  File "/Users/kyleking/.pyenv/versions/3.9.7/lib/python3.9/site-packages/beartype/_util/cls/utilclstest.py", line 159, in die_unless_type_isinstanceable
    isinstance(None, cls)  # type: ignore[arg-type]
  File "/Users/kyleking/.pyenv/versions/3.9.7/lib/python3.9/typing.py", line 1956, in __subclasscheck__
    raise TypeError('TypedDict does not support instance and class checks')
TypeError: TypedDict does not support instance and class checks

Should beartype properly check TypedDicts? There were similar errors found in Pydantic and some notes here. TypedDict can't be used with isinstance by design. There is a reference to tests for TypedDict, but they don't appear to be present

And this isn't promising 😅

# is_typeddict <-- unusable as a type hint

@leycec
Copy link
Member

leycec commented Oct 7, 2021

...ohnoes. You caught us red-handed – or honey-pawed, as it were. badum ching

A long time ago in a codebase far, far away, @beartype once shallowly type-checked typing.TypedDict... I think, anyway. Tragically, our unavoidable laziness coupled with aggressive release schedules means we kinda failed to properly test that.

Welp, this is awkward. Some unspecified recent release of beartype (I am glaring at you, beartype 0.8.0) silently regressed that and broke both typing.TypedDict and typing.NamedTuple. I am now shaking my emaciated fists at my younger self, on whose behalf I now extend my most grievous apologies.

Thanks so much for the compassionate assistance, Master Kyle. Let's get this patched up for everyone and pretend this never happened! The sweat pouring off my Klingon-like forehead is real. 😓 💦

Klingon-like forehead

@leycec
Copy link
Member

leycec commented Oct 7, 2021

Welp, this is even more embarrassing...

Turns out we actually never supported typing.TypedDict at all! Our documentation claiming we supported typing.TypedDict shallow type-checking from beartype 0.1.0 onward was, in fact, complete balls.

On the bright side, at least we now know why a non-existent feature was never tested.

the shame is real

This is a pretty critical omission, as typing.TypedDict is a core type. So, I've slated this for inclusion in the upcoming beartype 0.9.0 release. Let's optimistically pretend that I'll get everything pushed out this Friday. 🤕

@KyleKing
Copy link
Author

KyleKing commented Oct 7, 2021

Thanks! I'm always impressed by your liberal use of puns and references

I would be happy to test and give feedback before you release, if that would help. And no rush!

@leycec
Copy link
Member

leycec commented Oct 7, 2021

Oh, thank you so much. You are too kind and complimentary. This elicits feelings of warmth and generosity, which means I now want to get this done even more! Nice-guy Worf approves.

Please do liberally test this after beartype 0.9.0 drops and complain with clenched fists here if we lied yet again about this working.

...if we type-check it, they will come

In theory, it should be trivial for beartype to at least shallowly type-check typing.TypedDict subclasses by just internally reducing the typing.TypedDict superclass on subclass types to the dict superclass at decoration time: e.g.,

# Let's just pretend this...
from typing import TypedDict
class Point2D(TypedDict):
    x: int
    y: int
    label: str

# ...was coded like this, instead!
class Point2D(dict):
    x: int
    y: int
    label: str

wut you gonna do

TypeDict Rant, Let's Go!

Lastly, I kinda agree with mpkocher's well-written typing.TypedDict tl;dr:

I believe TypedDict can be a value tool to help improve clarity of interfaces, specifically in legacy code that is a bit dictionary-mania heavy. However, for new code, I would suggest avoid using TypedDict in favor of the thin data models, such as pydantic and attrs [and beartype dataclasses – some day over the GitHub rainbow when I gather the internal strength to implement them].

typing.TypedDict occupies this lonely weird liminal space in Python's type-hinting landscape, where:

  • It doesn't really behave like anything else that's been standardized (even typing.NamedTuple, which behaves much more sensibly).
  • Breaks usability by preventing user-defined subclasses and instances from being compared with other arbitrary classes (e.g., by being passed to the isinstance() or issubclass() builtins).
  • Fails to interoperate cleanly at runtime with the rest of the Python ecosystem for aforementioned reasons.

It's a crying shame. Guido & Co. were clearly trying to extend the idea of fixed-length tuple type hints (e.g., typing.Tuple[int, str, bool]) to dictionaries. Sadly, they fumbled the ball in their own end zone after tripping over the marching band furry. Now, everyone just uses pydantic instead.

I am sighing.

leycec added a commit that referenced this issue Oct 13, 2021
This commit is the last in a commit chain adding support for
superficially type-checking **typed dictionaries** (i.e.,
`typing.TypedDict` and `typing_extensions.TypedDict` subclasses),
resolving issue #55 kindly submitted by Kyle (@KyleKing), the
undisputed King of Parexel AI Labs. Specifically, this commit:

* Refines our recently added
  `beartype._util.hint.pep.proposal.utilpep593.is_hint_pep593()` tester
  to additionally test for the existence of the `__total__` dunder
  attribute necessarily added to typed dictionaries.
* Improves our private
  `beartype._util.hint.pep.utilpepget.get_hint_pep_sign_or_none()`
  getter to uniquely identify typed dictionaries as `HintSignTypedDict`.
* Exhaustively tests `@beartype` support for typed dictionaries,
  including those defined via both:
  * The official `typing.TypedDict` factory under Python ≥ 3.8.
  * The third-party `typing_extensions.TypedDict` factory under Python
    3.6 and 3.7.

(*Unrequited requiem!*)
@leycec
Copy link
Member

leycec commented Oct 13, 2021

Brutally resolved! In commit 342e5fc (and the upcoming beartype 0.9.0 – it's any day now, we swear it on Bearzabubba), @beartype now shallowly type-checks both typing.TypedDict and typing_extensions.TypedDict type hints as semantically equivalent to collections.abc.Mapping[str, object].

Clearly, this is... suboptimal. But we can agree that something beats nothing. Well, conditionally depending on the exact nature of that something. So sometimes. And this is one of those times.

Thanks again for the thoughtful heads-up and bearing hyuk hyuk with us here, Kyle the undisputed King of Parexel AI Labs. You deserve all the academic citations that the @beartype community has to give. Reference Kyle, everyone! He rocks that AI. 📝

@leycec leycec closed this as completed Oct 13, 2021
leycec added a commit that referenced this issue Oct 22, 2021
This release adds voluminous support for **asynchronous callables**
(including both coroutines and asynchronous generators) while improving
existing support for **typed NumPy arrays** (i.e., `numpy.typed.NDArray`
type hints), **beartype validators** (i.e., `beartype.vale` type hints),
[PEP
484][PEP 484], [PEP 563][PEP 563], [PEP 585][PEP 585], [PEP 586][PEP
586], [PEP 589][PEP 589], and [PEP 593][PEP 593].

This release resolves **6 issues** and merges **2 pull requests.**
Non-cringe-worthy changes include:

## Compatibility Improved

* **Asynchronous coroutines.** `@beartype` now transparently supports
  coroutines (i.e., callables declared with `async def` rather than
  merely `def`) with the exact same shallow and deep type-checking
  semantics as standard synchronous callables. Notably, `@beartype` now
  accepts all valid variants of coroutine type hints standardized by
  [PEP 484][PEP 484], [PEP 585][PEP 585], and mypy. This includes:
  * `async def coroutine(...) -> {return}`, which `@beartype` now wraps
    with an asynchronous coroutine first awaiting the decorated
    `coroutine()` and then validating the value returned by
    `coroutine()` satisfies the `{return}` type hint.
  * `async def coroutine(...) -> typing.Coroutine[{yield}, {send},
    {return}]`, which `@beartype` now wraps with an asynchronous
    coroutine first awaiting the decorated `coroutine()` and then
    validating the value returned by `coroutine()` satisfies the
    `{return}` type hint (while continuing to silently ignore the
    `{yield}` and `{send}` child type hints).
* **Asynchronous and synchronous generators.** `@beartype` now
  transparently supports asynchronous generators (i.e., generators
  declared with `async def` rather than merely `def`) with the exact
  same shallow and deep type-checking semantics as standard synchronous
  generators. Notably, `@beartype` now requires the returns of:
  * Asynchronous generators to be annotated with either:
    * A [PEP 484][PEP 484]-compliant `typing.AsyncGenerator[...]` type
      hint.
    * A [PEP 585][PEP 585]-compliant
      `collections.abc.AsyncGenerator[...]` type hint.
  * Synchronous generators to be annotated with either:
    * A [PEP 484][PEP 484]-compliant `typing.Generator[...]` type hint.
    * A [PEP 585][PEP 585]-compliant `collections.abc.Generator[...]`
      type hint.
* **Beartype validators under Python 3.6 and 3.7.** Beartype validators
  (which previously required Python ≥ 3.8) are now portably usable
  across *all* supported Python versions, including Python 3.6 and 3.7.
  `beartype 0.9.0` refactors the entire `beartype.vale` class hierarchy
  to leverage the widely supported `__getitem__()` dunder method
  supported by Python ≥ 3.6 rather than the [PEP 560][PEP 560]-compliant
  `__class_getitem__()` dunder method supported only under Python ≥ 3.8
  and *not* supported by mypy. Naturally, this was pain.
* **Typed NumPy arrays.** `@beartype` now accepts all valid variants of
  `numpy.typing.NDArray[{dtype}]` type hints also accepted by mypy,
  where `{dtype}` is either:
  * An actual NumPy dtype (e.g.,
    `numpy.typing.NDArray[numpy.dtype(numpy.float64)]`).
  * An object safely coercible into an actual NumPy dtype, including:
    * A scalar NumPy type (e.g., `numpy.typing.NDArray[numpy.float64]`).
  * A scalar NumPy abstract base class (ABC) (e.g.,
    `numpy.typing.NDArray[numpy.floating]`).
  Previously, `@beartype` rejected scalar NumPy ABCs. Since `@beartype`
  now accepts these ABCs, the most portable means of type-checking NumPy
  arrays of arbitrary precision is to subscript `numpy.typing.NDArray`
  by the appropriate scalar ABC: e.g.,
  * `numpy.typing.NDArray[numpy.floating]` rather than
    `numpy.typing.NDArray[numpy.float64]`, matching *any* floating-point
    NumPy array (regardless of precision).
  * `numpy.typing.NDArray[numpy.integer]` rather than
    `numpy.typing.NDArray[numpy.int64]`., matching *any* integer NumPy
    array (regardless of precision).
  Lastly, `@beartype` now supports these hints across *all* Python
  versions. Under Python ≥ 3.9, this support works as expected
  out-of-the-box. Under Python 3.6, 3.7, and 3.8:
  * If the optional third-party `typing_extensions` package is also
    importable, `@beartype` now deeply type-checks these hints as
    expected.
  * Else, `@beartype` now only shallowly type-checks these hints by
    internally reducing all `numpy.typing.NDArray[{dtype}]` type hints
    to the untyped NumPy array class `numpy.ndarray`. Since this is
    admittedly non-ideal, `@beartype` now emits one non-fatal warning of
    category `beartype.roar.BeartypeDecorHintNonpepNumpyWarning` at
    decoration time for each such reduction. [Don't blame us. We voted
    for Kodos.](https://www.youtube.com/watch?v=zTABEQ4Qh5Y) How could
    this be *our* fault!?!? <sup>it's totally our fault</sup>
* **[PEP 484][PEP 484].** `@beartype` now:
  * Deeply type-checks [PEP 484][PEP 484]-compliant `typing.Type` type
    hints, validating parameters and returns to be subclasses of the
    subscripted type. This includes *all* syntactic variants
    standardized by [PEP 484][PEP 484]:
    * `typing.Type`, matching *any* **issubclassable type** (i.e.,
      normal class passable as the second parameter to the
      `issubclass()` builtin).
    * `typing.Type[Any]`, also matching *any* issubclassable type.
    * `typing.Type[{type}]`, matching both the issubclassable type
      `{type}` and any subclass of that type.
    * `typing.Type[{forward_ref}]`, first dynamically resolving the
      forward reference `{forward_ref}' to an issubclassable type
      `{type}` at call time and then matching both that type and any
      subclass of that type.
    * `typing.Type[typing.Union[{type1}, {type2}, ..., {typeN}]`,
      permissively matching the issubclassable types `{type1}`,
      `{type2}`, and `{typeN}` as well as any subclass of those types.
  * Partially deeply type-checks [PEP 484][PEP 484]-compliant
    `typing.Coroutine` type hints, validating callables to be
    coroutines. Given a type hint `typing.Coroutine[{yield}, {send},
    {return}]`, `@beartype` now deeply type-checks the `{return}` child
    type hint (while continuing to silently ignore the `{yield}` and
    `{send}` child type hints).
  * Shallowly type-checks [PEP 484][PEP 484]-compliant **parametrized
    type variables** (i.e., `typing.TypeVar` instances instantiated with
    either two or more constraints *or* one upper bound). `@beartype`
    continues to silently ignore **unparametrized type variables**
    (i.e., type variables instantiated with neither constraints nor
    upper bounds). Notably, `@beartype` now shallowly type-checks any
    type variable instantiated with:
    * Constraints passed as positional parameters (e.g.,
      `typing.TypeVar('T', str, bytes)`) as a union of those positional
      parameters instead (e.g., as `typing.Union[str, bytes]`).
    * An upper bound passed as the `bound` keyword parameter (e.g.,
      `typing.TypeVar('T', bound=float)`) as that upper bound instead
      (e.g., as `float`).
  * Emits more self-explanatory deprecation warnings for [PEP 484][PEP
    484]-compliant type hints deprecated by [PEP 585][PEP 585] under
    Python ≥ 3.9. Specifically:
    * A [new "PEP 484 Deprecations"
      subsection](https://github.com/beartype/beartype#pep-484-deprecations)
      has been added to our front-facing `README.rst` documentation.
    * Our existing `beartype.roar.BeartypeDecorHintPepDeprecatedWarning`
      class has been refined into a new
      `beartype.roar.BeartypeDecorHintPep484DeprecationWarning` class
      specific to this category of deprecation, enabling downstream
      consumers (*this means you*) to selectively ignore only this
      category of deprecation.
    * This deprecation warning message now references [this "PEP 484
      Deprecations"
      subsection](https://github.com/beartype/beartype#pep-484-deprecations)
      subsection with improved clarity and an anxiety-provoking speech
      invoking developer horror by suggesting your codebase will die in
      2025 unless you do something painful today.
* **[PEP 563][PEP 563].** `@beartype` now:
  * Reverts our unconditionally enable of [PEP 563][PEP 563] under
    Python ≥ 3.10 in solidarity with the recent (pydantic|FastAPI)-led
    casus belli. [PEP 563][PEP 563] must now be explicitly enabled under
    *all* Python interpreters via the standard `from __future__ import
    annotation` pragma.
  * Explicitly avoids resolving [PEP 563][PEP 563]-postponed type hints
    that are relative forward references to parent callables or classes;
    by definition, parent callables and classes have yet to be defined
    and thus *cannot* be reasonably resolved and thus *must* be
    preserved as relative forward references until eventually resolved
    at call time.
* **[PEP 585][PEP 585].** `@beartype` now:
  * Deeply type-checks supports [PEP 585][PEP 585]-compliant `type` type
    hints, exactly as described for [PEP 484][PEP 484]-compliant
    `typing.Type` type hints above.
  * Partially deeply type-checks [PEP 585][PEP 585]-compliant
    `collections.abc.Coroutine` type hints, exactly as described for
    [PEP 484][PEP 484]-compliant `typing.Coroutine` type hints above.
  * **Deduplicates all [PEP 585][PEP 585] type hints,** dramatically
    reducing both the space and time complexity associated with such
    hints. [PEP 484][PEP 484]-compliant type hints (e.g., `List[str]`)
    and indeed *most* other PEP-compliant type hints are already
    effectively deduplicated by caching hidden in the standard `typing`
    module (e.g., `List[str] is List[str]`). Despite deprecating [PEP
    484][PEP 484], [PEP 585][PEP 585] fails to deduplicate its hints
    (e.g., `list[str] is not list[str]`). `@beartype` now internally
    deduplicates duplicated [PEP 585][PEP 585]-compliant type hints at
    decoration time via a thread-safe cache from the machine-readable
    string representations of such hints to such hints.
* **[PEP 586][PEP 586]** (i.e., `Literal`). `@beartype` now
  transparently supports both the official [PEP 586-compliant
  `typing.Literal` type hint][PEP 586] *and* its quasi-official
  `typing_extensions.Literal` backport to older Python versions. Thanks
  to cutting-edge Microsoft luminary @pbourke for his detailed
  assessment and resolution of everything that wrong with `@beartype`.
* **[PEP 588][PEP 589]** (i.e., `TypedDict`). `@beartype` now shallowly
  type-checks **typed dictionaries** (i.e., both `typing.TypedDict` type
  hints under Python ≥ 3.8 and `typing_extensions.TypedDict` type hints
  under Python < 3.8) by internally reducing these hints to simply
  `Mapping[str, object]`. Doing so was surprisingly non-trivial, as the
  Python 3.8-specific implementation of the `typing.TypedDict` subclass
  is functionally deficient and (presumably) never meaningfully
  unit-tested. *It's not a good look.*
* **[PEP 593][PEP 593]** (i.e., `Annotated`). `@beartype` now
  transparently supports both the official [PEP 593-compliant
  `typing.Annotated` type hint][PEP 593] *and* its quasi-official
  `typing_extensions.Annotated` backport to older Python versions.
  Thanks to cutting-edge Microsoft luminary @pbourke for his detailed
  assessment and resolution of everything that wrong with `@beartype`...
  *yet again.*

## Features Added

* **Subclass beartype validator.** The new
  `beartype.vale.IsSubclass[{type}]` beartype validator validates
  arbitrary objects and object attributes to be subclasses of the
  superclass `{type}`. Whereas the comparable [PEP 484][PEP
  484]-compliant `typing.Type[{type}]` and [PEP 585][PEP 585]-compliant
  `type[{type}]` type hints validate the same semantics only on
  `@beartype`-decorated callable parameters and returns annotated by
  those hints, `beartype.vale.IsSubclass[{type}]` validates those
  semantics on *any* objects reachable with beartype validators –
  including arbitrary deeply nested attributes of when coupled with the
  existing `beartype.vale.IsAttr[{attr_name}, {validator}]` beartype
  validator. In fact, `@beartype` internally reduces *all* typed NumPy
  arrays subscripted by scalar NumPy ABCs** (e.g.,
  `numpy.typing.NDArray[numpy.floating]`) to semantically equivalent
  beartype validators (e.g.,
  `typing.Annotated[numpy.ndarray, beartype.vale.IsAttr['dtype',
  beartype.vale.IsAttr['type',
  beartype.vale.IsSubclass[numpy.floating]]]]`).

## Features Deprecated

`beartype 0.9.0` deprecates decrepit relics of a long-forgotten past
littering the beartype codebase with unseemly monoliths to human hubris.
Specifically, importing these deprecated attributes under beartype ≥ 9.0
now emits non-fatal `DeprecationWarning` warnings at runtime:

* `beartype.cave.HintPep585Type`, which should now be accessed as the
  non-deprecated `beartype.cave.HintGenericSubscriptedType` attribute.
* `beartype.cave.NumpyArrayType`, which should now be accessed directly
  as `numpy.ndarray`.
* `beartype.cave.NumpyScalarType`, which should now be accessed directly
  as `numpy.generic`.
* `beartype.cave.SequenceOrNumpyArrayTypes`, which should now be
  annotated as `typing.Union[collections.abc.Sequence, numpy.ndarray]`.
* `beartype.cave.SequenceMutableOrNumpyArrayTypes`, which should now be
  annotated directly as
  `typing.Union[collections.abc.MutableSequence, numpy.ndarray]`.
* `beartype.cave.SetuptoolsVersionTypes`, which should now be accessed
  directly as `packaging.version.Version`.
* `beartype.cave.VersionComparableTypes`, which should now be annotated
  directly as `typing.Union[tuple, packaging.version.Version]`.
* `beartype.cave.VersionTypes`, which should now be annotated
  directly as `typing.Union[str, tuple, packaging.version.Version]`.
* `beartype.roar.BeartypeDecorHintNonPepException`, which should now be
  accessed as the non-deprecated
  `beartype.roar.BeartypeDecorHintNonpepException` attribute.
* `beartype.roar.BeartypeDecorHintNonPepNumPyException, which should now
  be accessed as the non-deprecated
  `beartype.roar.BeartypeDecorHintNonpepNumpyException` attribute.
* `beartype.roar.BeartypeDecorHintPepDeprecatedWarning, which should now
  be accessed as the non-deprecated
  `beartype.roar.BeartypeDecorHintPepDeprecationWarning` attribute.

## Issues Resolved

* **Typed NumPy arrays subscripted by scalar NumPy ABCs** (e.g.,
  `numpy.typing.NDArray[numpy.floating]`), resolving issue #48 kindly
  submitted by @braniii the bran-eating brainiac. See above for details.
* **[PEP 563][PEP 563]-postponed relative forward references,**
  resolving issue #49 kindly submitted by the positive
  positron emitter and all-around stand-up statistics guru @posita. See
  above for details. Thanks to @posita for his ongoing commitment to
  awesome posita/dyce rolling type-checked by the growling bear!
* **[PEP 586][PEP 586] `typing_extensions.Literal` and [PEP 593][PEP
  593] `typing_extensions.Annotated` backports,**  resolving issue #52
  kindly submitted by cutting-edge Microsoft graph luminary @pbourke.
  See above for details.
* **[PEP 589][PEP 589] typed dictionaries** (i.e., `TypedDict`),
  resolving issue #55 kindly submitted by Kyle (@KyleKing), the
  undisputed King of Parexel AI Labs.
* **mypy-specific ~~logorrhea~~ valid complaints**, including:
  * **Implicit reexport complaints** `beartype 0.9.0` is now compatible
    with both the `--no-implicit-reexport` mypy CLI option and
    equivalent `no_implicit_reexport = True` configuration setting in
    `.mypy.ini`, resolving issue #57 kindly submitted by Göteborg
    melodic death metal protégé and assumed academic luminary
    @antonagestam. Specifically, `beartype` now internally reexports all
    exception and warning classes in the private
    `beartype.roar.__init__` submodule under... their exact same names.
    Look. We don't make the rules. We just circumvent them.
  * **Beartype validator subscription complaints.** `beartype 0.9.0`
    resolves a long-standing integration issue when subjecting beartype
    to static type checking by a static type checker that is almost
    certainly mypy. Previously, mypy erroneously emitted one false
    positive for each otherwise valid beartype validator (e.g., `error:
    The type "Type[IsAttr]" is not generic and not indexable  [misc]`).
    Mypy and presumably other static type checkers now no longer do so,
    substantially improving the usability of downstream packages
    leveraging both static type checking *and* beartype validators.
* **Windows-compatible testing,** kindly submitted by cutting-edge
  Microsoft luminary @pbourke. Previously, our `test_doc_readme()` unit
  test non-portably assumed UTF-8 to be the default file encoding under
  all platforms and thus loudly failed under Windows, which still
  defaults to the single-byte encoding `cp1252`. Thanks to @pbourke and
  the valiant team at microsoft/graspologic, the logical statistical
  graph grasper.

## Tests Improved

* **Asynchronous testing.** Our new `beartype_test.conftest` pytest
  plugin effectively implements the useful subset of the mostly
  unmaintained, overly obfuscatory, and poorly commented and documented
  `pytest-asyncio` project -- which, unsurprisingly, has an outrageous
  number of unresolved issues and unmerged pull requests. Thus dies
  another prospective mandatory test dependency. We now give thanks.
* **Git-agnostic testing.** The `beartype` test suite has been
  generalized to support testing from arbitrary directory layouts,
  including testing of both local clones of our remote `git` repository
  *and* local extractions of our remote PyPI- and GitHub-hosted source
  tarballs. Previously, our test suite only supported the former – due
  to bad assumptions that will haunt our issue tracker like the stench
  of uncooked salmon on the banks of Bear River.
* **PyPy 3.6 testing support dropped.** `beartype 0.9.0` now circumvents
  obscure non-human-readable exceptions raised by the macOS-specific
  implementation of PyPy 3.6 when testing under GitHub Actions-based
  continuous integration (CI), resolving pypy/pypy#3314. Since Python
  3.6 has almost hit its official End of Life (EoL) anyway, we've chosen
  the Easy Road: unconditionally omit PyPy 3.6 from testing and pretend
  this never happened. You didn't see nuffin'.

  [PEP 484]: https://www.python.org/dev/peps/pep-0484/#id33
  [PEP 560]: https://www.python.org/dev/peps/pep-0560
  [PEP 563]: https://www.python.org/dev/peps/pep-0563
  [PEP 585]: https://www.python.org/dev/peps/pep-0585
  [PEP 586]: https://www.python.org/dev/peps/pep-0586
  [PEP 589]: https://www.python.org/dev/peps/pep-0589
  [PEP 593]: https://www.python.org/dev/peps/pep-0593
  [PEP 3119]: https://www.python.org/dev/peps/pep-3119/#overloading-isinstance-and-issubclass

(*Reticulated ticks gesticulate; ant antics masticate!*)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants