cpython/Tools/clinic/libclinic/parser.py

54 lines
1.5 KiB
Python

from __future__ import annotations
import contextlib
import functools
import io
from types import NoneType
from typing import Any, Protocol, TYPE_CHECKING
from libclinic import unspecified
from libclinic.block_parser import Block
from libclinic.converter import CConverter, converters
from libclinic.converters import buffer, robuffer, rwbuffer
from libclinic.return_converters import CReturnConverter, return_converters
if TYPE_CHECKING:
from libclinic.app import Clinic
class Parser(Protocol):
def __init__(self, clinic: Clinic) -> None: ...
def parse(self, block: Block) -> None: ...
@functools.cache
def _create_parser_base_namespace() -> dict[str, Any]:
ns = dict(
CConverter=CConverter,
CReturnConverter=CReturnConverter,
buffer=buffer,
robuffer=robuffer,
rwbuffer=rwbuffer,
unspecified=unspecified,
NoneType=NoneType,
)
for name, converter in converters.items():
ns[f'{name}_converter'] = converter
for name, return_converter in return_converters.items():
ns[f'{name}_return_converter'] = return_converter
return ns
def create_parser_namespace() -> dict[str, Any]:
base_namespace = _create_parser_base_namespace()
return base_namespace.copy()
class PythonParser:
def __init__(self, clinic: Clinic) -> None:
pass
def parse(self, block: Block) -> None:
namespace = create_parser_namespace()
with contextlib.redirect_stdout(io.StringIO()) as s:
exec(block.input, namespace)
block.output = s.getvalue()