Per-key priorities for dictionary-like settings #1135
Comments
Great work Jakob, thanks! I really like your implementation ideas. Some thoughts: Another place where you can update settings is in the class attribute I don’t particularly like using Settings objects directly in I particularly like the idea of deprecating _BASE settings, one of the purposes of using settings priorities was to avoid these kinds of patterns. Not sure if I would keep those _BASE settings with an empty dict for backward compatibility, we’re modifying their value so users using them probably won’t get what they were expecting. I think supporting to set _BASE settings in There are some missing things to consider about the old setting and getting dictionaries usage. It makes sense that Another thing we have to make sure is that every dictionary setting allows to disable keys, otherwise we won’t be able to ‘turn off’ keys that were already set (For example, ‘scrapy.contrib.downloadermiddleware.retry.RetryMiddleware', a default downloader middleware, is added as key to DOWNLOADER_MIDDLEWARES with a default value of 500, there should be a value to indicate we want to disable it in the middleware manager). I think most dictionary settings allow to set Also we should evaluate what to do with user defined settings (those not mentioned in |
Right! I missed that. I think with that in mind the check whether a
I agree. As the default settings are loaded with a
Sounds reasonable. As
I also think we should return the
We should definitely check whether all builtin settings allow disabling via On a side note, I think it would be nice if we could completely decouple |
Implemented via #1149 :) |
I'm new, so here's a quick intro: Hi! I'm Jakob :) I came upon this while working on my GSoC proposal.
During Julia's GSoC, settings priorities were introduced to allow updating settings from different places without paying attention to order. They work great for 'simple' (non-compound) settings, but there are two issues with the dictionary-like settings (e.g.
DOWNLOADER_MIDDLEWARES
orEXTENSIONS
) mainly used to manage extensions:This should prove especially problematic for the proposed add-on structure (SEP-021, discussed in #591). To resolve this, every key could have its own priority associated with it. @curita suggested making the compound setting variables an instance of the
Settings
class (and no longer an instance ofdict
). This could further clean up theSettings
API by deprecating the_BASE
settings, as the 'real' settings dictionaries (without appendix) could be used for default settings without fearing that they get lost when reading fromsettings.py
. I've gathered some thoughts on this in my proposal (rather long, sorry, tl;dr is that it should be possible in a fully transparent, as in "backwards-compatible with no changes to the API", fashion):As the
Settings
class already provides a__getitem__()
method, this will introduce no API change to reading these settings.There are currently three places where the dict-like settings are written to:
scrapy/settings/default_settings.py
settings.py
in theSettings.setmodule()
method_BASE
inscrapy.utils.conf.build_component_list()
Scrapy's code could be updated in the following fashion with full backwards compatibility, even for non-intended uses (such as users working directly on a
_BASE
dictionary):Complete
Settings
dictionary-like interface by implementing:__setitem__(self, k, v)
method that will use some default priority (maybe 'project')__iter__(self)
method which returns an iterator overSettings.attributes
update(self, custom, priority = 'project')
method that behaves likedict.update()
while respecting mutability and priorities. Ifcustom
is adict
object, the given priority will be used for all keys. If it is aSettings
object, the already existing per-key priority values will be used. Thesetdict()
method should become a proxy to this (more general) methodDeprecate
_BASE
dictionaries by replacing them with empty ones (for backwards-compatibility) and moving default settings into 'real' dictionary, i.e.becomes
Configuration in
settings.py
should be no different for the user. TheSettings.setmodule()
method should therefore recognise which of its attributes are themselvesSettings
instances, and call their respectiveupdate()
methods instead of replacing them. Alternatively, this check could be done in theSettingsAttribute.set()
method.Introduce a small change to the
build_component_list()
helper function such that it works onSettings
instances instead of ondict
:For the
1.0
release, the settings, middleware managers andbuild_component_list()
helper function could be tidied up by removing support for the deprecated_BASE
settingsThe text was updated successfully, but these errors were encountered: