Skip to content

スタンドアロン/開発実行での output ディレクトリ解決を一元化#21

Merged
maple60 merged 2 commits into
fix/output-path-standalone-appfrom
codex/fix-output-directory-creation-logic
Apr 2, 2026
Merged

スタンドアロン/開発実行での output ディレクトリ解決を一元化#21
maple60 merged 2 commits into
fix/output-path-standalone-appfrom
codex/fix-output-directory-creation-logic

Conversation

@maple60

@maple60 maple60 commented Apr 2, 2026

Copy link
Copy Markdown
Owner

Motivation

This PR fixes an issue where the output directory for distributed applications (frozen / .app / .exe) was created relative to the current working directory (CWD) or directly under the user’s home directory at launch.
The goal is to eliminate CWD-dependent behavior while preserving the convenience of the current behavior during development.

Description

A new utility module, leaf_contour_efd.utils.paths, was added to centralize output path resolution. It provides get_output_base_dir() and get_output_dir(...).

For frozen builds, the base path is resolved relative to sys.executable. When launched from inside a macOS .app bundle, the parent directory of the .app is used as the base path. sys._MEIPASS is intentionally not used as a writable destination.

The default save paths in each widget and save routine were updated from relative output/... paths to get_output_dir(...)-based paths. Directory creation is now explicitly guaranteed at each call site with mkdir(parents=True, exist_ok=True).

Main changed files:

  • src/leaf_contour_efd/utils/paths.py (new)
  • updated to use the shared helper:
    • src/leaf_contour_efd/widgets/binarize_image.py
    • src/leaf_contour_efd/widgets/calculate_efd.py
    • src/leaf_contour_efd/widgets/clear_viewer.py
    • src/leaf_contour_efd/widgets/crop_rectangle.py
    • src/leaf_contour_efd/widgets/extract_contour.py
    • src/leaf_contour_efd/widgets/rotate_image.py

Testing

As a static verification step, I searched the codebase with rg and confirmed that no direct relative paths such as ./output or output/ remained.

I also ran compileall to byte-compile the Python modules and confirmed that all modules compiled successfully. The first attempt failed because of the environment’s .python-version, but recompilation with an available Python interpreter succeeded.

The automated checks performed were limited to the above, and all of them passed. Runtime behavior and actual file creation should still be verified by running the application locally.

(Japanese)

Motivation

  • アプリ配布(frozen/.app/.exe)で output が起動時の CWD やホーム直下に作られてしまう問題を修正するため。
  • 開発時は従来の扱いやすさを損なわず、少なくとも cwd 依存を排除することを目的とする。

Description

  • 出力パス解決を集中管理する新規ユーティリティ leaf_contour_efd.utils.paths を追加し、get_output_base_dir()get_output_dir(...) を提供した。
  • frozen 実行時は sys.executable を基準とし、macOS の .app 内からの起動は .app の親フォルダを基準にする実装とし、sys._MEIPASS は書き込み先として使わない設計にした。
  • 各ウィジェット・保存処理のデフォルトパスを相対 output/... から get_output_dir(...) ベースへ置換し、呼び出し側で mkdir(parents=True, exist_ok=True) を保証するようにした。
  • 変更箇所(主なファイル): src/leaf_contour_efd/utils/paths.py(新規追加)、および src/leaf_contour_efd/widgets/ 以下の binarize_image.py, calculate_efd.py, clear_viewer.py, crop_rectangle.py, extract_contour.py, rotate_image.py を修正して共通ヘルパを利用するようにした。

Testing

  • ソースの静的確認として rg による検索で ./output / output/ 等の直接相対パスが残っていないことを確認した(該当パターンは検出されなかった)。
  • Python モジュールのバイトコンパイル compileall を実行して全モジュールが問題なくコンパイルされることを確認した(最初は環境の .python-version による実行失敗が出たが、利用可能な Python を指定して再実行したところコンパイルは成功した)。
  • 自動テストは上記のみで、すべて成功したことを確認している(ファイル作成やランタイム動作は手元のアプリ実行での確認を推奨)。

Codex Task

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 135c05b934

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/leaf_contour_efd/utils/paths.py Outdated
Comment on lines +32 to +35
return executable_path.parent

# Development mode: src/leaf_contour_efd/utils/paths.py -> repo root
return Path(__file__).resolve().parents[3]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Resolve output path to a user-writable location

This fallback makes output/ live next to the installed binaries/source tree (sys.executable parent in frozen mode, __file__.parents[3] otherwise), which is often read-only (e.g., /Applications, Program Files, or system site-packages). Because get_output_dir() immediately runs mkdir(...) and is invoked while widgets are constructed, the app can fail at startup with PermissionError before any user action in those install contexts.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex thank you. How can we avoid this issue? Please fix.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

  • Updated output path resolution to always have a user-writable fallback via appdirs.user_data_dir("leaf_contour_efd"), preventing startup-time PermissionError when installed in read-only locations. src/leaf_contour_efd/utils/paths.pyL8-L16
  • Added a writability probe for development mode so repo-root output is only used when it is actually writable; otherwise it falls back to user data automatically. src/leaf_contour_efd/utils/paths.pyL18-L48
  • Hardened get_output_dir(...) with a defensive retry path: if mkdir(...) fails in the primary base, it transparently recreates the same output path under the user-writable base. src/leaf_contour_efd/utils/paths.pyL51-L69
  • Committed the fix on the current branch (027c3f9) and created a follow-up PR message via the make_pr tool summarizing the change set on top of the original PR.

Testing

  • python3 -m compileall src/leaf_contour_efd/utils/paths.py

View task →

@maple60
maple60 merged commit bdcb3e9 into fix/output-path-standalone-app Apr 2, 2026
6 checks passed
@maple60
maple60 deleted the codex/fix-output-directory-creation-logic branch April 2, 2026 01:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant