docs: def args_to_props(target: Target, builder: Builder, args: list, kwargs: dict):
      """Convert build file `args` and `kwargs` to `target` props.
  
      Use builder signature to validate builder usage in build-file, raising
      appropriate exceptions on signature-mismatches.
  
      Use builder signature default values to assign props values to args that
      were not passed in the build-file call.
  
      This function handles only the arg/kwargs-to-prop assignment, including
      default values when necessary. When it returns, if no exception was raised,
      it is guaranteed that `target.props` contains all args defined in the
      builder registered signature, with values taken either from the build-file
      call, or from default values provided in the signature.
  
      Specifically, this function DOES NOT do anything about the arg types
      defined in the builder signature.
  
      :raise TypeError: On signature-call mismatch.
      """
      if len(args) > len(builder.sig):
          # too many positional arguments supplied - say how many we can take
          raise TypeError('{}() takes {}, but {} were given'
                          .format(target.builder_name,
                                  format_num_positional_arguments(builder),
                                  len(args)))
      # read given args into the matching props according to the signature
      for arg_name, value in zip(builder.sig.keys(), args):
          target.props[arg_name] = value
      # read given kwargs into the named props, asserting matching sig arg names
      for arg_name, value in kwargs.items():
          if arg_name not in builder.sig:
              raise TypeError("{}() got an unexpected keyword argument '{}'"
                              .format(target.builder_name, arg_name))
          if arg_name in target.props:
              raise TypeError("{}() got multiple values for argument '{}'"
                              .format(target.builder_name, arg_name))
          target.props[arg_name] = value
      # go over signature args, assigning default values to anything that wasn't
      # assigned from args / kwargs, making sure no positional args are missing
      missing_args = []
      for arg_name, sig_spec in builder.sig.items():
          if arg_name not in target.props:
              if sig_spec.default == Empty:
                  missing_args.append(arg_name)
              else:
                  target.props[arg_name] = sig_spec.default
      if missing_args:
          # not enough positional arguments supplied - say which
          # TODO(itamar): match Python's error more closely (last "and "):
          # foo() missing 3 required positional arguments: 'a', 'b', and 'c'
          # TODO(itamar): use inflect
          raise TypeError('{}() missing {} required positional argument{}: {}'
                          .format(target.builder_name, len(missing_args),
                                  's' if len(missing_args) > 1 else '',
                                  ', '.join("'{}'".format(arg)
                                            for arg in missing_args)))
      logger.debug('Got props for target: {}', target)