Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

loader.py: Wrong directory inserted into sys.path for modules

オープン
#969 コメント 1 件 リアクション 3 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
45/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
停滞
技術スタック
python
領域
cli

調査の方向性

Read invoke/loader.py, especially load and the path insertion around the referenced line, and compare module and package resolution. Update the inserted path so package-based tasks can import sibling modules such as barutils, then add tests covering both tasks.py and tasks/init.py cases.

索引モデルが issue の本文から書いたものです。

説明

Background

In loader.py, invoke uses this load function to load the tasks collection. This function attempts to detect whether tasks is a module or a package:

https://github.com/pyinvoke/invoke/blob/07b836f2663bb073a7bcef3d6c454e1dc6b867ae/invoke/loader.py#L49-L96

It first sets enclosing_dir to be the parent directory of whatever file the import resolved to (this is tasks.py for modules, and __init__.py within the package directory for packages). Then, it checks if the discovered ModuleSpec has a non-empty entry for .parent, which would indicate that the imported tasks is a package. If it is a package, it sets module_parent to be one level above enclosing_dir. If it is not a package, module_parent is set to be enclosing_dir.

Bug

This is all correct, however the path that gets inserted into the path is always enclosing_dir, not module_parent. If we have:

foo
| -- pyinvoke
     | -- tasks.py

and then resolve the ModuleSpec for tasks, we correctly insert /foo/pyinvoke into the path. However, if we have:

foo
| -- pyinvoke
     | -- tasks
          | -- __init__.py

we end up inserting /foo/pyinvoke/tasks into the path, which is wrong, the path inserted should still be /foo/pyinvoke.

Note: #944 is similar but predates the refactor to load that happened in 2.1.3. In https://github.com/pyinvoke/invoke/commit/aa8b815d7a7a43c8ac814c6deb9c4555b8ac6b9e logic was added to fix the search path for config files, but that did not extend to search path for packages.

Note 2: This is all fine and dandy for most use cases where everything lives in tasks or tasks.py. This only broke because we have the following structure:

foo
| -- pyinvoke
    | -- tasks
        | -- __init__.py
        | -- foo_task.py
    | -- barutils
        | -- __init__.py
        | -- bar.py

From within foo_task.py we have from barutils.bar import bartender, which won't work when the inserted path is /foo/pyinvoke/tasks/ since barutils isn't in tasks.

Solution?

I'd like to propose that in:

https://github.com/pyinvoke/invoke/blob/07b836f2663bb073a7bcef3d6c454e1dc6b867ae/invoke/loader.py#L85

we replace enclosing_dir with module_parent.

@bitprophet if this fix seems reasonable I can put in a PR and add some tests for this.

主要言語
Python
スター
4.8k
フォーク
412
PR マージ指標
30日以内にマージされた PR はありません

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

pyinvoke/invoke のほかの issue

pyinvoke/invoke の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。