From fc64c4d10f13d6382d7e7b0a788af5e5246760d4 Mon Sep 17 00:00:00 2001 From: Nikita Shulga <2453524+malfet@users.noreply.github.com> Date: Fri, 7 Nov 2025 09:49:55 -0800 Subject: [PATCH 1/3] Add event loop setup for Python 3.14 compatibility Set a new event loop for asyncio in Python 3.14 and above. Otherwise invoking `ghstack` crashes with ``` ERROR: Fatal exception Traceback (most recent call last): File "/Users/nshulga/py3.14-local/lib/python3.14/site-packages/ghstack/logs.py", line 105, in manager yield File "/Users/nshulga/py3.14-local/lib/python3.14/site-packages/ghstack/cli.py", line 47, in cli_context yield shell, config, github File "/Users/nshulga/py3.14-local/lib/python3.14/site-packages/ghstack/cli.py", line 281, in submit ghstack.submit.main( ~~~~~~~~~~~~~~~~~~~^ msg=message, ^^^^^^^^^^^^ ...<13 lines>... direct_opt=direct_opt, ^^^^^^^^^^^^^^^^^^^^^^ ) ^ File "/Users/nshulga/py3.14-local/lib/python3.14/site-packages/ghstack/submit.py", line 259, in main submitter = Submitter(**kwargs) File "", line 24, in __init__ File "/Users/nshulga/py3.14-local/lib/python3.14/site-packages/ghstack/submit.py", line 379, in __post_init__ repo = ghstack.github_utils.get_github_repo_info( github=self.github, ...<4 lines>... remote_name=self.remote_name, ) File "/Users/nshulga/py3.14-local/lib/python3.14/site-packages/ghstack/github_utils.py", line 71, in get_github_repo_info name_with_owner = get_github_repo_name_with_owner( sh=sh, github_url=github_url, remote_name=remote_name, ) File "/Users/nshulga/py3.14-local/lib/python3.14/site-packages/ghstack/github_utils.py", line 28, in get_github_repo_name_with_owner remote_url = sh.git("remote", "get-url", remote_name) File "/Users/nshulga/py3.14-local/lib/python3.14/site-packages/ghstack/shell.py", line 281, in git return self._maybe_rstrip(self.sh(*(("git",) + args), **kwargs)) ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/nshulga/py3.14-local/lib/python3.14/site-packages/ghstack/shell.py", line 200, in sh loop = asyncio.get_event_loop() File "/opt/homebrew/Cellar/python@3.14/3.14.0_1/Frameworks/Python.framework/Versions/3.14/lib/python3.14/asyncio/events.py", line 715, in get_event_loop raise RuntimeError('There is no current event loop in thread %r.' % threading.current_thread().name) RuntimeError: There is no current event loop in thread 'MainThread'. ``` --- src/ghstack/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ghstack/__init__.py b/src/ghstack/__init__.py index bb565c9..051e891 100644 --- a/src/ghstack/__init__.py +++ b/src/ghstack/__init__.py @@ -7,4 +7,9 @@ else: import importlib_metadata +if sys.version_info >= (3, 14): + # Create new event loop as asyncio.get_event_loop() throws runtime error in 3.14 + import asyncio as _asyncio + _asyncio.set_event_loop(_asyncio.new_event_loop()) + __version__ = importlib_metadata.version("ghstack") # type: ignore[no-untyped-call] From 21dca7d71f9e0f5824bc48a33d643fd36b9a6a3b Mon Sep 17 00:00:00 2001 From: Nikita Shulga <2453524+malfet@users.noreply.github.com> Date: Fri, 7 Nov 2025 10:17:05 -0800 Subject: [PATCH 2/3] Update src/ghstack/__init__.py --- src/ghstack/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ghstack/__init__.py b/src/ghstack/__init__.py index 051e891..ab4e0b0 100644 --- a/src/ghstack/__init__.py +++ b/src/ghstack/__init__.py @@ -10,6 +10,7 @@ if sys.version_info >= (3, 14): # Create new event loop as asyncio.get_event_loop() throws runtime error in 3.14 import asyncio as _asyncio + _asyncio.set_event_loop(_asyncio.new_event_loop()) __version__ = importlib_metadata.version("ghstack") # type: ignore[no-untyped-call] From fc091fbbe54fb00e8ade6a2e375201470be59034 Mon Sep 17 00:00:00 2001 From: Nikita Shulga Date: Fri, 7 Nov 2025 10:57:26 -0800 Subject: [PATCH 3/3] Move to main --- src/ghstack/__init__.py | 6 ------ src/ghstack/cli.py | 7 +++++++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ghstack/__init__.py b/src/ghstack/__init__.py index ab4e0b0..bb565c9 100644 --- a/src/ghstack/__init__.py +++ b/src/ghstack/__init__.py @@ -7,10 +7,4 @@ else: import importlib_metadata -if sys.version_info >= (3, 14): - # Create new event loop as asyncio.get_event_loop() throws runtime error in 3.14 - import asyncio as _asyncio - - _asyncio.set_event_loop(_asyncio.new_event_loop()) - __version__ = importlib_metadata.version("ghstack") # type: ignore[no-untyped-call] diff --git a/src/ghstack/cli.py b/src/ghstack/cli.py index 5a37868..d27fe65 100644 --- a/src/ghstack/cli.py +++ b/src/ghstack/cli.py @@ -1,5 +1,6 @@ import asyncio import contextlib +import sys from typing import Generator, List, Optional, Tuple import click @@ -79,6 +80,12 @@ def main( """ Submit stacks of diffs to Github """ + if sys.version_info >= (3, 14): + # Create new event loop as asyncio.get_event_loop() throws runtime error in 3.14 + import asyncio as _asyncio + + _asyncio.set_event_loop(_asyncio.new_event_loop()) + EXIT_STACK.enter_context(ghstack.logs.manager(debug=debug)) if not ctx.invoked_subcommand: