[Fixes #14155] Fixes parameter order for mdict to set precedence from settings.PYCSW to pycsw_local defaults#14162
[Fixes #14155] Fixes parameter order for mdict to set precedence from settings.PYCSW to pycsw_local defaults#14162cmotadev wants to merge 1 commit intoGeoNode:masterfrom
Conversation
…ce from settings.PYCSW to pycsw_local defaults
There was a problem hiding this comment.
Code Review
This pull request updates the configuration merging logic in pycsw_local.py and views.py to prioritize user settings over defaults. Feedback indicates that the current shallow merge approach leads to regressions by completely overwriting nested dictionaries like server, causing default values to be lost. Furthermore, the implementation risks mutating global constants. Suggestions have been provided to use a more robust merging strategy that preserves nested defaults and maintains immutability.
| mdict = dict(CONFIGURATION, **settings.PYCSW["CONFIGURATION"]) | ||
| # if "server" in settings.PYCSW["CONFIGURATION"]: | ||
| # # override server system defaults with user specified directives | ||
| # # When swapping parameters from dict(), this if statement becomes useless | ||
| # mdict["server"].update(settings.PYCSW["CONFIGURATION"]["server"]) |
There was a problem hiding this comment.
The current implementation performs a shallow merge, which causes the server dictionary to be completely replaced by the one in settings.PYCSW. This leads to a regression where default values defined in CONFIGURATION["server"] (such as domainquerytype) are lost if they are not explicitly redefined in the user settings.
Furthermore, the original code (now commented out) had a bug where it mutated the global CONFIGURATION constant because dict() only creates a shallow copy, and update() modifies the dictionary in place.
It is recommended to remove the commented-out code and use a merge strategy that preserves nested defaults and avoids mutating global constants.
| mdict = dict(CONFIGURATION, **settings.PYCSW["CONFIGURATION"]) | |
| # if "server" in settings.PYCSW["CONFIGURATION"]: | |
| # # override server system defaults with user specified directives | |
| # # When swapping parameters from dict(), this if statement becomes useless | |
| # mdict["server"].update(settings.PYCSW["CONFIGURATION"]["server"]) | |
| mdict = dict(CONFIGURATION, **settings.PYCSW["CONFIGURATION"]) | |
| if "server" in settings.PYCSW["CONFIGURATION"]: | |
| mdict["server"] = dict(CONFIGURATION.get("server", {}), **settings.PYCSW["CONFIGURATION"]["server"]) |
| return HttpResponseRedirect(settings.CATALOGUE["default"]["URL"]) | ||
|
|
||
| mdict = dict(settings.PYCSW["CONFIGURATION"], **CONFIGURATION) | ||
| mdict = dict(CONFIGURATION, **settings.PYCSW["CONFIGURATION"]) |
There was a problem hiding this comment.
This shallow merge will cause the server dictionary from settings.PYCSW to completely overwrite the defaults in CONFIGURATION. Additionally, since dict() creates a shallow copy, any subsequent modifications to nested dictionaries in mdict (for example, by config_updater on line 50) will inadvertently mutate the global CONFIGURATION object. It is safer to create a new dictionary for the nested server configuration to ensure defaults are preserved and the global state remains immutable.
| mdict = dict(CONFIGURATION, **settings.PYCSW["CONFIGURATION"]) | |
| mdict = dict(CONFIGURATION, **settings.PYCSW["CONFIGURATION"]) | |
| if "server" in settings.PYCSW["CONFIGURATION"]: | |
| mdict["server"] = dict(CONFIGURATION.get("server", {}), **settings.PYCSW["CONFIGURATION"]["server"]) |
Now it's possible to overwrite PyCSW parameterrs from settings and view mods in pyCSW GetCapabilites
Checklist
For all pull requests:
The following are required only for core and extension modules (they are welcomed, but not required, for contrib modules):
Submitting the PR does not require you to check all items, but by the time it gets merged, they should be either satisfied or inapplicable.