code: def from_uci(cls, uci: str) -> "Move":
          
          if uci == "0000":
              return cls.null()
          elif len(uci) == 4 and "@" == uci[1]:
              drop = PIECE_SYMBOLS.index(uci[0].lower())
              square = SQUARE_NAMES.index(uci[2:])
              return cls(square, square, drop=drop)
          elif len(uci) == 4:
              return cls(SQUARE_NAMES.index(uci[0:2]), SQUARE_NAMES.index(uci[2:4]))
          elif len(uci) == 5:
              promotion = PIECE_SYMBOLS.index(uci[4])
              return cls(SQUARE_NAMES.index(uci[0:2]), SQUARE_NAMES.index(uci[2:4]), promotion=promotion)
          else:
              raise ValueError("expected uci string to be of length 4 or 5: {!r}".format(uci))
docs: Parses an UCI string.
  
          :raises: :exc:`ValueError` if the UCI string is invalid.