Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

conditional blocks in class definitions seem to be evaluating types even when these conditionals are false #130881

Copy link
Copy link
Closed
@zzzeek

Description

@zzzeek
Issue body actions

Bug report

Bug description:

using a conditional in a class definition like if TYPE_CHECKING where TYPE_CHECKING is False, or any kind of false conditional, seems to be ignored when types are evaluated under non-future annotations mode:

class MyClass:
    somevalue: str

    if False:
        someothervalue: int

assert MyClass.__annotations__ == {"somevalue": str}, f"MyClass.__annotations__ == {MyClass.__annotations__}"

this seems to be something that might have been done with some intention, which is extremely troubling as this would be a huge showstopper for SQLAlchemy if these conditionals are no longer honored at runtime. A similar example

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    # is not evaluated under any python at runtime
    from some_module import SpecialType

class MyClass:
    somevalue: str

    if TYPE_CHECKING:
        # **is** evaluated under python 3.14.0a5, fails
        someothervalue: SpecialType

assert MyClass.__annotations__ == {"somevalue": str}, f"MyClass.__annotations__ == {MyClass.__annotations__}"

calling upon __annotations__ seems to be the trigger that makes the above fail:

Traceback (most recent call last):
  File "/home/classic/dev/sqlalchemy/test4.py", line 14, in <module>
    assert MyClass.__annotations__ == {"somevalue": str}, f"MyClass.__annotations__ == {MyClass.__annotations__}"
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/classic/dev/sqlalchemy/test4.py", line 12, in __annotate__
    someothervalue: SpecialType
                    ^^^^^^^^^^^
NameError: name 'SpecialType' is not defined

however this appears to be some very strange quantum-physics type of evaluation that isn't actually running Python fully; below, the "someothervalue" type is evaluted, but not the value function assigned!

from typing import TYPE_CHECKING

def do_my_thing() -> int:
    print("HEY!")
    assert False
    return 3 + 4

class MyClass:
    somevalue: str

    if TYPE_CHECKING:
        someothervalue: int = do_my_thing()

assert MyClass.__annotations__ == {"somevalue": str}, f"MyClass.__annotations__ == {MyClass.__annotations__}"

This is an enormous and strange behavioral change that is really going to make things extremely difficult for SQLAlchemy, starting with we will have to rewrite thousands (OK, it turned out to be "dozens") of lines of test suite code into a much bigger exploded form and also a lot of end-user use cases we've defined using TYPE_CHECKING blocks aren't going to work anymore, it's not clear how much further this change will go.

I suppose if the whole thing boils down to what __annotations__ does, and we can call upon something like __annotations_but_not_false_blocks__, that could save us, but overall I'm really hoping this is just a bad dream that we can wake up from.

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Status

    Done
    Show more project fields

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.