From b58b260eaa2001ed84768fe5c48bdf87bb1f7d46 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 20 Dec 2023 09:52:45 +0100 Subject: [PATCH] gh-113299: Create libclinic package * Create Tools/clinic/libclinic/ package. * Move cpp.py to libclinic. * Create libclinic.utils. --- Tools/clinic/clinic.py | 79 ++------------------------ Tools/clinic/libclinic/__init__.py | 0 Tools/clinic/{ => libclinic}/cpp.py | 0 Tools/clinic/libclinic/utils.py | 87 +++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 73 deletions(-) create mode 100644 Tools/clinic/libclinic/__init__.py rename Tools/clinic/{ => libclinic}/cpp.py (100%) create mode 100644 Tools/clinic/libclinic/utils.py diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 87feef1b82ca39..b0f9739a5fcdb6 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -13,7 +13,6 @@ import collections import contextlib import copy -import cpp import dataclasses as dc import enum import functools @@ -47,9 +46,13 @@ Protocol, TypeVar, cast, - overload, ) +from libclinic import cpp +from libclinic import utils +from libclinic.utils import ClinicError, warn, fail + + # TODO: # # soon: @@ -144,77 +147,6 @@ def text_accumulator() -> TextAccumulator: return TextAccumulator(append, output) -@dc.dataclass -class ClinicError(Exception): - message: str - _: dc.KW_ONLY - lineno: int | None = None - filename: str | None = None - - def __post_init__(self) -> None: - super().__init__(self.message) - - def report(self, *, warn_only: bool = False) -> str: - msg = "Warning" if warn_only else "Error" - if self.filename is not None: - msg += f" in file {self.filename!r}" - if self.lineno is not None: - msg += f" on line {self.lineno}" - msg += ":\n" - msg += f"{self.message}\n" - return msg - - -@overload -def warn_or_fail( - *args: object, - fail: Literal[True], - filename: str | None = None, - line_number: int | None = None, -) -> NoReturn: ... - -@overload -def warn_or_fail( - *args: object, - fail: Literal[False] = False, - filename: str | None = None, - line_number: int | None = None, -) -> None: ... - -def warn_or_fail( - *args: object, - fail: bool = False, - filename: str | None = None, - line_number: int | None = None, -) -> None: - joined = " ".join([str(a) for a in args]) - if clinic: - if filename is None: - filename = clinic.filename - if getattr(clinic, 'block_parser', None) and (line_number is None): - line_number = clinic.block_parser.line_number - error = ClinicError(joined, filename=filename, lineno=line_number) - if fail: - raise error - else: - print(error.report(warn_only=True)) - - -def warn( - *args: object, - filename: str | None = None, - line_number: int | None = None, -) -> None: - return warn_or_fail(*args, filename=filename, line_number=line_number, fail=False) - -def fail( - *args: object, - filename: str | None = None, - line_number: int | None = None, -) -> NoReturn: - warn_or_fail(*args, filename=filename, line_number=line_number, fail=True) - - def quoted_for_c_string(s: str) -> str: for old, new in ( ('\\', '\\\\'), # must be first! @@ -2681,6 +2613,7 @@ def __init__( global clinic clinic = self + utils.clinic = self def add_include(self, name: str, reason: str, *, condition: str | None = None) -> None: diff --git a/Tools/clinic/libclinic/__init__.py b/Tools/clinic/libclinic/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Tools/clinic/cpp.py b/Tools/clinic/libclinic/cpp.py similarity index 100% rename from Tools/clinic/cpp.py rename to Tools/clinic/libclinic/cpp.py diff --git a/Tools/clinic/libclinic/utils.py b/Tools/clinic/libclinic/utils.py new file mode 100644 index 00000000000000..b603e14b191a90 --- /dev/null +++ b/Tools/clinic/libclinic/utils.py @@ -0,0 +1,87 @@ +from __future__ import annotations + +import dataclasses as dc +from typing import ( + Literal, + NoReturn, + overload, + TYPE_CHECKING, +) + +if TYPE_CHECKING: + from clinic import Clinic + + +# Clinic instance +clinic: 'Clinic' | None = None + + +@dc.dataclass +class ClinicError(Exception): + message: str + _: dc.KW_ONLY + lineno: int | None = None + filename: str | None = None + + def __post_init__(self) -> None: + super().__init__(self.message) + + def report(self, *, warn_only: bool = False) -> str: + msg = "Warning" if warn_only else "Error" + if self.filename is not None: + msg += f" in file {self.filename!r}" + if self.lineno is not None: + msg += f" on line {self.lineno}" + msg += ":\n" + msg += f"{self.message}\n" + return msg + + +@overload +def warn_or_fail( + *args: object, + fail: Literal[True], + filename: str | None = None, + line_number: int | None = None, +) -> NoReturn: ... + +@overload +def warn_or_fail( + *args: object, + fail: Literal[False] = False, + filename: str | None = None, + line_number: int | None = None, +) -> None: ... + +def warn_or_fail( + *args: object, + fail: bool = False, + filename: str | None = None, + line_number: int | None = None, +) -> None: + joined = " ".join([str(a) for a in args]) + if clinic: + if filename is None: + filename = clinic.filename + if getattr(clinic, 'block_parser', None) and (line_number is None): + line_number = clinic.block_parser.line_number + error = ClinicError(joined, filename=filename, lineno=line_number) + if fail: + raise error + else: + print(error.report(warn_only=True)) + + +def warn( + *args: object, + filename: str | None = None, + line_number: int | None = None, +) -> None: + return warn_or_fail(*args, filename=filename, line_number=line_number, fail=False) + +def fail( + *args: object, + filename: str | None = None, + line_number: int | None = None, +) -> NoReturn: + warn_or_fail(*args, filename=filename, line_number=line_number, fail=True)