Skip to content

[Feature Request] Make beartype.typing Actually Do Something #237

@leycec

Description

@leycec

This feature request comes courtesy @JWCS via this secretive commit comment that has already been lost to the sands of time. @JWCS wisely notes that beartype.typing is currently undocumented, largely useless, and a pox upon the good name of @beartype:

Out of curiousity, why doesn't beartype.typing backport types?
I had previously expected that when I have to dip back to an earlier version of python, I can just from beartype.typing import List, Dict, Self, Never, TypeAlias, Literal, Final, TypeGuard, Protocol, OrderedDict, without having to sort through that these, respectively (depr sometime, depr sometime, 3.11+, 3.11+, 3.8+, 3.8+, 3.10+, 3.8+, 3.7.2+), etc.

@JWCS is not wrong. beartype.typing should do considerably more for everyone. It currently doesn't, mostly because I wasn't convinced anyone even used beartype.typing – let alone wanted beartype.typing to do considerably more for everyone.

Like beartype.cave, beartype.typing is this basically undocumented thing that I quietly maintain out of a nostalgic wistfulness for the halcyon past when I was young, less bald, and enthusiastic. But you've convinced me that somebody actually cares about beartype.typing!

Thankfully, I'm convinced that what everyone wants can be done without adding typing_extensions as a mandatory runtime dependency to either @beartype or your workflow. If anyone would like to require typing_extensions in their workflow, of course, that's perfectly fine – but we won't be mandating that on @beartype's end.

What Is This Inchoate Madness You Speak Of!?

Here is what the implementation of beartype.typing should look like. It doesn't currently, because I am contemptible, degenerate, and/or an inveterate pauper. But it should:

# In "beartype.typing.__init__": the future of typing backports begins today.
from typing import TYPE_CHECKING

# If @beartype is currently being statically type-checked (e.g.,
# by mypy or pyright), just defer to the third-party
# "typing_extensions" package.
#
# Note that this does *NOT* mean that @beartype now unconditionally
# requires "typing_extensions" at either runtime or static
# type-checking time. Any code in an "if TYPE_CHECKING:" is (basically)
# just a convincing semantic lie that everything syntactically ignores.
if TYPE_CHECKING:
    from typing_extensions import *  # <-- heh
# Else, @beartype is currently being imported from at runtime. This is
# the common case. This is also the non-trivial case, because @beartype
# does *NOT* require "typing_extensions" as a mandatory runtime
# dependency, because @beartype requires *NOTHING* as a runtime
# dependency. This is the only rule in @beartype's Rule of Law.
else:
    # Import the requisite machinery that will make the magic happen.
    from beartype._util.mod.lib.utiltyping import (
        import_typing_attr_or_fallback as _import_typing_attr_or_fallback)

    # Dynamically define the "Self" type hint as follows:
    # * If the active Python interpreter targets Python >= 3.11, just
    #   defer to the canonical "typing.Self" type hint.
    # * Else if "typing_extensions" is importable *AND* of a sufficiently
    #   recent version to define the backported "typing_extensions.Self"
    #   type hint, fallback to that hint.
    # * Else, synthesize a placeholder type hint that @beartype internally
    #   recognizes as semantically equivalent to "typing.Self".
    Self = _import_typing_attr_or_fallback('Self', TypeHintTypeFactory(object))

    #FIXME: Repeat the above logic for *ALL* existing "typing" attributes.

💪 🐻 👍

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions