"dictionary changed size during iteration" error from AdaptationManager operations
- Dominant language
- Python
- Stars
- 462
- Forks
- 90
- PR merge metrics
- No merged PRs in 30d
Description
When iterating through existing adaptation offers for the first time, Traits resolves string-based protocols by performing the appropriate import. That import can execute arbitrary Python code, including code that itself registers adaptation offers. If that occurs, we get a "dictionary changed size during iteration" RuntimeError.
To reproduce, create files `file1.py` and `file2.py` in the current directory, with the following contents. For `file1.py`:
```python
from traits.api import adapt, Adapter, Interface, provides, register_factory
class ISomeInterface(Interface):
pass
@provides(ISomeInterface)
class MyAdapter(Adapter):
pass
register_factory(MyAdapter, "file2.SomeFactory", ISomeInterface)
adapt(range(10), ISomeInterface)
```
For `file2.py`:
```python
from traits.api import Adapter, Interface, provides, register_factory
class ISomeOtherInterface(Interface):
pass
@provides(ISomeOtherInterface)
class SliceAdapter(Adapter):
pass
register_factory(SliceAdapter, slice, ISomeOtherInterface)
class SomeFactory():
pass
```
Now executing `file1.py` gives the following traceback:
```python
(traits) mdickinson@mirzakhani Desktop % python file1.py
Traceback (most recent call last):
File "/Users/mdickinson/Desktop/file1.py", line 11, in
adapt(range(10), ISomeInterface)
File "/Users/mdickinson/Enthought/ETS/traits/traits/adaptation/adaptation_manager.py", line 413, in adapt
return manager.adapt(adaptee, to_protocol, default)
File "/Users/mdickinson/Enthought/ETS/traits/traits/adaptation/adaptation_manager.py", line 133, in adapt
result = self._adapt(adaptee, to_protocol)
File "/Users/mdickinson/Enthought/ETS/traits/traits/adaptation/adaptation_manager.py", line 260, in _adapt
edges = self._get_applicable_offers(current_protocol, path)
File "/Users/mdickinson/Enthought/ETS/traits/traits/adaptation/adaptation_manager.py", line 321, in _get_applicable_offers
for from_protocol_name, offers in self._adaptation_offers.items():
RuntimeError: dictionary changed size during iteration
```
We should fix the code to be more robust against this kind of change.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.