(
api: SemanticAnalyzerPluginInterface | CheckerPluginInterface,
info: TypeInfo,
name: str,
spec: MethodSpec,
*,
is_classmethod: bool,
is_staticmethod: bool,
)
| 322 | |
| 323 | |
| 324 | def _add_method_by_spec( |
| 325 | api: SemanticAnalyzerPluginInterface | CheckerPluginInterface, |
| 326 | info: TypeInfo, |
| 327 | name: str, |
| 328 | spec: MethodSpec, |
| 329 | *, |
| 330 | is_classmethod: bool, |
| 331 | is_staticmethod: bool, |
| 332 | ) -> tuple[FuncDef | Decorator, SymbolTableNode]: |
| 333 | args, return_type, self_type, tvar_defs = spec |
| 334 | |
| 335 | assert not ( |
| 336 | is_classmethod is True and is_staticmethod is True |
| 337 | ), "Can't add a new method that's both staticmethod and classmethod." |
| 338 | |
| 339 | if isinstance(api, SemanticAnalyzerPluginInterface): |
| 340 | function_type = api.named_type("builtins.function") |
| 341 | else: |
| 342 | function_type = api.named_generic_type("builtins.function", []) |
| 343 | |
| 344 | if is_classmethod: |
| 345 | self_type = self_type or TypeType(fill_typevars(info)) |
| 346 | first = [Argument(Var("_cls"), self_type, None, ARG_POS, True)] |
| 347 | elif is_staticmethod: |
| 348 | first = [] |
| 349 | else: |
| 350 | self_type = self_type or fill_typevars(info) |
| 351 | first = [Argument(Var("self"), self_type, None, ARG_POS)] |
| 352 | args = first + args |
| 353 | |
| 354 | arg_types, arg_names, arg_kinds = [], [], [] |
| 355 | for arg in args: |
| 356 | assert arg.type_annotation, "All arguments must be fully typed." |
| 357 | arg_types.append(arg.type_annotation) |
| 358 | arg_names.append(arg.variable.name) |
| 359 | arg_kinds.append(arg.kind) |
| 360 | |
| 361 | signature = CallableType(arg_types, arg_kinds, arg_names, return_type, function_type) |
| 362 | if tvar_defs: |
| 363 | signature.variables = tuple(tvar_defs) |
| 364 | |
| 365 | func = FuncDef(name, args, Block([PassStmt()])) |
| 366 | func.info = info |
| 367 | func.type = set_callable_name(signature, func) |
| 368 | func.is_class = is_classmethod |
| 369 | func.is_static = is_staticmethod |
| 370 | func._fullname = info.fullname + "." + name |
| 371 | func.line = info.line |
| 372 | |
| 373 | # Add decorator for is_staticmethod. It's unnecessary for is_classmethod. |
| 374 | if is_staticmethod: |
| 375 | func.is_decorated = True |
| 376 | v = Var(name, func.type) |
| 377 | v.info = info |
| 378 | v._fullname = func._fullname |
| 379 | v.is_staticmethod = True |
| 380 | dec = Decorator(func, [], v) |
| 381 | dec.line = info.line |
no test coverage detected
searching dependent graphs…