gh-104683: Argument clinic: remove the LandMine class (#107541)

This commit is contained in:
Alex Waygood 2023-08-01 21:10:54 +01:00 • committed by GitHub
parent 2bd04d4234
commit 030f6b1e84
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 23 deletions

View file

@ -331,8 +331,7 @@ class ClinicWholeFileTest(_ParserBase):
[clinic start generated code]*/
""")
msg = (
"Stepped on a land mine, trying to access attribute 'noaccess':\n"
"Don't access members of self.function inside converter_init!"
"accessing self.function inside converter_init is disallowed!"
)
self.assertIn(msg, out)

View file

@ -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: