Component: guidata.config / guidata.userconfig
Affected version: 3.15.0 and, as far as can be told, every earlier version
Severity: low to medium — settings are stored under a meaningless name, in a directory shared with any other unnamed UserConfig
Symptom
Importing guidata creates ~/.config/.none/ (Windows: %USERPROFILE%\.none\), and guidata's own settings are persisted to ~/.config/.none/none.ini, with sections:
[faulthandler] [arrayeditor] [dicteditor] [texteditor] [codeeditor] [console] [color_schemes]
Expected location would be something like ~/.config/.guidata/guidata.ini.
Root cause
guidata/config.py:
CONF = UserConfig(DEFAULTS)
UserConfig.__init__ sets self.name = "none" as a placeholder, and set_application() is never called on this instance. Since UserConfig.get_path() builds ~/.config/.{self.name}/… and filename() returns {self.name}.ini, everything ends up in .none/none.ini.
Two aggravating factors:
get_path() has a side effect: it calls os.makedirs on the directory. The stray directory is therefore created even by a read-only path lookup, e.g. when guidata merely checks whether a file exists.
- The
.none directory is a shared namespace: any library that forgets to call set_application resolves to the same directory, and to the same none.ini filename. Two such libraries saving in the same process would overwrite each other's file, since ConfigParser.write() rewrites the whole file from the sections the instance knows about. PlotPy currently falls in this category (it never names its CONF), though it happens not to call CONF.save(), so no collision is observed today.
Component:
guidata.config/guidata.userconfigAffected version: 3.15.0 and, as far as can be told, every earlier version
Severity: low to medium — settings are stored under a meaningless name, in a directory shared with any other unnamed
UserConfigSymptom
Importing guidata creates
~/.config/.none/(Windows:%USERPROFILE%\.none\), and guidata's own settings are persisted to~/.config/.none/none.ini, with sections:Expected location would be something like
~/.config/.guidata/guidata.ini.Root cause
guidata/config.py:UserConfig.__init__setsself.name = "none"as a placeholder, andset_application()is never called on this instance. SinceUserConfig.get_path()builds~/.config/.{self.name}/…andfilename()returns{self.name}.ini, everything ends up in.none/none.ini.Two aggravating factors:
get_path()has a side effect: it callsos.makedirson the directory. The stray directory is therefore created even by a read-only path lookup, e.g. when guidata merely checks whether a file exists..nonedirectory is a shared namespace: any library that forgets to callset_applicationresolves to the same directory, and to the samenone.inifilename. Two such libraries saving in the same process would overwrite each other's file, sinceConfigParser.write()rewrites the whole file from the sections the instance knows about. PlotPy currently falls in this category (it never names itsCONF), though it happens not to callCONF.save(), so no collision is observed today.