Parse positional-only parameter marker '/'. The 'version' parameter signifies the future version from which the marker will take effect (None means it is already in effect).
(self, function: Function, version: VersionTuple | None)
| 1220 | f"(Unexpected state {st}.c)") |
| 1221 | |
| 1222 | def parse_slash(self, function: Function, version: VersionTuple | None) -> None: |
| 1223 | """Parse positional-only parameter marker '/'. |
| 1224 | |
| 1225 | The 'version' parameter signifies the future version from which |
| 1226 | the marker will take effect (None means it is already in effect). |
| 1227 | """ |
| 1228 | if not self.expecting_parameters: |
| 1229 | fail("Encountered '/' when not expecting parameters") |
| 1230 | |
| 1231 | if version is None: |
| 1232 | if self.deprecated_keyword: |
| 1233 | fail(f"Function {function.name!r}: '/' must precede '/ [from ...]'") |
| 1234 | if self.deprecated_positional: |
| 1235 | fail(f"Function {function.name!r}: '/' must precede '* [from ...]'") |
| 1236 | if self.keyword_only: |
| 1237 | fail(f"Function {function.name!r}: '/' must precede '*'") |
| 1238 | if self.positional_only: |
| 1239 | fail(f"Function {function.name!r} uses '/' more than once.") |
| 1240 | else: |
| 1241 | if self.deprecated_keyword: |
| 1242 | if self.deprecated_keyword == version: |
| 1243 | fail(f"Function {function.name!r} uses '/ [from " |
| 1244 | f"{version[0]}.{version[1]}]' more than once.") |
| 1245 | if self.deprecated_keyword > version: |
| 1246 | fail(f"Function {function.name!r}: '/ [from " |
| 1247 | f"{version[0]}.{version[1]}]' must precede '/ [from " |
| 1248 | f"{self.deprecated_keyword[0]}.{self.deprecated_keyword[1]}]'") |
| 1249 | if self.deprecated_positional: |
| 1250 | fail(f"Function {function.name!r}: '/ [from ...]' must precede '* [from ...]'") |
| 1251 | if self.keyword_only: |
| 1252 | fail(f"Function {function.name!r}: '/ [from ...]' must precede '*'") |
| 1253 | self.positional_only = True |
| 1254 | self.deprecated_keyword = version |
| 1255 | if version is not None: |
| 1256 | found = False |
| 1257 | for p in reversed(function.parameters.values()): |
| 1258 | found = p.kind is inspect.Parameter.POSITIONAL_OR_KEYWORD |
| 1259 | break |
| 1260 | if not found: |
| 1261 | fail(f"Function {function.name!r} specifies '/ [from ...]' " |
| 1262 | f"without preceding parameters.") |
| 1263 | # REQUIRED and OPTIONAL are allowed here, that allows positional-only |
| 1264 | # without option groups to work (and have default values!) |
| 1265 | allowed = { |
| 1266 | ParamState.REQUIRED, |
| 1267 | ParamState.OPTIONAL, |
| 1268 | ParamState.RIGHT_SQUARE_AFTER, |
| 1269 | ParamState.GROUP_BEFORE, |
| 1270 | } |
| 1271 | if (self.parameter_state not in allowed) or self.group: |
| 1272 | fail(f"Function {function.name!r} has an unsupported group configuration. " |
| 1273 | f"(Unexpected state {self.parameter_state}.d)") |
| 1274 | # fixup preceding parameters |
| 1275 | for p in function.parameters.values(): |
| 1276 | if p.kind is inspect.Parameter.POSITIONAL_OR_KEYWORD: |
| 1277 | if version is None: |
| 1278 | p.kind = inspect.Parameter.POSITIONAL_ONLY |
| 1279 | elif p.deprecated_keyword is None: |
no test coverage detected