Skip to content

Commit

Permalink
Drop Python 3.6.
Browse files Browse the repository at this point in the history
Use `asyncio.get_running_loop()` and `asyncio.run()`. Stop using
`asyncio.get_event_loop()` and `asyncio.set_event_loop()`.
  • Loading branch information
jonathanslenders committed Feb 14, 2023
1 parent 7776bf9 commit a775996
Show file tree
Hide file tree
Showing 22 changed files with 93 additions and 129 deletions.
23 changes: 11 additions & 12 deletions examples/ssh/asyncssh-server.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
"""
import asyncio
import logging
from asyncio import run

import asyncssh
from pygments.lexers.html import HtmlLexer

from prompt_toolkit.completion import WordCompleter
from prompt_toolkit.contrib.ssh import PromptToolkitSSHServer, PromptToolkitSSHSession
from prompt_toolkit.eventloop import get_event_loop
from prompt_toolkit.lexers import PygmentsLexer
from prompt_toolkit.shortcuts import ProgressBar, print_formatted_text
from prompt_toolkit.shortcuts.dialogs import input_dialog, yes_no_dialog
Expand Down Expand Up @@ -101,22 +101,21 @@ async def interact(ssh_session: PromptToolkitSSHSession) -> None:
await input_dialog("Input dialog", "Running over asyncssh").run_async()


def main(port=8222):
async def main(port=8222):
# Set up logging.
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)

loop = get_event_loop()
loop.run_until_complete(
asyncssh.create_server(
lambda: PromptToolkitSSHServer(interact),
"",
port,
server_host_keys=["/etc/ssh/ssh_host_ecdsa_key"],
)
await asyncssh.create_server(
lambda: PromptToolkitSSHServer(interact),
"",
port,
server_host_keys=["/etc/ssh/ssh_host_ecdsa_key"],
)
loop.run_forever()

# Run forever.
await asyncio.Future()


if __name__ == "__main__":
main()
asyncio.run(main())
10 changes: 6 additions & 4 deletions examples/telnet/chat-app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
"""
import logging
import random
from asyncio import Future, run

from prompt_toolkit.contrib.telnet.server import TelnetServer
from prompt_toolkit.eventloop import get_event_loop
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.shortcuts import PromptSession, clear

Expand Down Expand Up @@ -91,11 +91,13 @@ def _send_to_everyone(sender_connection, name, message, color):
)


def main():
async def main():
server = TelnetServer(interact=interact, port=2323)
server.start()
get_event_loop().run_forever()

# Run forever.
await Future()


if __name__ == "__main__":
main()
run(main())
10 changes: 6 additions & 4 deletions examples/telnet/dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
Example of a telnet application that displays a dialog window.
"""
import logging
from asyncio import Future, run

from prompt_toolkit.contrib.telnet.server import TelnetServer
from prompt_toolkit.eventloop import get_event_loop
from prompt_toolkit.shortcuts.dialogs import yes_no_dialog

# Set up logging
Expand All @@ -22,11 +22,13 @@ async def interact(connection):
connection.send("Bye.\n")


def main():
async def main():
server = TelnetServer(interact=interact, port=2323)
server.start()
get_event_loop().run_forever()

# Run forever.
await Future()


if __name__ == "__main__":
main()
run(main())
10 changes: 6 additions & 4 deletions examples/telnet/hello-world.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
That is probably the preferred way if you only need Python 3 support.
"""
import logging
from asyncio import Future, run

from prompt_toolkit.contrib.telnet.server import TelnetServer
from prompt_toolkit.eventloop import get_event_loop
from prompt_toolkit.shortcuts import PromptSession, clear

# Set up logging
Expand All @@ -30,11 +30,13 @@ async def interact(connection):
connection.send("Bye.\n")


def main():
async def main():
server = TelnetServer(interact=interact, port=2323)
server.start()
get_event_loop().run_forever()

# Run forever.
await Future()


if __name__ == "__main__":
main()
run(main())
10 changes: 6 additions & 4 deletions examples/telnet/toolbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
in the prompt.
"""
import logging
from asyncio import Future, run

from prompt_toolkit.completion import WordCompleter
from prompt_toolkit.contrib.telnet.server import TelnetServer
from prompt_toolkit.eventloop import get_event_loop
from prompt_toolkit.shortcuts import PromptSession

# Set up logging
Expand Down Expand Up @@ -35,11 +35,13 @@ def get_toolbar():
connection.send("Bye.\n")


def main():
async def main():
server = TelnetServer(interact=interact, port=2323)
server.start()
get_event_loop().run_forever()

# Run forever.
await Future()


if __name__ == "__main__":
main()
run(main())
16 changes: 3 additions & 13 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,16 @@ def get_version(package):
package_dir={"": "src"},
package_data={"prompt_toolkit": ["py.typed"]},
install_requires=["wcwidth"],
# We require Python 3.6.2 for three reasons:
# - Syntax for variable annotations - PEP 526.
# - Asynchronous generators - PEP 525.
# - New type annotations in 3.6.2 (i.e. NoReturn)
# Also, 3.6.0 doesn't have `typing.AsyncGenerator` yet. 3.6.1 does.
# Python 3.7 is suggested, because:
# We require Python 3.7, because we need:
# - Context variables - PEP 567
# (The current application is derived from a context variable.)
# There is no intension to support Python 3.5, because prompt_toolkit 2.0
# does run fine on any older Python version starting from Python 2.6, and
# it is possible to write code that runs both against prompt_toolkit
# version 2 and 3.
python_requires=">=3.6.2",
# - `asyncio.run()`
python_requires=">=3.7.0",
classifiers=[
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
Expand Down
39 changes: 8 additions & 31 deletions src/prompt_toolkit/application/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
Future,
Task,
ensure_future,
new_event_loop,
set_event_loop,
get_running_loop,
sleep,
)
from contextlib import ExitStack, contextmanager
Expand Down Expand Up @@ -49,7 +48,7 @@
get_traceback_from_context,
run_in_executor_with_context,
)
from prompt_toolkit.eventloop.utils import call_soon_threadsafe, get_event_loop
from prompt_toolkit.eventloop.utils import call_soon_threadsafe
from prompt_toolkit.filters import Condition, Filter, FilterOrBool, to_filter
from prompt_toolkit.formatted_text import AnyFormattedText
from prompt_toolkit.input.base import Input
Expand Down Expand Up @@ -458,7 +457,7 @@ def invalidate(self) -> None:
"""
if not self._is_running:
# Don't schedule a redraw if we're not running.
# Otherwise, `get_event_loop()` in `call_soon_threadsafe` can fail.
# Otherwise, `get_running_loop()` in `call_soon_threadsafe` can fail.
# See: https://github.com/dbcli/mycli/issues/797
return

Expand Down Expand Up @@ -787,7 +786,7 @@ def flush_input() -> None:

@contextmanager
def get_loop() -> Iterator[AbstractEventLoop]:
loop = get_event_loop()
loop = get_running_loop()
self.loop = loop

try:
Expand Down Expand Up @@ -941,14 +940,6 @@ def run_in_thread() -> None:
)
except BaseException as e:
exception = e
finally:
# Make sure to close the event loop in this thread. Running
# the application creates a new loop (because we're in
# another thread), but it doesn't get closed automatically
# (also not by the garbage collector).
loop = get_event_loop()
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()

thread = threading.Thread(target=run_in_thread)
thread.start()
Expand All @@ -958,21 +949,7 @@ def run_in_thread() -> None:
raise exception
return result

# We don't create a new event loop by default, because we want to be
# sure that when this is called multiple times, each call of `run()`
# goes through the same event loop. This way, users can schedule
# background-tasks that keep running across multiple prompts.
try:
loop = get_event_loop()
except RuntimeError:
# Possibly we are not running in the main thread, where no event
# loop is set by default. Or somebody called `asyncio.run()`
# before, which closes the existing event loop. We can create a new
# loop.
loop = new_event_loop()
set_event_loop(loop)

return loop.run_until_complete(
return asyncio.run(
self.run_async(
pre_run=pre_run,
set_exception_handler=set_exception_handler,
Expand Down Expand Up @@ -1074,7 +1051,7 @@ def create_background_task(
This is not threadsafe.
"""
loop = self.loop or get_event_loop()
loop = self.loop or get_running_loop()
task: asyncio.Task[None] = loop.create_task(coroutine)
self._background_tasks.add(task)

Expand All @@ -1093,7 +1070,7 @@ def _on_background_task_done(self, task: "asyncio.Task[None]") -> None:

exc = task.exception()
if exc is not None:
get_event_loop().call_exception_handler(
get_running_loop().call_exception_handler(
{
"message": f"prompt_toolkit.Application background task {task!r} "
"raised an unexpected exception.",
Expand Down Expand Up @@ -1501,7 +1478,7 @@ def attach_winch_signal_handler(

# Keep track of the previous handler.
# (Only UnixSelectorEventloop has `_signal_handlers`.)
loop = get_event_loop()
loop = get_running_loop()
previous_winch_handler = getattr(loop, "_signal_handlers", {}).get(sigwinch)

try:
Expand Down
2 changes: 1 addition & 1 deletion src/prompt_toolkit/completion/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ async def get_completions_async(
# def get_all_in_thread() -> List[Completion]:
# return list(self.get_completions(document, complete_event))

# completions = await get_event_loop().run_in_executor(None, get_all_in_thread)
# completions = await get_running_loop().run_in_executor(None, get_all_in_thread)
# for completion in completions:
# yield completion

Expand Down
6 changes: 3 additions & 3 deletions src/prompt_toolkit/contrib/ssh/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
"""
import asyncio
import traceback
from asyncio import get_running_loop
from typing import Any, Awaitable, Callable, Optional, TextIO, cast

import asyncssh

from prompt_toolkit.application.current import AppSession, create_app_session
from prompt_toolkit.data_structures import Size
from prompt_toolkit.eventloop import get_event_loop
from prompt_toolkit.input import PipeInput, create_pipe_input
from prompt_toolkit.output.vt100 import Vt100_Output

Expand Down Expand Up @@ -75,7 +75,7 @@ def shell_requested(self) -> bool:
return True

def session_started(self) -> None:
self.interact_task = get_event_loop().create_task(self._interact())
self.interact_task = get_running_loop().create_task(self._interact())

async def _interact(self) -> None:
if self._chan is None:
Expand Down Expand Up @@ -141,7 +141,7 @@ async def interact(ssh_session: PromptToolkitSSHSession) -> None:
print_formatted_text('You said: ', text)
server = PromptToolkitSSHServer(interact=interact)
loop = get_event_loop()
loop = get_running_loop()
loop.run_until_complete(
asyncssh.create_server(
lambda: MySSHServer(interact),
Expand Down
12 changes: 6 additions & 6 deletions src/prompt_toolkit/contrib/telnet/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
import asyncio
import socket
import sys
from asyncio import get_running_loop
from typing import Any, Awaitable, Callable, List, Optional, Set, TextIO, Tuple, cast

from prompt_toolkit.application.current import create_app_session, get_app
from prompt_toolkit.application.run_in_terminal import run_in_terminal
from prompt_toolkit.data_structures import Size
from prompt_toolkit.eventloop import get_event_loop
from prompt_toolkit.formatted_text import AnyFormattedText, to_formatted_text
from prompt_toolkit.input import PipeInput, create_pipe_input
from prompt_toolkit.output.vt100 import Vt100_Output
Expand Down Expand Up @@ -193,7 +193,7 @@ def handle_incoming_data() -> None:
self.close()

# Add reader.
loop = get_event_loop()
loop = get_running_loop()
loop.add_reader(self.conn, handle_incoming_data)

try:
Expand All @@ -219,7 +219,7 @@ def close(self) -> None:
self._closed = True

self.vt100_input.close()
get_event_loop().remove_reader(self.conn)
get_running_loop().remove_reader(self.conn)
self.conn.close()
self.stdout.close()

Expand Down Expand Up @@ -310,11 +310,11 @@ def start(self) -> None:
"Listening for telnet connections on %s port %r", self.host, self.port
)

get_event_loop().add_reader(self._listen_socket, self._accept)
get_running_loop().add_reader(self._listen_socket, self._accept)

async def stop(self) -> None:
if self._listen_socket:
get_event_loop().remove_reader(self._listen_socket)
get_running_loop().remove_reader(self._listen_socket)
self._listen_socket.close()

# Wait for all applications to finish.
Expand Down Expand Up @@ -379,5 +379,5 @@ async def run() -> None:
finally:
self._application_tasks.remove(task)

task = get_event_loop().create_task(run())
task = get_running_loop().create_task(run())
self._application_tasks.append(task)
Loading

0 comments on commit a775996

Please sign in to comment.