docs: def register_sig(self, builder_name: str, sig: list, docstring: str,
                       cachable: bool=True, attempts=1):
          """Register a builder signature & docstring for `builder_name`.
  
          The input for the builder signature is a list of "sig-spec"s
          representing the builder function arguments.
  
          Each sig-spec in the list can be:
          1. A string. This represents a simple untyped positional argument name,
              with no default value.
          2. A 1-tuple with one string element. Same as #1.
          3. A 2-tuple with ('arg-name', arg_type). This represents a typed
              positional argument, if arg_type is an instance of PropType enum.
          4. A 2-tuple with ('arg-name', default_value). This represents an
              un-typed keyword argument with a default value.
          5. A 3-tuple with ('arg-name', arg_type, default_value). This
              represents a typed keyword argument with a default value,
              if arg_type is an instance of PropType enum.
  
          In addition to the args specified in the `sig` list, there are several
          *injected* args:
          1. A positional arg `name` of type TargetName is always the first arg.
          2. A keyword arg `deps` of type TargetList and default value `None`
              (or empty list) is always the first after all builder args.
          3. A keyword arg `cachable` of type bool and default value taken from
             the signature registration call (`cachable` arg).
          4. A keyword arg `license` of type StrList and default value [].
          5. A keyword arg `policies` of type StrList and default value [].
          6. A keyword arg `packaging_params` of type dict and default value {}
              (empty dict).
          7. A keyword arg `runtime_params` of type dict and default value {}
              (empty dict).
          8. A keyword arg `build_params` of type dict and default value {}
              (empty dict).
          9. A keyword arg `attempts` of type int and default value 1.
          """
          if self.sig is not None:
              raise KeyError('{} already registered a signature!'
                             .format(builder_name))
          self.sig = OrderedDict(name=ArgSpec(PropType.TargetName, Empty))
          self.docstring = docstring
          kwargs_section = False
          for arg_spec in listify(sig):
              arg_name, sig_spec = evaluate_arg_spec(arg_spec)
              if arg_name in self.sig or arg_name in INJECTED_ARGS:
                  raise SyntaxError(
                      "duplicate argument '{}' in function definition"
                      .format(arg_name))
              self.sig[arg_name] = sig_spec
              if sig_spec.default == Empty:
                  if kwargs_section:
                      # TODO(itamar): how to give syntax error source annotation?
                      # (see: http://stackoverflow.com/questions/33717804)
                      raise SyntaxError(
                          'non-default argument follows default argument')
                  self.min_positional_args += 1
              else:
                  kwargs_section = True
          self.sig['deps'] = ArgSpec(PropType.TargetList, None)
          self.sig['cachable'] = ArgSpec(PropType.bool, cachable)
          self.sig['license'] = ArgSpec(PropType.StrList, None)
          self.sig['policies'] = ArgSpec(PropType.StrList, None)
          self.sig['packaging_params'] = ArgSpec(PropType.dict, None)
          self.sig['runtime_params'] = ArgSpec(PropType.dict, None)
          self.sig['build_params'] = ArgSpec(PropType.dict, None)
          self.sig['attempts'] = ArgSpec(PropType.numeric, 1)