summaryrefslogtreecommitdiffstats
path: root/Tools/clinic
diff options
context:
space:
mode:
authorAlex Waygood <Alex.Waygood@Gmail.com>2023-08-01 20:10:54 (GMT)
committerGitHub <noreply@github.com>2023-08-01 20:10:54 (GMT)
commit030f6b1e84274616c22666f27c5695867ab85833 (patch)
tree9ad8be05856535bb6b03879ca4d52b3ed5f882df /Tools/clinic
parent2bd04d423404e5ea862c858f62af76feade4d831 (diff)
downloadcpython-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-xTools/clinic/clinic.py41
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: