From 3bbf639fb3ae2651dee4668763b2b393dec419dd Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Thu, 19 Dec 2019 14:58:31 +0800 Subject: [PATCH 1/3] Make winreg import compatible to modern Python --- src/pip/_internal/utils/appdirs.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pip/_internal/utils/appdirs.py b/src/pip/_internal/utils/appdirs.py index 06cd8314a5c..44e297ecc38 100644 --- a/src/pip/_internal/utils/appdirs.py +++ b/src/pip/_internal/utils/appdirs.py @@ -204,7 +204,10 @@ def _get_win_folder_from_registry(csidl_name): registry for this guarantees us the correct answer for all CSIDL_* names. """ - import _winreg + if PY2: + import _winreg as winreg + else: + import winreg shell_folder_name = { "CSIDL_APPDATA": "AppData", @@ -212,11 +215,11 @@ def _get_win_folder_from_registry(csidl_name): "CSIDL_LOCAL_APPDATA": "Local AppData", }[csidl_name] - key = _winreg.OpenKey( - _winreg.HKEY_CURRENT_USER, + key = winreg.OpenKey( + winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" ) - directory, _type = _winreg.QueryValueEx(key, shell_folder_name) + directory, _type = winreg.QueryValueEx(key, shell_folder_name) return directory From ecec9f067e756140e28ccb9ef33f41cf2c8235c3 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Thu, 19 Dec 2019 21:34:51 +0800 Subject: [PATCH 2/3] News --- news/7495.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/7495.bugfix diff --git a/news/7495.bugfix b/news/7495.bugfix new file mode 100644 index 00000000000..8b2557dac3a --- /dev/null +++ b/news/7495.bugfix @@ -0,0 +1 @@ +Make the bundled appdirs compatible with Python 3 on Windows when ``ctypes`` is not available. From 4ebe4fa746a22c9947c873e3ebb4985752f88fae Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Fri, 20 Dec 2019 19:52:48 +0800 Subject: [PATCH 3/3] Add tests for appdirs._get_win_folder variant --- tests/unit/test_appdirs.py | 76 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/tests/unit/test_appdirs.py b/tests/unit/test_appdirs.py index 1ee68ef2f72..a35e46c2637 100644 --- a/tests/unit/test_appdirs.py +++ b/tests/unit/test_appdirs.py @@ -2,6 +2,7 @@ import os import posixpath import sys +import types import pretend @@ -300,3 +301,78 @@ def test_user_config_dir_linux_home_slash(self, monkeypatch): monkeypatch.setattr(sys, "platform", "linux2") assert appdirs.user_config_dir("pip") == "/.config/pip" + + +class TestGetWinFolder: + + def test_win_folder_ctypes(self, monkeypatch): + if sys.platform != 'win32': + return + + @pretend.call_recorder + def _get_win_folder_from_registry(csidl_name): + return "return-value-from-registry" + + @pretend.call_recorder + def _get_win_folder_with_ctypes(csidl_name): + return "return-value-from-ctypes" + + monkeypatch.setitem(sys.modules, 'ctypes', types.ModuleType('ctypes')) + monkeypatch.setattr( + appdirs, + "_get_win_folder_from_registry", + _get_win_folder_from_registry, + raising=False, + ) + monkeypatch.setattr( + appdirs, + "_get_win_folder_with_ctypes", + _get_win_folder_with_ctypes, + raising=False, + ) + + assert ( + appdirs._get_win_folder("place-holder") == + "return-value-from-ctypes" + ) + assert ( + _get_win_folder_with_ctypes.calls == + [pretend.call("place-holder")] + ) + assert _get_win_folder_from_registry.calls == [] + + def test_win_folder_registry(self, monkeypatch): + if sys.platform != 'win32': + return + + @pretend.call_recorder + def _get_win_folder_from_registry(csidl_name): + return "return-value-from-registry" + + @pretend.call_recorder + def _get_win_folder_with_ctypes(csidl_name): + return "return-value-from-ctypes" + + monkeypatch.setitem(sys.modules, 'ctypes', None) + monkeypatch.setattr( + appdirs, + "_get_win_folder_from_registry", + _get_win_folder_from_registry, + raising=False, + ) + monkeypatch.setattr( + appdirs, + "_get_win_folder_with_ctypes", + _get_win_folder_with_ctypes, + raising=False, + ) + + assert ( + appdirs._get_win_folder("place-holder") == + "return-value-from-registry" + ) + assert _get_win_folder_with_ctypes.calls == [] + assert ( + _get_win_folder_from_registry.calls == + [pretend.call("place-holder")] + )