Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Cannot import Astroid with schemathesis 3.19.6. #11053

Closed
kain88-de opened this issue May 29, 2023 · 2 comments
Closed

[BUG] Cannot import Astroid with schemathesis 3.19.6. #11053

kain88-de opened this issue May 29, 2023 · 2 comments

Comments

@kain88-de
Copy link

kain88-de commented May 29, 2023

Describe the bug
When I start a pytest session the astroid package enters an infinite loop when it is imported.

To Reproduce
I prepared a pipenv file that creates an environment to reproduce the issues.

Once you downloaded all files run

  1. make .venv
  2. run-pipenv run python -m pytest t.py --pdb

This will drop you in a debugger session at the place where astroid is stuck in a loop. With version 3.19.0 everything still works.

Expected behavior

Adding schemathesis as a dependency has no impact if I can import astroid in a pytest environment or not.

Environment (please complete the following information):

  • OS: linux
  • Python version: 3.11

Additional context
I'm not sure what the root cause is so I will also open tickets for this with schemathesis and astroid.

@The-Compiler
Copy link
Member

With the help of some print() in astroid, there is certainly something strange going on here. It ends up in an endless loop here:

t.py:3: in <module>
    from astroid.nodes import Import
.venv/lib/python3.11/site-packages/astroid/__init__.py:46: in <module>
    from astroid import inference, raw_building
.venv/lib/python3.11/site-packages/astroid/inference.py:17: in <module>
    from astroid import bases, constraint, decorators, helpers, nodes, protocols, util
.venv/lib/python3.11/site-packages/astroid/helpers.py:11: in <module>
    from astroid import bases, manager, nodes, objects, raw_building, util
.venv/lib/python3.11/site-packages/astroid/raw_building.py:643: in <module>
    _astroid_bootstrapping()
.venv/lib/python3.11/site-packages/astroid/raw_building.py:544: in _astroid_bootstrapping
    astroid_builtin = builder.inspect_build(builtins)
.venv/lib/python3.11/site-packages/astroid/raw_building.py:404: in inspect_build
    self.object_build(node, module)
.venv/lib/python3.11/site-packages/astroid/raw_building.py:455: in object_build
    attach_const_node(node, name, member)
.venv/lib/python3.11/site-packages/astroid/raw_building.py:78: in attach_const_node
    _attach_local_node(node, nodes.const_factory(value), name)
.venv/lib/python3.11/site-packages/astroid/nodes/node_classes.py:5644: in const_factory
    instance.postinit(_create_dict_items(value, instance))
.venv/lib/python3.11/site-packages/astroid/nodes/node_classes.py:5618: in _create_dict_items
    value_node = const_factory(value)
.venv/lib/python3.11/site-packages/astroid/nodes/node_classes.py:5644: in const_factory
    instance.postinit(_create_dict_items(value, instance))
.venv/lib/python3.11/site-packages/astroid/nodes/node_classes.py:5618: in _create_dict_items
    value_node = const_factory(value)
.venv/lib/python3.11/site-packages/astroid/nodes/node_classes.py:5644: in const_factory
    instance.postinit(_create_dict_items(value, instance))
.venv/lib/python3.11/site-packages/astroid/nodes/node_classes.py:5618: in _create_dict_items
    value_node = const_factory(value)

And this happens because somehow, __builtins__ turned into a dictionary (rather than a module object), and for some reason, there is a __builtins__["__builtins__"] which again recursively contains that dictionary.

With your example and pytest:

(Pdb) type(__builtins__)
<class 'dict'>
(Pdb) __builtins__["__builtins__"] is __builtins__
True

outside of it, when running with Python directly:

>>> __builtins__
<module 'builtins' (built-in)>
>>> __builtins__.__builtins__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'builtins' has no attribute '__builtins__'

When simply running a module containing print(type(__builtins__)), with pytest I get dict, outside of pytest module. However, there, there is no __builtins__["__builtins__"]. Neither is there when running your example, but with -p no:schemathesis.

That seems to come from schemathesis somehow:

>>> hasattr(__builtins__, "__builtins__")
False
>>> import schemathesis
>>> hasattr(__builtins__, "__builtins__")
True

so to summarize:

  • pytest (?) somehow causes __builtins__ to be a dict instead of a module object
  • schemathesis (or possibly one of its dependencies) adds a __builtins__ to __builtins__ at import time
  • astroid then chokes on the recursive reference in that dict

I have no answers, but many questions.

@The-Compiler
Copy link
Member

The-Compiler commented Jun 1, 2023

It gets weirder!

The "turning __builtins__ into a dict" thing seems to be coming from pdb. With a t.py such as:

print(type(__builtins__))

This happens:

$ python3 t.py
<class 'module'>

$ python3 -m pdb -c cont -c quit t.py
<class 'dict'>
The program finished and will be restarted

And the "adding __builtins__ to __builtins__" thing comes from dataclass (I bisected it to schemathesis/schemathesis#1736).

This example:

from dataclasses import dataclass

print(type(__builtins__))
print(hasattr(__builtins__, "__builtins__"))

@dataclass
class Bla(Exception):

    __module__ = "builtins"

print(type(__builtins__))
print(hasattr(__builtins__, "__builtins__"))

import astroid.nodes

results in:

<class 'module'>
False
<class 'module'>
True

followed by the same endless recursion (even if __builtins__ is not a dict, actually):

Traceback (most recent call last):
  File "/home/florian/tmp/blabla/dc.py", line 14, in <module>
    import astroid.nodes
  File "/usr/lib/python3.11/site-packages/astroid/__init__.py", line 46, in <module>
    from astroid import inference, raw_building
  File "/usr/lib/python3.11/site-packages/astroid/inference.py", line 17, in <module>
    from astroid import bases, constraint, decorators, helpers, nodes, protocols, util
  File "/usr/lib/python3.11/site-packages/astroid/helpers.py", line 11, in <module>
    from astroid import bases, manager, nodes, objects, raw_building, util
  File "/usr/lib/python3.11/site-packages/astroid/raw_building.py", line 643, in <module>
    _astroid_bootstrapping()
  File "/usr/lib/python3.11/site-packages/astroid/raw_building.py", line 544, in _astroid_bootstrapping
    astroid_builtin = builder.inspect_build(builtins)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/astroid/raw_building.py", line 404, in inspect_build
    self.object_build(node, module)
  File "/usr/lib/python3.11/site-packages/astroid/raw_building.py", line 455, in object_build
    attach_const_node(node, name, member)
  File "/usr/lib/python3.11/site-packages/astroid/raw_building.py", line 78, in attach_const_node
    _attach_local_node(node, nodes.const_factory(value), name)
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/astroid/nodes/node_classes.py", line 5641, in const_factory
    instance.postinit(_create_dict_items(value, instance))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/astroid/nodes/node_classes.py", line 5615, in _create_dict_items
    value_node = const_factory(value)
                 ^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/astroid/nodes/node_classes.py", line 5641, in const_factory
    instance.postinit(_create_dict_items(value, instance))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/astroid/nodes/node_classes.py", line 5615, in _create_dict_items
    value_node = const_factory(value)
                 ^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/astroid/nodes/node_classes.py", line 5641, in const_factory
    instance.postinit(_create_dict_items(value, instance))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I don't know what to make of this. Two stdlib bugs (?) for the price of one? In any case, pytest seems to be out of the picture. Going to comment in the other threads.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants