Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wx.FileConfig does not work as indicated in documentation #2579

Open
git-n-pissed opened this issue Jul 15, 2024 · 1 comment
Open

wx.FileConfig does not work as indicated in documentation #2579

git-n-pissed opened this issue Jul 15, 2024 · 1 comment

Comments

@git-n-pissed
Copy link

Operating system: Windows 11 Pro 23H2
wxPython version & source: 4.2.1, PyPi install
Python version & source: 3.10.6, stock install

Description of the problem:
Attempting to use wx.FileConfig as a cross-platform way to quickly store some app settings and have discovered several problems. Basically, regardless of what arguments are used when creating a wx.FileConfig object, once the Flush method is called the file is either not created at all, or is created at the root of AppData\Roaming. Code sample shows a few of the problems. More specifically:

1.) On Windows, localFilename and globalFilename should cause a file to be created somewhere within the AppData\Local and AppData\Roaming directories respectively. Regardless of the dozens of combinations I've tried, if the file is created, it is always created in AppData\Roaming.

2.) The test file Phoenix/demo/Main.py shows a path being provided to the wx.FileConfig constructor, but in reality, if any path is provided that doesn't point to a child of the AppData\Roaming directory, no config file will be created when Flush is called.

3.) Setting the config object's path using SetPath inherited from wx.ConfigBase is completely ignored when reading/writing the config file.

4.) The wx.CONFIG_USE_SUBDIR as described in the wx.ConfigBase documentation is completely ignored.

The ultimate desire is to have a cross platform compliant way to create local and global config files in such a way that they can be segregated from the config files of other vendors and applications.

Code Example (click to expand)
import os
import wx


app = wx.App(False)

vendor_name = 'my_company'
app_name = 'my_app'
config_file_name = 'config.ini'

# No config file will be created.  Error 267: The directory name is invalid, probably because it doesn't exist...
# why wasn't it created automatically?
cf = wx.FileConfig(style=wx.CONFIG_USE_GLOBAL_FILE | wx.CONFIG_USE_SUBDIR)
cf.Write('foo', 'bar')
cf.Flush()

# Try again with and this time specify the localFilename, but still no config file will be created...
# Same error 267 as before... 
config_path = os.path.join(wx.StandardPaths.Get().GetUserConfigDir(), vendor_name + '1', app_name, config_file_name)
cf = wx.FileConfig(localFilename=config_path)
cf.Write('foo', 'bar')
cf.Flush()

# Ok, lets make sure the directory exists prior to creating the FileConfig object.  Yet still no config file will be
# created.  Error 5: Access is denied.  My user is an admin with full permissions to the directory we created, why
# is permission denied?  
config_path = os.path.join(wx.StandardPaths.Get().GetUserConfigDir(), vendor_name + '2', app_name)
if not os.path.exists(config_path):
    os.makedirs(config_path)

cf = wx.FileConfig(localFilename=config_path)
cf.Write('foo', 'bar')
cf.Flush()

# This will create the config file at "AppData\Roaming\my_company" (no .ini extension), unfortunately this is the wrong
# directory since "localFilename" is provided, file should be created in "AppData\Local"
config_path = os.path.join(wx.StandardPaths.Get().GetUserConfigDir(), vendor_name + '3')
cf = wx.FileConfig(localFilename=config_path)
cf.Write('foo', 'bar')
cf.Flush()
@infinity77
Copy link
Contributor

I don't think wx.FileConfig makes any promise that it will create folders for you - so your first two points in the code may be invalid. I may be mistaken and may have missed it from the docs, but what I do is preemptively create the folder I need before using wx.FileConfig.

Your third point in the code is fundamentally incorrect: you are providing a folder path, not a file name. This works better:

config_path = os.path.join(wx.StandardPaths.Get().GetUserConfigDir(), vendor_name + '2', app_name)
os.makedirs(config_path, exist_ok=True)

file_path = os.path.join(config_path, config_file_name)
cf = wx.FileConfig(localFilename=file_path)
cf.Write('foo', 'bar')
cf.Flush()

Similar story for point (4) (of course there is no .ini extension, unless this was your intention all the way). Looking at your code:

config_path = os.path.join(wx.StandardPaths.Get().GetUserConfigDir(), vendor_name + '3')
cf = wx.FileConfig(localFilename=config_path)
cf.Write('foo', 'bar')
cf.Flush()

The documentation for GetUserConfigDir() states this:

image

If you want your stuff in AppData\Local, use the appropriate method:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants