diff --git a/qtribu/toolbelt/application_folder.py b/qtribu/toolbelt/application_folder.py new file mode 100644 index 00000000..792a374a --- /dev/null +++ b/qtribu/toolbelt/application_folder.py @@ -0,0 +1,66 @@ +#! python3 # noqa: E265 + +"""Find application folder. + +Inspired from Click: https://github.com/pallets/click/blob/14f735cf59618941cf2930e633eb77651b1dc7cb/src/click/utils.py#L449 + +""" + +# ############################################################################ +# ########## Imports ############### +# ################################## + +# standard library +from functools import lru_cache +from os import getenv +from pathlib import Path + +# ############################################################################ +# ########## Functions ############# +# ################################## + + +def _posixify(in_name: str) -> str: + """Make sure a string is POSIX friendly. + + :param in_name: input string to posixify + :type name: str + + :return: posixyfied string + :rtype: str + """ + return "-".join(in_name.split()).lower() + + +@lru_cache +def get_app_dir( + dir_name: str, roaming: bool = True, app_prefix: str = ".geotribu" +) -> Path: + """Get application directory, typically cache or config folder. The default + behavior is to return whatever is most appropriate for the operating system. + + :param dir_name: the directory name. Could be cache of config for example. + :type dir_name: str + :param roaming: controls if the folder should be roaming or not on Windows. Has no + effect otherwise, defaults to True + :type roaming: bool, optional + :param app_prefix: application prefix, defaults to ".geotribu" + :type app_prefix: str, optional + + :return: application folder path + :rtype: Path + + :example: + + .. code-block:: python + + print(get_app_dir(dir_name="rss")) + # Mac OS X: ~/Library/Application Support/.geotribu/rss + # Unix: /home//.geotribu/rss + # Windows (roaming): C:\\Users\\\\AppData\\Roaming\\.geotribu\\rss + print(get_app_dir(dir_name="rss", roaming=False)) + # Windows (not roaming): C:\\Users\\\\AppData\\Local\\.geotribu\\rss + """ + key = "APPDATA" if roaming else "LOCALAPPDATA" + base_folder = Path(getenv(key, Path.home())) + return base_folder.joinpath(f"{app_prefix}/{_posixify(dir_name)}") diff --git a/qtribu/toolbelt/preferences.py b/qtribu/toolbelt/preferences.py index 43efc07e..251166cf 100644 --- a/qtribu/toolbelt/preferences.py +++ b/qtribu/toolbelt/preferences.py @@ -6,6 +6,7 @@ # standard from dataclasses import asdict, dataclass, fields +from pathlib import Path # PyQGIS from qgis.core import QgsSettings @@ -13,6 +14,7 @@ # package import qtribu.toolbelt.log_handler as log_hdlr from qtribu.__about__ import __title__, __version__ +from qtribu.toolbelt.application_folder import get_app_dir # ############################################################################ # ########## Classes ############### @@ -26,6 +28,7 @@ class PlgSettingsStructure: # global debug_mode: bool = False version: str = __version__ + local_app_folder: Path = get_app_dir(dir_name="cache") # RSS feed rss_source: str = "https://geotribu.fr/feed_rss_created.xml" diff --git a/tests/qgis/test_utils_application_folder.py b/tests/qgis/test_utils_application_folder.py new file mode 100755 index 00000000..2a9fed32 --- /dev/null +++ b/tests/qgis/test_utils_application_folder.py @@ -0,0 +1,45 @@ +#! python3 # noqa E265 + +""" + Usage from the repo root folder: + + .. code-block:: bash + # for whole tests + python -m unittest tests.qgis.test_utils_application_folder + # for specific test + python -m unittest tests.qgis.test_utils_application_folder.TestToolbeltApplicationFolder.test_get_app_folder +""" + +# standard library +import unittest +from os import getenv +from pathlib import Path + +# project +from qtribu.toolbelt.application_folder import _posixify, get_app_dir + +# ############################################################################ +# ########## Classes ############# +# ################################ + + +class TestToolbeltApplicationFolder(unittest.TestCase): + """Test toolbelt application folder module""" + + def test_get_app_folder(self): + """Test application folder retrieval.""" + self.assertEqual( + get_app_dir(dir_name="cache", roaming=False), + Path(getenv("LOCALAPPDATA", Path.home())).joinpath(".geotribu/cache"), + ) + + def test_posixify(self): + """Test posixify util.""" + self.assertEqual(_posixify("test PoSiXiFieD string"), "test-posixified-string") + + +# ############################################################################ +# ####### Stand-alone run ######## +# ################################ +if __name__ == "__main__": + unittest.main()