-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Description
ConfigItems does not work as expected and results in a list of items that contains only the same values.
Reproduciton
plugin.py
class TestPlugin(BasePlugin):
config_scheme = (
(
"items", mkdocs.config.config_options.ConfigItems(
("value", mkdocs.config.config_options.Type(str)),
),
),
)
def on_config(self, config):
print(self.config)mkdocs.yml
site_name: Test Site
plugins:
- test:
items:
- value: a
- value: bThis results in:
INFO - Building documentation...
{'items': [{'value': 'b'}, {'value': 'b'}]}
INFO - Cleaning site directory
INFO - Documentation built in 0.05 seconds
INFO - [12:21:39] Watching paths for changes: 'docs', 'mkdocs.yml'
INFO - [12:21:39] Serving on http://127.0.0.1:8000/
Note that both "value" values are b rather than the first one being a.
Cause
ConfigItems creates a single SubConfig instance when it is instantiated:
mkdocs/mkdocs/config/config_options.py
Line 77 in a17a25c
| self.item_config = SubConfig(*config_options) |
It then uses this instance to do validation:
mkdocs/mkdocs/config/config_options.py
Line 94 in a17a25c
| return [self.item_config.validate(item) for item in value] |
The SubConfig instance uses load_dict to populate self.data before validation.
mkdocs/mkdocs/config/config_options.py
Line 60 in a17a25c
| self.load_dict(value) |
The load_dict function uses update to make changes to self.data on the SubConfig instance:
Line 132 in a17a25c
| self.data.update(patch) |
Since there is only one SubConfig instance, when this dictionary gets updated it gets updated across all references to it.
Fix
A number of popular plugins already create their own ConfigItems to address this by making item_config a property that returns a separate SubConfig instance each time it is used. This seems like a reasonable approach.