diff options
author | Alex Waygood <Alex.Waygood@Gmail.com> | 2023-08-01 20:10:54 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-01 20:10:54 (GMT) |
commit | 030f6b1e84274616c22666f27c5695867ab85833 (patch) | |
tree | 9ad8be05856535bb6b03879ca4d52b3ed5f882df /Tools/clinic | |
parent | 2bd04d423404e5ea862c858f62af76feade4d831 (diff) | |
download | cpython-030f6b1e84274616c22666f27c5695867ab85833.zip cpython-030f6b1e84274616c22666f27c5695867ab85833.tar.gz cpython-030f6b1e84274616c22666f27c5695867ab85833.tar.bz2 |
gh-104683: Argument clinic: remove the `LandMine` class (#107541)
Diffstat (limited to 'Tools/clinic')
-rwxr-xr-x | Tools/clinic/clinic.py | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 3501c16..ba0132f 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -38,6 +38,7 @@ from collections.abc import ( ) from types import FunctionType, NoneType from typing import ( + TYPE_CHECKING, Any, Final, Literal, @@ -2638,18 +2639,6 @@ class Parameter: return f'"argument {i}"' -@dc.dataclass -class LandMine: - # try to access any - __message__: str - - def __getattribute__(self, name: str) -> Any: - if name in ('__repr__', '__message__'): - return super().__getattribute__(name) - # raise RuntimeError(repr(name)) - fail("Stepped on a land mine, trying to access attribute " + repr(name) + ":\n" + self.__message__) - - CConverterClassT = TypeVar("CConverterClassT", bound=type["CConverter"]) def add_c_converter( @@ -2844,16 +2833,28 @@ class CConverter(metaclass=CConverterAutoRegister): if annotation is not unspecified: fail("The 'annotation' parameter is not currently permitted.") - # this is deliberate, to prevent you from caching information - # about the function in the init. - # (that breaks if we get cloned.) - # so after this change we will noisily fail. - self.function: Function | LandMine = LandMine( - "Don't access members of self.function inside converter_init!" - ) + # Make sure not to set self.function until after converter_init() has been called. + # This prevents you from caching information + # about the function in converter_init(). + # (That breaks if we get cloned.) self.converter_init(**kwargs) self.function = function + # Add a custom __getattr__ method to improve the error message + # if somebody tries to access self.function in converter_init(). + # + # mypy will assume arbitrary access is okay for a class with a __getattr__ method, + # and that's not what we want, + # so put it inside an `if not TYPE_CHECKING` block + if not TYPE_CHECKING: + def __getattr__(self, attr): + if attr == "function": + fail( + f"{self.__class__.__name__!r} object has no attribute 'function'.\n" + f"Note: accessing self.function inside converter_init is disallowed!" + ) + return super().__getattr__(attr) + def converter_init(self) -> None: pass @@ -4005,7 +4006,6 @@ class self_converter(CConverter): def pre_render(self) -> None: f = self.function - assert isinstance(f, Function) default_type, default_name = correct_name_for_self(f) self.signature_name = default_name self.type = self.specified_type or self.type or default_type @@ -4056,7 +4056,6 @@ class self_converter(CConverter): @property def parser_type(self) -> str: assert self.type is not None - assert isinstance(self.function, Function) return required_type_for_self_for_parser(self.function) or self.type def render(self, parameter: Parameter, data: CRenderData) -> None: |