Skip to content

app_dirs

app_dirs

Application data directory and folder access utilities.

Resolve per-user application data paths and provide helpers for creating and opening the directory.

APP_NAME = 'TapMap' module-attribute

README_TEXT = 'Place GeoIP .mmdb databases here.\n\nIf running in Docker, this folder is mapped from the host to /data in the container.\nRequired files:\n- GeoLite2-City.mmdb\n- GeoLite2-ASN.mmdb\n\nDownload (free, account required):\nhttps://dev.maxmind.com/geoip/geolite2-free-geolocation-data\n' module-attribute

get_native_app_data_dir(app_name=APP_NAME)

Return the per-user application data directory for the current OS.

Windows: %APPDATA%\ macOS: ~/Library/Application Support/ Linux: ${XDG_DATA_HOME:-~/.local/share}/

Source code in app_dirs.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
def get_native_app_data_dir(app_name: str = APP_NAME) -> Path:
    r"""Return the per-user application data directory for the current OS.

    Windows: %APPDATA%\<app_name>
    macOS:   ~/Library/Application Support/<app_name>
    Linux:   ${XDG_DATA_HOME:-~/.local/share}/<app_name>
    """
    system = platform.system()

    if system == "Windows":
        base = os.environ.get("APPDATA")
        if base:
            return Path(base) / app_name
        return Path.home() / "AppData" / "Roaming" / app_name

    if system == "Darwin":
        return Path.home() / "Library" / "Application Support" / app_name

    xdg = os.environ.get("XDG_DATA_HOME")
    base_dir = Path(xdg) if xdg else (Path.home() / ".local" / "share")
    return base_dir / app_name

ensure_app_data_dir(app_dir)

Create the application data directory and README.txt file when missing.

Source code in app_dirs.py
52
53
54
55
56
57
58
59
def ensure_app_data_dir(app_dir: Path) -> None:
    """Create the application data directory and README.txt file when missing."""
    app_dir = app_dir.expanduser()
    app_dir.mkdir(parents=True, exist_ok=True)

    readme = app_dir / "README.txt"
    if not readme.exists():
        readme.write_text(README_TEXT, encoding="utf-8")

ensure_native_app_data_dir(app_name=APP_NAME)

Return native app data directory and ensure it exists.

Source code in app_dirs.py
62
63
64
65
66
def ensure_native_app_data_dir(app_name: str = APP_NAME) -> Path:
    """Return native app data directory and ensure it exists."""
    app_dir = get_native_app_data_dir(app_name)
    ensure_app_data_dir(app_dir)
    return app_dir

open_folder(path)

Open a folder in the system file manager.

Returns:

Name Type Description
ok bool

True on success.

message str

Status message suitable for UI.

Source code in app_dirs.py
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
def open_folder(path: Path) -> tuple[bool, str]:
    """Open a folder in the system file manager.

    Returns:
        ok: True on success.
        message: Status message suitable for UI.
    """
    try:
        path = path.expanduser()
        path.mkdir(parents=True, exist_ok=True)

        system = platform.system()

        if system == "Windows":
            os.startfile(str(path))
            return True, f"Opened: {path}"

        if system == "Darwin":
            subprocess.Popen(["open", str(path)])
            return True, f"Opened: {path}"

        xdg_open = shutil.which("xdg-open")
        if not xdg_open:
            return False, "xdg-open is not available on this system."

        cp = subprocess.run([xdg_open, str(path)], capture_output=True, text=True, check=False)
        if cp.returncode == 0:
            return True, f"Opened: {path}"

        detail = (cp.stderr or cp.stdout or "").strip()
        msg = "xdg-open failed."
        if detail:
            msg += f" {detail}"
        return False, msg

    except Exception as exc:
        return False, f"Failed to open folder: {path}. Error: {exc}"