Skip to content

Enable --no-wrap in the Jupyter kernel #687

Closed
@rtbs-dev

Description

@rtbs-dev

From the new documentation for type aliases, e.g.

[1]: type x = int
[2]: x

>>> 'int'

Is this expected behavior? I realize mypy probably doesn't care if typehints are str or not, but runtime typechecking (say, isinstance, or --- what i'm testing here --- beartype) needs class instances to operate.

Using eval can be a nasty work around for this, but I ran into a problem if the type aliases are used in future definitions.

type E_ID = int | str
type Entity[Data<=bt.Iterable] = (E_ID; Data?)

[3]: eval(E_ID)  # it's not an alias, it's just the classes
>>> int | str

[4]: eval(Entity)  # now we're getting relative fwd refs? 
>>> typing.Tuple[ForwardRef('int | str'), typing.Optional[~_coconut_typevar_Data_1]]

This nested generic type unfortunately can't be used with isinstance, but it's a normal check e.g. for beartype (which I thought the door API would pair lovely with coconut! 😄):

from beartype.door import TypeHint as th
def eth(typehint) = typehint |> eval |> th  # need to eval, then wrap in TypeHint

[5]: eth(Entity).is_bearable(('hi',(2,3,4)))
python3.10/site-packages/beartype/_util/hint/pep/utilpeptest.py:345: BeartypeDecorHintPep585DeprecationWarning: PEP 484 type hint typing.Tuple[ForwardRef('int | str'), typing.Optional[~_coconut_typevar_Data_1]] deprecated by PEP 585 scheduled for removal in the first Python version released after October 5th, 2025. To resolve this, import this hint from "beartype.typing" rather than "typing". See this discussion for further details and alternatives:
    https://github.com/beartype/beartype#pep-585-deprecations
  warn(

[...]

File ~/miniconda3/envs/grabble/lib/python3.10/site-packages/beartype/_check/checkmake.py:234, in make_func_tester(hint, conf, exception_cls)
    207 # If this hint contains one or more relative forward references, this hint
    208 # is non-portable across lexical scopes. Why? Because this hint is relative
    209 # to and thus valid only with respect to the caller's current lexical scope.
   (...)
    231 # factory (e.g., our increasingly popular public beartype.door.is_bearable()
    232 # tester) sufficiently slow as to be pragmatically infeasible.
    233 if hint_forwardrefs_class_basename:
--> 234     raise BeartypeDecorHintForwardRefException(
    235         f'{EXCEPTION_PLACEHOLDER}type hint {repr(hint)} '
    236         f'contains one or more relative forward references:\n'
    237         f'\t{repr(hint_forwardrefs_class_basename)}\n'
    238         f'Beartype prohibits relative forward references outside of '
    239         f'@beartype-decorated callables. For your own personal safety and '
    240         f'those of the codebases you love, consider canonicalizing these '
    241         f'relative forward references into absolute forward references '
    242         f'(e.g., by replacing "MuhClass" with "muh_module.MuhClass").'
    243     )
    244 # Else, this hint contains *NO* relative forward references.
    245 
    246 # Unqualified basename of this tester function, uniquified by suffixing an
    247 # arbitrary integer guaranteed to be unique to this tester function.
    248 func_tester_name = (
    249     f'{FUNC_TESTER_NAME_PREFIX}{next(_func_tester_name_counter)}')

BeartypeDecorHintForwardRefException: is_bearable() type hint typing.Tuple[ForwardRef('int | str'), typing.Optional[~_coconut_typevar_Data_1]] contains one or more relative forward references:
	('int | str',)
Beartype prohibits relative forward references outside of @beartype-decorated callables. For your own personal safety and those of the codebases you love, consider canonicalizing these relative forward references into absolute forward references (e.g., by replacing "MuhClass" with "muh_module.MuhClass").

as they point out, this use of ForwardRef probably won't be around forever, if I'm understanding?

It works fine without the new syntax:

E_ID = bt.Union[int,str]
DataType = bt.TypeVar('DataType', bound=bt.Iterable)
Entity = bt.Tuple[E_ID, bt.Optional[DataType]]
[0]: (th(Entity).is_bearable(('hi',(2,3,4))),
 th(Entity).is_bearable((1.20,(2,3,4))),
 th(Entity).is_bearable((0,None)))

>>> (True, False, True)

As an aside here, I do think friendly interop with beartype has a lot of potential for functional style e.g. coconut, since it clarifies a ton of nasty situations like type(MyEnum.member) is MyEnum, and runs very fast. Providing an option for beartype users to run coconut with e.g. a beartype.typing backend would be very nice. See some other examples if this is interesting to you, e.g. the explanation for numerary or ... this other proposal I'm on, dealing with faster type-based dispatch via plum. I'm hoping to use beartype+plum for some kind of typeclass approximation soon, for rich type-based ad hoc polymorphism 😅 (rather than just pattern matching... more like rust traits)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions