From 636e4c00d1b011f21e7d968200da083200cf7ce8 Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Thu, 17 Oct 2024 20:50:42 -0500 Subject: [PATCH 01/13] Fixing memory leak converting to PyObject from some SAFEARRAY elements (#2316) Some SAFEARRAY element types require ownership change when converted to PyObjects. This includes the BSTR, IUnknown and IDispatch types. Otherwise the memory gets leaked upon garbage collection. Co-authored-by: Kyle Johnson --- com/win32com/src/oleargs.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/com/win32com/src/oleargs.cpp b/com/win32com/src/oleargs.cpp index 33c925987..0e565ae5e 100644 --- a/com/win32com/src/oleargs.cpp +++ b/com/win32com/src/oleargs.cpp @@ -860,7 +860,7 @@ static PyObject *PyCom_PyObjectFromSAFEARRAYDimensionItem(SAFEARRAY *psa, VARENU hres = SafeArrayGetElement(psa, arrayIndices, &str); if (FAILED(hres)) break; - subitem = PyWinObject_FromBstr(str); + subitem = PyWinObject_FromBstr(str, TRUE); break; } case VT_DISPATCH: { @@ -868,7 +868,7 @@ static PyObject *PyCom_PyObjectFromSAFEARRAYDimensionItem(SAFEARRAY *psa, VARENU hres = SafeArrayGetElement(psa, arrayIndices, &pDisp); if (FAILED(hres)) break; - subitem = PyCom_PyObjectFromIUnknown(pDisp, IID_IDispatch, TRUE); + subitem = PyCom_PyObjectFromIUnknown(pDisp, IID_IDispatch, FALSE); break; } // case VT_ERROR - handled above with I4 @@ -895,7 +895,7 @@ static PyObject *PyCom_PyObjectFromSAFEARRAYDimensionItem(SAFEARRAY *psa, VARENU hres = SafeArrayGetElement(psa, arrayIndices, &pUnk); if (FAILED(hres)) break; - subitem = PyCom_PyObjectFromIUnknown(pUnk, IID_IUnknown, TRUE); + subitem = PyCom_PyObjectFromIUnknown(pUnk, IID_IUnknown, FALSE); break; } // case VT_DECIMAL From 3be4f697c59eb2cb5e08ff7fa8de6613288f1d21 Mon Sep 17 00:00:00 2001 From: Thomas Geppert Date: Fri, 18 Oct 2024 03:56:18 +0200 Subject: [PATCH 02/13] Implement record pointers as [in, out] method parameters of a Dispatch Interface (#2310) * Implement record pointers as method parameters of a Dispatch Interface to get server side modifications of a record marshaled back to the client. * Added a untitest for record pointers as [ in, out ] method parameters. --- com/TestSources/PyCOMTest/PyCOMImpl.cpp | 8 ++++++++ com/TestSources/PyCOMTest/PyCOMImpl.h | 2 ++ com/TestSources/PyCOMTest/PyCOMTest.idl | 2 ++ com/win32com/client/build.py | 1 - com/win32com/src/oleargs.cpp | 1 + com/win32com/test/testPyComTest.py | 12 ++++++++++++ 6 files changed, 25 insertions(+), 1 deletion(-) diff --git a/com/TestSources/PyCOMTest/PyCOMImpl.cpp b/com/TestSources/PyCOMTest/PyCOMImpl.cpp index a4616fef0..d58c00f99 100644 --- a/com/TestSources/PyCOMTest/PyCOMImpl.cpp +++ b/com/TestSources/PyCOMTest/PyCOMImpl.cpp @@ -618,6 +618,14 @@ HRESULT CPyCOMTest::GetStruct(TestStruct1 *ret) *ret = r; return S_OK; } + +HRESULT CPyCOMTest::ModifyStruct(TestStruct1 *prec) +{ + prec->int_value = 100; + prec->str_value = SysAllocString(L"Nothing is as constant as change"); + return S_OK; +} + HRESULT CPyCOMTest::DoubleString(BSTR in, BSTR *out) { *out = SysAllocStringLen(NULL, SysStringLen(in) * 2); diff --git a/com/TestSources/PyCOMTest/PyCOMImpl.h b/com/TestSources/PyCOMTest/PyCOMImpl.h index e285268f1..50eb8dd0d 100644 --- a/com/TestSources/PyCOMTest/PyCOMImpl.h +++ b/com/TestSources/PyCOMTest/PyCOMImpl.h @@ -119,6 +119,8 @@ class CPyCOMTest : public IDispatchImpl Date: Mon, 14 Oct 2024 22:25:14 -0400 Subject: [PATCH 03/13] Add missing CHANGELOG entries --- CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index a88445e9b..8d1012619 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -14,6 +14,9 @@ https://mhammond.github.io/pywin32_installers.html. Coming in build 309, as yet unreleased -------------------------------------- +* Implement record pointers as [in, out] method parameters of a Dispatch Interface (#2310) +* Fix memory leak converting to PyObject from some SAFEARRAY elements (#2316) +* Fix bug where makepy support was unnecessarily generated (#2354, #2353, @geppi) * Fail sooner on invalid `win32timezone.TimeZoneInfo` creation (#2338, @Avasam) * Removed temporary `win32com.server.policy` reexports hack (#2344, @Avasam) Import `DispatcherWin32trace` and `DispatcherTrace` from `win32com.server.dispatcher` instead. From ad3a991202d5d352488218d3419d03768c5a787e Mon Sep 17 00:00:00 2001 From: petur-keystrike <148981503+petur-keystrike@users.noreply.github.com> Date: Fri, 18 Oct 2024 02:49:41 +0000 Subject: [PATCH 04/13] Add support for WTSIsRemoteSession flag. (#2152) When WTSIsRemoteSession is passed to WTSQuerySessionInformation, it returns a single byte containing the return value. --- win32/src/win32tsmodule.cpp | 4 ++++ win32/test/test_win32ts.py | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 win32/test/test_win32ts.py diff --git a/win32/src/win32tsmodule.cpp b/win32/src/win32tsmodule.cpp index c4156f9f5..ddd383dee 100644 --- a/win32/src/win32tsmodule.cpp +++ b/win32/src/win32tsmodule.cpp @@ -409,6 +409,9 @@ static PyObject *PyWTSQuerySessionInformation(PyObject *self, PyObject *args, Py case WTSConnectState: // @flag WTSConnectState|Int, from WTS_CONNECTSTATE_CLASS ret = PyLong_FromLong(*(INT *)buf); break; + case WTSIsRemoteSession: // @flag WTSIsRemoteSession|Boolean + ret = PyBool_FromLong(*(BYTE *)buf); + break; case WTSClientDisplay: { // @flag WTSClientDisplay|Dict containing client's display settings WTS_CLIENT_DISPLAY *wcd = (WTS_CLIENT_DISPLAY *)buf; ret = Py_BuildValue("{s:k, s:k, s:k}", "HorizontalResolution", wcd->HorizontalResolution, @@ -768,6 +771,7 @@ PYWIN_MODULE_INIT_FUNC(win32ts) PyModule_AddIntConstant(module, "WTSClientAddress", WTSClientAddress); PyModule_AddIntConstant(module, "WTSClientDisplay", WTSClientDisplay); PyModule_AddIntConstant(module, "WTSClientProtocolType", WTSClientProtocolType); + PyModule_AddIntConstant(module, "WTSIsRemoteSession", WTSIsRemoteSession); // WTS_CONFIG_CLASS PyModule_AddIntConstant(module, "WTSUserConfigInitialProgram", WTSUserConfigInitialProgram); diff --git a/win32/test/test_win32ts.py b/win32/test/test_win32ts.py new file mode 100644 index 000000000..712b99272 --- /dev/null +++ b/win32/test/test_win32ts.py @@ -0,0 +1,19 @@ +# Tests for win32ts module + +import unittest + +import win32ts + + +class Win32TsTestCase(unittest.TestCase): + def test_is_remote_session(self): + ret = win32ts.WTSQuerySessionInformation( + win32ts.WTS_CURRENT_SERVER_HANDLE, + win32ts.WTS_CURRENT_SESSION, + win32ts.WTSIsRemoteSession, + ) + self.assertIsInstance(ret, bool) + + +if __name__ == "__main__": + unittest.main() From a940d6872130fe37d1019dde52f79e19256716d8 Mon Sep 17 00:00:00 2001 From: Alexander Reznikov Date: Fri, 18 Oct 2024 06:01:58 +0300 Subject: [PATCH 05/13] Added support for DBT_DEVTYP_PORT in UnpackDEV_BROADCAST (#2074) * Update win32gui_struct.py: Added support for DBT_DEVTYP_PORT in UnpackDEV_BROADCAST --- win32/Lib/win32gui_struct.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/win32/Lib/win32gui_struct.py b/win32/Lib/win32gui_struct.py index 945ededc9..41ef815fd 100644 --- a/win32/Lib/win32gui_struct.py +++ b/win32/Lib/win32gui_struct.py @@ -952,6 +952,8 @@ def UnpackDEV_BROADCAST(lparam): _, _, _, x["unitmask"], x["flags"] = struct.unpack( fmt, buf[: struct.calcsize(fmt)] ) + elif devtype == win32con.DBT_DEVTYP_PORT: + x["name"] = win32gui.PyGetString(lparam + struct.calcsize(hdr_format)) else: raise NotImplementedError("unknown device type %d" % (devtype,)) return DEV_BROADCAST_INFO(devtype, **extra) From 49c52f93d505feeb1f5f46c93b8f9af9ea3f2f42 Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 17 Oct 2024 23:52:21 -0400 Subject: [PATCH 06/13] Dropping support for Python 3.7 (#2207) --- .github/workflows/download-arm64-libs.py | 12 ++++++------ .github/workflows/main.yml | 11 +++++------ CHANGES.txt | 1 + Pythonwin/pywin/test/test_pywin.py | 5 ++--- build_all.bat | 4 ---- build_env.md | 1 - com/win32com/test/pippo_server.py | 5 +---- make_all.bat | 5 ----- mypy.ini | 1 - pyrightconfig.json | 2 +- ruff.toml | 2 +- setup.py | 20 +++++--------------- win32/Lib/pywin32_bootstrap.py | 10 +--------- win32/src/_win32sysloader.cpp | 6 ------ 14 files changed, 23 insertions(+), 62 deletions(-) diff --git a/.github/workflows/download-arm64-libs.py b/.github/workflows/download-arm64-libs.py index 51c5bcd02..841673f98 100644 --- a/.github/workflows/download-arm64-libs.py +++ b/.github/workflows/download-arm64-libs.py @@ -28,16 +28,16 @@ VERSION += f"-rc{sys.version_info.serial}" URL = f"https://www.nuget.org/api/v2/package/pythonarm64/{VERSION}" -PATH = dest / f"pythonarm64.{VERSION}.zip" +DEST_PATH = dest / f"pythonarm64.{VERSION}.zip" -if PATH.is_file(): - print("Skipping download because", PATH, "exists") +if DEST_PATH.is_file(): + print("Skipping download because", DEST_PATH, "exists") else: print("Downloading", URL) - urlretrieve(URL, PATH) - print("Downloaded", PATH) + urlretrieve(URL, DEST_PATH) + print("Downloaded", DEST_PATH) -with ZipFile(PATH, "r") as zf: +with ZipFile(DEST_PATH, "r") as zf: for name in zf.namelist(): zip_path = pathlib.PurePath(name) if zip_path.parts[:2] == ("tools", "libs"): diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index aa1049f06..2af0d70a0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13-dev"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13-dev"] architecture: ["x64", "x86"] steps: @@ -37,7 +37,7 @@ jobs: run: | python --version pip --version - pip install --upgrade setuptools wheel + pip install --upgrade setuptools>=74 wheel - name: Build and install run: | @@ -86,7 +86,7 @@ jobs: run: | python --version pip --version - pip install --upgrade setuptools wheel + pip install --upgrade setuptools>=74 wheel - name: Obtain ARM64 library files run: | @@ -117,7 +117,7 @@ jobs: cache-dependency-path: .github/workflows/main.yml - run: pip install clang-format pycln - run: pycln . --config=pycln.toml --check - - uses: chartboost/ruff-action@v1 + - uses: astral-sh/ruff-action@v1 with: version: "0.4.5" - uses: psf/black@stable @@ -134,7 +134,6 @@ jobs: strategy: fail-fast: false matrix: - # mypy 1.5 dropped support for Python 3.7 # mypy won't understand "3.13-dev", keeping the CI simple by just omitting it python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: @@ -154,7 +153,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13-dev"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13-dev"] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 diff --git a/CHANGES.txt b/CHANGES.txt index 8d1012619..d8978afd5 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -14,6 +14,7 @@ https://mhammond.github.io/pywin32_installers.html. Coming in build 309, as yet unreleased -------------------------------------- +* Dropped support for Python 3.7 (#2207, @Avasam) * Implement record pointers as [in, out] method parameters of a Dispatch Interface (#2310) * Fix memory leak converting to PyObject from some SAFEARRAY elements (#2316) * Fix bug where makepy support was unnecessarily generated (#2354, #2353, @geppi) diff --git a/Pythonwin/pywin/test/test_pywin.py b/Pythonwin/pywin/test/test_pywin.py index 6cf973a92..49acc9d5e 100644 --- a/Pythonwin/pywin/test/test_pywin.py +++ b/Pythonwin/pywin/test/test_pywin.py @@ -47,8 +47,7 @@ def setUpClass(cls): def _restore_oe(): sys.stdout, sys.stderr = cls.std_oe_orig - if sys.version_info >= (3, 8): - cls.addClassCleanup(_restore_oe) + cls.addClassCleanup(_restore_oe) sys.argv[1:] = ["/new", src_dir + "\\_dbgscript.py"] if not _indebugger: thisApp.InitInstance() @@ -65,7 +64,7 @@ def tearDownClass(cls): win32api.PostQuitMessage() win32gui.PumpWaitingMessages() cls.app.ExitInstance() - sys.stdout, sys.stderr = cls.std_oe_orig # py3.7 + sys.stdout, sys.stderr = cls.std_oe_orig def test_1_pydocs_and_finddlg(self): mf = win32ui.GetMainFrame() diff --git a/build_all.bat b/build_all.bat index 536aee00d..ec8cbbaa2 100644 --- a/build_all.bat +++ b/build_all.bat @@ -1,7 +1,3 @@ -py -3.7-32 setup.py -q build -@if errorlevel 1 goto failed -py -3.7 setup.py -q build -@if errorlevel 1 goto failed py -3.8-32 setup.py -q build @if errorlevel 1 goto failed py -3.8 setup.py -q build diff --git a/build_env.md b/build_env.md index d9c55ac10..4f616bf99 100644 --- a/build_env.md +++ b/build_env.md @@ -149,7 +149,6 @@ from the pywin32 directory. - Update `setuptools` and set the following environment variables to ensure it is used: ```shell - set SETUPTOOLS_USE_DISTUTILS=1 set DISTUTILS_USE_SDK=1 ``` diff --git a/com/win32com/test/pippo_server.py b/com/win32com/test/pippo_server.py index c5ae2df40..d8e964623 100644 --- a/com/win32com/test/pippo_server.py +++ b/com/win32com/test/pippo_server.py @@ -41,10 +41,7 @@ def Method3(self, in1): def BuildTypelib(): - if sys.version_info >= (3, 8): - from setuptools.modified import newer - else: - from distutils.dep_util import newer + from setuptools.modified import newer this_dir = os.path.dirname(__file__) idl = os.path.abspath(os.path.join(this_dir, "pippo.idl")) diff --git a/make_all.bat b/make_all.bat index c6d6a2b33..05855ddfb 100644 --- a/make_all.bat +++ b/make_all.bat @@ -13,11 +13,6 @@ rem Now the binaries. rem Check /build_env.md#build-environment to make sure you have all the required components installed rem (bdist_wininst needs --target-version to name the installers correctly!) -py -3.7-32 setup.py -q bdist_wininst --skip-build --target-version=3.7 -py -3.7-32 setup.py -q bdist_wheel --skip-build -py -3.7 setup.py -q bdist_wininst --skip-build --target-version=3.7 -py -3.7 setup.py -q bdist_wheel --skip-build - py -3.8-32 setup.py -q bdist_wininst --skip-build --target-version=3.8 py -3.8-32 setup.py -q bdist_wheel --skip-build py -3.8 setup.py -q bdist_wininst --skip-build --target-version=3.8 diff --git a/mypy.ini b/mypy.ini index bd1cd4316..e4676e0c7 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,7 +1,6 @@ [mypy] show_column_numbers = true ; Target the oldest supported version in editors and default CLI -; mypy 1.5 dropped support for Python 3.7 python_version = 3.8 strict = true diff --git a/pyrightconfig.json b/pyrightconfig.json index 1721da1a2..d96b3fc9d 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -1,7 +1,7 @@ { "typeCheckingMode": "basic", // Target the oldest supported version in editors and default CLI - "pythonVersion": "3.7", + "pythonVersion": "3.8", // Keep it simple for now by allowing both mypy and pyright to use `type: ignore` "enableTypeIgnoreComments": true, // Exclude from scanning when running pyright diff --git a/ruff.toml b/ruff.toml index 603043e8f..eab7fcce1 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,4 +1,4 @@ -target-version = "py37" # Target the oldest supported version +target-version = "py38" # Target the oldest supported version in editors and default CLI [lint] select = [ diff --git a/setup.py b/setup.py index ce0120e24..e25465fd7 100644 --- a/setup.py +++ b/setup.py @@ -40,6 +40,7 @@ from setuptools.command.build_ext import build_ext from setuptools.command.install import install from setuptools.command.install_lib import install_lib +from setuptools.modified import newer_group from tempfile import gettempdir from typing import Iterable @@ -47,11 +48,6 @@ from distutils._msvccompiler import MSVCCompiler from distutils.command.install_data import install_data -if sys.version_info >= (3, 8): - from setuptools.modified import newer_group -else: - from distutils.dep_util import newer_group - build_id_patch = build_id if not "." in build_id_patch: build_id_patch += ".0" @@ -868,12 +864,6 @@ def run(self): install.run(self) # Custom script we run at the end of installing - this is the same script # run by bdist_wininst - # This child process won't be able to install the system DLLs until our - # process has terminated (as distutils imports win32api!), so we must use - # some 'no wait' executor - spawn seems fine! We pass the PID of this - # process so the child will wait for us. - # XXX - hmm - a closer look at distutils shows it only uses win32api - # if _winreg fails - and this never should. Need to revisit this! # If self.root has a value, it means we are being "installed" into # some other directory than Python itself (eg, into a temp directory # for bdist_wininst to use) - in which case we must *not* run our @@ -885,7 +875,8 @@ def run(self): if not os.path.isfile(filename): raise RuntimeError(f"Can't find '{filename}'") print("Executing post install script...") - # What executable to use? This one I guess. + # As of setuptools>=74.0.0, we no longer need to + # be concerned about distutils calling win32api subprocess.Popen( [ sys.executable, @@ -905,8 +896,8 @@ def install(self): # This is crazy - in setuptools 61.1.0 (and probably some earlier versions), the # install_lib and build comments don't agree on where the .py files to install can # be found, so we end up with a warning logged: - # `warning: my_install_lib: 'build\lib.win-amd64-3.7' does not exist -- no Python modules to install` - # (because they are actually in `build\lib.win-amd64-cpython-37`!) + # `warning: my_install_lib: 'build\lib.win-amd64-3.8' does not exist -- no Python modules to install` + # (because they are actually in `build\lib.win-amd64-cpython-38`!) # It's not an error though, so we end up with .exe installers lacking our lib files! builder = self.get_finalized_command("build") if os.path.isdir(builder.build_platlib) and not os.path.isdir(self.build_dir): @@ -2151,7 +2142,6 @@ def convert_optional_data_files(files): "Intended Audience :: Developers", "License :: OSI Approved :: Python Software Foundation License", "Operating System :: Microsoft :: Windows", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", diff --git a/win32/Lib/pywin32_bootstrap.py b/win32/Lib/pywin32_bootstrap.py index fbc4f7be4..c9f59a56d 100644 --- a/win32/Lib/pywin32_bootstrap.py +++ b/win32/Lib/pywin32_bootstrap.py @@ -4,8 +4,6 @@ # In short, there's a directory installed by pywin32 named 'pywin32_system32' # with some important DLLs which need to be found by Python when some pywin32 # modules are imported. -# If Python has `os.add_dll_directory()`, we need to call it with this path. -# Otherwise, we add this path to PATH. try: @@ -19,11 +17,5 @@ # https://docs.python.org/3/reference/import.html#__path__ for path in pywin32_system32.__path__: if os.path.isdir(path): - if hasattr(os, "add_dll_directory"): - os.add_dll_directory(path) - # This is to ensure the pywin32 path is in the beginning to find the - # pywin32 DLLs first and prevent other PATH entries to shadow them - elif not os.environ["PATH"].startswith(path): - os.environ["PATH"] = os.environ["PATH"].replace(os.pathsep + path, "") - os.environ["PATH"] = path + os.pathsep + os.environ["PATH"] + os.add_dll_directory(path) break diff --git a/win32/src/_win32sysloader.cpp b/win32/src/_win32sysloader.cpp index 0a9e4dcac..9a9ef7c27 100644 --- a/win32/src/_win32sysloader.cpp +++ b/win32/src/_win32sysloader.cpp @@ -52,13 +52,7 @@ static PyObject *PyLoadModule(PyObject *self, PyObject *args) if (!modName) return NULL; - // 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 PyMem_Free(modName); if (hinst == NULL) { Py_INCREF(Py_None); From b922bf5bab4d098000e4a604ac46a60ae685b3f4 Mon Sep 17 00:00:00 2001 From: Thomas Geppert Date: Fri, 18 Oct 2024 14:52:55 +0200 Subject: [PATCH 07/13] Implement the creation of SAFEARRAY(VT_RECORD) from a sequence of COM Records (#2317) * Implemented the creation of SAFEARRAY(VT_RECORD) from a sequence of COM Records and the possibility to use instances of this type as COM Record fields. * Added a untitest for COM Records with SAFEARRAY(VT_RECORD) fields. * Added CHANGELOG entry. --- CHANGES.txt | 3 ++- com/TestSources/PyCOMTest/PyCOMImpl.cpp | 21 ++++++++++++++++ com/TestSources/PyCOMTest/PyCOMImpl.h | 1 + com/TestSources/PyCOMTest/PyCOMTest.idl | 6 +++++ com/win32com/src/PyRecord.cpp | 11 ++++++--- com/win32com/src/oleargs.cpp | 33 ++++++++++++++++++++++--- com/win32com/test/testPyComTest.py | 14 +++++++++++ 7 files changed, 80 insertions(+), 9 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index d8978afd5..82cf59213 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -15,7 +15,8 @@ Coming in build 309, as yet unreleased -------------------------------------- * Dropped support for Python 3.7 (#2207, @Avasam) -* Implement record pointers as [in, out] method parameters of a Dispatch Interface (#2310) +* Implement the creation of SAFEARRAY(VT_RECORD) from a sequence of COM Records (#2317, @geppi) +* Implement record pointers as [in, out] method parameters of a Dispatch Interface (#2304, #2310, @geppi) * Fix memory leak converting to PyObject from some SAFEARRAY elements (#2316) * Fix bug where makepy support was unnecessarily generated (#2354, #2353, @geppi) * Fail sooner on invalid `win32timezone.TimeZoneInfo` creation (#2338, @Avasam) diff --git a/com/TestSources/PyCOMTest/PyCOMImpl.cpp b/com/TestSources/PyCOMTest/PyCOMImpl.cpp index d58c00f99..6ba0af0c4 100644 --- a/com/TestSources/PyCOMTest/PyCOMImpl.cpp +++ b/com/TestSources/PyCOMTest/PyCOMImpl.cpp @@ -626,6 +626,27 @@ HRESULT CPyCOMTest::ModifyStruct(TestStruct1 *prec) return S_OK; } +HRESULT CPyCOMTest::VerifyArrayOfStructs(TestStruct2 *prec, VARIANT_BOOL *is_ok) +{ + long i; + TestStruct1 *pdata = NULL; + HRESULT hr; + + hr = SafeArrayAccessData(prec->array_of_records, reinterpret_cast(&pdata)); + if (FAILED(hr)) { + return E_FAIL; + } + *is_ok = VARIANT_TRUE; + for (i = 0; i < prec->rec_count; i++) + { + if (_wcsicmp(pdata[i].str_value, L"This is record number") != 0 || pdata[i].int_value != i + 1) { + *is_ok = VARIANT_FALSE; + break; + } + } + return S_OK; +} + HRESULT CPyCOMTest::DoubleString(BSTR in, BSTR *out) { *out = SysAllocStringLen(NULL, SysStringLen(in) * 2); diff --git a/com/TestSources/PyCOMTest/PyCOMImpl.h b/com/TestSources/PyCOMTest/PyCOMImpl.h index 50eb8dd0d..7b1f83c2b 100644 --- a/com/TestSources/PyCOMTest/PyCOMImpl.h +++ b/com/TestSources/PyCOMTest/PyCOMImpl.h @@ -120,6 +120,7 @@ class CPyCOMTest : public IDispatchImplowner); else if (V_VT(&vret) == (VT_BYREF | VT_ARRAY | VT_RECORD)) { SAFEARRAY *psa = *V_ARRAYREF(&vret); - int d = SafeArrayGetDim(psa); - if (sub_data == NULL) - return PyErr_Format(PyExc_RuntimeError, "Did not get a buffer for the array!"); if (SafeArrayGetDim(psa) != 1) return PyErr_Format(PyExc_TypeError, "Only support single dimensional arrays of records"); IRecordInfo *sub = NULL; @@ -526,7 +523,13 @@ PyObject *PyRecord::getattro(PyObject *self, PyObject *obname) ret_tuple = PyTuple_New(nelems); if (ret_tuple == NULL) goto array_end; - this_data = (BYTE *)sub_data; + // We're dealing here with a Record field that is a SAFEARRAY of Records. + // Therefore the VARIANT that was returned by the call to 'pyrec->pri->GetFieldNoCopy' + // does contain a reference to the SAFEARRAY of Records, i.e. the actual data of the + // Record elements of this SAFEARRAY is referenced by the 'pvData' field of the SAFEARRAY. + // In this particular case the implementation of 'GetFieldNoCopy' returns a NULL pointer + // in the last parameter, i.e. 'sub_data == NULL'. + this_data = (BYTE *)psa->pvData; for (i = 0; i < nelems; i++) { PyTuple_SET_ITEM(ret_tuple, i, new PyRecord(sub, this_data, pyrec->owner)); this_data += element_size; diff --git a/com/win32com/src/oleargs.cpp b/com/win32com/src/oleargs.cpp index a1338bab5..91fded5b1 100644 --- a/com/win32com/src/oleargs.cpp +++ b/com/win32com/src/oleargs.cpp @@ -4,6 +4,7 @@ #include "stdafx.h" #include "PythonCOM.h" +#include "PyRecord.h" extern PyObject *PyObject_FromRecordInfo(IRecordInfo *, void *, ULONG); extern PyObject *PyObject_FromSAFEARRAYRecordInfo(SAFEARRAY *psa); @@ -278,9 +279,23 @@ BOOL PyCom_VariantFromPyObject(PyObject *obj, VARIANT *var) // So make sure this check is after anything else which qualifies. else if (PySequence_Check(obj)) { V_ARRAY(var) = NULL; // not a valid, existing array. - if (!PyCom_SAFEARRAYFromPyObject(obj, &V_ARRAY(var))) - return FALSE; - V_VT(var) = VT_ARRAY | VT_VARIANT; + BOOL is_record_item = false; + if (PyObject_Length(obj) > 0) { + PyObject *obItemCheck = PySequence_GetItem(obj, 0); + is_record_item = PyRecord_Check(obItemCheck); + } + // If the sequence elements are PyRecord objects we do NOT package + // them as VARIANT elements but put them directly into the SAFEARRAY. + if (is_record_item) { + if (!PyCom_SAFEARRAYFromPyObject(obj, &V_ARRAY(var), VT_RECORD)) + return FALSE; + V_VT(var) = VT_ARRAY | VT_RECORD; + } + else { + if (!PyCom_SAFEARRAYFromPyObject(obj, &V_ARRAY(var))) + return FALSE; + V_VT(var) = VT_ARRAY | VT_VARIANT; + } } else if (PyRecord_Check(obj)) { if (!PyObject_AsVARIANTRecordInfo(obj, var)) @@ -554,6 +569,9 @@ static BOOL PyCom_SAFEARRAYFromPyObjectBuildDimension(PyObject *obj, SAFEARRAY * helper.m_reqdType = vt; ok = helper.MakeObjToVariant(item, &element); switch (vt) { + case VT_RECORD: + pvData = V_RECORD(&element); + break; case VT_DISPATCH: pvData = V_DISPATCH(&element); break; @@ -759,7 +777,14 @@ static BOOL PyCom_SAFEARRAYFromPyObjectEx(PyObject *obj, SAFEARRAY **ppSA, bool if (bAllocNewArray) { // OK - Finally can create the array... - *ppSA = SafeArrayCreate(vt, cDims, pBounds); + if (vt == VT_RECORD) { + // SAFEARRAYS of UDTs need a special treatment. + obItemCheck = PySequence_GetItem(obj, 0); + PyRecord *pyrec = (PyRecord *)obItemCheck; + *ppSA = SafeArrayCreateEx(vt, cDims, pBounds, pyrec->pri); + } + else + *ppSA = SafeArrayCreate(vt, cDims, pBounds); if (*ppSA == NULL) { delete[] pBounds; PyErr_SetString(PyExc_MemoryError, "CreatingSafeArray"); diff --git a/com/win32com/test/testPyComTest.py b/com/win32com/test/testPyComTest.py index dbe933669..50330e356 100644 --- a/com/win32com/test/testPyComTest.py +++ b/com/win32com/test/testPyComTest.py @@ -411,6 +411,7 @@ def TestDynamic(): def TestGenerated(): # Create an instance of the server. + from win32com.client import Record from win32com.client.gencache import EnsureDispatch o = EnsureDispatch("PyCOMTest.PyCOMTest") @@ -433,6 +434,19 @@ def TestGenerated(): coclass = GetClass("{B88DD310-BAE8-11D0-AE86-76F2C1000000}")() TestCounter(coclass, True) + # Test records with SAFEARRAY(VT_RECORD) fields. + progress("Testing records with SAFEARRAY(VT_RECORD) fields.") + l = [] + for i in range(3): + rec = Record("TestStruct1", o) + rec.str_value = "This is record number" + rec.int_value = i + 1 + l.append(rec) + test_rec = Record("TestStruct2", o) + test_rec.array_of_records = l + test_rec.rec_count = i + 1 + assert o.VerifyArrayOfStructs(test_rec) + # XXX - this is failing in dynamic tests, but should work fine. i1, i2 = o.GetMultipleInterfaces() # Yay - is now an instance returned! From b9256ff26bb64a85a11defe9c817bdde08ab0560 Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 10 Oct 2024 21:17:21 -0400 Subject: [PATCH 08/13] Update configs to use Ruff format instead of Black --- .editorconfig | 2 +- .github/workflows/main.yml | 13 +- .pre-commit-config.yaml | 6 +- adodbapi/adodbapi.py | 19 +- adodbapi/process_connect_string.py | 272 ++++++++++++++--------------- com/win32comext/adsi/demos/scp.py | 2 +- ruff.toml | 3 +- win32/Lib/win32gui_struct.py | 6 +- win32/Lib/win32pdhquery.py | 5 +- win32/test/test_win32file.py | 11 +- 10 files changed, 167 insertions(+), 172 deletions(-) diff --git a/.editorconfig b/.editorconfig index 51baf1204..6874683d6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,7 +9,7 @@ indent_size = 4 max_line_length = 120 # Same as .clang-format [*.py] -max_line_length = 88 # Same as Black +max_line_length = 88 # Same as Ruff's default [*.md] trim_trailing_whitespace = false diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2af0d70a0..db40b4254 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -110,23 +110,22 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - # This job only needs to target the oldest version supported by our checkers - # (black>=24.10.0 supports Python >=3.9) - python-version: "3.9" + # This job only needs to target the oldest supported version + python-version: "3.8" cache: pip cache-dependency-path: .github/workflows/main.yml - run: pip install clang-format pycln - run: pycln . --config=pycln.toml --check - uses: astral-sh/ruff-action@v1 with: - version: "0.4.5" - - uses: psf/black@stable + version: "0.4.9" + - uses: astral-sh/ruff-action@v1 with: - options: "--fast --check --diff --verbose" + version: "0.4.9" + args: "format --check" - run: | # Too many files to fit in a single command, also exclude vendored Scintilla and MAPIStubLibrary clang-format --Werror --dry-run $(git ls-files '*.cpp') clang-format --Werror --dry-run $(git ls-files '*.h' ':!:Pythonwin/Scintilla/' ':!:com/win32comext/mapi/src/MAPIStubLibrary/') - shell: powershell mypy: runs-on: windows-2019 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a89a958b7..566983fae 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,11 +29,7 @@ repos: hooks: - id: ruff # Run the linter. args: [--fix] - - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.4.2 - hooks: - - id: black - verbose: true + - id: ruff-format - repo: https://github.com/pre-commit/mirrors-clang-format rev: v18.1.5 hooks: diff --git a/adodbapi/adodbapi.py b/adodbapi/adodbapi.py index 4e85bc525..b63b829d8 100644 --- a/adodbapi/adodbapi.py +++ b/adodbapi/adodbapi.py @@ -395,9 +395,7 @@ def _rollback(self): # If attributes has adXactAbortRetaining it performs retaining aborts that is, # calling RollbackTrans automatically starts a new transaction. Not all providers support this. # If not, we will have to start a new transaction by this command: - if ( - not self.transaction_level - ): # if self.transaction_level == 0 or self.transaction_level is None: + if not self.transaction_level: self.transaction_level = self.connector.BeginTrans() except Exception as e: self._raiseConnectionError(api.ProgrammingError, e) @@ -634,9 +632,8 @@ def _makeDescriptionFromRS(self): if self.rs.EOF or self.rs.BOF: display_size = None else: - display_size = ( - f.ActualSize - ) # TODO: Is this the correct defintion according to the DB API 2 Spec ? + # TODO: Is this the correct defintion according to the DB API 2 Spec ? + display_size = f.ActualSize null_ok = bool(f.Attributes & adc.adFldMayBeNull) # v2.1 Cole desc.append( ( @@ -774,9 +771,8 @@ def get_returned_parameters(self): after the last recordset has been read. In that case, you must coll nextset() until it returns None, then call this method to get your returned information.""" - retLst = ( - [] - ) # store procedures may return altered parameters, including an added "return value" item + # store procedures may return altered parameters, including an added "return value" item + retLst = [] for p in tuple(self.cmd.Parameters): if verbose > 2: print( @@ -907,9 +903,8 @@ def _buildADOparameterList(self, parameters, sproc=False): ) i += 1 else: # -- build own parameter list - if ( - self._parameter_names - ): # we expect a dictionary of parameters, this is the list of expected names + # we expect a dictionary of parameters, this is the list of expected names + if self._parameter_names: for parm_name in self._parameter_names: elem = parameters[parm_name] adotype = api.pyTypeToADOType(elem) diff --git a/adodbapi/process_connect_string.py b/adodbapi/process_connect_string.py index d8b29f280..a134ad656 100644 --- a/adodbapi/process_connect_string.py +++ b/adodbapi/process_connect_string.py @@ -1,137 +1,135 @@ -""" a clumsy attempt at a macro language to let the programmer execute code on the server (ex: determine 64bit)""" - -from . import is64bit - - -def macro_call(macro_name, args, kwargs): - """allow the programmer to perform limited processing on the server by passing macro names and args - - :new_key - the key name the macro will create - :args[0] - macro name - :args[1:] - any arguments - :code - the value of the keyword item - :kwargs - the connection keyword dictionary. ??key has been removed - --> the value to put in for kwargs['name'] = value - """ - if isinstance(args, (str, str)): - args = [ - args - ] # the user forgot to pass a sequence, so make a string into args[0] - new_key = args[0] - try: - if macro_name == "is64bit": - if is64bit.Python(): # if on 64 bit Python - return new_key, args[1] # return first argument - else: - try: - return new_key, args[2] # else return second argument (if defined) - except IndexError: - return new_key, "" # else return blank - - elif ( - macro_name == "getuser" - ): # get the name of the user the server is logged in under - if not new_key in kwargs: - import getpass - - return new_key, getpass.getuser() - - elif macro_name == "getnode": # get the name of the computer running the server - import platform - - try: - return new_key, args[1] % platform.node() - except IndexError: - return new_key, platform.node() - - elif macro_name == "getenv": # expand the server's environment variable args[1] - try: - dflt = args[2] # if not found, default from args[2] - except IndexError: # or blank - dflt = "" - return new_key, os.environ.get(args[1], dflt) - - elif macro_name == "auto_security": - if ( - not "user" in kwargs or not kwargs["user"] - ): # missing, blank, or Null username - return new_key, "Integrated Security=SSPI" - return new_key, "User ID=%(user)s; Password=%(password)s" % kwargs - - elif ( - macro_name == "find_temp_test_path" - ): # helper function for testing ado operation -- undocumented - import os - import tempfile - - return new_key, os.path.join( - tempfile.gettempdir(), "adodbapi_test", args[1] - ) - - raise ValueError(f"Unknown connect string macro={macro_name}") - except: - raise ValueError(f"Error in macro processing {macro_name} {args!r}") - - -def process( - args, kwargs, expand_macros=False -): # --> connection string with keyword arguments processed. - """attempts to inject arguments into a connection string using Python "%" operator for strings - - co: adodbapi connection object - args: positional parameters from the .connect() call - kvargs: keyword arguments from the .connect() call - """ - try: - dsn = args[0] - except IndexError: - dsn = None - if isinstance( - dsn, dict - ): # as a convenience the first argument may be django settings - kwargs.update(dsn) - elif ( - dsn - ): # the connection string is passed to the connection as part of the keyword dictionary - kwargs["connection_string"] = dsn - try: - a1 = args[1] - except IndexError: - a1 = None - # historically, the second positional argument might be a timeout value - if isinstance(a1, int): - kwargs["timeout"] = a1 - # if the second positional argument is a string, then it is user - elif isinstance(a1, str): - kwargs["user"] = a1 - # if the second positional argument is a dictionary, use it as keyword arguments, too - elif isinstance(a1, dict): - kwargs.update(a1) - try: - kwargs["password"] = args[2] # the third positional argument is password - kwargs["host"] = args[3] # the fourth positional argument is host name - kwargs["database"] = args[4] # the fifth positional argument is database name - except IndexError: - pass - - # make sure connection string is defined somehow - if not "connection_string" in kwargs: - try: # perhaps 'dsn' was defined - kwargs["connection_string"] = kwargs["dsn"] - except KeyError: - try: # as a last effort, use the "host" keyword - kwargs["connection_string"] = kwargs["host"] - except KeyError: - raise TypeError("Must define 'connection_string' for ado connections") - if expand_macros: - for kwarg in list(kwargs.keys()): - if kwarg.startswith("macro_"): # If a key defines a macro - macro_name = kwarg[6:] # name without the "macro_" - macro_code = kwargs.pop( - kwarg - ) # we remove the macro_key and get the code to execute - new_key, rslt = macro_call( - macro_name, macro_code, kwargs - ) # run the code in the local context - kwargs[new_key] = rslt # put the result back in the keywords dict - return kwargs +""" a clumsy attempt at a macro language to let the programmer execute code on the server (ex: determine 64bit)""" + +from . import is64bit + + +def macro_call(macro_name, args, kwargs): + """allow the programmer to perform limited processing on the server by passing macro names and args + + :new_key - the key name the macro will create + :args[0] - macro name + :args[1:] - any arguments + :code - the value of the keyword item + :kwargs - the connection keyword dictionary. ??key has been removed + --> the value to put in for kwargs['name'] = value + """ + if isinstance(args, (str, str)): + args = [ + args + ] # the user forgot to pass a sequence, so make a string into args[0] + new_key = args[0] + try: + if macro_name == "is64bit": + if is64bit.Python(): # if on 64 bit Python + return new_key, args[1] # return first argument + else: + try: + return new_key, args[2] # else return second argument (if defined) + except IndexError: + return new_key, "" # else return blank + + elif ( + macro_name == "getuser" + ): # get the name of the user the server is logged in under + if not new_key in kwargs: + import getpass + + return new_key, getpass.getuser() + + elif macro_name == "getnode": # get the name of the computer running the server + import platform + + try: + return new_key, args[1] % platform.node() + except IndexError: + return new_key, platform.node() + + elif macro_name == "getenv": # expand the server's environment variable args[1] + try: + dflt = args[2] # if not found, default from args[2] + except IndexError: # or blank + dflt = "" + return new_key, os.environ.get(args[1], dflt) + + elif macro_name == "auto_security": + if ( + not "user" in kwargs or not kwargs["user"] + ): # missing, blank, or Null username + return new_key, "Integrated Security=SSPI" + return new_key, "User ID=%(user)s; Password=%(password)s" % kwargs + + elif ( + macro_name == "find_temp_test_path" + ): # helper function for testing ado operation -- undocumented + import os + import tempfile + + return new_key, os.path.join( + tempfile.gettempdir(), "adodbapi_test", args[1] + ) + + raise ValueError(f"Unknown connect string macro={macro_name}") + except: + raise ValueError(f"Error in macro processing {macro_name} {args!r}") + + +def process( + args, kwargs, expand_macros=False +): # --> connection string with keyword arguments processed. + """attempts to inject arguments into a connection string using Python "%" operator for strings + + co: adodbapi connection object + args: positional parameters from the .connect() call + kvargs: keyword arguments from the .connect() call + """ + try: + dsn = args[0] + except IndexError: + dsn = None + # as a convenience the first argument may be django settings + if isinstance(dsn, dict): + kwargs.update(dsn) + # the connection string is passed to the connection as part of the keyword dictionary + elif dsn: + kwargs["connection_string"] = dsn + try: + a1 = args[1] + except IndexError: + a1 = None + # historically, the second positional argument might be a timeout value + if isinstance(a1, int): + kwargs["timeout"] = a1 + # if the second positional argument is a string, then it is user + elif isinstance(a1, str): + kwargs["user"] = a1 + # if the second positional argument is a dictionary, use it as keyword arguments, too + elif isinstance(a1, dict): + kwargs.update(a1) + try: + kwargs["password"] = args[2] # the third positional argument is password + kwargs["host"] = args[3] # the fourth positional argument is host name + kwargs["database"] = args[4] # the fifth positional argument is database name + except IndexError: + pass + + # make sure connection string is defined somehow + if not "connection_string" in kwargs: + try: # perhaps 'dsn' was defined + kwargs["connection_string"] = kwargs["dsn"] + except KeyError: + try: # as a last effort, use the "host" keyword + kwargs["connection_string"] = kwargs["host"] + except KeyError: + raise TypeError("Must define 'connection_string' for ado connections") + if expand_macros: + for kwarg in list(kwargs.keys()): + if kwarg.startswith("macro_"): # If a key defines a macro + macro_name = kwarg[6:] # name without the "macro_" + macro_code = kwargs.pop( + kwarg + ) # we remove the macro_key and get the code to execute + new_key, rslt = macro_call( + macro_name, macro_code, kwargs + ) # run the code in the local context + kwargs[new_key] = rslt # put the result back in the keywords dict + return kwargs diff --git a/com/win32comext/adsi/demos/scp.py b/com/win32comext/adsi/demos/scp.py index b2ff016ec..dc5f831e8 100644 --- a/com/win32comext/adsi/demos/scp.py +++ b/com/win32comext/adsi/demos/scp.py @@ -419,7 +419,7 @@ def main(): "--test", action="store_true", help="Execute a mini-test suite, providing defaults for most options and args", - ), + ) parser.add_option( "", diff --git a/ruff.toml b/ruff.toml index eab7fcce1..6d75257db 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,4 +1,6 @@ target-version = "py38" # Target the oldest supported version in editors and default CLI +# This file is not UTF-8 +extend-exclude = ["Pythonwin/pywin/test/_dbgscript.py"] [lint] select = [ @@ -15,7 +17,6 @@ select = [ "FLY", # static-join-to-f-string "G", # flake8-logging-format # Note, we still want to allow multiline ISC - "ISC001", # single-line-implicit-string-concatenation "UP025", # Remove unicode literals from strings "UP030", # Use implicit references for positional format fields # TODO: Still lots of manual fixes needed diff --git a/win32/Lib/win32gui_struct.py b/win32/Lib/win32gui_struct.py index 41ef815fd..a4b7a4f4c 100644 --- a/win32/Lib/win32gui_struct.py +++ b/win32/Lib/win32gui_struct.py @@ -463,7 +463,7 @@ def EmptyTVITEM(hitem, mask=None, text_buf_size=512): else: text_addr = text_buf_size = 0 buf = struct.pack( - _tvitem_fmt, mask, hitem, 0, 0, text_addr, text_buf_size, 0, 0, 0, 0 # text + _tvitem_fmt, mask, hitem, 0, 0, text_addr, text_buf_size, 0, 0, 0, 0 ) return array.array("b", buf), extra @@ -758,7 +758,7 @@ def PackLVCOLUMN(fmt=None, cx=None, text=None, subItem=None, image=None, order=N text_addr, _ = text_buffer.buffer_info() text_len = len(text) buf = struct.pack( - _lvcolumn_fmt, mask, fmt, cx, text_addr, text_len, subItem, image, order # text + _lvcolumn_fmt, mask, fmt, cx, text_addr, text_len, subItem, image, order ) return array.array("b", buf), extra @@ -809,7 +809,7 @@ def EmptyLVCOLUMN(mask=None, text_buf_size=512): else: text_addr = text_buf_size = 0 buf = struct.pack( - _lvcolumn_fmt, mask, 0, 0, text_addr, text_buf_size, 0, 0, 0 # text + _lvcolumn_fmt, mask, 0, 0, text_addr, text_buf_size, 0, 0, 0 ) return array.array("b", buf), extra diff --git a/win32/Lib/win32pdhquery.py b/win32/Lib/win32pdhquery.py index 3f458e0a8..3e51b77b9 100644 --- a/win32/Lib/win32pdhquery.py +++ b/win32/Lib/win32pdhquery.py @@ -331,9 +331,8 @@ def collectdataslave(self, format=win32pdh.PDH_FMT_LONG): if not ok: temp.append(-1) # a better way to signal failure??? return temp - except ( - win32api.error - ): # will happen if, for instance, no counters are part of the query and we attempt to collect data for it. + # will happen if, for instance, no counters are part of the query and we attempt to collect data for it. + except win32api.error: return [-1] * len(self.counters) # pickle functions diff --git a/win32/test/test_win32file.py b/win32/test/test_win32file.py index 4763f9289..12ba8c31d 100644 --- a/win32/test/test_win32file.py +++ b/win32/test/test_win32file.py @@ -641,7 +641,10 @@ def _watcherThread(self, dn, dh, changes): try: print("waiting", dh) changes = win32file.ReadDirectoryChangesW( - dh, 8192, False, flags # sub-tree + dh, + 8192, + False, # sub-tree + flags, ) print("got", changes) except: @@ -655,7 +658,11 @@ def _watcherThreadOverlapped(self, dn, dh, changes): overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None) while 1: win32file.ReadDirectoryChangesW( - dh, buf, False, flags, overlapped # sub-tree + dh, + buf, + False, # sub-tree + flags, + overlapped, ) # Wait for our event, or for 5 seconds. rc = win32event.WaitForSingleObject(overlapped.hEvent, 5000) From b74bfdca97238735adbd1b20d7245cca7070900f Mon Sep 17 00:00:00 2001 From: Avasam Date: Mon, 14 Oct 2024 13:18:52 -0400 Subject: [PATCH 09/13] Run ruff format --- AutoDuck/Dump2HHC.py | 28 ++--- Pythonwin/pywin/dialogs/list.py | 19 ++-- Pythonwin/pywin/framework/app.py | 3 +- Pythonwin/pywin/framework/scriptutils.py | 4 +- Pythonwin/pywin/framework/stdin.py | 1 + Pythonwin/pywin/mfc/activex.py | 3 +- adodbapi/examples/db_print.py | 2 +- adodbapi/examples/db_table_names.py | 2 +- adodbapi/process_connect_string.py | 2 +- adodbapi/test/adodbapitest.py | 33 +++--- adodbapi/test/dbapi20.py | 14 +-- adodbapi/test/setuptestframework.py | 1 + com/win32com/client/combrowse.py | 27 +++-- com/win32com/client/dynamic.py | 7 +- com/win32com/client/genpy.py | 4 +- com/win32com/client/makepy.py | 7 +- com/win32com/client/selecttlb.py | 3 +- com/win32com/makegw/makegw.py | 102 ++++++++---------- com/win32com/makegw/makegwenum.py | 8 +- com/win32com/makegw/makegwparse.py | 14 +-- com/win32com/olectl.py | 2 +- com/win32com/server/connect.py | 2 +- com/win32com/server/exception.py | 14 +-- com/win32com/servers/interp.py | 14 +-- com/win32com/test/errorSemantics.py | 6 +- com/win32com/test/testExchange.py | 1 - com/win32com/test/testvb.py | 15 +-- com/win32com/util.py | 2 +- com/win32comext/axdebug/adb.py | 3 +- com/win32comext/axdebug/contexts.py | 4 +- com/win32comext/axdebug/documents.py | 3 +- com/win32comext/axdebug/dump.py | 4 +- com/win32comext/axscript/client/error.py | 4 +- com/win32comext/axscript/client/framework.py | 8 +- .../axscript/client/scriptdispatch.py | 6 +- isapi/samples/redirector_with_filter.py | 1 + isapi/simple.py | 1 + isapi/threaded_extension.py | 1 + setup.py | 68 +++--------- win32/Demos/security/GetTokenInformation.py | 4 +- win32/Demos/win32ts_logoff_disconnected.py | 2 +- win32/Lib/win32evtlogutil.py | 3 +- win32/Lib/win32gui_struct.py | 4 +- win32/Lib/win32rcparser.py | 1 + win32/scripts/regsetup.py | 7 +- win32/test/test_win32clipboard.py | 5 +- win32/test/test_win32cred.py | 1 - 47 files changed, 202 insertions(+), 268 deletions(-) diff --git a/AutoDuck/Dump2HHC.py b/AutoDuck/Dump2HHC.py index 343bdbca1..32c728c9d 100644 --- a/AutoDuck/Dump2HHC.py +++ b/AutoDuck/Dump2HHC.py @@ -293,9 +293,7 @@ def _genItemsFromDict(dict, cat, output, target, do_children=1): - """.format( - **locals() - ) + """.format(**locals()) ) if not do_children: continue @@ -339,9 +337,7 @@ def genTOC(cats, output, title, target):
    -""".format( - **locals() - ) +""".format(**locals()) ) for cat in cats: @@ -355,9 +351,7 @@ def genTOC(cats, output, title, target):
      - """.format( - **locals() - ) + """.format(**locals()) ) # Next write the overviews for this category output.write( @@ -368,9 +362,7 @@ def genTOC(cats, output, title, target):
        - """.format( - **locals() - ) + """.format(**locals()) ) _genItemsFromDict(cat.overviewTopics, cat, output, target) _genItemsFromDict(cat.extOverviewTopics, cat, output, target) @@ -387,9 +379,7 @@ def genTOC(cats, output, title, target):
          -""".format( - **locals() - ) +""".format(**locals()) ) _genItemsFromDict(cat.modules, cat, output, target) output.write( @@ -404,9 +394,7 @@ def genTOC(cats, output, title, target): -
            """.format( - **locals() - ) +
              """.format(**locals()) ) # Don't show 'children' for objects - params etc don't need their own child nodes! _genItemsFromDict(cat.objects, cat, output, target, do_children=0) @@ -423,9 +411,7 @@ def genTOC(cats, output, title, target):
                -""".format( - **locals() - ) +""".format(**locals()) ) _genItemsFromDict(cat.constants, cat, output, target) output.write( diff --git a/Pythonwin/pywin/dialogs/list.py b/Pythonwin/pywin/dialogs/list.py index 4e1877955..377a7cade 100644 --- a/Pythonwin/pywin/dialogs/list.py +++ b/Pythonwin/pywin/dialogs/list.py @@ -44,14 +44,17 @@ def OnListClick(self, id, code): return 1 def OnListItemChange(self, std, extra): - (hwndFrom, idFrom, code), ( - itemNotify, - sub, - newState, - oldState, - change, - point, - lparam, + ( + (hwndFrom, idFrom, code), + ( + itemNotify, + sub, + newState, + oldState, + change, + point, + lparam, + ), ) = (std, extra) oldSel = (oldState & commctrl.LVIS_SELECTED) != 0 newSel = (newState & commctrl.LVIS_SELECTED) != 0 diff --git a/Pythonwin/pywin/framework/app.py b/Pythonwin/pywin/framework/app.py index 4e0f09b94..9899e62fa 100644 --- a/Pythonwin/pywin/framework/app.py +++ b/Pythonwin/pywin/framework/app.py @@ -2,7 +2,8 @@ # The application is responsible for managing the main frame window. # # We also grab the FileOpen command, to invoke our Python editor -" The PythonWin application code. Manages most aspects of MDI, etc " +"The PythonWin application code. Manages most aspects of MDI, etc" + from __future__ import annotations import os diff --git a/Pythonwin/pywin/framework/scriptutils.py b/Pythonwin/pywin/framework/scriptutils.py index fe57113dd..32811190b 100644 --- a/Pythonwin/pywin/framework/scriptutils.py +++ b/Pythonwin/pywin/framework/scriptutils.py @@ -27,9 +27,7 @@ debugging_options = """No debugging Step-through in the debugger Run in the debugger -Post-Mortem of unhandled exceptions""".split( - "\n" -) +Post-Mortem of unhandled exceptions""".split("\n") byte_cr = b"\r" byte_lf = b"\n" diff --git a/Pythonwin/pywin/framework/stdin.py b/Pythonwin/pywin/framework/stdin.py index 1614fbe91..b7d71dc19 100644 --- a/Pythonwin/pywin/framework/stdin.py +++ b/Pythonwin/pywin/framework/stdin.py @@ -16,6 +16,7 @@ import sys sys.stdin = sys.stdin.real_file """ + import sys get_input_line = input diff --git a/Pythonwin/pywin/mfc/activex.py b/Pythonwin/pywin/mfc/activex.py index f3d9939a4..3d0207aca 100644 --- a/Pythonwin/pywin/mfc/activex.py +++ b/Pythonwin/pywin/mfc/activex.py @@ -1,5 +1,4 @@ -"""Support for ActiveX control hosting in Pythonwin. -""" +"""Support for ActiveX control hosting in Pythonwin.""" import win32ui import win32uiole diff --git a/adodbapi/examples/db_print.py b/adodbapi/examples/db_print.py index c0eb83ee4..fc86a8b3c 100644 --- a/adodbapi/examples/db_print.py +++ b/adodbapi/examples/db_print.py @@ -1,4 +1,4 @@ -""" db_print.py -- a simple demo for ADO database reads.""" +"""db_print.py -- a simple demo for ADO database reads.""" import sys diff --git a/adodbapi/examples/db_table_names.py b/adodbapi/examples/db_table_names.py index 907bdb85e..17ff58349 100644 --- a/adodbapi/examples/db_table_names.py +++ b/adodbapi/examples/db_table_names.py @@ -1,4 +1,4 @@ -""" db_table_names.py -- a simple demo for ADO database table listing.""" +"""db_table_names.py -- a simple demo for ADO database table listing.""" import sys diff --git a/adodbapi/process_connect_string.py b/adodbapi/process_connect_string.py index a134ad656..b1d4e4e93 100644 --- a/adodbapi/process_connect_string.py +++ b/adodbapi/process_connect_string.py @@ -1,4 +1,4 @@ -""" a clumsy attempt at a macro language to let the programmer execute code on the server (ex: determine 64bit)""" +"""a clumsy attempt at a macro language to let the programmer execute code on the server (ex: determine 64bit)""" from . import is64bit diff --git a/adodbapi/test/adodbapitest.py b/adodbapi/test/adodbapitest.py index 1b50e595f..dd8e9196d 100644 --- a/adodbapi/test/adodbapitest.py +++ b/adodbapi/test/adodbapitest.py @@ -1,4 +1,4 @@ -""" Unit tests version 2.6.1.0 for adodbapi""" +"""Unit tests version 2.6.1.0 for adodbapi""" """ adodbapi - A python DB API 2.0 interface to Microsoft ADO @@ -325,15 +325,16 @@ def helpTestDataType( rs = crsr.fetchone() if allowedReturnValues: allowedTypes = tuple([type(aRV) for aRV in allowedReturnValues]) - assert isinstance( - rs[0], allowedTypes - ), 'result type "%s" must be one of %s' % (type(rs[0]), allowedTypes) + assert isinstance(rs[0], allowedTypes), ( + 'result type "%s" must be one of %s' % (type(rs[0]), allowedTypes) + ) else: - assert isinstance( - rs[0], type(pyData) - ), 'result type "%s" must be instance of %s' % ( - type(rs[0]), - type(pyData), + assert isinstance(rs[0], type(pyData)), ( + 'result type "%s" must be instance of %s' + % ( + type(rs[0]), + type(pyData), + ) ) if compareAlmostEqual and DBAPIDataTypeString == "DATETIME": @@ -343,9 +344,9 @@ def helpTestDataType( elif compareAlmostEqual: s = float(pyData) v = float(rs[0]) - assert ( - abs(v - s) / s < 0.00001 - ), "Values not almost equal recvd=%s, expected=%f" % (rs[0], s) + assert abs(v - s) / s < 0.00001, ( + "Values not almost equal recvd=%s, expected=%f" % (rs[0], s) + ) else: if allowedReturnValues: ok = False @@ -487,7 +488,7 @@ def testDataTypeDate(self): ) def testDataTypeBinary(self): - binfld = b"\x07\x00\xE2\x40*" + binfld = b"\x07\x00\xe2\x40*" arv = [binfld, adodbapi.Binary(binfld), bytes(binfld)] if self.getEngine() == "PostgreSQL": self.helpTestDataType( @@ -692,9 +693,9 @@ def testRowIterator(self): rec = crsr.fetchone() # check that stepping through an emulated row works for j in range(len(inParam)): - assert ( - rec[j] == inParam[j] - ), 'returned value:"%s" != test value:"%s"' % (rec[j], inParam[j]) + assert rec[j] == inParam[j], ( + 'returned value:"%s" != test value:"%s"' % (rec[j], inParam[j]) + ) # check that we can get a complete tuple from a row assert ( tuple(rec) == inParam diff --git a/adodbapi/test/dbapi20.py b/adodbapi/test/dbapi20.py index 5639e4c3c..373b984d6 100644 --- a/adodbapi/test/dbapi20.py +++ b/adodbapi/test/dbapi20.py @@ -1,14 +1,14 @@ #!/usr/bin/env python -""" Python DB API 2.0 driver compliance unit test suite. +"""Python DB API 2.0 driver compliance unit test suite. - This software is Public Domain and may be used without restrictions. + This software is Public Domain and may be used without restrictions. - "Now we have booze and barflies entering the discussion, plus rumours of - DBAs on drugs... and I won't tell you what flashes through my mind each - time I read the subject line with 'Anal Compliance' in it. All around - this is turning out to be a thoroughly unwholesome unit test." +"Now we have booze and barflies entering the discussion, plus rumours of + DBAs on drugs... and I won't tell you what flashes through my mind each + time I read the subject line with 'Anal Compliance' in it. All around + this is turning out to be a thoroughly unwholesome unit test." - -- Ian Bicking + -- Ian Bicking """ __version__ = "$Revision: 1.15.0 $"[11:-2] diff --git a/adodbapi/test/setuptestframework.py b/adodbapi/test/setuptestframework.py index 65b99e990..e09549421 100644 --- a/adodbapi/test/setuptestframework.py +++ b/adodbapi/test/setuptestframework.py @@ -1,6 +1,7 @@ #!/usr/bin/python2 # Configure this in order to run the testcases. "setuptestframework.py v 2.6.0.8" + import os import shutil import tempfile diff --git a/com/win32com/client/combrowse.py b/com/win32com/client/combrowse.py index f83aa9c9b..4587a9aab 100644 --- a/com/win32com/client/combrowse.py +++ b/com/win32com/client/combrowse.py @@ -1,25 +1,25 @@ """A utility for browsing COM objects. - Usage: +Usage: - Command Prompt + Command Prompt - Use the command *"python.exe combrowse.py"*. This will display - display a fairly small, modal dialog. + Use the command *"python.exe combrowse.py"*. This will display + display a fairly small, modal dialog. - Pythonwin + Pythonwin - Use the "Run Script" menu item, and this will create the browser in an - MDI window. This window can be fully resized. + Use the "Run Script" menu item, and this will create the browser in an + MDI window. This window can be fully resized. - Details +Details - This module allows browsing of registered Type Libraries, COM categories, - and running COM objects. The display is similar to the Pythonwin object - browser, and displays the objects in a hierarchical window. + This module allows browsing of registered Type Libraries, COM categories, + and running COM objects. The display is similar to the Pythonwin object + browser, and displays the objects in a hierarchical window. - Note that this module requires the win32ui (ie, Pythonwin) distribution to - work. + Note that this module requires the win32ui (ie, Pythonwin) distribution to + work. """ @@ -581,7 +581,6 @@ def GetSubList(self): def main(modal=True, mdi=False): - root = HLIRoot("COM Browser") if mdi and "pywin.framework.app" in sys.modules: # do it in a MDI window diff --git a/com/win32com/client/dynamic.py b/com/win32com/client/dynamic.py index 7a269d514..3879aed2c 100644 --- a/com/win32com/client/dynamic.py +++ b/com/win32com/client/dynamic.py @@ -389,9 +389,10 @@ def _get_good_object_(self, ob, userName=None, ReturnCLSID=None): elif isinstance(ob, tuple): return tuple( map( - lambda o, s=self, oun=userName, rc=ReturnCLSID: s._get_good_single_object_( - o, oun, rc - ), + lambda o, + s=self, + oun=userName, + rc=ReturnCLSID: s._get_good_single_object_(o, oun, rc), ob, ) ) diff --git a/com/win32com/client/genpy.py b/com/win32com/client/genpy.py index b11d3b85b..c6d8b4319 100644 --- a/com/win32com/client/genpy.py +++ b/com/win32com/client/genpy.py @@ -969,9 +969,7 @@ def _Build_Interface(self, type_info_tuple): return oleItem, vtableItem def BuildOleItemsFromType(self): - assert ( - self.bBuildHidden - ), "This code doesn't look at the hidden flag - I thought everyone set it true!?!?!" + assert self.bBuildHidden, "This code doesn't look at the hidden flag - I thought everyone set it true!?!?!" oleItems = {} enumItems = {} recordItems = {} diff --git a/com/win32com/client/makepy.py b/com/win32com/client/makepy.py index 9f05ab5b5..4d60856ed 100644 --- a/com/win32com/client/makepy.py +++ b/com/win32com/client/makepy.py @@ -15,11 +15,12 @@ """Generate a .py file from an OLE TypeLibrary file. - This module is concerned only with the actual writing of - a .py file. It draws on the @build@ module, which builds - the knowledge of a COM interface. +This module is concerned only with the actual writing of +a .py file. It draws on the @build@ module, which builds +the knowledge of a COM interface. """ + usageHelp = """ \ Usage: diff --git a/com/win32com/client/selecttlb.py b/com/win32com/client/selecttlb.py index bf8627f5f..1d10c9ad8 100644 --- a/com/win32com/client/selecttlb.py +++ b/com/win32com/client/selecttlb.py @@ -1,5 +1,4 @@ -"""Utilities for selecting and enumerating the Type Libraries installed on the system -""" +"""Utilities for selecting and enumerating the Type Libraries installed on the system""" import pythoncom import win32api diff --git a/com/win32com/makegw/makegw.py b/com/win32com/makegw/makegw.py index 61e48ab37..2a12239c8 100644 --- a/com/win32com/makegw/makegw.py +++ b/com/win32com/makegw/makegw.py @@ -1,48 +1,48 @@ """Utility functions for writing out gateway C++ files - This module will generate a C++/Python binding for a specific COM - interface. - - Can be run from command line (passing required arguments) or the old way - (start Python, import this module, change to the directory where the generated code - should be written, and run the public function). - - This module is capable of generating both 'Interfaces' (ie, Python - client side support for the interface) and 'Gateways' (ie, Python - server side support for the interface). Many COM interfaces are useful - both as Client and Server. Other interfaces, however, really only make - sense to implement one side or the other. For example, it would be pointless - for Python to implement Server side for 'IRunningObjectTable', unless we were - implementing core COM for an operating system in Python (hey - now there's an idea!) - - Most COM interface code is totally boiler-plate - it consists of - converting arguments, dispatching the call to Python, and processing - any result values. - - This module automates the generation of such code. It has the ability to - parse a .H file generated by the MIDL tool (ie, almost all COM .h files) - and build almost totally complete C++ code. - - The module understands some of the well known data types, and how to - convert them. There are only a couple of places where hand-editing is - necessary, as detailed below: - - unsupported types -- If a type is not known, the generator will - pretty much ignore it, but write a comment to the generated code. You - may want to add custom support for this type. In some cases, C++ compile errors - will result. These are intentional - generating code to remove these errors would - imply a false sense of security that the generator has done the right thing. - - other return policies -- By default, Python never sees the return SCODE from - a COM function. The interface usually returns None if OK, else a COM exception - if "FAILED(scode)" is TRUE. You may need to change this if: - * EXCEPINFO is passed to the COM function. This is not detected and handled - * For some reason Python should always see the result SCODE, even if it - did fail or succeed. For example, some functions return a BOOLEAN result - in the SCODE, meaning Python should always see it. - * FAILED(scode) for the interface still has valid data to return (by default, - the code generated does not process the return values, and raise an exception - to Python/COM +This module will generate a C++/Python binding for a specific COM +interface. + +Can be run from command line (passing required arguments) or the old way +(start Python, import this module, change to the directory where the generated code +should be written, and run the public function). + +This module is capable of generating both 'Interfaces' (ie, Python +client side support for the interface) and 'Gateways' (ie, Python +server side support for the interface). Many COM interfaces are useful +both as Client and Server. Other interfaces, however, really only make +sense to implement one side or the other. For example, it would be pointless +for Python to implement Server side for 'IRunningObjectTable', unless we were +implementing core COM for an operating system in Python (hey - now there's an idea!) + +Most COM interface code is totally boiler-plate - it consists of +converting arguments, dispatching the call to Python, and processing +any result values. + +This module automates the generation of such code. It has the ability to +parse a .H file generated by the MIDL tool (ie, almost all COM .h files) +and build almost totally complete C++ code. + +The module understands some of the well known data types, and how to +convert them. There are only a couple of places where hand-editing is +necessary, as detailed below: + +unsupported types -- If a type is not known, the generator will +pretty much ignore it, but write a comment to the generated code. You +may want to add custom support for this type. In some cases, C++ compile errors +will result. These are intentional - generating code to remove these errors would +imply a false sense of security that the generator has done the right thing. + +other return policies -- By default, Python never sees the return SCODE from +a COM function. The interface usually returns None if OK, else a COM exception +if "FAILED(scode)" is TRUE. You may need to change this if: +* EXCEPINFO is passed to the COM function. This is not detected and handled +* For some reason Python should always see the result SCODE, even if it + did fail or succeed. For example, some functions return a BOOLEAN result + in the SCODE, meaning Python should always see it. +* FAILED(scode) for the interface still has valid data to return (by default, + the code generated does not process the return values, and raise an exception + to Python/COM """ import argparse @@ -202,9 +202,7 @@ def _write_ifc_cpp(f, interface): return ({name} *)Py{base}::GetI(self); }} -""".format( - **interface.__dict__ - ) +""".format(**interface.__dict__) ) ptr = re.sub(r"[a-z]", "", interface.name) @@ -219,9 +217,7 @@ def _write_ifc_cpp(f, interface): {interfacename} *p{ptr} = GetI(self); if ( p{ptr} == NULL ) return NULL; -""".format( - **strdict - ) +""".format(**strdict) ) argsParseTuple = argsCOM = formatChars = codePost = codePobjects = ( codeCobjects @@ -294,9 +290,7 @@ def _write_ifc_cpp(f, interface): {cleanup_gil} if ( FAILED(hr) ) return PyCom_BuildPyException(hr, p{ptr}, IID_{interfacename} ); -""".format( - **strdict - ) +""".format(**strdict) ) codePre = codePost = formatChars = codeVarsPass = codeDecl = "" for arg in method.args: @@ -348,9 +342,7 @@ def _write_ifc_cpp(f, interface): sizeof(Py{name}), Py{name}_methods, GET_PYCOM_CTOR(Py{name})); -""".format( - **locals() - ) +""".format(**locals()) ) diff --git a/com/win32com/makegw/makegwenum.py b/com/win32com/makegw/makegwenum.py index 3ba274a4e..d3698af75 100644 --- a/com/win32com/makegw/makegwenum.py +++ b/com/win32com/makegw/makegwenum.py @@ -191,9 +191,7 @@ def _write_enumifc_cpp(f, interface): sizeof(PyIEnum{enumtype}), PyIEnum{enumtype}_methods, GET_PYCOM_CTOR(PyIEnum{enumtype})); -""".format( - **locals() - ) +""".format(**locals()) ) @@ -329,7 +327,5 @@ def _write_enumgw_cpp(f, interface): return PyCom_CheckIEnumNextResult(hr, IID_IEnum{enumtype}); }} -""".format( - **locals() - ) +""".format(**locals()) ) diff --git a/com/win32com/makegw/makegwparse.py b/com/win32com/makegw/makegwparse.py index 89a574608..14e800db6 100644 --- a/com/win32com/makegw/makegwparse.py +++ b/com/win32com/makegw/makegwparse.py @@ -1,15 +1,15 @@ """Utilities for makegw - Parse a header file to build an interface - This module contains the core code for parsing a header file describing a - COM interface, and building it into an "Interface" structure. +This module contains the core code for parsing a header file describing a +COM interface, and building it into an "Interface" structure. - Each Interface has methods, and each method has arguments. +Each Interface has methods, and each method has arguments. - Each argument knows how to use Py_BuildValue or Py_ParseTuple to - exchange itself with Python. +Each argument knows how to use Py_BuildValue or Py_ParseTuple to +exchange itself with Python. - See the @win32com.makegw@ module for information in building a COM - interface +See the @win32com.makegw@ module for information in building a COM +interface """ from __future__ import annotations diff --git a/com/win32com/olectl.py b/com/win32com/olectl.py index f6be98bda..3ec5bf6ef 100644 --- a/com/win32com/olectl.py +++ b/com/win32com/olectl.py @@ -1,6 +1,6 @@ """Constants used by COM Controls - Hand created version of OLECTL.H constants. +Hand created version of OLECTL.H constants. """ import winerror diff --git a/com/win32com/server/connect.py b/com/win32com/server/connect.py index e99555a04..1fe7a0313 100644 --- a/com/win32com/server/connect.py +++ b/com/win32com/server/connect.py @@ -1,6 +1,6 @@ """Utilities for Server Side connections. - A collection of helpers for server side connection points. +A collection of helpers for server side connection points. """ import pythoncom diff --git a/com/win32com/server/exception.py b/com/win32com/server/exception.py index a6b3111fe..c31073e1c 100644 --- a/com/win32com/server/exception.py +++ b/com/win32com/server/exception.py @@ -1,15 +1,15 @@ """Exception Handling - Exceptions +Exceptions - To better support COM exceptions, the framework allows for an instance to be - raised. This instance may have a certain number of known attributes, which are - translated into COM exception details. + To better support COM exceptions, the framework allows for an instance to be + raised. This instance may have a certain number of known attributes, which are + translated into COM exception details. - This means, for example, that Python could raise a COM exception that includes details - on a Help file and location, and a description for the user. + This means, for example, that Python could raise a COM exception that includes details + on a Help file and location, and a description for the user. - This module provides a class which provides the necessary attributes. + This module provides a class which provides the necessary attributes. """ import sys diff --git a/com/win32com/servers/interp.py b/com/win32com/servers/interp.py index 37d83bd49..0676e2127 100644 --- a/com/win32com/servers/interp.py +++ b/com/win32com/servers/interp.py @@ -1,14 +1,14 @@ """Python.Interpreter COM Server - This module implements a very very simple COM server which - exposes the Python interpreter. +This module implements a very very simple COM server which +exposes the Python interpreter. - This is designed more as a demonstration than a full blown COM server. - General functionality and Error handling are both limited. +This is designed more as a demonstration than a full blown COM server. +General functionality and Error handling are both limited. - To use this object, ensure it is registered by running this module - from Python.exe. Then, from Visual Basic, use "CreateObject('Python.Interpreter')", - and call its methods! +To use this object, ensure it is registered by running this module +from Python.exe. Then, from Visual Basic, use "CreateObject('Python.Interpreter')", +and call its methods! """ import winerror diff --git a/com/win32com/test/errorSemantics.py b/com/win32com/test/errorSemantics.py index 843395c41..fe5045cc8 100644 --- a/com/win32com/test/errorSemantics.py +++ b/com/win32com/test/errorSemantics.py @@ -158,7 +158,7 @@ def test(): "The source in the exception tuple did not yield the correct string", str(com_exc), ) - assert exc[2] == "\U0001F600", ( + assert exc[2] == "\U0001f600", ( "The description in the exception tuple did not yield the correct string", str(com_exc), ) @@ -213,7 +213,7 @@ def testLogger(): except pythoncom.error as exc: # `excepinfo` is a tuple with elt 2 being the traceback we captured. message = exc.excepinfo[2] - assert message.endswith("Exception: \U0001F600\n") + assert message.endswith("Exception: \U0001f600\n") assert handler.num_emits == 1, handler.num_emits assert handler.last_record.startswith( "pythoncom error: Unexpected exception in gateway method 'Commit'" @@ -228,7 +228,7 @@ def testLogger(): except pythoncom.error as exc: # `excepinfo` is a tuple with elt 2 being the traceback we captured. message = exc.excepinfo[2] - assert message.endswith("Exception: \U0001F600\n") + assert message.endswith("Exception: \U0001f600\n") assert handler.num_emits == 1, handler.num_emits handler.reset() diff --git a/com/win32com/test/testExchange.py b/com/win32com/test/testExchange.py index 119c16a17..f54422bb6 100644 --- a/com/win32com/test/testExchange.py +++ b/com/win32com/test/testExchange.py @@ -91,7 +91,6 @@ def TestUser(session): def test(): - oldcwd = os.getcwd() try: session = gencache.EnsureDispatch("MAPI.Session") diff --git a/com/win32com/test/testvb.py b/com/win32com/test/testvb.py index ca5ab7689..65426559d 100644 --- a/com/win32com/test/testvb.py +++ b/com/win32com/test/testvb.py @@ -95,10 +95,13 @@ def TestVB(vbtest, bUseGenerated): vbtest.VariantProperty == "Hello from Python" ), "Could not set the variant string property correctly." vbtest.VariantProperty = (1.0, 2.0, 3.0) - assert vbtest.VariantProperty == ( - 1.0, - 2.0, - 3.0, + assert ( + vbtest.VariantProperty + == ( + 1.0, + 2.0, + 3.0, + ) ), f"Could not set the variant property to an array of floats correctly - '{vbtest.VariantProperty}'." TestArrays(vbtest, bUseGenerated) @@ -195,8 +198,8 @@ def _getcount(ob): check = [] for item in i: check.append(item) - assert check == list( - expected + assert ( + check == list(expected) ), f"Collection iterator {col_name} didn't have {expected!r} 2nd time around (had {check!r})" # but an iterator is not restartable check = [] diff --git a/com/win32com/util.py b/com/win32com/util.py index 0a5748f1e..2fa8931af 100644 --- a/com/win32com/util.py +++ b/com/win32com/util.py @@ -1,6 +1,6 @@ """General utility functions common to client and server. - This module contains a collection of general purpose utility functions. +This module contains a collection of general purpose utility functions. """ import pythoncom diff --git a/com/win32comext/axdebug/adb.py b/com/win32comext/axdebug/adb.py index 191041809..ee6b620c5 100644 --- a/com/win32comext/axdebug/adb.py +++ b/com/win32comext/axdebug/adb.py @@ -1,5 +1,4 @@ -"""The glue between the Python debugger interface and the Active Debugger interface -""" +"""The glue between the Python debugger interface and the Active Debugger interface""" import _thread import bdb diff --git a/com/win32comext/axdebug/contexts.py b/com/win32comext/axdebug/contexts.py index df6e97760..d732fbae1 100644 --- a/com/win32comext/axdebug/contexts.py +++ b/com/win32comext/axdebug/contexts.py @@ -1,6 +1,4 @@ -""" A module for managing the AXDebug I*Contexts - -""" +"""A module for managing the AXDebug I*Contexts""" from . import adb, axdebug, gateways diff --git a/com/win32comext/axdebug/documents.py b/com/win32comext/axdebug/documents.py index 560901fb4..eb45517e7 100644 --- a/com/win32comext/axdebug/documents.py +++ b/com/win32comext/axdebug/documents.py @@ -1,5 +1,4 @@ -""" Management of documents for AXDebugging. -""" +"""Management of documents for AXDebugging.""" import pythoncom import win32api diff --git a/com/win32comext/axdebug/dump.py b/com/win32comext/axdebug/dump.py index 61a1cfc7a..6500167c0 100644 --- a/com/win32comext/axdebug/dump.py +++ b/com/win32comext/axdebug/dump.py @@ -46,9 +46,7 @@ def dumpall(): e = Enumerator(dm.EnumApplications()) for app in e: print(f"Application: {app.GetName()}") - node = ( - app.GetRootNode() - ) # of type PyIDebugApplicationNode->PyIDebugDocumentProvider->PyIDebugDocumentInfo + node = app.GetRootNode() # of type PyIDebugApplicationNode->PyIDebugDocumentProvider->PyIDebugDocumentInfo DumpDebugApplicationNode(node) diff --git a/com/win32comext/axscript/client/error.py b/com/win32comext/axscript/client/error.py index 5aadbf9bc..f02e66603 100644 --- a/com/win32comext/axscript/client/error.py +++ b/com/win32comext/axscript/client/error.py @@ -1,7 +1,7 @@ """Exception and error handling. - This contains the core exceptions that the implementations should raise - as well as the IActiveScriptError interface code. +This contains the core exceptions that the implementations should raise +as well as the IActiveScriptError interface code. """ from __future__ import annotations diff --git a/com/win32comext/axscript/client/framework.py b/com/win32comext/axscript/client/framework.py index b9f0fd605..c4a04329f 100644 --- a/com/win32comext/axscript/client/framework.py +++ b/com/win32comext/axscript/client/framework.py @@ -1,10 +1,10 @@ """AXScript Client Framework - This module provides a core framework for an ActiveX Scripting client. - Derived classes actually implement the AX Client itself, including the - scoping rules, etc. +This module provides a core framework for an ActiveX Scripting client. +Derived classes actually implement the AX Client itself, including the +scoping rules, etc. - There are classes defined for the engine itself, and for ScriptItems +There are classes defined for the engine itself, and for ScriptItems """ from __future__ import annotations diff --git a/com/win32comext/axscript/client/scriptdispatch.py b/com/win32comext/axscript/client/scriptdispatch.py index ca696fe84..6bd29adcb 100644 --- a/com/win32comext/axscript/client/scriptdispatch.py +++ b/com/win32comext/axscript/client/scriptdispatch.py @@ -1,8 +1,8 @@ """dynamic dispatch objects for AX Script. - This is an IDispatch object that a scripting host may use to - query and invoke methods on the main script. Not may hosts use - this yet, so it is not well tested! +This is an IDispatch object that a scripting host may use to +query and invoke methods on the main script. Not may hosts use +this yet, so it is not well tested! """ from __future__ import annotations diff --git a/isapi/samples/redirector_with_filter.py b/isapi/samples/redirector_with_filter.py index 6d9914c04..393e89d05 100644 --- a/isapi/samples/redirector_with_filter.py +++ b/isapi/samples/redirector_with_filter.py @@ -84,6 +84,7 @@ def Dispatch(self, ecb): # The ISAPI filter. class Filter(SimpleFilter): "Sample Python Redirector" + filter_flags = isapicon.SF_NOTIFY_PREPROC_HEADERS | isapicon.SF_NOTIFY_ORDER_DEFAULT def HttpFilterProc(self, fc): diff --git a/isapi/simple.py b/isapi/simple.py index d5fcb04d7..177e8935c 100644 --- a/isapi/simple.py +++ b/isapi/simple.py @@ -40,6 +40,7 @@ def TerminateExtension(self, status): class SimpleFilter: "Base class for a a simple ISAPI filter" + filter_flags: int | None = None def __init__(self): diff --git a/isapi/threaded_extension.py b/isapi/threaded_extension.py index 044b90987..b6a161a23 100644 --- a/isapi/threaded_extension.py +++ b/isapi/threaded_extension.py @@ -60,6 +60,7 @@ def call_handler(self, cblock): # fully asynch extension. class ThreadPoolExtension(isapi.simple.SimpleExtension): "Base class for an ISAPI extension based around a thread-pool" + max_workers = 20 worker_shutdown_wait = 15000 # 15 seconds for workers to quit... diff --git a/setup.py b/setup.py index e25465fd7..e72edf0ad 100644 --- a/setup.py +++ b/setup.py @@ -1341,9 +1341,7 @@ def finalize_options(self): {win32com}/extensions/PyICancelMethodCalls.cpp {win32com}/extensions/PyIContext.cpp {win32com}/extensions/PyIEnumContextProps.cpp {win32com}/extensions/PyIClientSecurity.cpp {win32com}/extensions/PyIServerSecurity.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), depends=( """ @@ -1370,9 +1368,7 @@ def finalize_options(self): {win32com}/include\\PyICancelMethodCalls.h {win32com}/include\\PyIContext.h {win32com}/include\\PyIEnumContextProps.h {win32com}/include\\PyIClientSecurity.h {win32com}/include\\PyIServerSecurity.h - """.format( - **dirs - ) + """.format(**dirs) ).split(), libraries="oleaut32 ole32 user32 urlmon", export_symbol_file="com/win32com/src/PythonCOM.def", @@ -1400,9 +1396,7 @@ def finalize_options(self): {adsi}/adsilib.i {adsi}/PyADSIUtil.cpp {adsi}/PyDSOPObjects.cpp {adsi}/PyIADs.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), ), WinExt_win32com( @@ -1420,9 +1414,7 @@ def finalize_options(self): {axcontrol}/PyIOleClientSite.cpp {axcontrol}/PyIOleInPlaceSite.cpp {axcontrol}/PyIOleObject.cpp {axcontrol}/PyIViewObject2.cpp {axcontrol}/PyIOleCommandTarget.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), ), WinExt_win32com( @@ -1437,9 +1429,7 @@ def finalize_options(self): {axscript}/PyIActiveScriptParse.cpp {axscript}/PyIActiveScriptParseProcedure.cpp {axscript}/PyIActiveScriptSite.cpp {axscript}/PyIMultiInfos.cpp {axscript}/PyIObjectSafety.cpp {axscript}/stdafx.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), depends=( """ @@ -1448,9 +1438,7 @@ def finalize_options(self): {axscript}/PyIActiveScriptError.h {axscript}/PyIObjectSafety.h {axscript}/PyIProvideMultipleClassInfo.h {axscript}/stdafx.h - """.format( - **dirs - ) + """.format(**dirs) ).split(), extra_compile_args=["-DPY_BUILD_AXSCRIPT"], implib_name="axscript", @@ -1506,9 +1494,7 @@ def finalize_options(self): {axdebug}/PyIRemoteDebugApplicationEvents.cpp {axdebug}/PyIRemoteDebugApplicationThread.cpp {axdebug}/stdafx.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), ), WinExt_win32com( @@ -1521,9 +1507,7 @@ def finalize_options(self): {internet}/PyIInternetPriority.cpp {internet}/PyIInternetProtocol.cpp {internet}/PyIInternetProtocolInfo.cpp {internet}/PyIInternetProtocolRoot.cpp {internet}/PyIInternetProtocolSink.cpp {internet}/PyIInternetSecurityManager.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), depends=["{internet}/internet_pch.h".format(**dirs)], ), @@ -1559,9 +1543,7 @@ def finalize_options(self): {mapi}/mapiguids.cpp {mapi}/MAPIStubLibrary/library/mapiStubLibrary.cpp {mapi}/MAPIStubLibrary/library/stubutils.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), ), WinExt_win32com_mapi( @@ -1577,9 +1559,7 @@ def finalize_options(self): {mapi}/exchangeguids.cpp {mapi}/MAPIStubLibrary/library/mapiStubLibrary.cpp {mapi}/MAPIStubLibrary/library/stubutils.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), ), WinExt_win32com( @@ -1661,9 +1641,7 @@ def finalize_options(self): {shell}/PyIUniformResourceLocator.cpp {shell}/shell.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), ), WinExt_win32com( @@ -1691,9 +1669,7 @@ def finalize_options(self): {propsys}/PyIObjectWithPropertyKey.cpp {propsys}/PyIPropertyChange.cpp {propsys}/PyIPropertyChangeArray.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), implib_name="pypropsys", ), @@ -1709,9 +1685,7 @@ def finalize_options(self): {taskscheduler}/PyITaskScheduler.cpp {taskscheduler}/PyITaskTrigger.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), ), WinExt_win32com( @@ -1732,9 +1706,7 @@ def finalize_options(self): {bits}/PyIEnumBackgroundCopyJobs.cpp {bits}/PyIEnumBackgroundCopyFiles.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), ), WinExt_win32com( @@ -1755,18 +1727,14 @@ def finalize_options(self): {directsound}/PyIDirectSoundBuffer.cpp {directsound}/PyIDirectSoundCapture.cpp {directsound}/PyIDirectSoundCaptureBuffer.cpp {directsound}/PyIDirectSoundNotify.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), depends=( """ {directsound}/directsound_pch.h {directsound}/PyIDirectSound.h {directsound}/PyIDirectSoundBuffer.h {directsound}/PyIDirectSoundCapture.h {directsound}/PyIDirectSoundCaptureBuffer.h {directsound}/PyIDirectSoundNotify.h - """.format( - **dirs - ) + """.format(**dirs) ).split(), optional_headers=["dsound.h"], libraries="user32 dsound dxguid", @@ -1778,9 +1746,7 @@ def finalize_options(self): """ {authorization}/authorization.cpp {authorization}/PyGSecurityInformation.cpp - """.format( - **dirs - ) + """.format(**dirs) ).split(), ), ] diff --git a/win32/Demos/security/GetTokenInformation.py b/win32/Demos/security/GetTokenInformation.py index 192c549e1..745e0e78e 100644 --- a/win32/Demos/security/GetTokenInformation.py +++ b/win32/Demos/security/GetTokenInformation.py @@ -1,5 +1,5 @@ -""" Lists various types of information about current user's access token, - including UAC status on Vista +"""Lists various types of information about current user's access token, +including UAC status on Vista """ import pywintypes diff --git a/win32/Demos/win32ts_logoff_disconnected.py b/win32/Demos/win32ts_logoff_disconnected.py index 2a8bcc940..3b7f882e0 100644 --- a/win32/Demos/win32ts_logoff_disconnected.py +++ b/win32/Demos/win32ts_logoff_disconnected.py @@ -1,4 +1,4 @@ -""" Finds any disconnected terminal service sessions and logs them off""" +"""Finds any disconnected terminal service sessions and logs them off""" import pywintypes import win32ts diff --git a/win32/Lib/win32evtlogutil.py b/win32/Lib/win32evtlogutil.py index 05cabe2b8..58d3326ef 100644 --- a/win32/Lib/win32evtlogutil.py +++ b/win32/Lib/win32evtlogutil.py @@ -1,5 +1,4 @@ -"""Event Log Utilities - helper for win32evtlog.pyd -""" +"""Event Log Utilities - helper for win32evtlog.pyd""" import win32api import win32con diff --git a/win32/Lib/win32gui_struct.py b/win32/Lib/win32gui_struct.py index a4b7a4f4c..5651c7bc8 100644 --- a/win32/Lib/win32gui_struct.py +++ b/win32/Lib/win32gui_struct.py @@ -808,9 +808,7 @@ def EmptyLVCOLUMN(mask=None, text_buf_size=512): text_addr, _ = text_buffer.buffer_info() else: text_addr = text_buf_size = 0 - buf = struct.pack( - _lvcolumn_fmt, mask, 0, 0, text_addr, text_buf_size, 0, 0, 0 - ) + buf = struct.pack(_lvcolumn_fmt, mask, 0, 0, text_addr, text_buf_size, 0, 0, 0) return array.array("b", buf), extra diff --git a/win32/Lib/win32rcparser.py b/win32/Lib/win32rcparser.py index b87bd96fe..183f075b1 100644 --- a/win32/Lib/win32rcparser.py +++ b/win32/Lib/win32rcparser.py @@ -7,6 +7,7 @@ This is a parser for Windows .rc files, which are text files which define dialogs and other Windows UI resources. """ + from __future__ import annotations import os diff --git a/win32/scripts/regsetup.py b/win32/scripts/regsetup.py index da2f870e1..fb33e11dd 100644 --- a/win32/scripts/regsetup.py +++ b/win32/scripts/regsetup.py @@ -447,8 +447,7 @@ def RegisterShellInfo(searchPaths): # FindRegisterApp("win32", ["win32con.pyc", "win32api%s.pyd" % suffix], searchPaths) -usage = ( - """\ +usage = """\ regsetup.py - Setup/maintain the registry for Python apps. Run without options, (but possibly search paths) to repair a totally broken @@ -475,9 +474,7 @@ def RegisterShellInfo(searchPaths): --description -- Print a description of the usage. --examples -- Print examples of usage. -""" - % sys.argv[0] -) +""" % sys.argv[0] description = """\ If no options are processed, the program attempts to validate and set diff --git a/win32/test/test_win32clipboard.py b/win32/test/test_win32clipboard.py index f5d5c28d1..ccfc32e53 100644 --- a/win32/test/test_win32clipboard.py +++ b/win32/test/test_win32clipboard.py @@ -5,7 +5,6 @@ class TestGetSetClipboardData(unittest.TestCase): - def copyData(self, data, format_): win32clipboard.OpenClipboard() ret = None @@ -30,13 +29,13 @@ def test_data(self): test_data = { "Dummy str": win32clipboard.CF_UNICODETEXT, b"Dummy bytes text": win32clipboard.CF_TEXT, - b"Dummy\x00\xFF bytes": win32clipboard.CF_DIB, + b"Dummy\x00\xff bytes": win32clipboard.CF_DIB, } for data, fmt in test_data.items(): self.assertEqual(data, self.copyData(data, fmt)) test_data = { "Dummy str": (win32clipboard.CF_TEXT, win32clipboard.CF_DIB), - b"Dummy\x00\xFF bytes": (win32clipboard.CF_UNICODETEXT,), + b"Dummy\x00\xff bytes": (win32clipboard.CF_UNICODETEXT,), } for data, formats in test_data.items(): for fmt in formats: diff --git a/win32/test/test_win32cred.py b/win32/test/test_win32cred.py index c44fe18b8..4b9fe08d7 100644 --- a/win32/test/test_win32cred.py +++ b/win32/test/test_win32cred.py @@ -5,7 +5,6 @@ class TestCredFunctions(unittest.TestCase): - def setUp(self): self.flags = 0 self.dummy_cred = { From 5a46a21be0fdf9472f1904c54bd301745cfc482d Mon Sep 17 00:00:00 2001 From: Avasam Date: Mon, 14 Oct 2024 13:21:36 -0400 Subject: [PATCH 10/13] Update git-blame-ignore-revs --- .git-blame-ignore-revs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 4816d046a..9309054aa 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -13,3 +13,6 @@ # 2024-05-28 formatted c++ source with clang-format 637448f8252ab142eedd539ddf9b08259b73eecc + +# 2024-10-14 formatted Python source with Ruff format +2b5191d8fc6f1d1fbde01481b49278c1957ef8f1 From 50cfd5958c63a9f9ac5ddd36447fa46219753a3f Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 24 Oct 2024 10:21:31 -0400 Subject: [PATCH 11/13] Fix various typos (#2300) --- AutoDuck/makedfromi.py | 2 +- AutoDuck/py2d.py | 2 +- CHANGES.txt | 4 ++-- Pythonwin/contents.d | 2 +- Pythonwin/pythondoc.h | 14 +++++++------- Pythonwin/pywin/debugger/fail.py | 2 +- Pythonwin/pywin/framework/editor/editor.py | 2 +- Pythonwin/pywin/framework/editor/vss.py | 2 +- Pythonwin/pywin/framework/intpyapp.py | 2 +- Pythonwin/pywin/framework/startup.py | 2 +- Pythonwin/pywin/scintilla/keycodes.py | 2 +- Pythonwin/pywin/scintilla/view.py | 2 +- Pythonwin/win32bitmap.cpp | 2 +- Pythonwin/win32dlg.cpp | 2 +- Pythonwin/win32virt.cpp | 2 +- adodbapi/adodbapi.py | 4 ++-- adodbapi/readme.txt | 2 +- adodbapi/test/adodbapitest.py | 4 ++-- adodbapi/test/dbapi20.py | 4 ++-- adodbapi/test/setuptestframework.py | 2 +- build_env.md | 2 +- com/changes.txt | 2 +- com/win32com/changes.txt | 2 +- com/win32com/server/policy.py | 2 +- com/win32com/server/register.py | 2 +- com/win32com/src/dllmain.cpp | 2 +- com/win32com/src/univgw_dataconv.cpp | 2 +- com/win32comext/axdebug/documents.py | 2 +- com/win32comext/axscript/client/pyscript.py | 2 +- .../axscript/demos/client/ie/demo_intro.htm | 2 +- com/win32comext/bits/src/bits.cpp | 8 ++++---- com/win32comext/shell/demos/servers/folder_view.py | 2 +- com/win32comext/shell/src/PyIShellItem2.cpp | 2 +- ruff.toml | 2 +- win32/Demos/security/set_file_audit.py | 2 +- win32/Lib/pywin32_testutil.py | 4 ++-- win32/Lib/win32cryptcon.py | 2 +- win32/Lib/win32pdhquery.py | 4 ++-- win32/Lib/win32timezone.py | 2 +- win32/scripts/regsetup.py | 4 ++-- win32/src/PySECURITY_DESCRIPTOR.cpp | 4 ++-- win32/src/PythonService.cpp | 2 +- win32/src/win32file.i | 12 ++++++------ 43 files changed, 65 insertions(+), 65 deletions(-) diff --git a/AutoDuck/makedfromi.py b/AutoDuck/makedfromi.py index 4fd2f44ac..53edf0111 100644 --- a/AutoDuck/makedfromi.py +++ b/AutoDuck/makedfromi.py @@ -20,7 +20,7 @@ def GetComments(line, lineNo, lines): if len(data) != 2: break if data[0].strip(): - break # Not a continutation! + break # Not a continuation! if data[1].strip().startswith("@"): # new command break diff --git a/AutoDuck/py2d.py b/AutoDuck/py2d.py index 647fb7121..2b2d779b8 100644 --- a/AutoDuck/py2d.py +++ b/AutoDuck/py2d.py @@ -75,7 +75,7 @@ def format_desc(desc): # 'first_para_of_docstring' # '@comm next para of docstring' # '@comm next para of docstring' ... etc - # BUT - also handling enbedded doctests, where we write + # BUT - also handling embedded doctests, where we write # '@iex >>> etc.' if not desc: return "" diff --git a/CHANGES.txt b/CHANGES.txt index 82cf59213..d02c6fcae 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -68,7 +68,7 @@ as the .chm file, certain MAPI libraries etc, and .exe installers. * `win32com.client.build.error` * `win32com.client.genpy.error` * Add EnumDesktopWindows (#2219, @CristiFati) -* Marked `exc_type` and `exc_traceback` in `win32comext.axscript.client.error.AXScriptException.__init__` as deprecated. (#2236 , @Avasam) +* Marked `exc_type` and `exc_traceback` in `win32comext.axscript.client.error.AXScriptException.__init__` as deprecated. (#2236, @Avasam) They are now unused and all information is taken from the `exc_value` parameter. * Fixed non-overriden `pywin.scintilla.formatter.Formatter.ColorizeString` raising `TypeError` instead of `RuntimeError` due to too many parameters (#2216, @Avasam) * Fixed broken since Python 3 tokenization in `win32comext.axdebug.codecontainer.pySourceCodeContainer.GetSyntaxColorAttributes` (#2216, @Avasam) @@ -189,7 +189,7 @@ as the .chm file, certain MAPI libraries etc, and .exe installers. * Use byte-string (`b""`) for constant bytes values instead of superfluous `.encode` calls (#2046, @Avasam) * Cleaned up unused imports (#1986, #2051, #1990, #2124, #2126, @Avasam) * Removed duplicated declarations, constants and definitions (#2050, #1950, #1990, @Avasam) -* Small generalized optimization by using augmented assignements (in-place operators) where possible (#2274, @Avasam) +* Small generalized optimization by using augmented assignments (in-place operators) where possible (#2274, @Avasam) * General speed and size improvements due to all the removed code. (#2046, #1986, #2050, #1950, #2085, #2087, #2051, #1990, #2106, #2127, #2124, #2126, #2177, #2218, #2202, #2205, #2217) ### adodbapi diff --git a/Pythonwin/contents.d b/Pythonwin/contents.d index 86101de59..581380465 100644 --- a/Pythonwin/contents.d +++ b/Pythonwin/contents.d @@ -119,7 +119,7 @@ it uses overrides the default. Thus, regardless of your preferences, if the fir indent in the file is a tab, Pythonwin uses tabs for the entire file (and similarly, uses spaces if the first block is indented with spaces) -Things can appear to get wierd when editing a file with mixed tabs and spaces. +Things can appear to get weird when editing a file with mixed tabs and spaces. Although mixed tabs and spaces in the same indent is evil, there are a number of source files that have certain classes/functions indented with spaces, and others that use tabs. The editor will not correctly adjust to the current block - whatever diff --git a/Pythonwin/pythondoc.h b/Pythonwin/pythondoc.h index d0c2811d2..fb5f4b13c 100644 --- a/Pythonwin/pythondoc.h +++ b/Pythonwin/pythondoc.h @@ -112,7 +112,7 @@ BOOL CPythonDocTemp

                ::OnSaveDocument(const TCHAR *fileName) // @pyparm string|fileName||The name of the file being saved. // @xref // @comm If a handler is defined for this function, the base (MFC) function will not - // be called. If necessary, the handler must call this function explicitely. + // be called. If necessary, the handler must call this function explicitly. CVirtualHelper helper("OnSaveDocument", this); if (helper.call(fileName)) { int ret; @@ -131,7 +131,7 @@ BOOL CPythonDocTemp

                ::OnOpenDocument(const TCHAR *fileName) // @pyvirtual int|PyCDocument|OnOpenDocument|Called by the MFC architecture. // @xref // @comm If a handler is defined for this function, the base (MFC) function will not - // be called. If necessary, the handler must call this function explicitely. + // be called. If necessary, the handler must call this function explicitly. CVirtualHelper helper("OnOpenDocument", this); if (!helper.HaveHandler()) { PyErr_SetString(ui_module_error, "PyCDocument::OnOpenDocument handler does not exist."); @@ -155,7 +155,7 @@ BOOL CPythonDocTemp

                ::OnNewDocument() // @pyvirtual int|PyCDocument|OnNewDocument|Called by the MFC architecture. // @xref // @comm If a handler is defined for this function, the base (MFC) function will not - // be called. If necessary, the handler must call this function explicitely. + // be called. If necessary, the handler must call this function explicitly. CVirtualHelper helper("OnNewDocument", this); if (!helper.HaveHandler()) { helper.release_full(); @@ -182,7 +182,7 @@ void CPythonDocTemp

                ::OnCloseDocument() // @pyvirtual |PyCDocument|OnCloseDocument|Called by the MFC architecture. // @xref // @comm If a handler is defined for this function, the base (MFC) function will not - // be called. If necessary, the handler must call this function explicitely. + // be called. If necessary, the handler must call this function explicitly. CVirtualHelper helper("OnCloseDocument", this); if (helper.HaveHandler()) { helper.call(); @@ -215,7 +215,7 @@ void CPythonDocTemp

                ::DeleteContents() P::DeleteContents(); } // @comm If a handler is defined for this function, the base (MFC) function will not - // be called. If necessary, the handler must call this function explicitely. + // be called. If necessary, the handler must call this function explicitly. } template BOOL CPythonDocTemp

                ::SaveModified() @@ -223,7 +223,7 @@ BOOL CPythonDocTemp

                ::SaveModified() // @pyvirtual int|PyCDocument|SaveModified|Called by the MFC architecture when a document is closed. // @xref // @comm If a handler is defined for this function, the base (MFC) function will not - // be called. If necessary, the handler must call this function explicitely. + // be called. If necessary, the handler must call this function explicitly. CVirtualHelper helper("SaveModified", this); if (!helper.HaveHandler()) { helper.release_full(); @@ -244,7 +244,7 @@ void CPythonDocTemp

                ::OnChangedViewList() // @pyvirtual int|PyCDocument|OnChangedViewList|Called by the MFC architecture when after a view is attached. // @xref // @comm If a handler is defined for this function, the base (MFC) function will not - // be called. If necessary, the handler must call this function explicitely. + // be called. If necessary, the handler must call this function explicitly. CVirtualHelper helper("OnChangedViewList", this); if (helper.HaveHandler() && helper.call()) { return; diff --git a/Pythonwin/pywin/debugger/fail.py b/Pythonwin/pywin/debugger/fail.py index dbb5320ae..0afc70eb3 100644 --- a/Pythonwin/pywin/debugger/fail.py +++ b/Pythonwin/pywin/debugger/fail.py @@ -28,7 +28,7 @@ def b(): b = 1 pywin.debugger.set_trace() # After importing or running this module, you are likely to be - # sitting at the next line. This is because we explicitely + # sitting at the next line. This is because we explicitly # broke into the debugger using the "set_trace() function # "pywin.debugger.brk()" is a shorter alias for this. c() diff --git a/Pythonwin/pywin/framework/editor/editor.py b/Pythonwin/pywin/framework/editor/editor.py index facb5b23f..1095cbe97 100644 --- a/Pythonwin/pywin/framework/editor/editor.py +++ b/Pythonwin/pywin/framework/editor/editor.py @@ -9,7 +9,7 @@ # We now support reloading of externally modified documented # (eg, presumably by some other process, such as source control or # another editor. -# We also suport auto-loading of externally modified files. +# We also support auto-loading of externally modified files. # - if the current document has not been modified in this # editor, but has been modified on disk, then the file # can be automatically reloaded. diff --git a/Pythonwin/pywin/framework/editor/vss.py b/Pythonwin/pywin/framework/editor/vss.py index 4a772acef..fa3b51ed3 100644 --- a/Pythonwin/pywin/framework/editor/vss.py +++ b/Pythonwin/pywin/framework/editor/vss.py @@ -86,7 +86,7 @@ def CheckoutFile(fileName): project, vssFname, database = rc if g_sourceSafe is None: g_sourceSafe = win32com.client.Dispatch("SourceSafe") - # SS seems a bit wierd. It defaults the arguments as empty strings, but + # SS seems a bit weird. It defaults the arguments as empty strings, but # then complains when they are used - so we pass "Missing" if not database: database = pythoncom.Missing diff --git a/Pythonwin/pywin/framework/intpyapp.py b/Pythonwin/pywin/framework/intpyapp.py index acbd34cc1..de02fdace 100644 --- a/Pythonwin/pywin/framework/intpyapp.py +++ b/Pythonwin/pywin/framework/intpyapp.py @@ -467,7 +467,7 @@ def OnFileLocate(self, id, code): else: win32ui.GetApp().OpenDocumentFile(newName) - # Display all the "options" proprety pages we can find + # Display all the "options" property pages we can find def OnViewOptions(self, id, code): win32ui.InitRichEdit() sheet = dialog.PropertySheet("Pythonwin Options") diff --git a/Pythonwin/pywin/framework/startup.py b/Pythonwin/pywin/framework/startup.py index 3cc6c0169..ca7a44d87 100644 --- a/Pythonwin/pywin/framework/startup.py +++ b/Pythonwin/pywin/framework/startup.py @@ -50,7 +50,7 @@ pywin.__path__[0] = win32ui.FullPath(pywin.__path__[0]) pywin.framework.__path__[0] = win32ui.FullPath(pywin.framework.__path__[0]) -# make a few wierd sys values. This is so later we can clobber sys.argv to trick +# make a few weird sys values. This is so later we can clobber sys.argv to trick # scripts when running under a GUI environment. moduleName = "pywin.framework.intpyapp" diff --git a/Pythonwin/pywin/scintilla/keycodes.py b/Pythonwin/pywin/scintilla/keycodes.py index d94ccda47..12867080a 100644 --- a/Pythonwin/pywin/scintilla/keycodes.py +++ b/Pythonwin/pywin/scintilla/keycodes.py @@ -70,7 +70,7 @@ def get_vk(chardesc): def parse_key_name(name): - name += "-" # Add a sentinal + name += "-" # Add a sentinel start = pos = 0 max = len(name) toks = [] diff --git a/Pythonwin/pywin/scintilla/view.py b/Pythonwin/pywin/scintilla/view.py index 99680f18e..0134f3151 100644 --- a/Pythonwin/pywin/scintilla/view.py +++ b/Pythonwin/pywin/scintilla/view.py @@ -749,7 +749,7 @@ def CalculatePageRanges(self, dc, pInfo): pageStart = self.FormatRange(dc, pageStart, textLen, rc, 0) maxPage += 1 self.starts[maxPage] = pageStart - # And a sentinal for one page past the end + # And a sentinel for one page past the end self.starts[maxPage + 1] = textLen # When actually printing, maxPage doesn't have any effect at this late state. # but is needed to make the Print Preview work correctly. diff --git a/Pythonwin/win32bitmap.cpp b/Pythonwin/win32bitmap.cpp index 157457063..0422fbf75 100644 --- a/Pythonwin/win32bitmap.cpp +++ b/Pythonwin/win32bitmap.cpp @@ -210,7 +210,7 @@ PyObject *ui_bitmap_load_bitmap_file(PyObject *self, PyObject *args) return NULL; } */ - /* Attempt to load wierd bitmap format. + /* Attempt to load weird bitmap format. if (bmFileHeader.bfOffBits) { PyObject *args = Py_BuildValue("(i)", bmFileHeader.bfOffBits); result = gui_call_object(seeker, args); diff --git a/Pythonwin/win32dlg.cpp b/Pythonwin/win32dlg.cpp index 598aae410..6a0e2fecb 100644 --- a/Pythonwin/win32dlg.cpp +++ b/Pythonwin/win32dlg.cpp @@ -162,7 +162,7 @@ PyCDialog::~PyCDialog() GlobalFree(hSaved); } - ui_assoc_object::SetAssocInvalid(); // must call this explicitely, as I ignore SetAssocInvalid + ui_assoc_object::SetAssocInvalid(); // must call this explicitly, as I ignore SetAssocInvalid Py_XDECREF(ddlist); // we can not have the pointer deleted at window destruction time // for a dialog (as MFC still needs it after the dialog has completed BOOL bManDeleteSave = bManualDelete; diff --git a/Pythonwin/win32virt.cpp b/Pythonwin/win32virt.cpp index 5d049fbf3..a53aa58a8 100644 --- a/Pythonwin/win32virt.cpp +++ b/Pythonwin/win32virt.cpp @@ -42,7 +42,7 @@ CVirtualHelper::CVirtualHelper(const char *iname, void *iassoc, EnumVirtualError PyErr_Fetch(&t, &v, &tb); handler = PyObject_GetAttrString(py_bob->virtualInst, (char *)iname); if (handler) { - // explicitely check a method returned, else the classes + // explicitly check a method returned, else the classes // delegation may cause a circular call chain. if (!PyMethod_Check(handler)) { if (!PyCFunction_Check(handler)) { diff --git a/adodbapi/adodbapi.py b/adodbapi/adodbapi.py index b63b829d8..19adbfb30 100644 --- a/adodbapi/adodbapi.py +++ b/adodbapi/adodbapi.py @@ -66,7 +66,7 @@ def getIndexedValue(obj, index): def make_COM_connecter(): try: pythoncom.CoInitialize() # v2.1 Paj - c = Dispatch("ADODB.Connection") # connect _after_ CoIninialize v2.1.1 adamvan + c = Dispatch("ADODB.Connection") # connect _after_ CoInitialize v2.1.1 adamvan except: raise api.InterfaceError( "Windows COM Error: Dispatch('ADODB.Connection') failed." @@ -593,7 +593,7 @@ def _raiseCursorError(self, errorclass, errorvalue): eh(self.connection, self, errorclass, errorvalue) def build_column_info(self, recordset): - self.converters = [] # convertion function for each column + self.converters = [] # conversion function for each column self.columnNames = {} # names of columns {lowercase name : number,...} self._description = None diff --git a/adodbapi/readme.txt b/adodbapi/readme.txt index 00f76f7c2..877c400cb 100644 --- a/adodbapi/readme.txt +++ b/adodbapi/readme.txt @@ -34,7 +34,7 @@ Try: or: adodbapi.apibase.variantConversions[adodbapi.ado_consts.adNumeric] = adodbapi.apibase.cvtFloat or: - adodbapi.apibase.variantConversions[adodbapi.ado_consts.adNumeric] = write_your_own_convertion_function + adodbapi.apibase.variantConversions[adodbapi.ado_consts.adNumeric] = write_your_own_conversion_function ............ notes for 2.6.2: The definitive source has been moved to https://github.com/mhammond/pywin32/tree/master/adodbapi. diff --git a/adodbapi/test/adodbapitest.py b/adodbapi/test/adodbapitest.py index dd8e9196d..88dab1267 100644 --- a/adodbapi/test/adodbapitest.py +++ b/adodbapi/test/adodbapitest.py @@ -213,7 +213,7 @@ def testUserDefinedConversionForExactNumericTypes(self): # now return strings adodbapi.variantConversions[ado_consts.adNumeric] = adodbapi.cvtString self.helpTestDataType("numeric(18,2)", "NUMBER", "3.45") - # now a completly weird user defined convertion + # now a completely weird user defined conversion adodbapi.variantConversions[ado_consts.adNumeric] = ( lambda x: "!!This function returns a funny unicode string %s!!" % x ) @@ -228,7 +228,7 @@ def testUserDefinedConversionForExactNumericTypes(self): finally: # now reset the converter to its original function adodbapi.variantConversions[ado_consts.adNumeric] = ( - oldconverter # Restore the original convertion function + oldconverter # Restore the original conversion function ) def helpTestDataType( diff --git a/adodbapi/test/dbapi20.py b/adodbapi/test/dbapi20.py index 373b984d6..ea920d42b 100644 --- a/adodbapi/test/dbapi20.py +++ b/adodbapi/test/dbapi20.py @@ -71,7 +71,7 @@ # - Now a subclass of TestCase, to avoid requiring the driver stub # to use multiple inheritance # - Reversed the polarity of buggy test in test_description -# - Test exception heirarchy correctly +# - Test exception hierarchy correctly # - self.populate is now self._populate(), so if a driver stub # overrides self.ddl1 this change propogates # - VARCHAR columns now have a width, which will hopefully make the @@ -198,7 +198,7 @@ def test_paramstyle(self): def test_Exceptions(self): # Make sure required exceptions exist, and are in the - # defined heirarchy. + # defined hierarchy. if sys.version[0] == "3": # under Python 3 StardardError no longer exists self.assertTrue(issubclass(self.driver.Warning, Exception)) self.assertTrue(issubclass(self.driver.Error, Exception)) diff --git a/adodbapi/test/setuptestframework.py b/adodbapi/test/setuptestframework.py index e09549421..4b9de6a7d 100644 --- a/adodbapi/test/setuptestframework.py +++ b/adodbapi/test/setuptestframework.py @@ -56,7 +56,7 @@ def makeadopackage(testfolder): shutil.copy(os.path.join(adoPath, f), newpackage) return testfolder else: - raise OSError("Connot find source of adodbapi to test.") + raise OSError("Cannot find source of adodbapi to test.") def makemdb(testfolder, mdb_name): diff --git a/build_env.md b/build_env.md index 4f616bf99..7e166c4d9 100644 --- a/build_env.md +++ b/build_env.md @@ -117,7 +117,7 @@ where mc ``` (Note that the above process for 'mc' doesn't appear necessary for VS2017, but -markh hasn't tried with VS2019 - please share your experiences!) +@mhammond hasn't tried with VS2019 - please share your experiences!) # Build diff --git a/com/changes.txt b/com/changes.txt index f94adde87..27e387a8c 100644 --- a/com/changes.txt +++ b/com/changes.txt @@ -110,7 +110,7 @@ Dec 1, 96 win32com.pythoncom works (and is the "official" way!). - Connection point support added. makepy will now generate code suitable to be used as an OCX, or as a connection point sink. - Slightly wierd connection point demo (client and server!) is in demos\connect.py + Slightly weird connection point demo (client and server!) is in demos\connect.py Note - All old OCX code will be broken. You must regenerate all .py files, AND CHANGE ALL SUPPORT CODE (sorry!). Specifically, the name of the class you should sub-class from will have changed - it diff --git a/com/win32com/changes.txt b/com/win32com/changes.txt index 3b3a0588e..57734d924 100644 --- a/com/win32com/changes.txt +++ b/com/win32com/changes.txt @@ -113,7 +113,7 @@ Dec 1, 96 win32com.pythoncom works (and is the "official" way!). - Connection point support added. makepy will now generate code suitable to be used as an OCX, or as a connection point sink. - Slightly wierd connection point demo (client and server!) is in demos\connect.py + Slightly weird connection point demo (client and server!) is in demos\connect.py Note - All old OCX code will be broken. You must regenerate all .py files, AND CHANGE ALL SUPPORT CODE (sorry!). Specifically, the name of the class you should sub-class from will have changed - it diff --git a/com/win32com/server/policy.py b/com/win32com/server/policy.py index 0c1f92427..f4593b4b9 100644 --- a/com/win32com/server/policy.py +++ b/com/win32com/server/policy.py @@ -321,7 +321,7 @@ def _getidsofnames_(self, names, lcid): # IDispatchEx support for policies. Most of the IDispathEx functionality # by default will raise E_NOTIMPL. Thus it is not necessary for derived - # policies to explicitely implement all this functionality just to not implement it! + # policies to explicitly implement all this functionality just to not implement it! def _GetDispID_(self, name, fdex): return self._getdispid_(name, fdex) diff --git a/com/win32com/server/register.py b/com/win32com/server/register.py index 04ffdca37..760a65701 100644 --- a/com/win32com/server/register.py +++ b/com/win32com/server/register.py @@ -448,7 +448,7 @@ def RegisterClasses(*classes, **flags): win32api.FindFiles(sys.argv[0])[0][8] )[0] except (IndexError, win32api.error): - # Can't find the script file - the user must explicitely set the _reg_... attribute. + # Can't find the script file - the user must explicitly set the _reg_... attribute. raise TypeError( "Can't locate the script hosting the COM object - please set _reg_class_spec_ in your object" ) diff --git a/com/win32com/src/dllmain.cpp b/com/win32com/src/dllmain.cpp index bac646ece..de857ed84 100644 --- a/com/win32com/src/dllmain.cpp +++ b/com/win32com/src/dllmain.cpp @@ -156,7 +156,7 @@ typedef HRESULT(WINAPI *PFNCoInitializeEx)(LPVOID pvReserved, DWORD dwCoInit); // particular about the order of shutdown - in MAPI's case, you MUST // do the CoUninit _before_ the MAPIUninit. // These functions have logic so the Python programmer can call either -// the Init for Term function explicitely, and the framework will detect +// the Init for Term function explicitly, and the framework will detect // it no longer needs doing. // XXX - Needs more thought about threading implications. HRESULT PyCom_CoInitializeEx(LPVOID reserved, DWORD dwInit) diff --git a/com/win32com/src/univgw_dataconv.cpp b/com/win32com/src/univgw_dataconv.cpp index 23107d01d..520adb66b 100644 --- a/com/win32com/src/univgw_dataconv.cpp +++ b/com/win32com/src/univgw_dataconv.cpp @@ -702,7 +702,7 @@ PyObject *dataconv_ReadFromInTuple(PyObject *self, PyObject *args) default: obArg = NULL; PyErr_SetString(PyExc_TypeError, "Unknown/bad type description type!"); - // barf here, we don't wtf they were thinking... + // barf here, we don't know wtf they were thinking... break; } // switch } // if ARRAY diff --git a/com/win32comext/axdebug/documents.py b/com/win32comext/axdebug/documents.py index eb45517e7..723d2bf13 100644 --- a/com/win32comext/axdebug/documents.py +++ b/com/win32comext/axdebug/documents.py @@ -105,7 +105,7 @@ class CodeContainerProvider: Given a Python file name (as the debugger knows it by) this will return a CodeContainer interface suitable for use. - This provides a simple base imlpementation that simply supports + This provides a simple base implementation that simply supports a dictionary of nodes and providers. """ diff --git a/com/win32comext/axscript/client/pyscript.py b/com/win32comext/axscript/client/pyscript.py index fd7806073..e281d16a7 100644 --- a/com/win32comext/axscript/client/pyscript.py +++ b/com/win32comext/axscript/client/pyscript.py @@ -100,7 +100,7 @@ def _FindAttribute_(self, attr): class NamedScriptAttribute: - "An explicitely named object in an objects namespace" + "An explicitly named object in an objects namespace" # Each named object holds a reference to one of these. # Whenever a sub-item appears in a namespace, it is really one of these diff --git a/com/win32comext/axscript/demos/client/ie/demo_intro.htm b/com/win32comext/axscript/demos/client/ie/demo_intro.htm index 9987d8972..c02be1a6e 100644 --- a/com/win32comext/axscript/demos/client/ie/demo_intro.htm +++ b/com/win32comext/axscript/demos/client/ie/demo_intro.htm @@ -30,7 +30,7 @@

                Known bugs and problems

              • Builtin objects such as MARQUEE are giving me grief. Objects accessed via forms are generally no problem.

              • If you are trying to use Python with the Windows Scripting Host, note that -.pys files are not correct registered - you will need to explicitely +.pys files are not correct registered - you will need to explicitly specify either cscript.exe or wscript.exe on the command line.

              diff --git a/com/win32comext/bits/src/bits.cpp b/com/win32comext/bits/src/bits.cpp index f92868f55..6b973f893 100755 --- a/com/win32comext/bits/src/bits.cpp +++ b/com/win32comext/bits/src/bits.cpp @@ -30,7 +30,7 @@ void PyObject_FreeBG_FILE_RANGE_LIST(DWORD num, BG_FILE_RANGE *fr) {} PyObject *PyObject_FromBG_FILE_PROGRESS(BG_FILE_PROGRESS *fp) { - // @object PyObject_FromBG_FILE_PROGRESS|A tuple of 3 elements (bytesTotal, bytesTransfered, completed), (int, int, + // @object PyObject_FromBG_FILE_PROGRESS|A tuple of 3 elements (bytesTotal, bytesTransferred, completed), (int, int, // bool) return Py_BuildValue("NNO", PyLong_FromLongLong(fp->BytesTotal), PyLong_FromLongLong(fp->BytesTransferred), fp->Completed ? Py_True : Py_False); @@ -38,14 +38,14 @@ PyObject *PyObject_FromBG_FILE_PROGRESS(BG_FILE_PROGRESS *fp) PyObject *PyObject_FromBG_JOB_PROGRESS(BG_JOB_PROGRESS *jp) { - // @object PyObject_FromBG_JOB_PROGRESS|A tuple of 4 elements (bytesTotal, bytesTransfered, filesTotal, - // filesTransfered), all ints. + // @object PyObject_FromBG_JOB_PROGRESS|A tuple of 4 elements (bytesTotal, bytesTransferred, filesTotal, + // filesTransferred), all ints. return Py_BuildValue("NNkk", PyLong_FromLongLong(jp->BytesTotal), PyLong_FromLongLong(jp->BytesTransferred), jp->FilesTotal, jp->FilesTransferred); } PyObject *PyObject_FromBG_JOB_REPLY_PROGRESS(BG_JOB_REPLY_PROGRESS *jrs) { - // @object BG_JOB_REPLY_PROGRESS|A tuple of 2 elements (bytesTotal, bytesTransfered), both ints. + // @object BG_JOB_REPLY_PROGRESS|A tuple of 2 elements (bytesTotal, bytesTransferred), both ints. return Py_BuildValue("NN", PyLong_FromLongLong(jrs->BytesTotal), PyLong_FromLongLong(jrs->BytesTransferred)); } diff --git a/com/win32comext/shell/demos/servers/folder_view.py b/com/win32comext/shell/demos/servers/folder_view.py index f2d039a15..f00e383cc 100644 --- a/com/win32comext/shell/demos/servers/folder_view.py +++ b/com/win32comext/shell/demos/servers/folder_view.py @@ -529,7 +529,7 @@ def QueryContextMenu(self, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags): def InvokeCommand(self, ci): mask, hwnd, verb, params, dir, nShow, hotkey, hicon = ci - # this seems very convuluted, but it's what the sample does :) + # this seems very convoluted, but it's what the sample does :) for verb_name, verb_id, flag in folderViewImplContextMenuIDs: if isinstance(verb, int): matches = verb == verb_id diff --git a/com/win32comext/shell/src/PyIShellItem2.cpp b/com/win32comext/shell/src/PyIShellItem2.cpp index eb0c1cdcf..9637882cc 100644 --- a/com/win32comext/shell/src/PyIShellItem2.cpp +++ b/com/win32comext/shell/src/PyIShellItem2.cpp @@ -485,7 +485,7 @@ STDMETHODIMP PyGShellItem2::GetProperty( PyObject *result; /* ??? Something strange with the format: If passing only a single object, and it's a tuple, - and you don't explicitely add the parens, + and you don't explicitly add the parens, the tuple gets unpacked and passed as separate args ??? */ HRESULT hr = InvokeViaPolicy("GetProperty", &result, "(N)", PyObject_FromSHCOLUMNID(&key)); diff --git a/ruff.toml b/ruff.toml index 6d75257db..315a9d41f 100644 --- a/ruff.toml +++ b/ruff.toml @@ -45,7 +45,7 @@ extend-ignore = [ # Explicit re-exports is fine in __init__.py, still a code smell elsewhere. "__init__.py" = ["PLC0414"] # TODO: Make adodbapi changes in their own PRs -"adodbapi/*" = ["C4", "YTT301", "UP031", "UP032", "ISC002"] +"adodbapi/*" = ["C4", "YTT301", "UP031", "UP032"] [lint.isort] combine-as-imports = true diff --git a/win32/Demos/security/set_file_audit.py b/win32/Demos/security/set_file_audit.py index 324d72748..e46d05d77 100644 --- a/win32/Demos/security/set_file_audit.py +++ b/win32/Demos/security/set_file_audit.py @@ -59,7 +59,7 @@ win32con.GENERIC_ALL, my_sid, ) -## keep dir from inheriting any permissions so it only has ACEs explicitely set here +## keep dir from inheriting any permissions so it only has ACEs explicitly set here win32security.SetNamedSecurityInfo( dir_name, SE_FILE_OBJECT, diff --git a/win32/Lib/pywin32_testutil.py b/win32/Lib/pywin32_testutil.py index d9e517913..e2b1b8b3a 100644 --- a/win32/Lib/pywin32_testutil.py +++ b/win32/Lib/pywin32_testutil.py @@ -273,7 +273,7 @@ def _makeResult(self): return TestResult(self.stream, self.descriptions, self.verbosity) -# TestProgream subclass necessary just to get our TestRunner hooked up, +# TestProgram subclass necessary just to get our TestRunner hooked up, # which is necessary to get our TestResult hooked up *sob* class TestProgram(unittest.TestProgram): def runTests(self): @@ -282,7 +282,7 @@ def runTests(self): unittest.TestProgram.runTests(self) -# A convenient entry-point - if used, 'SKIPPED' exceptions will be supressed. +# A convenient entry-point - if used, 'SKIPPED' exceptions will be suppressed. def testmain(*args, **kw): new_kw = kw.copy() if "testLoader" not in new_kw: diff --git a/win32/Lib/win32cryptcon.py b/win32/Lib/win32cryptcon.py index 8d71996a0..92aac96eb 100644 --- a/win32/Lib/win32cryptcon.py +++ b/win32/Lib/win32cryptcon.py @@ -972,7 +972,7 @@ def GET_CMSG_ENCODING_TYPE(X): CMC_FAIL_BAD_REQUEST = 2 CMC_FAIL_BAD_TIME = 3 CMC_FAIL_BAD_CERT_ID = 4 -CMC_FAIL_UNSUPORTED_EXT = 5 +CMC_FAIL_UNSUPORTED_EXT = 5 # Yes Microsoft made a typo in "UNSUPPORTED" CMC_FAIL_MUST_ARCHIVE_KEYS = 6 CMC_FAIL_BAD_IDENTITY = 7 CMC_FAIL_POP_REQUIRED = 8 diff --git a/win32/Lib/win32pdhquery.py b/win32/Lib/win32pdhquery.py index 3e51b77b9..724a668a7 100644 --- a/win32/Lib/win32pdhquery.py +++ b/win32/Lib/win32pdhquery.py @@ -504,10 +504,10 @@ def collectdatafor(self, totalperiod, period=1): def collectdatawhile(self, period=1): """ Threaded collection of performance data: - This method sets up a simple semaphor system for signalling + This method sets up a simple semaphore system for signalling when you would like to start and stop a threaded data collection method. The collection runs every period seconds until the - semaphor attribute is set to a non-true value (which normally + semaphore attribute is set to a non-true value (which normally should be done by calling query.collectdatawhile_stop() .) e.g.: query.collectdatawhile(2) diff --git a/win32/Lib/win32timezone.py b/win32/Lib/win32timezone.py index fdd71c855..01aa08d79 100644 --- a/win32/Lib/win32timezone.py +++ b/win32/Lib/win32timezone.py @@ -463,7 +463,7 @@ def _locate_day(year, cutoff): """ # MS stores Sunday as 0, Python datetime stores Monday as zero target_weekday = (cutoff.day_of_week + 6) % 7 - # For SYSTEMTIMEs relating to time zone inforamtion, cutoff.day + # For SYSTEMTIMEs relating to time zone information, cutoff.day # is the week of the month week_of_month = cutoff.day # so the following is the first day of that week diff --git a/win32/scripts/regsetup.py b/win32/scripts/regsetup.py index fb33e11dd..ca44ed672 100644 --- a/win32/scripts/regsetup.py +++ b/win32/scripts/regsetup.py @@ -497,9 +497,9 @@ def RegisterShellInfo(searchPaths): # Using raw string so that all paths meant to be copied read correctly inline and when printed examples = r""" Examples: -"regsetup c:\wierd\spot\1 c:\wierd\spot\2" +"regsetup c:\weird\spot\1 c:\weird\spot\2" Attempts to setup the core Python. Looks in some standard places, -as well as the 2 wierd spots to locate the core Python files (eg, Python.exe, +as well as the 2 weird spots to locate the core Python files (eg, Python.exe, pythonXX.dll, the standard library and Win32 Extensions). "regsetup -a myappname . .\subdir" diff --git a/win32/src/PySECURITY_DESCRIPTOR.cpp b/win32/src/PySECURITY_DESCRIPTOR.cpp index 4ad9aa1d0..f21cfaae7 100644 --- a/win32/src/PySECURITY_DESCRIPTOR.cpp +++ b/win32/src/PySECURITY_DESCRIPTOR.cpp @@ -451,7 +451,7 @@ PyObject *PySECURITY_DESCRIPTOR::GetSecurityDescriptorOwner(PyObject *self, PyOb PyObject *PySECURITY_DESCRIPTOR::SetSecurityDescriptorOwner(PyObject *self, PyObject *args) { // @pyparm |sid||The sid to be set as owner in the security descriptor. - // @pyparm int|bOwnerDefaulted||Normally set to false since this explicitely set the owner. + // @pyparm int|bOwnerDefaulted||Normally set to false since this explicitly set the owner. BOOL bOwnerDefaulted; PySECURITY_DESCRIPTOR *This = (PySECURITY_DESCRIPTOR *)self; PSID NewOwnerSid = NULL; @@ -494,7 +494,7 @@ PyObject *PySECURITY_DESCRIPTOR::SetSecurityDescriptorOwner(PyObject *self, PyOb PyObject *PySECURITY_DESCRIPTOR::SetSecurityDescriptorGroup(PyObject *self, PyObject *args) { // @pyparm |sid||The group sid to be set in the security descriptor. - // @pyparm int|bOwnerDefaulted||Normally set to false since this explicitely set the owner. + // @pyparm int|bOwnerDefaulted||Normally set to false since this explicitly set the owner. BOOL bGroupDefaulted; PySECURITY_DESCRIPTOR *This = (PySECURITY_DESCRIPTOR *)self; PSECURITY_DESCRIPTOR psd = NULL; diff --git a/win32/src/PythonService.cpp b/win32/src/PythonService.cpp index 181c97b50..c6d8e1364 100644 --- a/win32/src/PythonService.cpp +++ b/win32/src/PythonService.cpp @@ -92,7 +92,7 @@ typedef struct { DWORD g_serviceProcessFlags = 0; // The global SCM dispatch table. A trailing NULL indicates to the SCM -// how many are used, so we allocate one extra for this sentinal +// how many are used, so we allocate one extra for this sentinel static SERVICE_TABLE_ENTRY DispatchTable[MAX_SERVICES + 1] = {{NULL, NULL}}; // A parallel array of Python information for the service. static PY_SERVICE_TABLE_ENTRY PythonServiceTable[MAX_SERVICES]; diff --git a/win32/src/win32file.i b/win32/src/win32file.i index 5b1b010d7..714aed513 100644 --- a/win32/src/win32file.i +++ b/win32/src/win32file.i @@ -2,7 +2,7 @@ // @doc %module win32file // An interface to the win32 File API's -// This module includes the tranactional NTFS operations introduced with +// This module includes the transactional NTFS operations introduced with // Vista. The transacted functions are not wrapped separately, but are invoked by // passing a transaction handle to the corresponding Unicode API function. // This makes it simple to convert a set of file operations into a transaction by @@ -1179,13 +1179,13 @@ static PyObject *myGetQueuedCompletionStatus(PyObject *self, PyObject *args) PyObject *myPostQueuedCompletionStatus(PyObject *self, PyObject *args) { PyObject *obHandle, *obOverlapped = NULL, *obkey=Py_None; - DWORD bytesTransfered = 0; + DWORD bytesTransferred = 0; ULONG_PTR key = 0; // @pyparm |handle||handle to an I/O completion port - // @pyparm int|numberOfbytes|0|value to return via GetQueuedCompletionStatus' first result + // @pyparm int|numberOfBytes|0|value to return via GetQueuedCompletionStatus' first result // @pyparm int|completionKey|0|value to return via GetQueuedCompletionStatus' second result // @pyparm |overlapped|None|value to return via GetQueuedCompletionStatus' third result - if (!PyArg_ParseTuple(args, "O|iOO", &obHandle, &bytesTransfered, &obkey, &obOverlapped)) + if (!PyArg_ParseTuple(args, "O|iOO", &obHandle, &bytesTransferred, &obkey, &obOverlapped)) return NULL; if (obkey!=Py_None) if (!PyWinLong_AsVoidPtr(obkey, (void **)&key)) @@ -1198,7 +1198,7 @@ PyObject *myPostQueuedCompletionStatus(PyObject *self, PyObject *args) return NULL; BOOL ok; Py_BEGIN_ALLOW_THREADS - ok = ::PostQueuedCompletionStatus(handle, bytesTransfered, key, pOverlapped); + ok = ::PostQueuedCompletionStatus(handle, bytesTransferred, key, pOverlapped); Py_END_ALLOW_THREADS if (!ok) return PyWin_SetAPIError("PostQueuedCompletionStatus"); @@ -4168,7 +4168,7 @@ py_ReplaceFile(PyObject *self, PyObject *args) void encryptedfilecontextdestructor(PyObject *obctxt){ if (!PyCapsule_IsValid(obctxt, NULL)) return; // should not happen, but maybe print a warning just in case ? - // Check if context has already been explicitely destroyed + // Check if context has already been explicitly destroyed // The capsule's context is set to this value in CloseEncryptedFileRaw if (PyCapsule_GetContext(obctxt) == INVALID_HANDLE_VALUE) return; From 29c198473334805afa664d6e12da9a0d67588592 Mon Sep 17 00:00:00 2001 From: Cristi Fati Date: Fri, 25 Oct 2024 04:17:28 +0300 Subject: [PATCH 12/13] Last error wrongly set by some modules (#2302) --- CHANGES.txt | 1 + win32/src/PyWinTypes.h | 2 + win32/src/PyWinTypesmodule.cpp | 17 +++++-- win32/src/win32apimodule.cpp | 24 +++------- win32/src/win32consolemodule.cpp | 4 +- win32/src/win32file.i | 25 ++++------ win32/src/win32gui.i | 66 ++++++++++++--------------- win32/src/win32inet.i | 2 +- win32/src/win32job.i | 10 ++-- win32/src/win32net/win32netmodule.cpp | 4 +- win32/src/win32pipe.i | 8 ++-- win32/src/win32process.i | 27 ++++------- win32/src/win32profilemodule.cpp | 5 +- win32/src/win32service.i | 9 ++-- win32/src/win32transactionmodule.cpp | 6 +-- win32/src/win32tsmodule.cpp | 12 ++--- 16 files changed, 92 insertions(+), 130 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index d02c6fcae..c66d05f48 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -14,6 +14,7 @@ https://mhammond.github.io/pywin32_installers.html. Coming in build 309, as yet unreleased -------------------------------------- +* Last error wrongly set by some modules (#2302, @CristiFati) * Dropped support for Python 3.7 (#2207, @Avasam) * Implement the creation of SAFEARRAY(VT_RECORD) from a sequence of COM Records (#2317, @geppi) * Implement record pointers as [in, out] method parameters of a Dispatch Interface (#2304, #2310, @geppi) diff --git a/win32/src/PyWinTypes.h b/win32/src/PyWinTypes.h index 620aada9c..cd0fe7bdb 100644 --- a/win32/src/PyWinTypes.h +++ b/win32/src/PyWinTypes.h @@ -83,6 +83,8 @@ typedef Py_ssize_t Py_hash_t; #endif // _MSC_VER #endif // BUILD_PYWINTYPES +extern PYWINTYPES_EXPORT HMODULE PyWin_GetOrLoadLibraryHandle(const char *name); + // Py3k uses memoryview object in place of buffer, and we don't yet. extern PYWINTYPES_EXPORT PyObject *PyBuffer_New(Py_ssize_t size); extern PYWINTYPES_EXPORT PyObject *PyBuffer_FromMemory(void *buf, Py_ssize_t size); diff --git a/win32/src/PyWinTypesmodule.cpp b/win32/src/PyWinTypesmodule.cpp index 1564f84d5..e095fdf93 100644 --- a/win32/src/PyWinTypesmodule.cpp +++ b/win32/src/PyWinTypesmodule.cpp @@ -26,6 +26,17 @@ extern PyObject *PyWinMethod_NewHKEY(PyObject *self, PyObject *args); extern BOOL _PyWinDateTime_Init(); extern BOOL _PyWinDateTime_PrepareModuleDict(PyObject *dict); +HMODULE PyWin_GetOrLoadLibraryHandle(const char *name) +{ + DWORD lastErr = GetLastError(); + HMODULE hmodule = GetModuleHandleA(name); + if (hmodule == NULL) + hmodule = LoadLibraryA(name); + if (hmodule != NULL) + SetLastError(lastErr); + return hmodule; +} + // XXX - Needs py3k modernization! // For py3k, a function that returns new memoryview object instead of buffer. // ??? Byte array object is mutable, maybe just use that directly as a substitute ??? @@ -970,10 +981,8 @@ extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwR { FARPROC fp; // dll usually will already be loaded - HMODULE hmodule = GetModuleHandle(_T("AdvAPI32.dll")); - if (hmodule == NULL) - hmodule = LoadLibrary(_T("AdvAPI32.dll")); - if (hmodule) { + HMODULE hmodule = PyWin_GetOrLoadLibraryHandle("advapi32.dll"); + if (hmodule != NULL) { fp = GetProcAddress(hmodule, "AddAccessAllowedAce"); if (fp) addaccessallowedace = (addacefunc)(fp); diff --git a/win32/src/win32apimodule.cpp b/win32/src/win32apimodule.cpp index 026816e69..45d8d532e 100644 --- a/win32/src/win32apimodule.cpp +++ b/win32/src/win32apimodule.cpp @@ -4772,14 +4772,12 @@ static PyObject *PySetSystemTime(PyObject *self, PyObject *args) )) return NULL; PyW32_BEGIN_ALLOW_THREADS result = ::SetSystemTime(&t); - PyW32_END_ALLOW_THREADS + PyW32_END_ALLOW_THREADS; - if (!result) - { + if (!result) { return ReturnAPIError("SetSystemTime"); } - else - { + else { return Py_BuildValue("i", result); } } @@ -6263,17 +6261,13 @@ PYWIN_MODULE_INIT_FUNC(win32api) PyModule_AddIntConstant(module, "VS_FF_PRIVATEBUILD", VS_FF_PRIVATEBUILD); PyModule_AddIntConstant(module, "VS_FF_SPECIALBUILD", VS_FF_SPECIALBUILD); - HMODULE hmodule = GetModuleHandle(TEXT("secur32.dll")); - if (hmodule == NULL) - hmodule = LoadLibrary(TEXT("secur32.dll")); + HMODULE hmodule = PyWin_GetOrLoadLibraryHandle("secur32.dll"); if (hmodule != NULL) { pfnGetUserNameEx = (GetUserNameExfunc)GetProcAddress(hmodule, "GetUserNameExW"); pfnGetComputerObjectName = (GetUserNameExfunc)GetProcAddress(hmodule, "GetComputerObjectNameW"); } - hmodule = GetModuleHandle(TEXT("kernel32.dll")); - if (hmodule == NULL) - hmodule = LoadLibrary(TEXT("kernel32.dll")); + hmodule = PyWin_GetOrLoadLibraryHandle("kernel32.dll"); if (hmodule != NULL) { pfnGetComputerNameEx = (GetComputerNameExfunc)GetProcAddress(hmodule, "GetComputerNameExW"); pfnGetLongPathNameA = (GetLongPathNameAfunc)GetProcAddress(hmodule, "GetLongPathNameA"); @@ -6289,9 +6283,7 @@ PYWIN_MODULE_INIT_FUNC(win32api) pfnGetNativeSystemInfo = (GetNativeSystemInfofunc)GetProcAddress(hmodule, "GetNativeSystemInfo"); } - hmodule = GetModuleHandle(TEXT("user32.dll")); - if (hmodule == NULL) - hmodule = LoadLibrary(TEXT("user32.dll")); + hmodule = PyWin_GetOrLoadLibraryHandle("user32.dll"); if (hmodule != NULL) { pfnEnumDisplayMonitors = (EnumDisplayMonitorsfunc)GetProcAddress(hmodule, "EnumDisplayMonitors"); pfnEnumDisplayDevices = (EnumDisplayDevicesfunc)GetProcAddress(hmodule, "EnumDisplayDevicesW"); @@ -6304,9 +6296,7 @@ PYWIN_MODULE_INIT_FUNC(win32api) pfnGetLastInputInfo = (GetLastInputInfofunc)GetProcAddress(hmodule, "GetLastInputInfo"); } - hmodule = GetModuleHandle(TEXT("Advapi32.dll")); - if (hmodule == NULL) - hmodule = LoadLibrary(TEXT("Advapi32.dll")); + hmodule = PyWin_GetOrLoadLibraryHandle("advapi32.dll"); if (hmodule != NULL) { pfnRegRestoreKey = (RegRestoreKeyfunc)GetProcAddress(hmodule, "RegRestoreKeyW"); pfnRegSaveKeyEx = (RegSaveKeyExfunc)GetProcAddress(hmodule, "RegSaveKeyExW"); diff --git a/win32/src/win32consolemodule.cpp b/win32/src/win32consolemodule.cpp index daae981cf..48e84d727 100644 --- a/win32/src/win32consolemodule.cpp +++ b/win32/src/win32consolemodule.cpp @@ -2079,9 +2079,7 @@ PYWIN_MODULE_INIT_FUNC(win32console) PyDict_SetItemString(dict, "error", PyWinExc_ApiError); // load function pointers - kernel32_dll = GetModuleHandle(L"kernel32.dll"); - if (kernel32_dll == NULL) - kernel32_dll = LoadLibrary(L"kernel32.dll"); + kernel32_dll = PyWin_GetOrLoadLibraryHandle("kernel32.dll"); if (kernel32_dll != NULL) { pfnGetConsoleProcessList = (GetConsoleProcessListfunc)GetProcAddress(kernel32_dll, "GetConsoleProcessList"); pfnGetConsoleDisplayMode = (GetConsoleDisplayModefunc)GetProcAddress(kernel32_dll, "GetConsoleDisplayMode"); diff --git a/win32/src/win32file.i b/win32/src/win32file.i index 714aed513..716b76262 100644 --- a/win32/src/win32file.i +++ b/win32/src/win32file.i @@ -5932,11 +5932,8 @@ PyCFunction pfnpy_OpenFileById=(PyCFunction)py_OpenFileById; ) pmd->ml_flags = METH_VARARGS | METH_KEYWORDS; - HMODULE hmodule; - hmodule=GetModuleHandle(TEXT("AdvAPI32.dll")); - if (hmodule==NULL) - hmodule=LoadLibrary(TEXT("AdvAPI32.dll")); - if (hmodule){ + HMODULE hmodule = PyWin_GetOrLoadLibraryHandle("advapi32.dll"); + if (hmodule != NULL) { pfnEncryptFile=(EncryptFilefunc)GetProcAddress(hmodule, "EncryptFileW"); pfnDecryptFile=(DecryptFilefunc)GetProcAddress(hmodule, "DecryptFileW"); pfnEncryptionDisable=(EncryptionDisablefunc)GetProcAddress(hmodule, "EncryptionDisable"); @@ -5952,12 +5949,10 @@ PyCFunction pfnpy_OpenFileById=(PyCFunction)py_OpenFileById; pfnReadEncryptedFileRaw=(ReadEncryptedFileRawfunc)GetProcAddress(hmodule, "ReadEncryptedFileRaw"); pfnWriteEncryptedFileRaw=(WriteEncryptedFileRawfunc)GetProcAddress(hmodule, "WriteEncryptedFileRaw"); pfnCloseEncryptedFileRaw=(CloseEncryptedFileRawfunc)GetProcAddress(hmodule, "CloseEncryptedFileRaw"); - } + } - hmodule=GetModuleHandle(TEXT("kernel32.dll")); - if (hmodule==NULL) - hmodule=LoadLibrary(TEXT("kernel32.dll")); - if (hmodule){ + hmodule = PyWin_GetOrLoadLibraryHandle("kernel32.dll"); + if (hmodule != NULL) { pfnSetVolumeMountPoint=(SetVolumeMountPointfunc)GetProcAddress(hmodule, "SetVolumeMountPointW"); pfnDeleteVolumeMountPoint=(DeleteVolumeMountPointfunc)GetProcAddress(hmodule, "DeleteVolumeMountPointW"); pfnGetVolumeNameForVolumeMountPoint=(GetVolumeNameForVolumeMountPointfunc)GetProcAddress(hmodule, "GetVolumeNameForVolumeMountPointW"); @@ -6002,15 +5997,13 @@ PyCFunction pfnpy_OpenFileById=(PyCFunction)py_OpenFileById; pfnWow64RevertWow64FsRedirection=(Wow64RevertWow64FsRedirectionfunc)GetProcAddress(hmodule, "Wow64RevertWow64FsRedirection"); pfnReOpenFile=(ReOpenFilefunc)GetProcAddress(hmodule, "ReOpenFile"); pfnOpenFileById=(OpenFileByIdfunc)GetProcAddress(hmodule, "OpenFileById"); - } + } - hmodule=GetModuleHandle(TEXT("sfc.dll")); - if (hmodule==NULL) - hmodule=LoadLibrary(TEXT("sfc.dll")); - if (hmodule){ + hmodule = PyWin_GetOrLoadLibraryHandle("sfc.dll"); + if (hmodule != NULL) { pfnSfcGetNextProtectedFile=(SfcGetNextProtectedFilefunc)GetProcAddress(hmodule, "SfcGetNextProtectedFile"); pfnSfcIsFileProtected=(SfcIsFileProtectedfunc)GetProcAddress(hmodule, "SfcIsFileProtected"); - } + } %} diff --git a/win32/src/win32gui.i b/win32/src/win32gui.i index 518e84cf9..fa0906b7e 100644 --- a/win32/src/win32gui.i +++ b/win32/src/win32gui.i @@ -266,42 +266,36 @@ for (PyMethodDef *pmd = win32guiMethods; pmd->ml_name; pmd++) ) pmd->ml_flags = METH_VARARGS | METH_KEYWORDS; -HMODULE hmodule=GetModuleHandle(TEXT("user32.dll")); -if (hmodule==NULL) - hmodule=LoadLibrary(TEXT("user32.dll")); -if (hmodule){ - pfnSetLayeredWindowAttributes=(SetLayeredWindowAttributesfunc)GetProcAddress(hmodule,"SetLayeredWindowAttributes"); - pfnGetLayeredWindowAttributes=(GetLayeredWindowAttributesfunc)GetProcAddress(hmodule,"GetLayeredWindowAttributes"); - pfnUpdateLayeredWindow=(UpdateLayeredWindowfunc)GetProcAddress(hmodule,"UpdateLayeredWindow"); - pfnAnimateWindow=(AnimateWindowfunc)GetProcAddress(hmodule,"AnimateWindow"); - pfnGetMenuInfo=(GetMenuInfofunc)GetProcAddress(hmodule,"GetMenuInfo"); - pfnSetMenuInfo=(SetMenuInfofunc)GetProcAddress(hmodule,"SetMenuInfo"); - pfnDrawTextW=(DrawTextWfunc)GetProcAddress(hmodule, "DrawTextW"); - } - -hmodule=GetModuleHandle(TEXT("gdi32.dll")); -if (hmodule==NULL) - hmodule=LoadLibrary(TEXT("gdi32.dll")); -if (hmodule){ - pfnAngleArc=(AngleArcfunc)GetProcAddress(hmodule,"AngleArc"); - pfnPlgBlt=(PlgBltfunc)GetProcAddress(hmodule,"PlgBlt"); - pfnGetWorldTransform=(GetWorldTransformfunc)GetProcAddress(hmodule,"GetWorldTransform"); - pfnSetWorldTransform=(SetWorldTransformfunc)GetProcAddress(hmodule,"SetWorldTransform"); - pfnModifyWorldTransform=(ModifyWorldTransformfunc)GetProcAddress(hmodule,"ModifyWorldTransform"); - pfnCombineTransform=(CombineTransformfunc)GetProcAddress(hmodule,"CombineTransform"); - pfnMaskBlt=(MaskBltfunc)GetProcAddress(hmodule,"MaskBlt"); - pfnGetLayout=(GetLayoutfunc)GetProcAddress(hmodule,"GetLayout"); - pfnSetLayout=(SetLayoutfunc)GetProcAddress(hmodule,"SetLayout"); - } - -hmodule=GetModuleHandle(TEXT("msimg32.dll")); -if (hmodule==NULL) - hmodule=LoadLibrary(TEXT("msimg32.dll")); -if (hmodule){ - pfnGradientFill=(GradientFillfunc)GetProcAddress(hmodule,"GradientFill"); - pfnTransparentBlt=(TransparentBltfunc)GetProcAddress(hmodule,"TransparentBlt"); - pfnAlphaBlend=(AlphaBlendfunc)GetProcAddress(hmodule,"AlphaBlend"); - } +HMODULE hmodule = PyWin_GetOrLoadLibraryHandle("user32.dll"); +if (hmodule != NULL) { + pfnSetLayeredWindowAttributes = (SetLayeredWindowAttributesfunc)GetProcAddress(hmodule,"SetLayeredWindowAttributes"); + pfnGetLayeredWindowAttributes = (GetLayeredWindowAttributesfunc)GetProcAddress(hmodule,"GetLayeredWindowAttributes"); + pfnUpdateLayeredWindow = (UpdateLayeredWindowfunc)GetProcAddress(hmodule,"UpdateLayeredWindow"); + pfnAnimateWindow = (AnimateWindowfunc)GetProcAddress(hmodule,"AnimateWindow"); + pfnGetMenuInfo = (GetMenuInfofunc)GetProcAddress(hmodule,"GetMenuInfo"); + pfnSetMenuInfo = (SetMenuInfofunc)GetProcAddress(hmodule,"SetMenuInfo"); + pfnDrawTextW = (DrawTextWfunc)GetProcAddress(hmodule, "DrawTextW"); +} + +hmodule = PyWin_GetOrLoadLibraryHandle("gdi32.dll"); +if (hmodule != NULL) { + pfnAngleArc = (AngleArcfunc)GetProcAddress(hmodule,"AngleArc"); + pfnPlgBlt = (PlgBltfunc)GetProcAddress(hmodule,"PlgBlt"); + pfnGetWorldTransform = (GetWorldTransformfunc)GetProcAddress(hmodule,"GetWorldTransform"); + pfnSetWorldTransform = (SetWorldTransformfunc)GetProcAddress(hmodule,"SetWorldTransform"); + pfnModifyWorldTransform = (ModifyWorldTransformfunc)GetProcAddress(hmodule,"ModifyWorldTransform"); + pfnCombineTransform = (CombineTransformfunc)GetProcAddress(hmodule,"CombineTransform"); + pfnMaskBlt = (MaskBltfunc)GetProcAddress(hmodule,"MaskBlt"); + pfnGetLayout = (GetLayoutfunc)GetProcAddress(hmodule,"GetLayout"); + pfnSetLayout = (SetLayoutfunc)GetProcAddress(hmodule,"SetLayout"); +} + +hmodule = PyWin_GetOrLoadLibraryHandle("msimg32.dll"); +if (hmodule != NULL) { + pfnGradientFill = (GradientFillfunc)GetProcAddress(hmodule,"GradientFill"); + pfnTransparentBlt = (TransparentBltfunc)GetProcAddress(hmodule,"TransparentBlt"); + pfnAlphaBlend = (AlphaBlendfunc)GetProcAddress(hmodule,"AlphaBlend"); +} %} %{ diff --git a/win32/src/win32inet.i b/win32/src/win32inet.i index 33d5afa51..e9edf6c52 100644 --- a/win32/src/win32inet.i +++ b/win32/src/win32inet.i @@ -1941,7 +1941,7 @@ extern PyObject *PyWinHttpOpen(PyObject *, PyObject *); %init %{ PyDict_SetItemString(d, "error", PyWinExc_ApiError); - HMODULE hmod = GetModuleHandle(TEXT("wininet.dll")); + HMODULE hmod = PyWin_GetOrLoadLibraryHandle("wininet.dll"); assert(hmod); PyWin_RegisterErrorMessageModule(INTERNET_ERROR_BASE, INTERNET_ERROR_LAST, diff --git a/win32/src/win32job.i b/win32/src/win32job.i index 1b3af02e2..ccf0faf38 100644 --- a/win32/src/win32job.i +++ b/win32/src/win32job.i @@ -20,12 +20,10 @@ static IsProcessInJobfunc pfnIsProcessInJob=NULL; %init %{ -HMODULE hmodule=GetModuleHandle(L"kernel32.dll"); -if (hmodule==NULL) - hmodule=LoadLibrary(L"kernel32.dll"); -if (hmodule){ - pfnIsProcessInJob=(IsProcessInJobfunc)GetProcAddress(hmodule,"IsProcessInJob"); - } +HMODULE hmodule = PyWin_GetOrLoadLibraryHandle("kernel32.dll"); +if (hmodule != NULL) { + pfnIsProcessInJob = (IsProcessInJobfunc)GetProcAddress(hmodule, "IsProcessInJob"); +} %} diff --git a/win32/src/win32net/win32netmodule.cpp b/win32/src/win32net/win32netmodule.cpp index 1698bfb6f..e4b7ba108 100644 --- a/win32/src/win32net/win32netmodule.cpp +++ b/win32/src/win32net/win32netmodule.cpp @@ -1211,10 +1211,8 @@ PYWIN_MODULE_INIT_FUNC(win32net) AddConstant(dict, "USE_FORCE", USE_FORCE); AddConstant(dict, "USE_LOTS_OF_FORCE", USE_LOTS_OF_FORCE); - HMODULE hmodule = GetModuleHandle(_T("netapi32")); + HMODULE hmodule = PyWin_GetOrLoadLibraryHandle("netapi32.dll"); #if WINVER >= 0x0500 - if (hmodule == NULL) - hmodule = LoadLibrary(_T("netapi32")); if (hmodule != NULL) { pfnNetValidateName = (NetValidateNamefunc)GetProcAddress(hmodule, "NetValidateName"); pfnNetGetJoinInformation = (NetGetJoinInformationfunc)GetProcAddress(hmodule, "NetGetJoinInformation"); diff --git a/win32/src/win32pipe.i b/win32/src/win32pipe.i index 5311900c4..f29125c7c 100644 --- a/win32/src/win32pipe.i +++ b/win32/src/win32pipe.i @@ -25,15 +25,13 @@ static GetNamedPipeClientProcessIdfunc pfnGetNamedPipeServerSessionId = NULL; // All errors raised by this module are of this type. PyDict_SetItemString(d, "error", PyWinExc_ApiError); - HMODULE hmod=GetModuleHandle(_T("Kernel32.dll")); - if (!hmod) - hmod=LoadLibrary(_T("Kernel32.dll")); - if (hmod){ + HMODULE hmod = PyWin_GetOrLoadLibraryHandle("kernel32.dll"); + if (hmod != NULL) { pfnGetNamedPipeClientProcessId = (GetNamedPipeClientProcessIdfunc)GetProcAddress(hmod, "GetNamedPipeClientProcessId"); pfnGetNamedPipeServerProcessId = (GetNamedPipeClientProcessIdfunc)GetProcAddress(hmod, "GetNamedPipeServerProcessId"); pfnGetNamedPipeClientSessionId = (GetNamedPipeClientProcessIdfunc)GetProcAddress(hmod, "GetNamedPipeClientSessionId"); pfnGetNamedPipeServerSessionId = (GetNamedPipeClientProcessIdfunc)GetProcAddress(hmod, "GetNamedPipeServerSessionId"); - } + } %} %{ diff --git a/win32/src/win32process.i b/win32/src/win32process.i index 331ed0f23..c938f4566 100644 --- a/win32/src/win32process.i +++ b/win32/src/win32process.i @@ -1686,23 +1686,18 @@ PyObject *PyWriteProcessMemory(PyObject *self, PyObject *args) if (PyType_Ready(&PySTARTUPINFOType) == -1) return NULL; - FARPROC fp=NULL; - HMODULE hmodule=NULL; - hmodule=GetModuleHandle(_T("Psapi.dll")); - if (hmodule==NULL) - hmodule=LoadLibrary(_T("Psapi.dll")); - if (hmodule!=NULL){ + FARPROC fp = NULL; + HMODULE hmodule = PyWin_GetOrLoadLibraryHandle("psapi.dll"); + if (hmodule != NULL) { pfnEnumProcesses = (EnumProcessesfunc)GetProcAddress(hmodule, "EnumProcesses"); pfnEnumProcessModules = (EnumProcessModulesfunc)GetProcAddress(hmodule, "EnumProcessModules"); pfnEnumProcessModulesEx = (EnumProcessModulesExfunc)GetProcAddress(hmodule, "EnumProcessModulesEx"); pfnGetModuleFileNameEx = (GetModuleFileNameExfunc)GetProcAddress(hmodule, "GetModuleFileNameExW"); pfnGetProcessMemoryInfo = (GetProcessMemoryInfofunc)GetProcAddress(hmodule, "GetProcessMemoryInfo"); - } + } - hmodule=GetModuleHandle(_T("Kernel32.dll")); - if (hmodule==NULL) - hmodule=LoadLibrary(_T("Kernel32.dll")); - if (hmodule!=NULL){ + hmodule = PyWin_GetOrLoadLibraryHandle("kernel32.dll"); + if (hmodule != NULL) { pfnGetProcessTimes=(GetProcessTimesfunc)GetProcAddress(hmodule,"GetProcessTimes"); pfnGetProcessIoCounters=(GetProcessIoCountersfunc)GetProcAddress(hmodule,"GetProcessIoCounters"); pfnGetProcessShutdownParameters=(GetProcessShutdownParametersfunc)GetProcAddress(hmodule,"GetProcessShutdownParameters"); @@ -1720,15 +1715,13 @@ PyObject *PyWriteProcessMemory(PyObject *self, PyObject *args) pfnSetProcessAffinityMask=(SetProcessAffinityMaskfunc)GetProcAddress(hmodule,"SetProcessAffinityMask"); pfnGetProcessId=(GetProcessIdfunc)GetProcAddress(hmodule, "GetProcessId"); pfnIsWow64Process=(IsWow64Processfunc)GetProcAddress(hmodule, "IsWow64Process"); - } + } - hmodule=GetModuleHandle(_T("User32.dll")); - if (hmodule==NULL) - hmodule=LoadLibrary(_T("User32.dll")); - if (hmodule!=NULL){ + hmodule = PyWin_GetOrLoadLibraryHandle("user32.dll"); + if (hmodule != NULL) { pfnGetProcessWindowStation=(GetProcessWindowStationfunc)GetProcAddress(hmodule,"GetProcessWindowStation"); pfnGetGuiResources=(GetGuiResourcesfunc)GetProcAddress(hmodule,"GetGuiResources"); - } + } // *sob* - these symbols don't exist in the platform sdk needed to build // using Python 2.3 diff --git a/win32/src/win32profilemodule.cpp b/win32/src/win32profilemodule.cpp index 17299f00b..98c4fac72 100644 --- a/win32/src/win32profilemodule.cpp +++ b/win32/src/win32profilemodule.cpp @@ -489,10 +489,7 @@ PYWIN_MODULE_INIT_FUNC(win32profile) PyModule_AddIntConstant(module, "PT_ROAMING", PT_ROAMING); PyModule_AddIntConstant(module, "PT_TEMPORARY", PT_TEMPORARY); - HMODULE hmodule; - hmodule = GetModuleHandle(L"Userenv.dll"); - if (hmodule == NULL) - hmodule = LoadLibrary(L"Userenv.dll"); + HMODULE hmodule = PyWin_GetOrLoadLibraryHandle("userenv.dll"); if (hmodule != NULL) { pfnDeleteProfile = (DeleteProfilefunc)GetProcAddress(hmodule, "DeleteProfileW"); pfnExpandEnvironmentStringsForUser = diff --git a/win32/src/win32service.i b/win32/src/win32service.i index 1150dff74..b91a0e16b 100644 --- a/win32/src/win32service.i +++ b/win32/src/win32service.i @@ -36,12 +36,9 @@ EnumServicesStatusExfunc fpEnumServicesStatusEx=NULL; PyDict_SetItemString(d, "error", PyWinExc_ApiError); PyDict_SetItemString(d, "HWINSTAType", (PyObject *)&PyHWINSTAType); PyDict_SetItemString(d, "HDESKType", (PyObject *)&PyHDESKType); - HMODULE hmod; FARPROC fp; - hmod=GetModuleHandle(_T("Advapi32")); - if (hmod==NULL) - hmod=LoadLibrary(_T("Advapi32")); - if (hmod!=NULL){ + HMODULE hmod = PyWin_GetOrLoadLibraryHandle("advapi32.dll"); + if (hmod != NULL) { fp=GetProcAddress(hmod,"QueryServiceStatusEx"); if (fp!=NULL) fpQueryServiceStatusEx=(QueryServiceStatusExfunc)fp; @@ -54,7 +51,7 @@ EnumServicesStatusExfunc fpEnumServicesStatusEx=NULL; fp=GetProcAddress(hmod,"EnumServicesStatusExW"); if (fp!=NULL) fpEnumServicesStatusEx=(EnumServicesStatusExfunc)fp; - } + } %} %{ diff --git a/win32/src/win32transactionmodule.cpp b/win32/src/win32transactionmodule.cpp index 27c62d606..df39f67a1 100644 --- a/win32/src/win32transactionmodule.cpp +++ b/win32/src/win32transactionmodule.cpp @@ -235,10 +235,8 @@ PYWIN_MODULE_INIT_FUNC(win32transaction) " transacted NTFS and transacted registry functions."); // Load dll and function pointers to avoid dependency on newer libraries and headers - HMODULE hmodule = GetModuleHandle(L"Ktmw32.dll"); - if (hmodule == NULL) - hmodule = LoadLibrary(L"Ktmw32.dll"); - if (hmodule) { + HMODULE hmodule = PyWin_GetOrLoadLibraryHandle("ktmw32.dll"); + if (hmodule != NULL) { pfnCreateTransaction = (CreateTransactionfunc)GetProcAddress(hmodule, "CreateTransaction"); pfnRollbackTransaction = (RollbackTransactionfunc)GetProcAddress(hmodule, "RollbackTransaction"); pfnRollbackTransactionAsync = (RollbackTransactionAsyncfunc)GetProcAddress(hmodule, "RollbackTransactionAsync"); diff --git a/win32/src/win32tsmodule.cpp b/win32/src/win32tsmodule.cpp index ddd383dee..ac18c03dc 100644 --- a/win32/src/win32tsmodule.cpp +++ b/win32/src/win32tsmodule.cpp @@ -836,10 +836,8 @@ PYWIN_MODULE_INIT_FUNC(win32ts) PyModule_AddIntConstant(module, "NOTIFY_FOR_THIS_SESSION", NOTIFY_FOR_THIS_SESSION); PyModule_AddIntConstant(module, "NOTIFY_FOR_ALL_SESSIONS", NOTIFY_FOR_ALL_SESSIONS); - HMODULE h = GetModuleHandle(L"wtsapi32.dll"); - if (h == NULL) - h = LoadLibrary(L"wtsapi32.dll"); - if (h) { + HMODULE h = PyWin_GetOrLoadLibraryHandle("wtsapi32.dll"); + if (h != NULL) { pfnWTSQueryUserToken = (WTSQueryUserTokenfunc)GetProcAddress(h, "WTSQueryUserToken"); pfnWTSRegisterSessionNotification = (WTSRegisterSessionNotificationfunc)GetProcAddress(h, "WTSRegisterSessionNotification"); @@ -847,10 +845,8 @@ PYWIN_MODULE_INIT_FUNC(win32ts) (WTSUnRegisterSessionNotificationfunc)GetProcAddress(h, "WTSUnRegisterSessionNotification"); } - h = GetModuleHandle(L"kernel32.dll"); - if (h == NULL) - h = LoadLibrary(L"kernel32.dll"); - if (h) { + h = PyWin_GetOrLoadLibraryHandle("kernel32.dll"); + if (h != NULL) { pfnProcessIdToSessionId = (ProcessIdToSessionIdfunc)GetProcAddress(h, "ProcessIdToSessionId"); pfnWTSGetActiveConsoleSessionId = (WTSGetActiveConsoleSessionIdfunc)GetProcAddress(h, "WTSGetActiveConsoleSessionId"); From 30e3a753f5f23e8858b67c337edf7b67ba38aadc Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 24 Oct 2024 21:36:02 -0400 Subject: [PATCH 13/13] Fixed Pythonwin's editor failing due to invalid regex import (#2419) --- .github/workflows/main.yml | 4 ++-- CHANGES.txt | 1 + Pythonwin/pywin/framework/editor/editor.py | 10 +++++----- Pythonwin/pywin/framework/mdi_pychecker.py | 3 +-- Pythonwin/pywin/framework/sgrepmdi.py | 2 -- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index db40b4254..88e5ae6ca 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -143,7 +143,7 @@ jobs: cache: pip cache-dependency-path: .github/workflows/main.yml check-latest: true - - run: pip install types-regex types-setuptools PyOpenGL mypy==1.11 + - run: pip install types-setuptools PyOpenGL mypy==1.11 - run: mypy . --python-version=${{ matrix.python-version }} pyright: @@ -162,7 +162,7 @@ jobs: cache-dependency-path: .github/workflows/main.yml check-latest: true # pyright vendors typeshed, but let's make sure we have the most up to date stubs - - run: pip install types-regex types-setuptools PyOpenGL + - run: pip install types-setuptools PyOpenGL - uses: jakebailey/pyright-action@v2 with: python-version: ${{ matrix.python-version }} diff --git a/CHANGES.txt b/CHANGES.txt index c66d05f48..83ca2052e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -14,6 +14,7 @@ https://mhammond.github.io/pywin32_installers.html. Coming in build 309, as yet unreleased -------------------------------------- +* Fixed Pythonwin's editor failing due to invalid regex import (#2419, @Avasam) * Last error wrongly set by some modules (#2302, @CristiFati) * Dropped support for Python 3.7 (#2207, @Avasam) * Implement the creation of SAFEARRAY(VT_RECORD) from a sequence of COM Records (#2317, @geppi) diff --git a/Pythonwin/pywin/framework/editor/editor.py b/Pythonwin/pywin/framework/editor/editor.py index 1095cbe97..a83f20312 100644 --- a/Pythonwin/pywin/framework/editor/editor.py +++ b/Pythonwin/pywin/framework/editor/editor.py @@ -19,7 +19,6 @@ import re -import regex import win32api import win32con import win32ui @@ -36,8 +35,8 @@ # from pywin.mfc.docview import EditView as ParentEditorView # from pywin.mfc.docview import Document as ParentEditorDocument -patImport = regex.symcomp(r"import \(.*\)") -patIndent = regex.compile(r"^\([ \t]*[~ \t]\)") +patImport = re.compile(r"import (?P.*)") +patIndent = re.compile(r"^([ \t]*[~ \t])") ID_LOCATE_FILE = 0xE200 ID_GOTO_LINE = 0xE2001 @@ -364,9 +363,10 @@ def OnRClick(self, params): # look for a module name line = self._obj_.GetLine().strip() flags = win32con.MF_STRING | win32con.MF_ENABLED - if patImport.match(line) == len(line): + matchResult = patImport.match(line) + if matchResult and matchResult[0] == line: menu.AppendMenu( - flags, ID_LOCATE_FILE, "&Locate %s.py" % patImport.group("name") + flags, ID_LOCATE_FILE, "&Locate %s.py" % matchResult.group("name") ) menu.AppendMenu(win32con.MF_SEPARATOR) menu.AppendMenu(flags, win32ui.ID_EDIT_UNDO, "&Undo") diff --git a/Pythonwin/pywin/framework/mdi_pychecker.py b/Pythonwin/pywin/framework/mdi_pychecker.py index cd31a9a18..3108c2e81 100644 --- a/Pythonwin/pywin/framework/mdi_pychecker.py +++ b/Pythonwin/pywin/framework/mdi_pychecker.py @@ -145,8 +145,7 @@ def __radd__(self, other): # Group(1) is the filename, group(2) is the lineno. -# regexGrepResult=regex.compile(r"^\([a-zA-Z]:.*\)(\([0-9]+\))") -# regexGrep=re.compile(r"^([a-zA-Z]:[^(]*)\((\d+)\)") +# regexGrep = re.compile(r"^([a-zA-Z]:[^(]*)\((\d+)\)") regexGrep = re.compile(r"^(..[^\(:]+)?[\(:](\d+)[\):]:?\s*(.*)") # these are the atom numbers defined by Windows for basic dialog controls diff --git a/Pythonwin/pywin/framework/sgrepmdi.py b/Pythonwin/pywin/framework/sgrepmdi.py index f318f731f..0016cc854 100644 --- a/Pythonwin/pywin/framework/sgrepmdi.py +++ b/Pythonwin/pywin/framework/sgrepmdi.py @@ -127,8 +127,6 @@ def __radd__(self, other): # Group(1) is the filename, group(2) is the lineno. -# regexGrepResult=regex.compile(r"^\([a-zA-Z]:.*\)(\([0-9]+\))") - regexGrep = re.compile(r"^([a-zA-Z]:[^(]*)\(([0-9]+)\)") # these are the atom numbers defined by Windows for basic dialog controls