From 7e8d26b180ee054ca414aeec63795d9c0eaf601e Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Mon, 17 Jun 2024 11:08:07 -0400 Subject: [PATCH] 3.13 support (#2260) --- .github/workflows/main.yml | 11 +++++++---- .gitignore | 1 + Pythonwin/win32thread.cpp | 2 +- Pythonwin/win32uimodule.cpp | 2 +- adodbapi/test/adodbapitest.py | 24 ++++++++++++++++++------ build_all.bat | 4 ++++ com/win32com/src/oleargs.cpp | 2 +- com/win32com/src/univgw.cpp | 2 +- com/win32com/test/testIterators.py | 2 +- com/win32comext/shell/src/shell.cpp | 2 +- make_all.bat | 5 +++++ setup.py | 1 + win32/src/PyTime.cpp | 2 +- win32/src/timermodule.cpp | 2 +- win32/src/win32gui.i | 2 +- win32/src/win32pdhmodule.cpp | 2 +- win32/src/win32process.i | 2 +- win32/src/win32rasmodule.cpp | 2 +- 18 files changed, 48 insertions(+), 22 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3478f91f7..f81e09133 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,7 +17,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12-dev"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13-dev"] architecture: ["x64", "x86"] steps: @@ -30,6 +30,7 @@ jobs: architecture: ${{ matrix.architecture }} cache: pip cache-dependency-path: .github/workflows/main.yml + check-latest: true - name: Setup environment run: | @@ -66,8 +67,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.10", "3.11", "3.12-dev"] - + python-version: ["3.10", "3.11", "3.12", "3.13-dev"] steps: - uses: actions/checkout@v4 @@ -78,6 +78,7 @@ jobs: architecture: "x64" cache: pip cache-dependency-path: .github/workflows/main.yml + check-latest: true - name: Setup Environment run: | @@ -137,6 +138,7 @@ jobs: python-version: ${{ matrix.python-version }} cache: pip cache-dependency-path: .github/workflows/main.yml + check-latest: true - run: pip install types-regex types-setuptools mypy==1.9 - run: mypy . --python-version=${{ matrix.python-version }} @@ -145,7 +147,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13-dev"] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 @@ -153,6 +155,7 @@ jobs: python-version: ${{ matrix.python-version }} cache: pip 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 - uses: jakebailey/pyright-action@v2 diff --git a/.gitignore b/.gitignore index dc0875a8f..ca30ad34d 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,4 @@ venv.bak/ .idea/ .DS_Store vagrant_helpers/bootstrap-salt.ps1 +.vscode/ diff --git a/Pythonwin/win32thread.cpp b/Pythonwin/win32thread.cpp index c26e8c7a1..f2b04f43c 100644 --- a/Pythonwin/win32thread.cpp +++ b/Pythonwin/win32thread.cpp @@ -164,7 +164,7 @@ unsigned int ThreadWorkerEntryPoint(LPVOID lpvoid) { CPythonWinThread *pThis = (CPythonWinThread *)lpvoid; CEnterLeavePython _celp; - PyObject *result = PyEval_CallObject(pThis->obFunc, pThis->obArgs); + PyObject *result = PyObject_CallObject(pThis->obFunc, pThis->obArgs); if (result == NULL) { if (PyErr_Occurred() == PyExc_SystemExit) PyErr_Clear(); diff --git a/Pythonwin/win32uimodule.cpp b/Pythonwin/win32uimodule.cpp index 25cb0d8af..e5e03878f 100644 --- a/Pythonwin/win32uimodule.cpp +++ b/Pythonwin/win32uimodule.cpp @@ -600,7 +600,7 @@ static DWORD FilterFunc(DWORD dwExceptionCode) return (dwRet); } -PyObject *gui_call_object(PyObject *themeth, PyObject *thearglst) { return PyEval_CallObject(themeth, thearglst); } +PyObject *gui_call_object(PyObject *themeth, PyObject *thearglst) { return PyObject_CallObject(themeth, thearglst); } void gui_print_error(void) { diff --git a/adodbapi/test/adodbapitest.py b/adodbapi/test/adodbapitest.py index b8d98593d..fc5babf9b 100644 --- a/adodbapi/test/adodbapitest.py +++ b/adodbapi/test/adodbapitest.py @@ -1546,17 +1546,29 @@ def testTimestamp(self): assert t1 < obj < t2, obj -suites = [unittest.makeSuite(TestPythonDateTimeConverter, "test")] +suites = [ + unittest.defaultTestLoader.loadTestsFromModule(TestPythonDateTimeConverter, "test") +] if config.doTimeTest: - suites.append(unittest.makeSuite(TestPythonTimeConverter, "test")) + suites.append( + unittest.defaultTestLoader.loadTestsFromModule(TestPythonTimeConverter, "test") + ) if config.doAccessTest: - suites.append(unittest.makeSuite(TestADOwithAccessDB, "test")) + suites.append( + unittest.defaultTestLoader.loadTestsFromModule(TestADOwithAccessDB, "test") + ) if config.doSqlServerTest: - suites.append(unittest.makeSuite(TestADOwithSQLServer, "test")) + suites.append( + unittest.defaultTestLoader.loadTestsFromModule(TestADOwithSQLServer, "test") + ) if config.doMySqlTest: - suites.append(unittest.makeSuite(TestADOwithMySql, "test")) + suites.append( + unittest.defaultTestLoader.loadTestsFromModule(TestADOwithMySql, "test") + ) if config.doPostgresTest: - suites.append(unittest.makeSuite(TestADOwithPostgres, "test")) + suites.append( + unittest.defaultTestLoader.loadTestsFromModule(TestADOwithPostgres, "test") + ) class cleanup_manager: diff --git a/build_all.bat b/build_all.bat index 616e03a5e..536aee00d 100644 --- a/build_all.bat +++ b/build_all.bat @@ -22,6 +22,10 @@ py -3.12-32 setup.py -q build @if errorlevel 1 goto failed py -3.12 setup.py -q build @if errorlevel 1 goto failed +py -3.13-32 setup.py -q build +@if errorlevel 1 goto failed +py -3.13 setup.py -q build +@if errorlevel 1 goto failed goto xit :failed diff --git a/com/win32com/src/oleargs.cpp b/com/win32com/src/oleargs.cpp index 0187949f6..33c925987 100644 --- a/com/win32com/src/oleargs.cpp +++ b/com/win32com/src/oleargs.cpp @@ -1671,7 +1671,7 @@ BOOL PyCom_MakeOlePythonCall(PyObject *handler, DISPPARAMS FAR *params, VARIANT argList = Py_BuildValue("OO", varArgs, addnlArgs); Py_DECREF(varArgs); } - PyObject *result = PyEval_CallObject(handler, argList); + PyObject *result = PyObject_CallObject(handler, argList); Py_XDECREF(argList); Py_XDECREF(namedArgList); // handlers reference cleaned up by virtual manager. diff --git a/com/win32com/src/univgw.cpp b/com/win32com/src/univgw.cpp index aec11ad12..73616e48a 100644 --- a/com/win32com/src/univgw.cpp +++ b/com/win32com/src/univgw.cpp @@ -98,7 +98,7 @@ static HRESULT univgw_dispatch(DWORD index, gw_object *_this, va_list argPtr) PyTuple_SET_ITEM(obArgs, 2, obArgPtr); // call the provided method - PyObject *result = PyEval_CallObjectWithKeywords(vtbl->dispatcher, obArgs, NULL); + PyObject *result = PyObject_CallObject(vtbl->dispatcher, obArgs); // done with the arguments and the contained objects Py_DECREF(obArgs); diff --git a/com/win32com/test/testIterators.py b/com/win32com/test/testIterators.py index fe336e54e..260cce673 100644 --- a/com/win32com/test/testIterators.py +++ b/com/win32com/test/testIterators.py @@ -132,7 +132,7 @@ def suite(): and issubclass(item, unittest.TestCase) and item != _BaseTestCase ): - suite.addTest(unittest.makeSuite(item)) + suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(item)) return suite diff --git a/com/win32comext/shell/src/shell.cpp b/com/win32comext/shell/src/shell.cpp index 27d51f8d6..b6d133734 100644 --- a/com/win32comext/shell/src/shell.cpp +++ b/com/win32comext/shell/src/shell.cpp @@ -1068,7 +1068,7 @@ static int CALLBACK PyBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LP #endif if (!args) goto done; - result = PyEval_CallObject(pc->fn, args); + result = PyObject_CallObject(pc->fn, args); // API says must return 0, but there might be a good reason. if (result && PyLong_Check(result)) rc = PyLong_AsLong(result); diff --git a/make_all.bat b/make_all.bat index 527b292ad..638d6a166 100644 --- a/make_all.bat +++ b/make_all.bat @@ -40,6 +40,10 @@ py -3.9 setup.py -q bdist_wininst --skip-build --target-version=3.12 py -3.12-32 setup.py -q bdist_wheel --skip-build py -3.12 setup.py -q bdist_wheel --skip-build +py -3.9 setup.py -q bdist_wininst --skip-build --target-version=3.13 +py -3.13-32 setup.py -q bdist_wheel --skip-build +py -3.13 setup.py -q bdist_wheel --skip-build + rem ARM64 builds - requires you to select: rem * "Visual C++ compilers and libraries for ARM64" rem * "Visual C++ for MFC for ARM64" @@ -47,6 +51,7 @@ rem from "Individual Components" in VS setup. py -3.10 setup.py -q build_ext --plat-name win-arm64 build --plat-name win-arm64 bdist_wheel --plat-name win-arm64 py -3.11 setup.py -q build_ext --plat-name win-arm64 build --plat-name win-arm64 bdist_wheel --plat-name win-arm64 py -3.12 setup.py -q build_ext --plat-name win-arm64 build --plat-name win-arm64 bdist_wheel --plat-name win-arm64 +py -3.13 setup.py -q build_ext --plat-name win-arm64 build --plat-name win-arm64 bdist_wheel --plat-name win-arm64 @goto xit :couldnt_rm diff --git a/setup.py b/setup.py index a55cbef77..6ce1ed77d 100644 --- a/setup.py +++ b/setup.py @@ -2207,6 +2207,7 @@ def convert_optional_data_files(files): "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Programming Language :: Python :: Implementation :: CPython", ] diff --git a/win32/src/PyTime.cpp b/win32/src/PyTime.cpp index 502ed8787..2110ef5b6 100644 --- a/win32/src/PyTime.cpp +++ b/win32/src/PyTime.cpp @@ -273,7 +273,7 @@ PyObject *PyWin_NewTime(PyObject *timeOb) if (method == NULL) PyErr_Clear(); else { - timeOb = PyEval_CallObject(method, NULL); + timeOb = PyObject_CallObject(method, NULL); Py_DECREF(method); if (!timeOb) return NULL; diff --git a/win32/src/timermodule.cpp b/win32/src/timermodule.cpp index cc4788918..f06e8a4e6 100644 --- a/win32/src/timermodule.cpp +++ b/win32/src/timermodule.cpp @@ -34,7 +34,7 @@ VOID CALLBACK py_win32_timer_callback(HWND hwnd, UINT msg, UINT_PTR timer_id, DW // the callback itself removes the function from the map. Py_INCREF(callback_function); PyObject *callback_args = Py_BuildValue("(Ok)", py_timer_id, time); - PyObject *result = PyEval_CallObject(callback_function, callback_args); + PyObject *result = PyObject_CallObject(callback_function, callback_args); if (!result) { // Is this necessary, or will python already have flagged diff --git a/win32/src/win32gui.i b/win32/src/win32gui.i index a59ae2823..c579241cd 100644 --- a/win32/src/win32gui.i +++ b/win32/src/win32gui.i @@ -6065,7 +6065,7 @@ static int CALLBACK PySortFunc( assert(!PyErr_Occurred()); args = Py_BuildValue("llO", lParam1, lParam2, pc->data); if (!args) goto done; - result = PyEval_CallObject(pc->fn, args); + result = PyObject_CallObject(pc->fn, args); // API says must return 0, but there might be a good reason. if (!result) goto done; if (!PyLong_Check(result)) { diff --git a/win32/src/win32pdhmodule.cpp b/win32/src/win32pdhmodule.cpp index 5631da52a..8d3c7d700 100644 --- a/win32/src/win32pdhmodule.cpp +++ b/win32/src/win32pdhmodule.cpp @@ -977,7 +977,7 @@ PDH_STATUS __stdcall PyCounterPathCallback(DWORD_PTR dwArg) rc = ERROR_OUTOFMEMORY; } else { - result = PyEval_CallObject(pMy->func, args); + result = PyObject_CallObject(pMy->func, args); if (result == NULL) { PyErr_Print(); // *Don't* leave exception hanging rc = PDH_INVALID_DATA; diff --git a/win32/src/win32process.i b/win32/src/win32process.i index beeb85981..331ed0f23 100644 --- a/win32/src/win32process.i +++ b/win32/src/win32process.i @@ -361,7 +361,7 @@ unsigned __stdcall ThreadEntryPoint( void *arg ) { CEnterLeavePython _celp; PythonThreadData *ptd = (PythonThreadData *)arg; - PyObject *pyrc = PyEval_CallObject(ptd->m_obFunc, ptd->m_obArgs); + PyObject *pyrc = PyObject_CallObject(ptd->m_obFunc, ptd->m_obArgs); delete ptd; if (pyrc==NULL) { fprintf(stderr, "Unhandled exception in beginthreadex created thread:\n"); diff --git a/win32/src/win32rasmodule.cpp b/win32/src/win32rasmodule.cpp index fe19ee053..3ed8c33fe 100644 --- a/win32/src/win32rasmodule.cpp +++ b/win32/src/win32rasmodule.cpp @@ -480,7 +480,7 @@ VOID CALLBACK PyRasDialFunc1(HRASCONN hrasconn, // handle to RAS connection PyObject *args = Py_BuildValue("Niiii", PyWinLong_FromHANDLE(hrasconn), unMsg, rascs, dwError, dwExtendedError); if (args == NULL) return; - PyObject *res = PyEval_CallObject(handler, args); + PyObject *res = PyObject_CallObject(handler, args); Py_DECREF(args); if (res == NULL) { PyErr_Print();