0

Linux、MacOS、Windows で動作するオープン ソースの Python ライブラリを開発していますが、開発者チームには Windows の経験や経験があまりありません。テスト スイートをセットアップして実行する方法は、Linux と Mac では問題なく動作しますが、Windows では最適ではありません。私たちのテストでは、一時的な場所に新しいディレクトリを設定し、その.gitconfig中に関連する構成を含む偽物を配置し、テスト中に構成を取得するために、関連するHOME環境変数がホーム ディレクトリとしてこの場所を指すようにします。

コードは短縮されており、実行できませんが、うまくいけば、私たちが行うことの要点を示しています。

with make_tempfile(mkdir=True) as new_home:
    pass
for v, val in get_home_envvars(new_home).items():
    set_envvar(v, val)
if not os.path.exists(new_home):
    os.makedirs(new_home)
with open(os.path.join(new_home, '.gitconfig'), 'w') as f:
    f.write("""\
[user]
    name = Tester
    email = test@example.com
[more configs for testing]
    exc = 1
""")

whereは、 env 変数が新しい一時的なテスト ホームを指してget_home_envvars()いることを確認します。$HOMEPython 3.8 以降の Windows では、ユーザーのホームを決定するために変数をos.path照会することはなくなりましたが、 [ 1 ][ 2 ] であるため、この変数を一時的なテスト ホームで上書きしました。$HOMEUSERPROFILE

def get_home_envvars(new_home):
    environ = os.environ
    out = {'HOME': new_home}
    if on_windows:
        # requires special handling, since it has a number of relevant variables
        # and also Python changed its behavior and started to respect USERPROFILE only
        # since python 3.8: https://bugs.python.org/issue36264
        out['USERPROFILE'] = new_home
        out['HOMEDRIVE'], out['HOMEPATH'] = splitdrive(new_home)
    return {v: val for v, val in out.items() if v in os.environ}

ただし、これにより Windows でのテスト セットアップが壊れることがわかりました。テストは、キャッシュや Cookie データベースなどを単体テストを実行する場所に「出血」させ、これにより、テストの仮定を破るファイルとディレクトリを作成します。 . 正確に何が起こるかについての理解は非常に限られていますが、私の現在の仮説は次のとおりです。私たちのライブラリは、開始時にappdirs[ 3 ] を使用してキャッシュ、ログ、Cookie などの適切な場所を決定します。CSIDLWindows が持っているID [ 4 ]。この情報は、Windows レジストリで決定されます。これは、USERPROFILE. この変更に対する Python バグ トラッカーの特定の返信を引用すると、次のようになります。

これは残念です。USERPROFILE を変更することは非常に珍しいことです。USERPROFILE は、ユーザーの "NTUSER.DAT" レジストリ ハイブと、"UsrClass.dat" ("Software\Classes" レジストリ ハイブ) を含むローカル アプリケーション データ ("AppData\Local") の場所です。これは、ユーザーの既知のシェル フォルダーとホーム ディレクトリの既定の場所でもあります。USERPROFILE を変更しても、これで問題が発生することはありませんが、完全に安心できるわけではありません。

テストスイートのセットアップが完了したら、テストを実行する新しいプロセスを開始します。新しいプロセスは new のみを認識し、それが見つかったパスをnormpathUSERPROFILE経由で送信して返します。これは、残念ながら、相対パス ( )としてもはや見つからない CSIDL に対してによって返された空の文字列を解釈します。appdirs_get_win_folder.

# snippet from appdirs source code
path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA"))

これに基づいて、各テストの現在の作業ディレクトリをユーザー データ、ユーザー キャッシュなどの場所として構成します。

私の質問は次のとおりです。どうすればこれを修正できますか? 私のおそらく不完全な理解に基づいて、最終的にはUSERPROFILE. 「特別なフォルダー」IDを取得するためにレジストリを指す必要があります(それを使用するappdirsか、より現代的な代替品を使用します)-しかし、テスト固有のGit構成で偽のホームを指す必要もあります。後者はUSERPROFILEPython3.8 以降で上書きする必要があると思います。レジストリをコピーまたはモックして、新しいホームの下に配置する方法があるかどうか疑問に思っていますか? 関連する CSIDL/KNOWNFOLDERID を別の方法で設定しますか? キャッシュディレクトリなどとして使用する他の一時的な場所をハードコードしますか? それとも、偽のホームを必要としない、Windows でテスト スイートを実行するためのより賢い方法があるのでしょうか?

より経験豊富な Windows 開発者から、何をすべきか、また何をすべきでないかを教えていただければ幸いです。よろしくお願いします。

[1] https://docs.python.org/3.11/library/os.path.html#os.path.expanduser

[2] https://bugs.python.org/issue36264

[3] https://github.com/ActiveState/appdirs

[4] https://docs.microsoft.com/en-us/windows/win32/shell/csidl

4

0 に答える 0