Skip to content

Commit b7dc0d3

Browse files
authored
fix: ensure event loop creation for Python 3.14 compatibility (#41)
1 parent a05a668 commit b7dc0d3

87 files changed

Lines changed: 6017 additions & 3453 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/cd.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- uses: actions/checkout@v4
1919
- uses: actions/setup-python@v5
2020
with:
21-
python-version: '3.13'
21+
python-version: '3.14'
2222
- name: version
2323
run: sed -i "s/__version__ = '.*'/__version__ = '$VERSION'/g" aiocli/__init__.py
2424
- name: deps

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
strategy:
1515
matrix:
1616
os: [ ubuntu-latest ]
17-
python-version: [ '3.10', '3.11', '3.12', '3.13' ]
17+
python-version: [ '3.10', '3.11', '3.12', '3.13', '3.14' ]
1818
steps:
1919
- uses: actions/checkout@v4
2020
- uses: actions/setup-python@v5

Containerfile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ FROM docker.io/continuumio/miniconda3:latest AS miniconda3
22

33
WORKDIR /app
44

5-
RUN conda install -y --download-only "python=3.12" && \
5+
RUN conda install -y --download-only "python=3.13" && \
6+
conda install -y --download-only "python=3.12" && \
67
conda install -y --download-only "python=3.11" && \
78
conda install -y --download-only "python=3.10"
89

@@ -11,6 +12,11 @@ COPY . ./
1112
ENTRYPOINT ["python3"]
1213
CMD ["run-script"]
1314

15+
FROM miniconda3 AS py313
16+
17+
RUN conda install -y "python=3.13"
18+
RUN --mount=type=cache,target=/root/.cache/pip python3 run-script dev-install
19+
1420
FROM miniconda3 AS py312
1521

1622
RUN conda install -y "python=3.12"

aiocli/commander.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import asyncio
22
import signal
33
import sys
4-
from asyncio import all_tasks, gather, get_event_loop
4+
from asyncio import (
5+
all_tasks,
6+
gather,
7+
get_event_loop,
8+
get_running_loop,
9+
new_event_loop,
10+
set_event_loop,
11+
)
512
from asyncio.events import AbstractEventLoop
613
from typing import Any, Callable, List, Optional, Set, Union
714

@@ -140,7 +147,16 @@ def run_app(
140147
override_return: Optional[bool] = None,
141148
) -> Any:
142149
def wrapper(*args, **kwargs) -> Optional[int]: # type: ignore
143-
loop_ = loop or get_event_loop()
150+
try:
151+
# Try to get the currently running event loop (Python ≥3.10 preferred API).
152+
# In Python 3.14+, get_event_loop() no longer creates a default loop automatically.
153+
# If no loop is running yet, this raises RuntimeError — we handle that below.
154+
loop_ = loop or get_running_loop()
155+
except RuntimeError:
156+
# No event loop exists in the current thread (Python 3.14+ behavior).
157+
# Create and set a new loop to preserve backward compatibility with Python ≤3.13.
158+
loop_ = new_event_loop()
159+
set_event_loop(loop_)
144160

145161
app_ = app if isinstance(app, Application) else app()
146162

aiocli/commander_app.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -726,11 +726,13 @@ async def _resolve_or_retrieve_from_cache_dependency(self, of: str, annotation:
726726

727727
async def _execute_command_handler(self, handler: CommandHandler, kwargs: Dict[str, Any]) -> Any:
728728
self._log(
729-
msg='Executing command handler with: {0}.'.format(
730-
', '.join(['{0}={1}'.format(key, val) for key, val in kwargs.items()])
731-
)
732-
if kwargs
733-
else 'Executing command handler.',
729+
msg=(
730+
'Executing command handler with: {0}.'.format(
731+
', '.join(['{0}={1}'.format(key, val) for key, val in kwargs.items()])
732+
)
733+
if kwargs
734+
else 'Executing command handler.'
735+
),
734736
)
735737
return await resolve_function(handler, **kwargs)
736738

compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ services:
55
dockerfile: Containerfile
66
# target: py310
77
# target: py311
8-
target: py312
8+
# target: py312
99
# image: ghcr.io/aiopy/python-aiocli:py310-${VERSION:-latest}
1010
# image: ghcr.io/aiopy/python-aiocli:py311-${VERSION:-latest}
11-
image: ghcr.io/aiopy/python-aiocli:py312-${VERSION:-latest}
11+
image: ghcr.io/aiopy/python-aiocli:py314-${VERSION:-latest}
1212
volumes:
1313
- .:/app

docs_src/docs/en/release-notes.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,32 @@
11
## CHANGELOG
22

3+
### **1.11.x**
4+
5+
* Drop Python 3.9 support.
6+
* Bump dev deps.
7+
8+
### **1.10.x**
9+
10+
* Drop Python 3.8 support.
11+
* Add Python 3.13 support.
12+
13+
### **1.9.x**
14+
15+
* Drop Python 3.7 support.
16+
* Add Python 3.12 support.
17+
18+
### **1.8.x**
19+
20+
* Add more controls over the original input and app output.
21+
22+
### **1.7.x**
23+
24+
* Improve commands and app help usage.
25+
* Lazy loading of the App and State instances.
26+
* Improve command hooks.
27+
* Add after middlware hook.
28+
* Colorize help usage.
29+
330
### **1.6.x**
431

532
* Add State.

docs_src/generated/en/404.html

Lines changed: 240 additions & 119 deletions
Large diffs are not rendered by default.

docs_src/generated/en/advanced/exception_handler/index.html

Lines changed: 265 additions & 164 deletions
Large diffs are not rendered by default.

docs_src/generated/en/advanced/hooks/index.html

Lines changed: 270 additions & 169 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)