tox-dev/platformdirs

macOS `user_config_dir` goes against OS guidelines

Closed this issue · 23 comments

config_dir points to ~/Library/Preferences on macOS:
https://github.com/platformdirs/platformdirs/blob/2e225082877dd83329594933a69301b8c5b9246e/src/platformdirs/macos.py#L27-L34

This goes against macOS guidelines:

Preferences

Contains the user’s preferences. You should never create files in this directory yourself. To get or set preference values, you should always use the NSUserDefaults class or an equivalent system-provided interface.

To get or set preference values, you should always use the [NSUserDefaults](../../../../LegacyTechnologies/WebObjects/WebObjects_3.5/Reference/Frameworks/ObjC/Foundation/Classes/NSUserDefaults/Description.html#//apple_ref/occ/cl/NSUserDefaults) class or an equivalent system-provided interface.

This reads to me that you can use this folder, just need to use a system class for it, which in Python case is missing so using file API instead feels ok.

I don't think that's the case because the guidelines also say you can put configuration files in Application Support:

Put app-created support files in the Library/Application support/ directory. In general, this directory includes files that the app uses to run but that should remain hidden from the user. This directory can also include data files, configuration files, templates and modified versions of resources loaded from the app bundle.

https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW6

I'm not sure I agree with that. Would Apple bother to create a CPython version of NSUserDefaults we could put it there.

The defaults system is a database like the Windows Registry. There are pypi packages that let you interact with it, but I imagine it's probably out of scope for this package to provide an API to the defaults database.

The docs state you "should never create files in this directory yourself" and that the Library/Application Support can include configuration files. The Where You Should Put Your App’s Files section does not mention the Preferences folder at all - it only says that Application Support can include configuration files.

The NSUserDefaults docs also has a warning about accessing it directly:

Don’t try to access the preferences subsystem directly. Modifying preference property list files may result in loss of changes, delay of reflecting changes, and app crashes. To configure preferences, use the defaults command-line utility in macOS instead.

I hope that clears it up

The problem is this would be a breaking change 🤔 for a lot of apps.

Yes it sure would :/ Luckily, migrating should be fairly easy in most cases:

  • if new config dir exists:
    • if old config dir exists:
      • move old config dir files into new config dir (providing a helper function could be useful for this, especially for versioned configs)

Can you create a PR for that?

Yeah I might give it a go

ofek commented

The problem is this would be a breaking change 🤔 for a lot of apps.

New major release?

@probablykasper I agree that Preferences is the wrong folder as it's only meant for plist files that are generated/edited via the special APIs meant for the "defaults system" you mentioned, not for a user-facing config .jsons and .tomls and what not

Though isn't it also the case that Application support isn't for user-editable configs either?
Per the Apple docs (emphasis mine)

Put app-created support files in the Library/Application support/ directory. In general, this directory includes files that the app uses to run but that should remain hidden from the user. This directory can also include data files, configuration files, templates and modified versions of resources loaded from the app bundle

So it's really meant for various GUI apps that create the preference files themselves, but if a user is creating a supporting config file, it shouldn't be there

I think you're making a false assumption that user-editable configs are intended to exist at all. I think the guidelines are designed with accessibility in mind, and manually editing config files is something only very advanced users do

Interesting perspective, but in that case no folder is good and the guidelines are useless as a guide, why use them then? What's the point of referencing Application Support from the guidelines as though it's the officially sanctioned way to store user-editable cli files and then ignore the fact that the guidelines say you're supposed to hide this folder from, not expose it to, the users.
(and /Documents is for files

the user created and works with directly

)

I'd say it's more that it's assumed that users don't manually edit config files, and that a user isn't someone advanced enough to understand how a config file works.

What's the point of referencing Application Support from the guidelines as though it's the officially sanctioned way to store user-editable cli files

I never suggested it's the officially sanctioned way to store user-editable cli files. I mentioned it as the standard location for config files, not a standard location for user-editable cli files.

It says to Put app-created support files in the Library/Application support/ directory. It doesn't say that you shouldn't put non-app-created support files there, and it doesn't say that the app-created support files shouldn't be user-editable.

the guidelines say you're supposed to hide this folder from, not expose it to, the users

They say to store config files that should be hidden there. I very rarely see config files that aren't hidden. Usually they're hidden in locations like ~/Library/Application Support, the defaults system, or the non-standard ~/.config

Exactly the same discussion happened in the Rust equivalent of platformdirs:
dirs-dev/directories-rs#62
The maintainer was also skeptical at the beginning, but eventually it was changed to ~/Library/Application Support. They just added additional var preference_dir pointing to ~/Library/Preferences if anyone really needs it (e.g. to support reading from both locations or create some migration logic).

Side note - if both libraries (and any other equivalents) could align on the approach and have the same variables pointing to the same locations - that would be really beneficial for language-agnostic standardisation:
https://github.com/dirs-dev/directories-rs#basedirs
Maybe it could be even officially defined as conventional directories spec one day? Similarly to:
https://www.conventionalcommits.org/en/v1.0.0/

Feel free to put in a PR to address it.

kytta commented

Just as an extra argument for "Application Support": it's the default in Go as well.

It would be good to decide / implement this rather sooner than later.

The longer you wait, the more applications will have adopted platformdirs (like us, borgbackup) and the more will then have to deal with a breaking platformdirs upgrade for their macOS users.

This is an open source project. There's no plan to implement this ourselves. PR welcome if you're offering and want this feature 👋

Fixed by #137, can be closed.

Yes it sure would :/ Luckily, migrating should be fairly easy in most cases:

  • if new config dir exists:

    • if old config dir exists:

      • move old config dir files into new config dir (providing a helper function could be useful for this, especially for versioned configs)

Hi @probablykasper, is there any example on how to implement this migration? For example how to obtain the old value for the config dir? (Is it required to hardcode the value and do manually do the OS detection?)

Yeah you'd have to take care of it manually. If you look through the PR you should see how to get the old path