Checks if s declares a ParamSpec; if yes, store it in symbol table. Return True if this looks like a ParamSpec (maybe with errors), otherwise return False. In the future, ParamSpec may accept bounds and variance arguments, in which case more aggressive sharing of code with
(self, s: AssignmentStmt)
| 5032 | return lvalue.name |
| 5033 | |
| 5034 | def process_paramspec_declaration(self, s: AssignmentStmt) -> bool: |
| 5035 | """Checks if s declares a ParamSpec; if yes, store it in symbol table. |
| 5036 | |
| 5037 | Return True if this looks like a ParamSpec (maybe with errors), otherwise return False. |
| 5038 | |
| 5039 | In the future, ParamSpec may accept bounds and variance arguments, in which |
| 5040 | case more aggressive sharing of code with process_typevar_declaration should be pursued. |
| 5041 | """ |
| 5042 | call = self.get_typevarlike_declaration( |
| 5043 | s, ("typing_extensions.ParamSpec", "typing.ParamSpec") |
| 5044 | ) |
| 5045 | if not call: |
| 5046 | return False |
| 5047 | |
| 5048 | name = self.extract_typevarlike_name(s, call) |
| 5049 | if name is None: |
| 5050 | return False |
| 5051 | |
| 5052 | n_values = call.arg_kinds[1:].count(ARG_POS) |
| 5053 | if n_values != 0: |
| 5054 | self.fail('Too many positional arguments for "ParamSpec"', s) |
| 5055 | |
| 5056 | default: Type = AnyType(TypeOfAny.from_omitted_generics) |
| 5057 | for param_value, param_name in zip( |
| 5058 | call.args[1 + n_values :], call.arg_names[1 + n_values :] |
| 5059 | ): |
| 5060 | if param_name == "default": |
| 5061 | tv_arg = self.get_typevarlike_argument( |
| 5062 | "ParamSpec", |
| 5063 | param_name, |
| 5064 | param_value, |
| 5065 | s, |
| 5066 | allow_unbound_tvars=True, |
| 5067 | allow_param_spec_literals=True, |
| 5068 | report_invalid_typevar_arg=False, |
| 5069 | ) |
| 5070 | default = tv_arg or AnyType(TypeOfAny.from_error) |
| 5071 | default = self.check_paramspec_default(default, param_value) |
| 5072 | else: |
| 5073 | # ParamSpec is different from a regular TypeVar: |
| 5074 | # arguments are not semantically valid. But, allowed in runtime. |
| 5075 | # So, we need to warn users about possible invalid usage. |
| 5076 | self.fail( |
| 5077 | "The variance and bound arguments to ParamSpec do not have defined semantics yet", |
| 5078 | s, |
| 5079 | ) |
| 5080 | |
| 5081 | # PEP 612 reserves the right to define bound, covariant and contravariant arguments to |
| 5082 | # ParamSpec in a later PEP. If and when that happens, we should do something |
| 5083 | # on the lines of process_typevar_parameters |
| 5084 | |
| 5085 | if not call.analyzed: |
| 5086 | paramspec_var = ParamSpecExpr( |
| 5087 | name, self.qualified_name(name), self.object_type(), default, INVARIANT |
| 5088 | ) |
| 5089 | paramspec_var.line = call.line |
| 5090 | call.analyzed = paramspec_var |
| 5091 | updated = True |
no test coverage detected