mirror of
https://github.com/python/cpython
synced 2026-09-29 12:10:30 +03:00
gh-104683: Argument clinic: remove the LandMine class (#107541)
This commit is contained in:
parent
2bd04d4234
commit
030f6b1e84
2 changed files with 21 additions and 23 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue