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:
		 Mohammad Almoghrabi
					Mohammad Almoghrabi
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user