[Python][Support 3.14] Enable 3.14 in Python Basic, Bazel and Distrib tests#40403
[Python][Support 3.14] Enable 3.14 in Python Basic, Bazel and Distrib tests#40403sreenithi wants to merge 25 commits intogrpc:masterfrom
Conversation
| not be set as the default event loop for the main thread. | ||
| """ | ||
| try: | ||
| return asyncio.get_running_loop() |
There was a problem hiding this comment.
This method returns a running loop, but in the new method introduced, we are not returning a running loop.
Question - Do we need to make the loop running before returning?
There was a problem hiding this comment.
Good point, but we're just retaining the previous behaviour here. Even previously, we returned a running loop only if it was already running, and otherwise just return an existing (not running) event loop returned by asyncio.get_event_loop_policy().get_event_loop() or a new loop returned by asyncio.get_event_loop_policy().new_event_loop().
We're using the same behaviour here, and in addition also setting this newly created loop as the current event loop for the thread using asyncio.set_event_loop(loop).
And following that, we bind to the event loop and continue using it here.
There was a problem hiding this comment.
For posterity: this will be handled separately, as a fix for #39507.
|
The current implementation doesn't return a running loop and creates a new loop every time we call the function import asyncio
import threading
# Global variable to track the created loop
_global_loop = None
_loop_lock = threading.Lock()
def get_running_event_loop():
global _global_loop
try:
return asyncio.get_running_loop()
except RuntimeError:
with _loop_lock:
if _global_loop is not None and _global_loop.is_running():
print("reusing existing loop")
return _global_loop
# No loop is running, so we need to create and start one
print("creating a loop")
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
# Start the loop in a daemon thread so it doesn't block the main thread
def run_forever():
loop.run_forever()
thread = threading.Thread(target=run_forever, daemon=True)
thread.start()
_global_loop = loop
return loop |
…ts (#40289) This PR adds Python 3.14 support for Distribtests by updating relevant docker images and distribtest build files for Linux, MacOS and Windows environments. However, artifact generation in distribtests will be enabled in the next PR #40403 Prerequisites merged before this PR: - #40317 - #40354 - #40383 Closes #40289 COPYBARA_INTEGRATE_REVIEW=#40289 from sreenithi:python_314_test_support 3b8bf96 PiperOrigin-RevId: 802967999
sergiitk
left a comment
There was a problem hiding this comment.
Approved as is. There's a few comments I left, but nothing that can't be done in a follow-up PR.
| # The default start method of multiprocessing in linux has changed to | ||
| # `forkserver` instead of `fork` from Python 3.14. This causes problems | ||
| # with pickling target methods that use decorators. | ||
| # Hence manually set to use the `fork` start method. | ||
| if sys.version_info >= (3, 14) and ("linux" in sys.platform): | ||
| multiprocessing.set_start_method("fork", force=True) |
There was a problem hiding this comment.
A few notes regarding this change. First, we can do this once in DynamicStubTest.setUpClass(), and force=True won't be needed. Second, we should add the same logic to tools/distrib/python/grpcio_tools/grpc_tools/test/protoc_test.py.
But this doesn't block this PR, we can fix it in a follow-up.
|
|
||
| @unittest.skipIf( | ||
| sys.version_info >= (3, 14), | ||
| "Skip for Python 3.14+ until https://github.com/grpc/grpc/pull/40293 is merged", |
There was a problem hiding this comment.
That PR was pretty much a demo I wasn't intending to merge this specific branch. I'd rather change this to
| "Skip for Python 3.14+ until https://github.com/grpc/grpc/pull/40293 is merged", | |
| "Skip for Python 3.14+ until https://github.com/grpc/grpc/issues/39507 is fixed", |
|
|
||
| @unittest.skipIf( | ||
| sys.version_info >= (3, 14), | ||
| "Skip for Python 3.14+ until https://github.com/grpc/grpc/pull/40293 is merged", |
There was a problem hiding this comment.
Same
| "Skip for Python 3.14+ until https://github.com/grpc/grpc/pull/40293 is merged", | |
| "Skip for Python 3.14+ until https://github.com/grpc/grpc/issues/39507 is fixed", |
…ts (grpc#40289) This PR adds Python 3.14 support for Distribtests by updating relevant docker images and distribtest build files for Linux, MacOS and Windows environments. However, artifact generation in distribtests will be enabled in the next PR grpc#40403 Prerequisites merged before this PR: - grpc#40317 - grpc#40354 - grpc#40383 Closes grpc#40289 COPYBARA_INTEGRATE_REVIEW=grpc#40289 from sreenithi:python_314_test_support 3b8bf96 PiperOrigin-RevId: 802967999
…ts (grpc#40289) This PR adds Python 3.14 support for Distribtests by updating relevant docker images and distribtest build files for Linux, MacOS and Windows environments. However, artifact generation in distribtests will be enabled in the next PR grpc#40403 Prerequisites merged before this PR: - grpc#40317 - grpc#40354 - grpc#40383 Closes grpc#40289 COPYBARA_INTEGRATE_REVIEW=grpc#40289 from sreenithi:python_314_test_support 3b8bf96 PiperOrigin-RevId: 802967999
…ters for distribtests (#40637) Backport of #40289 to v1.75.x. --- This PR adds Python 3.14 support for Distribtests by updating relevant docker images and distribtest build files for Linux, MacOS and Windows environments. However, artifact generation in distribtests will be enabled in the next PR #40403 Prerequisites merged before this PR: - #40317 - #40354 - #40383
…ts (grpc#40289) This PR adds Python 3.14 support for Distribtests by updating relevant docker images and distribtest build files for Linux, MacOS and Windows environments. However, artifact generation in distribtests will be enabled in the next PR grpc#40403 Prerequisites merged before this PR: - grpc#40317 - grpc#40354 - grpc#40383 Closes grpc#40289 COPYBARA_INTEGRATE_REVIEW=grpc#40289 from sreenithi:python_314_test_support 3b8bf96 PiperOrigin-RevId: 802967999
… tests (grpc#40403) This PR enables Python 3.14 in all the different tests - Basic tests (Native Python tests), Bazel tests and Distrib tests to build Python 3.14 artifacts. In addition, it also updates all the public facing METADATA versions. ## Distribtests Required pre-requisite changes to enable 3.14 artifacts are covered in grpc#40289 . ## Bazel tests Enabling Python 3.14 required updating the rules_python version to a more recent version that supports 3.14. This was done in grpc#40602 ## Basic tests The following errors were caught by the Basic tests when running via Python 3.14 and resolved in this PR: ### 1) No running event loop for AsyncIO when run outside an async function ``` Traceback (most recent call last): File "src/python/grpcio/grpc/_cython/_cygrpc/aio/common.pyx.pxi", line 184, in grpc._cython.cygrpc.get_working_loop RuntimeError: no running event loop ``` This was caught by the `tests_aio.unit.outside_init_test.TestOutsideInit` and `tests_aio.unit.init_test.TestInit` tests, and was also previously reported in grpc#39507 with the root cause. Following some investigation, the fix is being worked on by @sergiitk in PR grpc#40293. In order to parallelize the fix and this PR, these 2 tests are currently being skipped for Python 3.14 and above. ### 2) Pickling error from the `multiprocessing` library ``` _pickle.PicklingError: Can't pickle <function _test_well_known_types at 0x7f3937eee610>: it's not the same object as tests.unit._dynamic_stubs_test._test_well_known_types when serializing dict item '_target' when serializing multiprocessing.context.Process state when serializing multiprocessing.context.Process object ``` This was caught by the `tests.unit._dynamic_stubs_test.DynamicStubTest` which runs test cases in a subprocess using the `multiprocessing` library. Error root cause: - The default start method of multiprocessing in linux has changed to `forkserver` instead of `fork` from Python 3.14. - `forkserver` has a few extra restrictions for picklability as compared to `fork` (Ref: [Python Docs](https://docs.python.org/3.14/library/multiprocessing.html#the-spawn-and-forkserver-start-methods)) - All the [test case functions](https://github.com/grpc/grpc/blob/0243842d5d10f624bf8f09f45026dd300805502f/src/python/grpcio_tests/tests/unit/_dynamic_stubs_test.py#L115) in the DynamicStubTest that are provided as `target` to the `multiprocessing.Process` use decorators. This causes problems when pickling them. Hence to resolve this, we manually set the 'start method' of `multiprocessing` to use the `fork` start method. Closes grpc#40403 PiperOrigin-RevId: 804290760
… tests (grpc#40403) This PR enables Python 3.14 in all the different tests - Basic tests (Native Python tests), Bazel tests and Distrib tests to build Python 3.14 artifacts. In addition, it also updates all the public facing METADATA versions. Required pre-requisite changes to enable 3.14 artifacts are covered in grpc#40289 . Enabling Python 3.14 required updating the rules_python version to a more recent version that supports 3.14. This was done in grpc#40602 The following errors were caught by the Basic tests when running via Python 3.14 and resolved in this PR: ``` Traceback (most recent call last): File "src/python/grpcio/grpc/_cython/_cygrpc/aio/common.pyx.pxi", line 184, in grpc._cython.cygrpc.get_working_loop RuntimeError: no running event loop ``` This was caught by the `tests_aio.unit.outside_init_test.TestOutsideInit` and `tests_aio.unit.init_test.TestInit` tests, and was also previously reported in grpc#39507 with the root cause. Following some investigation, the fix is being worked on by @sergiitk in PR grpc#40293. In order to parallelize the fix and this PR, these 2 tests are currently being skipped for Python 3.14 and above. ``` _pickle.PicklingError: Can't pickle <function _test_well_known_types at 0x7f3937eee610>: it's not the same object as tests.unit._dynamic_stubs_test._test_well_known_types when serializing dict item '_target' when serializing multiprocessing.context.Process state when serializing multiprocessing.context.Process object ``` This was caught by the `tests.unit._dynamic_stubs_test.DynamicStubTest` which runs test cases in a subprocess using the `multiprocessing` library. Error root cause: - The default start method of multiprocessing in linux has changed to `forkserver` instead of `fork` from Python 3.14. - `forkserver` has a few extra restrictions for picklability as compared to `fork` (Ref: [Python Docs](https://docs.python.org/3.14/library/multiprocessing.html#the-spawn-and-forkserver-start-methods)) - All the [test case functions](https://github.com/grpc/grpc/blob/0243842d5d10f624bf8f09f45026dd300805502f/src/python/grpcio_tests/tests/unit/_dynamic_stubs_test.py#L115) in the DynamicStubTest that are provided as `target` to the `multiprocessing.Process` use decorators. This causes problems when pickling them. Hence to resolve this, we manually set the 'start method' of `multiprocessing` to use the `fork` start method. Closes grpc#40403 PiperOrigin-RevId: 804290760
#40726) Backport of #40403 to v1.75.x. --- This PR enables Python 3.14 in all the different tests - Basic tests (Native Python tests), Bazel tests and Distrib tests to build Python 3.14 artifacts. In addition, it also updates all the public facing METADATA versions. ## Distribtests Required pre-requisite changes to enable 3.14 artifacts are covered in #40289 . ## Bazel tests Enabling Python 3.14 required updating the rules_python version to a more recent version that supports 3.14. This was done in #40602 ## Basic tests The following errors were caught by the Basic tests when running via Python 3.14 and resolved in this PR: ### 1) No running event loop for AsyncIO when run outside an async function ``` Traceback (most recent call last): File "src/python/grpcio/grpc/_cython/_cygrpc/aio/common.pyx.pxi", line 184, in grpc._cython.cygrpc.get_working_loop RuntimeError: no running event loop ``` This was caught by the `tests_aio.unit.outside_init_test.TestOutsideInit` and `tests_aio.unit.init_test.TestInit` tests, and was also previously reported in #39507 with the root cause. Following some investigation, the fix is being worked on by @sergiitk in PR #40293. In order to parallelize the fix and this PR, these 2 tests are currently being skipped for Python 3.14 and above. ### 2) Pickling error from the `multiprocessing` library ``` _pickle.PicklingError: Can't pickle <function _test_well_known_types at 0x7f3937eee610>: it's not the same object as tests.unit._dynamic_stubs_test._test_well_known_types when serializing dict item '_target' when serializing multiprocessing.context.Process state when serializing multiprocessing.context.Process object ``` This was caught by the `tests.unit._dynamic_stubs_test.DynamicStubTest` which runs test cases in a subprocess using the `multiprocessing` library. Error root cause: - The default start method of multiprocessing in linux has changed to `forkserver` instead of `fork` from Python 3.14. - `forkserver` has a few extra restrictions for picklability as compared to `fork` (Ref: [Python Docs](https://docs.python.org/3.14/library/multiprocessing.html#the-spawn-and-forkserver-start-methods)) - All the [test case functions](https://github.com/grpc/grpc/blob/0243842d5d10f624bf8f09f45026dd300805502f/src/python/grpcio_tests/tests/unit/_dynamic_stubs_test.py#L115) in the DynamicStubTest that are provided as `target` to the `multiprocessing.Process` use decorators. This causes problems when pickling them. Hence to resolve this, we manually set the 'start method' of `multiprocessing` to use the `fork` start method.
This PR enables Python 3.14 in all the different tests - Basic tests (Native Python tests), Bazel tests and Distrib tests to build Python 3.14 artifacts. In addition, it also updates all the public facing METADATA versions.
Distribtests
Required pre-requisite changes to enable 3.14 artifacts are covered in #40289 .
Bazel tests
Enabling Python 3.14 required updating the rules_python version to a more recent version that supports 3.14. This was done in #40602
Basic tests
The following errors were caught by the Basic tests when running via Python 3.14 and resolved in this PR:
1) No running event loop for AsyncIO when run outside an async function
This was caught by the
tests_aio.unit.outside_init_test.TestOutsideInitandtests_aio.unit.init_test.TestInittests, and was also previously reported in #39507 with the root cause.Following some investigation, the fix is being worked on by @sergiitk in PR #40293. In order to parallelize the fix and this PR, these 2 tests are currently being skipped for Python 3.14 and above.
2) Pickling error from the
multiprocessinglibraryThis was caught by the
tests.unit._dynamic_stubs_test.DynamicStubTestwhich runs test cases in a subprocess using themultiprocessinglibrary.Error root cause:
forkserverinstead offorkfrom Python 3.14.forkserverhas a few extra restrictions for picklability as compared tofork(Ref: Python Docs)targetto themultiprocessing.Processuse decorators. This causes problems when pickling them.Hence to resolve this, we manually set the 'start method' of
multiprocessingto use theforkstart method.