code: def attemptCrack(self, ctext: str) -> List[CrackResult]:
      logging.info("Trying vigenere cipher")
      # Convert it to lower case
      if self.lower:
          message = ctext.lower()
      else:
          message = ctext
  
      # Analysis must be done here, where we know the case for the cache
      if self.keysize is not None:
          return self.crackOne(
              message,
              self.cache.get_or_update(
                  ctext,
                  f"vigenere::{self.keysize}",
                  lambda: cipheycore.analyse_string(
                      message, self.keysize, self.group
                  ),
              ),
              ctext,
          )
  
      arrs = []
      likely_lens = self.cache.get_or_update(
          ctext,
          "vigenere::likely_lens",
          lambda: cipheycore.vigenere_likely_key_lens(
              message, self.expected, self.group
          ),
      )
      possible_lens = [i for i in likely_lens]
      possible_lens.sort(key=lambda i: i.p_value)
      logging.debug(
          f"Got possible lengths {[i.len for i in likely_lens]}"
      )
      # TODO: work out length
      for i in possible_lens:
          arrs.extend(
              self.crackOne(
                  message,
                  self.cache.get_or_update(
                      ctext,
                      f"vigenere::{i.len}",
                      lambda: cipheycore.analyse_string(
                          message, i.len, self.group
                      ),
                  ),
                  ctext,
              )
          )
  
      logging.info(f"Vigenere returned {len(arrs)} candidates")
      return arrs
  
file_path: Ciphey/ciphey/basemods/Crackers/vigenere.py
imports: from distutils import util
  from typing import Dict, List, Optional, Union
  import cipheycore
  import logging
  from rich.logging import RichHandler
  from ciphey.common import fix_case
  from ciphey.iface import Config, Cracker, CrackInfo, CrackResult, ParamSpec, registry
label_desc: Use image node_id 4 for calling the Vigenere obj's underlying member method code with example usage: obj.attemptCrack(ctext) and returns: arrs, self