Guido van Rossum <gu...@python.org> added the comment:

No need to open the attachment -- a simpler repro is:

>>> from typing import Literal
>>> Literal[1]
typing.Literal[1]
>>> Literal[True]
typing.Literal[1]
>>> 

However, in a fresh session

>>> from typing import Literal
>>> Literal[True]
typing.Literal[True]
>>> 

This must be because there's a cache in typing.py that use == but doesn't check 
the type. We can demonstrate that this is the case using a similar equivalence 
between 2.0 and 2:

>>> Literal[2.0]
typing.Literal[2.0]
>>> Literal[2]
typing.Literal[2.0]
>>> 

It looks like the function _tp_cache() is the culprit -- it uses 
functools.lru_cache() which apparently uses simple equality.

def _tp_cache(func):
    """..."""
    cached = functools.lru_cache()(func)
    _cleanups.append(cached.cache_clear)

    @functools.wraps(func)
    def inner(*args, **kwds):
        try:
            return cached(*args, **kwds)
        except TypeError:
            pass  # All real errors (not unhashable args) are raised below.
        return func(*args, **kwds)
    return inner

Here's a confusing demo:

>> @functools.lru_cache()
... def f(a): return a
... 
>>> f(1)
1
>>> f(True)
True
>>> f(1)
1
>>> f(1.0)
True
>>> 

(Confusing because it distinguishes between 1 and True, unlike Literal, but it 
then maps 1.0 to True.)

However a possible fix might be to add typed=True to the functools.lru_cache() 
call in typing.py, which should have the desired effect (not tested).

----------
title: Literal declarations are not typed. Literal[True] can be Literal[1] if 
declared after latter. -> Literal[True] prints as Literal[1] in some cases

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue39308>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to