docstr: Args:
      path (str): The path to the card
  
  Raises:
      Exception: When the card_path is invalid
  
  Returns:
      CardInfo
docstr_tok: ["Args",":","path","(","str",")",":","The","path","to","the","card","Raises",":","Exception",":","When","the","card_path","is","invalid","Returns",":","CardInfo"]
code: def info_from_path(path, suffix=CardNameSuffix.CARD):
      """
      Args:
          path (str): The path to the card
  
      Raises:
          Exception: When the card_path is invalid
  
      Returns:
          CardInfo
      """
      card_file_name = path.split("/")[-1]
      file_split = card_file_name.split("-")
  
      if len(file_split) not in [2, 3]:
          raise Exception(
              "Invalid file name %s. Card/Data file names should be of form TYPE-HASH.%s or TYPE-ID-HASH.%s"
              % (card_file_name, suffix, suffix)
          )
      card_type, card_hash, card_id = None, None, None
  
      if len(file_split) == 2:
          card_type, card_hash = file_split
      else:
          card_type, card_id, card_hash = file_split
  
      card_hash = card_hash.split("." + suffix)[0]
      return CardInfo(card_type, card_hash, card_id, card_file_name)
  
imports: from collections import namedtuple
  from io import BytesIO
  import os
  import json
  import shutil
  from metaflow.plugins.datastores.local_storage import LocalStorage
  from metaflow.metaflow_config import CARD_S3ROOT, CARD_LOCALROOT, DATASTORE_LOCAL_DIR, CARD_SUFFIX, CARD_AZUREROOT, CARD_GSROOT, SKIP_CARD_DUALWRITE
  import metaflow.metaflow_config
  from .exception import CardNotPresentException
label_desc: Use image node_id 9 for calling the CardDatastore obj's underlying member method code with example usage: obj.info_from_path(path, suffix) and returns: CardInfo