Skip to content

Test failures with "RuntimeError: dictionary changed size during iteration" #1191

Open
@mrbean-bremen

Description

@mrbean-bremen

This came up in this comment by @schuylermartin45:

I'm seeing some odd test failures in our conda-forge build for CRM that are not present elsewhere. Looks like some of the pyfakefs fixtures are not being initialized properly: https://dev.azure.com/conda-forge/feedstock-builds/_build/results?buildId=1274733&view=logs&j=7b6f2c87-f3a7-5133-8d84-7c03a75d9dfc&t=9eb77fd2-8ddd-5444-8fc0-71cb28dcb736&l=5034

Here's a small snippet from that log:


        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E       AttributeError: 'NoneType' object has no attribute 'add_real_directory'

tests/fetcher/test_http_artifact_fetcher.py:100: AttributeError
___________________ test_scan[dummy_py_project_01-expected0] ___________________
[gw0] linux -- Python 3.11.13 $PREFIX/bin/python

project_name = 'dummy_py_project_01'
expected = {ProjectDependency(data=MatchSpec("python"), type=<DependencySection.RUN: 3>), ProjectDependency(data=MatchSpec("conda... type=<DependencySection.RUN: 3>), ProjectDependency(data=MatchSpec("requests"), type=<DependencySection.RUN: 3>), ...}
request = <FixtureRequest for <Function test_scan[dummy_py_project_01-expected0]>>

    @pytest.mark.parametrize(
        "project_name,expected",
        [
            (
                "dummy_py_project_01",
                {
                    ProjectDependency(MatchSpec("conda_recipe_manager"), DependencySection.RUN),
                    ProjectDependency(MatchSpec("matplotlib"), DependencySection.RUN),  # Two imports on one line
                    ProjectDependency(MatchSpec("networkx"), DependencySection.RUN),  # Two imports on one line
                    ProjectDependency(MatchSpec("python"), DependencySection.HOST),
                    ProjectDependency(MatchSpec("python"), DependencySection.RUN),
                    ProjectDependency(MatchSpec("pyyaml"), DependencySection.TESTS),
                    ProjectDependency(MatchSpec("requests"), DependencySection.RUN),  # Found in source and test code.
                },
            ),
        ],
    )
    def test_scan(project_name: str, expected: set[ProjectDependency], request: pytest.FixtureRequest) -> None:
        """
        Tests scanning for Python dependencies with a mocked-out Python project.
    
        :param project_name: Name of the dummy Python project directory to use
        :param expected: Expected value
        """
        fs = cast(FakeFilesystem, request.getfixturevalue("fs"))
        project_path: Final[Path] = get_test_path() / "software_projects" / project_name
>       fs.add_real_directory(project_path)
        ^^^^^^^^^^^^^^^^^^^^^
E       AttributeError: 'NoneType' object has no attribute 'add_real_directory'

While examining the log file from the test, I found the following part:

==================================== ERRORS ====================================
_ ERROR at setup of test_bump_recipe_cli[pytest-pep8.yaml-None-bump_recipe/pytest-pep8_build_num_2.yaml] _
[gw0] linux -- Python 3.11.13 $PREFIX/bin/python

request = <SubRequest 'fs' for <Function test_bump_recipe_cli[pytest-pep8.yaml-None-bump_recipe/pytest-pep8_build_num_2.yaml]>>

    @pytest.fixture
    def fs(request):
        """Fake filesystem."""
        if hasattr(request, "param"):
            # pass optional parameters via @pytest.mark.parametrize
            patcher = Patcher(*request.param)
        else:
            patcher = Patcher()
>       patcher.setUp()

../_test_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_place/lib/python3.11/site-packages/pyfakefs/pytest_plugin.py:38: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../_test_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_place/lib/python3.11/site-packages/pyfakefs/fake_filesystem_unittest.py:1033: in setUp
    self._find_modules()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pyfakefs.fake_filesystem_unittest.Patcher object at 0x7ff8021acf90>

    def _find_modules(self) -> None:
        """Find and cache all modules that import file system modules.
        Later, `setUp()` will stub these with the fake file system
        modules.
        """
        module_names = list(self._fake_module_classes.keys()) + [PATH_MODULE]
>       for name, module in list(sys.modules.items()):
                            ^^^^^^^^^^^^^^^^^^^^^^^^^
E       RuntimeError: dictionary changed size during iteration

I'm not sure if this is the root of the problem, but it looks like the modules change while iterating over them - probably some module behaving unexpectedly, but this should be avoided, maybe by making a copy of the modules before iterating over them (have to check the performance impact).

A related problem (#338) had been reported (and fixed) quite some time ago, though I have never seen this specific problem until now.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions