code: def get_plugin_info(gh_repo, path=None):
      """Returns a dict of plugin info for a FiftyOne plugin hosted in GitHub.
  
      Example usage::
  
          import fiftyone.plugins.utils as fopu
  
          # Directly link to a repository with a top-level`fiftyone YAML
          info = fopu.get_plugin_info("https://github.com/voxel51/voxelgpt")
          print(info)
  
          # Provide repository and path separately
          info = fopu.get_plugin_info(
              "voxel51/fiftyone-plugins",
              path="plugins/annotation",
          )
          print(info)
  
          # Directly link to a plugin directory
          info = fopu.get_plugin_info("https://github.com/voxel51/fiftyone-plugins/tree/main/plugins/annotation")
          print(info)
  
          # Directly link to a fiftyone YAML file
          info = fopu.get_plugin_info("https://github.com/voxel51/fiftyone-plugins/blob/main/plugins/annotation/fiftyone.yml")
          print(info)
  
      Args:
          gh_repo: a GitHub repository, identifier, tree root, or blob. See
              :class:`GitHubRepository <fiftyone.utils.github.GitHubRepository>`
              for details
          path (None): the path to a fiftyone YAML file or the directory that
              contains it. This is only necessary if the fiftyone YAML file is
              not at the root of the repository and you have not implicitly
              included this path in ``gh_repo`` by providing a tree or blob path
  
      Returns:
          a dict or list of dicts of plugin info
      """
      if path is None:
          try:
              path = GitHubRepository.parse_url(gh_repo).get(
                  "path", None
              )
          except:
              pass
  
      # If the user didn't directly provide a blob path, we must try all possible
      # `PLUGIN_METADATA_FILENAMES` values
      paths = []
      if path is None:
          paths.extend(PLUGIN_METADATA_FILENAMES)
      elif not path.endswith(PLUGIN_METADATA_FILENAMES):
          paths.extend(
              path + "/" + f for f in PLUGIN_METADATA_FILENAMES
          )
      else:
          paths = [path]
  
      repo = GitHubRepository(gh_repo)
  
      content = None
      exception = None
      for path in paths:
          try:
              content = repo.get_file(path).decode()
              break
          except Exception as e:
              if exception is None:
                  exception = e
  
      if content is None:
          raise exception
  
      return yaml.safe_load(content)
  
file_path: fiftyone/fiftyone/plugins/utils.py
imports: import logging
  import multiprocessing.dummy
  import os
  from bs4 import BeautifulSoup
  import yaml
  import fiftyone.core.utils
  from fiftyone.utils.github import GitHubRepository
  from fiftyone.plugins.core import PLUGIN_METADATA_FILENAMES
label_desc: Use image node_id 3 for calling a global function with example usage: get_plugin_info(gh_repo, path) and returns: yaml