aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsay <say@yandex-team.ru>2022-05-14 02:04:16 +0300
committersay <say@yandex-team.ru>2022-05-14 02:04:16 +0300
commit492822761567bdac7f2dbe844de1bb3086e9e28e (patch)
tree5b527a1555338279656fb67212cdcfc3c37bfc49
parente5ffe7fe05e7f9d1fd1825a902f5bbbed331d817 (diff)
downloadydb-492822761567bdac7f2dbe844de1bb3086e9e28e.tar.gz
YMAKE-144: Fix RuntimeError: dictionary changed size during iteration
ref:919db9913468e91d031bbd511beeacdcfdd74489
-rw-r--r--library/python/runtime_py3/importer.pxi8
-rw-r--r--library/python/runtime_py3/test/test_arcadia_source_finder.py24
2 files changed, 30 insertions, 2 deletions
diff --git a/library/python/runtime_py3/importer.pxi b/library/python/runtime_py3/importer.pxi
index 904f94dea2..579a276d02 100644
--- a/library/python/runtime_py3/importer.pxi
+++ b/library/python/runtime_py3/importer.pxi
@@ -451,11 +451,15 @@ class ArcadiaSourceFinder:
# Yield from cache
import re
rx = re.compile(re.escape(package_prefix) + r'([^.]+)$')
+ # Save result to temporary list to prevent 'RuntimeError: dictionary changed size during iteration'
+ found = []
for mod, path in self.module_path_cache.items():
if path is not None:
m = rx.match(mod)
if m:
- yield prefix + m.group(1), self.is_package(mod)
+ found.append((prefix + m.group(1), self.is_package(mod)))
+ for cm in found:
+ yield cm
# Yield from file system
for path in paths:
@@ -491,7 +495,7 @@ class ArcadiaSourceFinder:
return package_paths
def _cache_module_path(self, fullname, find_package_only=False):
- """
+ """
Find module path or package directory paths and save result in the cache
find_package_only=True - don't try to find module
diff --git a/library/python/runtime_py3/test/test_arcadia_source_finder.py b/library/python/runtime_py3/test/test_arcadia_source_finder.py
index ff80d0a0a2..c01435f7df 100644
--- a/library/python/runtime_py3/test/test_arcadia_source_finder.py
+++ b/library/python/runtime_py3/test/test_arcadia_source_finder.py
@@ -315,3 +315,27 @@ class TestEmptyResources(ArcadiaSourceFinderTestCase):
def test_iter_modules(self):
assert [] == list(self.arcadia_source_finder.iter_modules('', 'PFX.'))
+
+
+class TestDictionaryChangedSizeDuringIteration(ArcadiaSourceFinderTestCase):
+ def _get_mock_fs(self):
+ return '''
+ home:
+ arcadia:
+ project:
+ lib1:
+ mod1.py: ''
+ lib2:
+ mod2.py: ''
+ '''
+
+ def _get_mock_resources(self):
+ return {
+ b'py/namespace/unique_prefix1/project/lib1': b'project.lib1.',
+ b'py/namespace/unique_prefix1/project/lib2': b'project.lib2.',
+ }
+
+ def test_no_crash_on_recusive_iter_modules(self):
+ for package in self.arcadia_source_finder.iter_modules('project.', ''):
+ for _ in self.arcadia_source_finder.iter_modules(package[0], ''):
+ pass