diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 7d72417..90c5b1f 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: '3.13' + python-version: '3.14' - name: version run: sed -i "s/__version__ = '.*'/__version__ = '$VERSION'/g" aiocli/__init__.py - name: deps diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db7cb66..26b2853 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: os: [ ubuntu-latest ] - python-version: [ '3.10', '3.11', '3.12', '3.13' ] + python-version: [ '3.10', '3.11', '3.12', '3.13', '3.14' ] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 diff --git a/Containerfile b/Containerfile index b90c085..cd9495b 100644 --- a/Containerfile +++ b/Containerfile @@ -2,7 +2,8 @@ FROM docker.io/continuumio/miniconda3:latest AS miniconda3 WORKDIR /app -RUN conda install -y --download-only "python=3.12" && \ +RUN conda install -y --download-only "python=3.13" && \ + conda install -y --download-only "python=3.12" && \ conda install -y --download-only "python=3.11" && \ conda install -y --download-only "python=3.10" @@ -11,6 +12,11 @@ COPY . ./ ENTRYPOINT ["python3"] CMD ["run-script"] +FROM miniconda3 AS py313 + +RUN conda install -y "python=3.13" +RUN --mount=type=cache,target=/root/.cache/pip python3 run-script dev-install + FROM miniconda3 AS py312 RUN conda install -y "python=3.12" diff --git a/aiocli/commander.py b/aiocli/commander.py index 405b514..81f3aae 100644 --- a/aiocli/commander.py +++ b/aiocli/commander.py @@ -1,7 +1,14 @@ import asyncio import signal import sys -from asyncio import all_tasks, gather, get_event_loop +from asyncio import ( + all_tasks, + gather, + get_event_loop, + get_running_loop, + new_event_loop, + set_event_loop, +) from asyncio.events import AbstractEventLoop from typing import Any, Callable, List, Optional, Set, Union @@ -140,7 +147,16 @@ def run_app( override_return: Optional[bool] = None, ) -> Any: def wrapper(*args, **kwargs) -> Optional[int]: # type: ignore - loop_ = loop or get_event_loop() + try: + # Try to get the currently running event loop (Python ≥3.10 preferred API). + # In Python 3.14+, get_event_loop() no longer creates a default loop automatically. + # If no loop is running yet, this raises RuntimeError — we handle that below. + loop_ = loop or get_running_loop() + except RuntimeError: + # No event loop exists in the current thread (Python 3.14+ behavior). + # Create and set a new loop to preserve backward compatibility with Python ≤3.13. + loop_ = new_event_loop() + set_event_loop(loop_) app_ = app if isinstance(app, Application) else app() diff --git a/aiocli/commander_app.py b/aiocli/commander_app.py index da63735..42ef6be 100644 --- a/aiocli/commander_app.py +++ b/aiocli/commander_app.py @@ -726,11 +726,13 @@ async def _resolve_or_retrieve_from_cache_dependency(self, of: str, annotation: async def _execute_command_handler(self, handler: CommandHandler, kwargs: Dict[str, Any]) -> Any: self._log( - msg='Executing command handler with: {0}.'.format( - ', '.join(['{0}={1}'.format(key, val) for key, val in kwargs.items()]) - ) - if kwargs - else 'Executing command handler.', + msg=( + 'Executing command handler with: {0}.'.format( + ', '.join(['{0}={1}'.format(key, val) for key, val in kwargs.items()]) + ) + if kwargs + else 'Executing command handler.' + ), ) return await resolve_function(handler, **kwargs) diff --git a/compose.yml b/compose.yml index 3289e23..4304458 100644 --- a/compose.yml +++ b/compose.yml @@ -5,9 +5,9 @@ services: dockerfile: Containerfile # target: py310 # target: py311 - target: py312 +# target: py312 # image: ghcr.io/aiopy/python-aiocli:py310-${VERSION:-latest} # image: ghcr.io/aiopy/python-aiocli:py311-${VERSION:-latest} - image: ghcr.io/aiopy/python-aiocli:py312-${VERSION:-latest} + image: ghcr.io/aiopy/python-aiocli:py314-${VERSION:-latest} volumes: - .:/app diff --git a/docs_src/docs/en/release-notes.md b/docs_src/docs/en/release-notes.md index f5d93dc..1a7c8fa 100644 --- a/docs_src/docs/en/release-notes.md +++ b/docs_src/docs/en/release-notes.md @@ -1,5 +1,32 @@ ## CHANGELOG +### **1.11.x** + +* Drop Python 3.9 support. +* Bump dev deps. + +### **1.10.x** + +* Drop Python 3.8 support. +* Add Python 3.13 support. + +### **1.9.x** + +* Drop Python 3.7 support. +* Add Python 3.12 support. + +### **1.8.x** + +* Add more controls over the original input and app output. + +### **1.7.x** + +* Improve commands and app help usage. +* Lazy loading of the App and State instances. +* Improve command hooks. +* Add after middlware hook. +* Colorize help usage. + ### **1.6.x** * Add State. diff --git a/docs_src/generated/en/404.html b/docs_src/generated/en/404.html index 676c7ca..89f7c49 100644 --- a/docs_src/generated/en/404.html +++ b/docs_src/generated/en/404.html @@ -10,8 +10,11 @@ + + + - + @@ -19,13 +22,17 @@ - + - - + + + + + + @@ -37,12 +44,13 @@ - + + @@ -56,9 +64,6 @@ - - - @@ -72,16 +77,19 @@ -
+ + +