def convert_subscript( config: ParserConfig, children: typing.Sequence[typing.Any] ) -> typing.Any: if len(children) == 1 and not isinstance(children[0], Token): # This is just an index node (test,) = children return WithLeadingWhitespace(Index(test.value), test.whitespace_before) if isinstance(children[-1], SlicePartial): # We got a partial slice as the final param. Extract the final # bits of the full subscript. *others, sliceop = children whitespace_before = others[0].whitespace_before second_colon = sliceop.second_colon step = sliceop.step else: # We can just parse this below, without taking extras from the # partial child. others = children whitespace_before = others[0].whitespace_before second_colon = MaybeSentinel.DEFAULT step = None # We need to create a partial slice to pass up. So, align so we have # a list that's always [Optional[Test], Colon, Optional[Test]]. if isinstance(others[0], Token): # First token is a colon, so insert an empty test on the LHS. We # know the RHS is a test since it's not a sliceop. slicechildren = [None, *others] else: # First token is non-colon, so its a test. slicechildren = [*others] if len(slicechildren) < 3: # Now, we have to fill in the RHS. We know its two long # at this point if its not already 3. slicechildren = [*slicechildren, None] lower, first_colon, upper = slicechildren return WithLeadingWhitespace( Slice( lower=lower.value if lower is not None else None, first_colon=Colon( whitespace_before=parse_parenthesizable_whitespace( config, first_colon.whitespace_before ), whitespace_after=parse_parenthesizable_whitespace( config, first_colon.whitespace_after ), ), upper=upper.value if upper is not None else None, second_colon=second_colon, step=step, ), whitespace_before=whitespace_before, )
def convert_sliceop(config: ParserConfig, children: typing.Sequence[typing.Any]) -> typing.Any: if len(children) == 2: colon, test = children step = test.value else: (colon, ) = children step = None return SlicePartial( second_colon=Colon( whitespace_before=parse_parenthesizable_whitespace( config, colon.whitespace_before), whitespace_after=parse_parenthesizable_whitespace( config, colon.whitespace_after), ), step=step, )
def convert_lambda(config: ParserConfig, children: typing.Sequence[typing.Any]) -> typing.Any: lambdatoken, *params, colontoken, test = children # Grab the whitespace around the colon. If there are no params, then # the colon owns the whitespace before and after it. If there are # any params, then the last param owns the whitespace before the colon. # We handle the parameter movement below. colon = Colon( whitespace_before=parse_parenthesizable_whitespace( config, colontoken.whitespace_before), whitespace_after=parse_parenthesizable_whitespace( config, colontoken.whitespace_after), ) # Unpack optional parameters if len(params) == 0: parameters = Parameters() whitespace_after_lambda = MaybeSentinel.DEFAULT else: (parameters, ) = params whitespace_after_lambda = parse_parenthesizable_whitespace( config, lambdatoken.whitespace_after) # Handle pre-colon whitespace if parameters.star_kwarg is not None: if parameters.star_kwarg.comma == MaybeSentinel.DEFAULT: parameters = parameters.with_changes( star_kwarg=parameters.star_kwarg.with_changes( whitespace_after_param=colon.whitespace_before)) elif parameters.kwonly_params: if parameters.kwonly_params[-1].comma == MaybeSentinel.DEFAULT: parameters = parameters.with_changes(kwonly_params=( *parameters.kwonly_params[:-1], parameters.kwonly_params[-1].with_changes( whitespace_after_param=colon.whitespace_before), )) elif isinstance(parameters.star_arg, Param): if parameters.star_arg.comma == MaybeSentinel.DEFAULT: parameters = parameters.with_changes( star_arg=parameters.star_arg.with_changes( whitespace_after_param=colon.whitespace_before)) elif parameters.default_params: if parameters.default_params[-1].comma == MaybeSentinel.DEFAULT: parameters = parameters.with_changes(default_params=( *parameters.default_params[:-1], parameters.default_params[-1].with_changes( whitespace_after_param=colon.whitespace_before), )) elif parameters.params: if parameters.params[-1].comma == MaybeSentinel.DEFAULT: parameters = parameters.with_changes(params=( *parameters.params[:-1], parameters.params[-1].with_changes( whitespace_after_param=colon.whitespace_before), )) # Colon doesn't own its own pre-whitespace now. colon = colon.with_changes(whitespace_before=SimpleWhitespace("")) # Return a lambda return WithLeadingWhitespace( Lambda( whitespace_after_lambda=whitespace_after_lambda, params=parameters, body=test.value, colon=colon, ), lambdatoken.whitespace_before, )