Create a list of new type arguments.
(self, args, new_arg_by_param)
| 1428 | return tuple(self._make_substitution(self.__args__, new_arg_by_param)) |
| 1429 | |
| 1430 | def _make_substitution(self, args, new_arg_by_param): |
| 1431 | """Create a list of new type arguments.""" |
| 1432 | new_args = [] |
| 1433 | for old_arg in args: |
| 1434 | if isinstance(old_arg, type): |
| 1435 | new_args.append(old_arg) |
| 1436 | continue |
| 1437 | |
| 1438 | substfunc = getattr(old_arg, '__typing_subst__', None) |
| 1439 | if substfunc: |
| 1440 | new_arg = substfunc(new_arg_by_param[old_arg]) |
| 1441 | else: |
| 1442 | subparams = getattr(old_arg, '__parameters__', ()) |
| 1443 | if not subparams: |
| 1444 | new_arg = old_arg |
| 1445 | else: |
| 1446 | subargs = [] |
| 1447 | for x in subparams: |
| 1448 | if isinstance(x, TypeVarTuple): |
| 1449 | subargs.extend(new_arg_by_param[x]) |
| 1450 | else: |
| 1451 | subargs.append(new_arg_by_param[x]) |
| 1452 | new_arg = old_arg[tuple(subargs)] |
| 1453 | |
| 1454 | if self.__origin__ == collections.abc.Callable and isinstance(new_arg, tuple): |
| 1455 | # Consider the following `Callable`. |
| 1456 | # C = Callable[[int], str] |
| 1457 | # Here, `C.__args__` should be (int, str) - NOT ([int], str). |
| 1458 | # That means that if we had something like... |
| 1459 | # P = ParamSpec('P') |
| 1460 | # T = TypeVar('T') |
| 1461 | # C = Callable[P, T] |
| 1462 | # D = C[[int, str], float] |
| 1463 | # ...we need to be careful; `new_args` should end up as |
| 1464 | # `(int, str, float)` rather than `([int, str], float)`. |
| 1465 | new_args.extend(new_arg) |
| 1466 | elif _is_unpacked_typevartuple(old_arg): |
| 1467 | # Consider the following `_GenericAlias`, `B`: |
| 1468 | # class A(Generic[*Ts]): ... |
| 1469 | # B = A[T, *Ts] |
| 1470 | # If we then do: |
| 1471 | # B[float, int, str] |
| 1472 | # The `new_arg` corresponding to `T` will be `float`, and the |
| 1473 | # `new_arg` corresponding to `*Ts` will be `(int, str)`. We |
| 1474 | # should join all these types together in a flat list |
| 1475 | # `(float, int, str)` - so again, we should `extend`. |
| 1476 | new_args.extend(new_arg) |
| 1477 | elif isinstance(old_arg, tuple): |
| 1478 | # Corner case: |
| 1479 | # P = ParamSpec('P') |
| 1480 | # T = TypeVar('T') |
| 1481 | # class Base(Generic[P]): ... |
| 1482 | # Can be substituted like this: |
| 1483 | # X = Base[[int, T]] |
| 1484 | # In this case, `old_arg` will be a tuple: |
| 1485 | new_args.append( |
| 1486 | tuple(self._make_substitution(old_arg, new_arg_by_param)), |
| 1487 | ) |
no test coverage detected