diff --git a/CHANGES.txt b/CHANGES.txt index 0c91da4418..b6cf4259c0 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,6 +8,9 @@ Note that build 228 was the last version supporting Python 2. Since build 302: ---------------- +* Tweaks to how DLLs are loaded and our installation found, which should + improve virtualenv support and version mismatch issues (#1787, #1794) + * Binary installers for 32-bit 3.10+ are no longer released (#1805) Since build 301: diff --git a/win32/Lib/pywintypes.py b/win32/Lib/pywintypes.py index 54dbcd122c..6b2f189c01 100644 --- a/win32/Lib/pywintypes.py +++ b/win32/Lib/pywintypes.py @@ -79,13 +79,24 @@ def __import_pywin32_system_module__(modname, globs): # easy_install... if os.path.isfile(os.path.join(os.path.dirname(__file__), filename)): found = os.path.join(os.path.dirname(__file__), filename) + + # There are 2 site-packages directories - one "global" and one "user". + # We could be in either, or both (but with different versions!). Factors include + # virtualenvs, post-install script being run or not, `setup.py install` flags, etc. + + # In a worst-case, it means, say 'python -c "import win32api"' + # will not work but 'python -c "import pywintypes, win32api"' will, + # but it's better than nothing. + # We prefer the "user" site-packages if it exists... + if found is None: + import site + + maybe = os.path.join(site.USER_SITE, "pywin32_system32", filename) + if os.path.isfile(maybe): + found = maybe + + # Or the "global" site-packages. if found is None: - # We might have been installed via PIP and without the post-install - # script having been run, so they might be in the - # lib/site-packages/pywin32_system32 directory. - # This isn't ideal as it means, say 'python -c "import win32api"' - # will not work but 'python -c "import pywintypes, win32api"' will, - # but it's better than nothing... import sysconfig maybe = os.path.join( @@ -93,6 +104,7 @@ def __import_pywin32_system_module__(modname, globs): ) if os.path.isfile(maybe): found = maybe + if found is None: # give up in disgust. raise ImportError("No system module '%s' (%s)" % (modname, filename)) diff --git a/win32/src/_win32sysloader.cpp b/win32/src/_win32sysloader.cpp index 0bf81e0c5f..d2681931f0 100644 --- a/win32/src/_win32sysloader.cpp +++ b/win32/src/_win32sysloader.cpp @@ -56,8 +56,17 @@ static PyObject *PyLoadModule(PyObject *self, PyObject *args) TCHAR *modName = NULL; if (!PyArg_ParseTuple(args, fmt, &modName)) return NULL; - HINSTANCE hinst = LoadLibrary(modName); + // Python 3.7 vs 3.8 use different flags for LoadLibraryEx and we match them. + // See github issue 1787. +#if (PY_VERSION_HEX < 0x03080000) + HINSTANCE hinst = LoadLibraryEx(modName, NULL, + LOAD_WITH_ALTERED_SEARCH_PATH); +#else + HINSTANCE hinst = LoadLibraryEx(modName, NULL, + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | + LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); +#endif if (hinst == NULL) { Py_INCREF(Py_None); return Py_None;