# PEP 649: Behavior of the REPL

**URL:** <https://discuss.python.org/t/pep-649-behavior-of-the-repl/54109>\
**Category:** Core Development\
**Created:** [May 24, 2024, 5:55am UTC](https://discuss.python.org/t/pep-649-behavior-of-the-repl/54109 "2024-05-24T05:55:20Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jelle](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jelle/32/1049_2.png) [@Jelle](https://discuss.python.org/u/Jelle)\
**Post date:** [May 24, 2024, 5:55am UTC](https://discuss.python.org/t/pep-649-behavior-of-the-repl/54109/1 "2024-05-24T05:55:20Z")

</div>

PEP 649 [states](https://peps.python.org/pep-0649/#interactive-repl-shell):

> The semantics established in this PEP also hold true when executing code in Python’s interactive REPL shell, except for module annotations in the interactive module (` __main__ `) itself. Since that module is never “finished”, there’s no specific point where we can compile the ` __annotate__ ` function.  
> For the sake of simplicity, in this case we forego delayed evaluation. Module-level annotations in the REPL shell will continue to work exactly as they do with “stock semantics”, evaluating immediately and setting the result directly inside the ` __annotations__ ` dict.

I [implemented](https://github.com/python/cpython/pull/119361/commits/5f5cf115122815e85b1b7d6528c6898231aedaa5) this behavior:

```pycon
>>> x: int = 3
>>> __annotations__
{'x': <class 'int'>}
>>> class X:
... y: doesntexist
...     
>>> X. __annotations__
Traceback (most recent call last):
  File "<python-input-4>", line 1, in <module>
    X. __annotations__
  File "<python-input-2>", line 2, in <annotations of X>
    y: doesntexist
       ^^^^^^^^^^^
NameError: name 'doesntexist' is not defined

```

But I’m not sure it’s a good idea. The interactive console would be the only place in the language that eagerly evaluates annotations, and it seems confusing to have core language behavior that differs based on whether the “interactive” compilation mode was used.

If there are multiple statements in a line, the new 3.13 REPL actually compiles all but the final statement in `exec` (i.e., module) mode, so my current code applies PEP 649 semantics to them.

```pycon
>>> x: x = 3; pass
>>> __annotate__ (1)
{'x': 3}

```

There is surely some way to fix that and make all of the REPL code get compiled as “interactive”, but it shows how subtle this behavior change is.

Another implication of the proposed behavior is that pasting code into the REPL line by line will sometimes not work:

```python
x: X | None = None
class X: pass

```

With PEP 649 applied, this code will work fine when placed in a module. But if you paste it into the console line by line, the first line will throw an error.

Here’s an alternative proposal: treat the interactive console like any other module-level code, and make annotations lazily evaluated. This makes the language more consistent and avoids subtle behavior changes between modules and the REPL.

---

<div class="post-metadata">

**Author:** ![carljm](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/carljm/32/959_2.png) [@carljm](https://discuss.python.org/u/carljm)\
**Post date:** [May 28, 2024, 12:36am UTC](https://discuss.python.org/t/pep-649-behavior-of-the-repl/54109/2 "2024-05-28T00:36:34Z")

</div>

I’m curious how you will address the problem noted in the PEP quote. When do you actually compile the ` __annotate__ ` function for the module-level code in the REPL?

---

<div class="post-metadata">

**Author:** ![Jelle](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jelle/32/1049_2.png) [@Jelle](https://discuss.python.org/u/Jelle)\
**Post date:** [May 28, 2024, 12:38am UTC](https://discuss.python.org/t/pep-649-behavior-of-the-repl/54109/3 "2024-05-28T00:38:31Z")

</div>

A new one would get created for every statement that is evaluated. This would mean that earlier annotations get lost when you add a new one.

---

<div class="post-metadata">

**Author:** ![carljm](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/carljm/32/959_2.png) [@carljm](https://discuss.python.org/u/carljm)\
**Post date:** [May 28, 2024, 12:42am UTC](https://discuss.python.org/t/pep-649-behavior-of-the-repl/54109/4 "2024-05-28T00:42:40Z")

</div>

Ok, that’s what I suspected.

I think this is likely fine; I don’t really know under what circumstances someone would care about the contents of ` __annotations__ ` reflecting their full REPL session history. But it does still mean that the REPL is a bit odd in terms of ` __annotations__ ` behavior.

In practice, given that we have to choose, I think “forward references working the same as everywhere else” is much more valuable in the REPL than a useful “module” level ` __annotations__ ` is.
