Construct *args and **kwargs from a collection of arguments This is pretty complicated, and almost all of the complication here stems from one of two things (but mostly the second): * The handling of ARG_STAR/ARG_STAR2. We want to create as much of the args/kwargs
(
self,
args: Sequence[tuple[Value, ArgKind, str | None]],
line: int,
*,
has_star: bool,
has_star2: bool,
)
| 894 | # Calls |
| 895 | |
| 896 | def _construct_varargs( |
| 897 | self, |
| 898 | args: Sequence[tuple[Value, ArgKind, str | None]], |
| 899 | line: int, |
| 900 | *, |
| 901 | has_star: bool, |
| 902 | has_star2: bool, |
| 903 | ) -> tuple[Value | None, Value | None]: |
| 904 | """Construct *args and **kwargs from a collection of arguments |
| 905 | |
| 906 | This is pretty complicated, and almost all of the complication here stems from |
| 907 | one of two things (but mostly the second): |
| 908 | * The handling of ARG_STAR/ARG_STAR2. We want to create as much of the args/kwargs |
| 909 | values in one go as we can, so we collect values until our hand is forced, and |
| 910 | then we emit creation of the list/tuple, and expand it from there if needed. |
| 911 | |
| 912 | * Support potentially nullable argument values. This has very narrow applicability, |
| 913 | as this will never be done by our compiled Python code, but is critically used |
| 914 | by gen_glue_method when generating glue methods to mediate between the function |
| 915 | signature of a parent class and its subclasses. |
| 916 | |
| 917 | For named-only arguments, this is quite simple: if it is |
| 918 | null, don't put it in the dict. |
| 919 | |
| 920 | For positional-or-named arguments, things are much more complicated. |
| 921 | * First, anything that was passed as a positional arg |
| 922 | must be forwarded along as a positional arg. It *must |
| 923 | not* be converted to a named arg. This is because mypy |
| 924 | does not enforce that positional-or-named arguments |
| 925 | have the same name in subclasses, and it is not |
| 926 | uncommon for code to have different names in |
| 927 | subclasses (a bunch of mypy's visitors do this, for |
| 928 | example!). This is arguably a bug in both mypy and code doing |
| 929 | this, and they ought to be using positional-only arguments, but |
| 930 | positional-only arguments are new and ugly. |
| 931 | |
| 932 | * On the flip side, we're willing to accept the |
| 933 | infelicity of sometimes turning an argument that was |
| 934 | passed by keyword into a positional argument. It's wrong, |
| 935 | but it's very marginal, and avoiding it would require passing |
| 936 | a bitmask of which arguments were named with every function call, |
| 937 | or something similar. |
| 938 | (See some discussion of this in testComplicatedArgs) |
| 939 | |
| 940 | Thus, our strategy for positional-or-named arguments is to |
| 941 | always pass them as positional, except in the one |
| 942 | situation where we can not, and where we can be absolutely |
| 943 | sure they were passed by name: when an *earlier* |
| 944 | positional argument was missing its value. |
| 945 | |
| 946 | This means that if we have a method `f(self, x: int=..., y: object=...)`: |
| 947 | * x and y present: args=(x, y), kwargs={} |
| 948 | * x present, y missing: args=(x,), kwargs={} |
| 949 | * x missing, y present: args=(), kwargs={'y': y} |
| 950 | |
| 951 | To implement this, when we have multiple optional |
| 952 | positional arguments, we maintain a flag in a register |
| 953 | that tracks whether an argument has been missing, and for |
no test coverage detected