Skip to content

Commit 32142a4

Browse files
authored
Merge pull request #22 from maple60/codex/add-output-folder-for-standalone-app
Prefer portable output directory in standalone builds (スタンドアロン版でポータブル出力ディレクトリを優先)
2 parents bdcb3e9 + 8f01349 commit 32142a4

3 files changed

Lines changed: 20 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ flowchart LR
149149

150150
Each processing step corresponds to a dedicated GUI widget,
151151
and all results (images, contours, metadata, EFDs) are automatically exported to the `output/` directory.
152+
For standalone builds, `output/` is created next to the app/executable when writable; otherwise it falls back to the OS user data directory.
152153

153154
For a detailed step-by-step guide, please refer to the [Usage page](https://maple60.github.io/leaf-contour-efd/usage.html).
154155

README_ja.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ flowchart LR
147147

148148
各処理ステップは専用のGUIウィジェットに対応しており、
149149
解析結果(画像・輪郭・メタデータ・EFD)は自動的に `output/` ディレクトリに保存されます。
150+
スタンドアロン版では、書き込み可能な場合はアプリ/実行ファイルと同じ場所に `output/` を作成し、不可の場合はOSのユーザーデータ領域へ自動的にフォールバックします。
150151

151152
詳しい操作手順については、[Usage ページ](https://maple60.github.io/leaf-contour-efd/usage.html) を参照してください。
152153

src/leaf_contour_efd/utils/paths.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,34 @@ def _is_writable_dir(path: Path) -> bool:
2828
return False
2929

3030

31+
def _frozen_portable_base_dir() -> Path | None:
32+
"""Return a portable base dir near the frozen app/executable when possible."""
33+
executable = Path(sys.executable).resolve()
34+
35+
if sys.platform == "darwin":
36+
# pyinstaller .app executable path example:
37+
# /path/MyApp.app/Contents/MacOS/MyApp
38+
app_bundle = next((p for p in executable.parents if p.suffix == ".app"), None)
39+
if app_bundle is not None:
40+
return app_bundle.parent
41+
42+
return executable.parent
43+
44+
3145
def get_output_base_dir() -> Path:
3246
"""Return the base directory used for writing the ``output`` folder.
3347
3448
Rules
3549
-----
36-
- Frozen on all platforms: user-writable application data directory.
50+
- Frozen: directory near app/executable when writable, otherwise user data.
3751
- Non-frozen: repository/application root when writable, otherwise user data.
3852
"""
3953
fallback = _user_writable_base_dir()
4054

4155
if getattr(sys, "frozen", False):
56+
portable_base = _frozen_portable_base_dir()
57+
if portable_base is not None and _is_writable_dir(portable_base):
58+
return portable_base
4259
return fallback
4360

4461
# Development mode: src/leaf_contour_efd/utils/paths.py -> repo root

0 commit comments

Comments
 (0)