Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-113299: Create libclinic package #113309

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 6 additions & 73 deletions Tools/clinic/clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import collections
import contextlib
import copy
import cpp
import dataclasses as dc
import enum
import functools
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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!
Expand Down Expand Up @@ -2681,6 +2613,7 @@ def __init__(

global clinic
clinic = self
utils.clinic = self
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, putting a global from one file into another file is not a good idea.


def add_include(self, name: str, reason: str,
*, condition: str | None = None) -> None:
Expand Down
Empty file.
File renamed without changes.
87 changes: 87 additions & 0 deletions Tools/clinic/libclinic/utils.py
Original file line number Diff line number Diff line change
@@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR feels like it only does my least favourite thing about your other PR :// #113299 (comment)



@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)
Loading