docs: def sprintf(self, fmt, relax=1):
          """sprintf(format, [relax=1]) -> str
  where format is a string that can include directives. A directive begins and
  ends by % and has the following format %[fmt[r],][cls[:nb].]field%.
  
  fmt is a classic printf directive, "r" can be appended for raw substitution
  (ex: IP.flags=0x18 instead of SA), nb is the number of the layer we want
  (ex: for IP/IP packets, IP:2.src is the src of the upper IP layer).
  Special case : "%.time%" is the creation time.
  Ex : p.sprintf("%.time% %-15s,IP.src% -> %-15s,IP.dst% %IP.chksum% "
                 "%03xr,IP.proto% %r,TCP.flags%")
  
  Moreover, the format string can include conditional statements. A conditional
  statement looks like : {layer:string} where layer is a layer name, and string
  is the string to insert in place of the condition if it is true, i.e. if layer
  is present. If layer is preceded by a "!", the result is inverted. Conditions
  can be imbricated. A valid statement can be :
    p.sprintf("This is a{TCP: TCP}{UDP: UDP}{ICMP:n ICMP} packet")
    p.sprintf("{IP:%IP.dst% {ICMP:%ICMP.type%}{TCP:%TCP.dport%}}")
  
  A side effect is that, to obtain "{" and "}" characters, you must use
  "%(" and "%)".
  """
  
          escape = {"%": "%",
                    "(": "{",
                    ")": "}"}
  
          # Evaluate conditions
          while "{" in fmt:
              i = fmt.rindex("{")
              j = fmt[i + 1:].index("}")
              cond = fmt[i + 1:i + j + 1]
              k = cond.find(":")
              if k < 0:
                  raise Scapy_Exception("Bad condition in format string: [%s] (read sprintf doc!)" % cond)  # noqa: E501
              cond, format_ = cond[:k], cond[k + 1:]
              res = False
              if cond[0] == "!":
                  res = True
                  cond = cond[1:]
              if self.haslayer(cond):
                  res = not res
              if not res:
                  format_ = ""
              fmt = fmt[:i] + format_ + fmt[i + j + 2:]
  
          # Evaluate directives
          s = ""
          while "%" in fmt:
              i = fmt.index("%")
              s += fmt[:i]
              fmt = fmt[i + 1:]
              if fmt and fmt[0] in escape:
                  s += escape[fmt[0]]
                  fmt = fmt[1:]
                  continue
              try:
                  i = fmt.index("%")
                  sfclsfld = fmt[:i]
                  fclsfld = sfclsfld.split(",")
                  if len(fclsfld) == 1:
                      f = "s"
                      clsfld = fclsfld[0]
                  elif len(fclsfld) == 2:
                      f, clsfld = fclsfld
                  else:
                      raise Scapy_Exception
                  if "." in clsfld:
                      cls, fld = clsfld.split(".")
                  else:
                      cls = self.__class__.__name__
                      fld = clsfld
                  num = 1
                  if ":" in cls:
                      cls, num = cls.split(":")
                      num = int(num)
                  fmt = fmt[i + 1:]
              except Exception:
                  raise Scapy_Exception("Bad format string [%%%s%s]" % (fmt[:25], fmt[25:] and "..."))  # noqa: E501
              else:
                  if fld == "time":
                      val = time.strftime("%H:%M:%S.%%06i", time.localtime(self.time)) % int((self.time - int(self.time)) * 1000000)  # noqa: E501
                  elif cls == self.__class__.__name__ and hasattr(self, fld):
                      if num > 1:
                          val = self.payload.sprintf("%%%s,%s:%s.%s%%" % (f, cls, num - 1, fld), relax)  # noqa: E501
                          f = "s"
                      elif f[-1] == "r":  # Raw field value
                          val = getattr(self, fld)
                          f = f[:-1]
                          if not f:
                              f = "s"
                      else:
                          val = getattr(self, fld)
                          if fld in self.fieldtype:
                              val = self.fieldtype[fld].i2repr(self, val)
                  else:
                      val = self.payload.sprintf("%%%s%%" % sfclsfld, relax)
                      f = "s"
                  s += ("%" + f) % val
  
          s += fmt
          return s