Sanic on pypy (#2682)
Co-authored-by: L. Kärkkäinen <98187+Tronic@users.noreply.github.com> Co-authored-by: Adam Hopkins <admhpkns@gmail.com> Co-authored-by: Adam Hopkins <adam@amhopkins.com>
This commit is contained in:
parent
9a7dafd531
commit
273825dab6
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -21,4 +21,5 @@ dist/*
|
||||||
pip-wheel-metadata/
|
pip-wheel-metadata/
|
||||||
.pytest_cache/*
|
.pytest_cache/*
|
||||||
.venv/*
|
.venv/*
|
||||||
|
venv/*
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
|
|
@ -3,7 +3,7 @@ import sys
|
||||||
|
|
||||||
from os import environ
|
from os import environ
|
||||||
|
|
||||||
from sanic.compat import is_atty
|
from sanic.helpers import is_atty
|
||||||
|
|
||||||
|
|
||||||
BASE_LOGO = """
|
BASE_LOGO = """
|
||||||
|
|
|
@ -4,7 +4,7 @@ from textwrap import indent, wrap
|
||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from sanic import __version__
|
from sanic import __version__
|
||||||
from sanic.compat import is_atty
|
from sanic.helpers import is_atty
|
||||||
from sanic.log import logger
|
from sanic.log import logger
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
import signal
|
import signal
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
@ -10,6 +11,7 @@ from typing import Awaitable, Union
|
||||||
from multidict import CIMultiDict # type: ignore
|
from multidict import CIMultiDict # type: ignore
|
||||||
|
|
||||||
from sanic.helpers import Default
|
from sanic.helpers import Default
|
||||||
|
from sanic.log import error_logger
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info < (3, 8): # no cov
|
if sys.version_info < (3, 8): # no cov
|
||||||
|
@ -22,6 +24,7 @@ else: # no cov
|
||||||
]
|
]
|
||||||
|
|
||||||
OS_IS_WINDOWS = os.name == "nt"
|
OS_IS_WINDOWS = os.name == "nt"
|
||||||
|
PYPY_IMPLEMENTATION = platform.python_implementation() == "PyPy"
|
||||||
UVLOOP_INSTALLED = False
|
UVLOOP_INSTALLED = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -73,6 +76,38 @@ def enable_windows_color_support():
|
||||||
kernel.SetConsoleMode(kernel.GetStdHandle(-11), 7)
|
kernel.SetConsoleMode(kernel.GetStdHandle(-11), 7)
|
||||||
|
|
||||||
|
|
||||||
|
def pypy_os_module_patch() -> None:
|
||||||
|
"""
|
||||||
|
The PyPy os module is missing the 'readlink' function, which causes issues
|
||||||
|
withaiofiles. This workaround replaces the missing 'readlink' function
|
||||||
|
with 'os.path.realpath', which serves the same purpose.
|
||||||
|
"""
|
||||||
|
if hasattr(os, "readlink"):
|
||||||
|
error_logger.warning(
|
||||||
|
"PyPy: Skipping patching of the os module as it appears the "
|
||||||
|
"'readlink' function has been added."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
module = sys.modules["os"]
|
||||||
|
module.readlink = os.path.realpath # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
def pypy_windows_set_console_cp_patch() -> None:
|
||||||
|
"""
|
||||||
|
A patch function for PyPy on Windows that sets the console code page to
|
||||||
|
UTF-8 encodingto allow for proper handling of non-ASCII characters. This
|
||||||
|
function uses ctypes to call the Windows API functions SetConsoleCP and
|
||||||
|
SetConsoleOutputCP to set the code page.
|
||||||
|
"""
|
||||||
|
from ctypes import windll # type: ignore
|
||||||
|
|
||||||
|
code: int = windll.kernel32.GetConsoleOutputCP()
|
||||||
|
if code != 65001:
|
||||||
|
windll.kernel32.SetConsoleCP(65001)
|
||||||
|
windll.kernel32.SetConsoleOutputCP(65001)
|
||||||
|
|
||||||
|
|
||||||
class Header(CIMultiDict):
|
class Header(CIMultiDict):
|
||||||
"""
|
"""
|
||||||
Container used for both request and response headers. It is a subclass of
|
Container used for both request and response headers. It is a subclass of
|
||||||
|
@ -86,7 +121,7 @@ class Header(CIMultiDict):
|
||||||
<https://multidict.readthedocs.io/en/stable/multidict.html#multidict>`_
|
<https://multidict.readthedocs.io/en/stable/multidict.html#multidict>`_
|
||||||
for more details about how to use the object. In general, it should work
|
for more details about how to use the object. In general, it should work
|
||||||
very similar to a regular dictionary.
|
very similar to a regular dictionary.
|
||||||
"""
|
""" # noqa: E501
|
||||||
|
|
||||||
def __getattr__(self, key: str) -> str:
|
def __getattr__(self, key: str) -> str:
|
||||||
if key.startswith("_"):
|
if key.startswith("_"):
|
||||||
|
@ -112,6 +147,12 @@ if use_trio: # pragma: no cover
|
||||||
open_async = trio.open_file
|
open_async = trio.open_file
|
||||||
CancelledErrors = tuple([asyncio.CancelledError, trio.Cancelled])
|
CancelledErrors = tuple([asyncio.CancelledError, trio.Cancelled])
|
||||||
else:
|
else:
|
||||||
|
if PYPY_IMPLEMENTATION:
|
||||||
|
pypy_os_module_patch()
|
||||||
|
|
||||||
|
if OS_IS_WINDOWS:
|
||||||
|
pypy_windows_set_console_cp_patch()
|
||||||
|
|
||||||
from aiofiles import open as aio_open # type: ignore
|
from aiofiles import open as aio_open # type: ignore
|
||||||
from aiofiles.os import stat as stat_async # type: ignore # noqa: F401
|
from aiofiles.os import stat as stat_async # type: ignore # noqa: F401
|
||||||
|
|
||||||
|
@ -143,7 +184,3 @@ def ctrlc_workaround_for_windows(app):
|
||||||
die = False
|
die = False
|
||||||
signal.signal(signal.SIGINT, ctrlc_handler)
|
signal.signal(signal.SIGINT, ctrlc_handler)
|
||||||
app.add_task(stay_active)
|
app.add_task(stay_active)
|
||||||
|
|
||||||
|
|
||||||
def is_atty() -> bool:
|
|
||||||
return bool(sys.stdout and sys.stdout.isatty())
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
"""Defines basics of HTTP standard."""
|
"""Defines basics of HTTP standard."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
from inspect import ismodule
|
from inspect import ismodule
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
@ -157,6 +159,10 @@ def import_string(module_name, package=None):
|
||||||
return obj()
|
return obj()
|
||||||
|
|
||||||
|
|
||||||
|
def is_atty() -> bool:
|
||||||
|
return bool(sys.stdout and sys.stdout.isatty())
|
||||||
|
|
||||||
|
|
||||||
class Default:
|
class Default:
|
||||||
"""
|
"""
|
||||||
It is used to replace `None` or `object()` as a sentinel
|
It is used to replace `None` or `object()` as a sentinel
|
||||||
|
|
|
@ -5,7 +5,7 @@ from enum import Enum
|
||||||
from typing import TYPE_CHECKING, Any, Dict
|
from typing import TYPE_CHECKING, Any, Dict
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
|
||||||
from sanic.compat import is_atty
|
from sanic.helpers import is_atty
|
||||||
|
|
||||||
|
|
||||||
# Python 3.11 changed the way Enum formatting works for mixed-in types.
|
# Python 3.11 changed the way Enum formatting works for mixed-in types.
|
||||||
|
|
|
@ -41,9 +41,9 @@ from sanic.application.logo import get_logo
|
||||||
from sanic.application.motd import MOTD
|
from sanic.application.motd import MOTD
|
||||||
from sanic.application.state import ApplicationServerInfo, Mode, ServerStage
|
from sanic.application.state import ApplicationServerInfo, Mode, ServerStage
|
||||||
from sanic.base.meta import SanicMeta
|
from sanic.base.meta import SanicMeta
|
||||||
from sanic.compat import OS_IS_WINDOWS, StartMethod, is_atty
|
from sanic.compat import OS_IS_WINDOWS, StartMethod
|
||||||
from sanic.exceptions import ServerKilled
|
from sanic.exceptions import ServerKilled
|
||||||
from sanic.helpers import Default, _default
|
from sanic.helpers import Default, _default, is_atty
|
||||||
from sanic.http.constants import HTTP
|
from sanic.http.constants import HTTP
|
||||||
from sanic.http.tls import get_ssl_context, process_to_context
|
from sanic.http.tls import get_ssl_context, process_to_context
|
||||||
from sanic.http.tls.context import SanicSSLContext
|
from sanic.http.tls.context import SanicSSLContext
|
||||||
|
|
Loading…
Reference in New Issue
Block a user