text: #!/usr/bin/env python3
  
  # Copyright (c) Facebook, Inc. and its affiliates.
  # This source code is licensed under the MIT license found in the
  # LICENSE file in the root directory of this source tree.
  
  from typing import Union, Type, Dict, Any, List, TYPE_CHECKING
  from mephisto.utils.dirs import get_root_dir, get_provider_dir
  from mephisto.operations.hydra_config import register_abstraction_config
  import importlib
  import os
  
  if TYPE_CHECKING:
      from mephisto.abstractions.blueprint import Blueprint
      from mephisto.abstractions.crowd_provider import CrowdProvider
      from mephisto.abstractions.architect import Architect
  
  
  BLUEPRINTS: Dict[str, Type["Blueprint"]] = {}
  ARCHITECTS: Dict[str, Type["Architect"]] = {}
  PROVIDERS: Dict[str, Type["CrowdProvider"]] = {}
  
  
  def register_mephisto_abstraction():
      """
      Decorator method for classes that extend a mephisto abstraction, used
      to pull Mephisto abstractions out of anywhere that defines them.
      """
  
      def register_cls(
          base_class: Union[Type["Blueprint"], Type["Architect"], Type["CrowdProvider"]]
      ):
          from mephisto.abstractions.blueprint import Blueprint
          from mephisto.abstractions.crowd_provider import CrowdProvider
          from mephisto.abstractions.architect import Architect
  
          if issubclass(base_class, Blueprint):
              name = base_class.BLUEPRINT_TYPE
              BLUEPRINTS[name] = base_class
              type_key = "blueprint"
          elif issubclass(base_class, Architect):
              name = base_class.ARCHITECT_TYPE
              ARCHITECTS[name] = base_class
              type_key = "architect"
          elif issubclass(base_class, CrowdProvider):
              name = base_class.PROVIDER_TYPE
              PROVIDERS[name] = base_class
              type_key = "provider"
          else:
              raise AssertionError(
                  f"Provided class {base_class} not a child of one of the mephisto "
                  "abstractions, expected one of Blueprint, Architect, or CrowdProvider."
              )
          register_abstraction_config(
              name=name, node=base_class.ArgsClass, abstraction_type=type_key
          )
          return base_class
  
      return register_cls
  
  
  def uses_mephisto(module: Any):
      """
      Register a module as having defined classes for special Mephisto abstractions.
      Should be put in the __init__.py of the base module.
      """
      # TODO(#653) register the module and file path to the local mephisto registry file
      pass
  
  
  def fill_registries():
      """
      Ensure that all of the required modules are picked up by the mephisto server
      """
      # TODO(#653) pick up on local file changes such that Mephisto won't need to be
      # restarted to add new abstractions
  
      # TODO(#653) pass through all of the use_mephisto modules in the local registry file
      # to ensure that all of the modules are added
  
      # TODO(WISH) these can be made recursive finds with os.walk to pass through subfolders
      # Import Mephisto CrowdProviders
      provider_root = get_provider_dir()
      for dir_name in os.listdir(provider_root):
          provider_dir = os.path.join(provider_root, dir_name)
          if not os.path.isdir(provider_dir):
              continue
          for filename in os.listdir(provider_dir):
              if filename.endswith("provider.py"):
                  provider_name = filename[: filename.find(".py")]
                  importlib.import_module(
                      f"mephisto.abstractions.providers.{dir_name}.{provider_name}"
                  )
  
      # Import Mephisto Architects
      architect_root = os.path.join(
          get_root_dir(), "mephisto", "abstractions", "architects"
      )
      for filename in os.listdir(architect_root):
          if filename.endswith("architect.py"):
              architect_name = filename[: filename.find(".py")]
              importlib.import_module(
                  f"mephisto.abstractions.architects.{architect_name}"
              )
      # After imports are recursive, manage this more cleanly
      importlib.import_module("mephisto.abstractions.architects.ec2.ec2_architect")
  
      # Import Mephisto Blueprints
      blueprint_root = os.path.join(
          get_root_dir(), "mephisto", "abstractions", "blueprints"
      )
      for dir_name in os.listdir(blueprint_root):
          blueprint_dir = os.path.join(blueprint_root, dir_name)
          if not os.path.isdir(blueprint_dir):
              continue
          for filename in os.listdir(blueprint_dir):
              if filename.endswith("blueprint.py"):
                  blueprint_name = filename[: filename.find(".py")]
                  importlib.import_module(
                      f"mephisto.abstractions.blueprints.{dir_name}.{blueprint_name}"
                  )
  
  
  def get_crowd_provider_from_type(provider_type: str) -> Type["CrowdProvider"]:
      """Return the crowd provider class for the given string"""
      if provider_type in PROVIDERS:
          return PROVIDERS[provider_type]
      else:
          raise NotImplementedError(
              f"Missing provider type {provider_type}, is it registered?"
          )
  
  
  def get_blueprint_from_type(task_type: str) -> Type["Blueprint"]:
      """Return the blueprint class for the given string"""
      if task_type in BLUEPRINTS:
          return BLUEPRINTS[task_type]
      else:
          raise NotImplementedError(
              f"Missing blueprint type {task_type}, is it registered?"
          )
  
  
  def get_architect_from_type(architect_type: str) -> Type["Architect"]:
      """Return the architect class for the given string"""
      if architect_type in ARCHITECTS:
          return ARCHITECTS[architect_type]
      else:
          raise NotImplementedError(
              f"Missing architect type {architect_type}, is it registered?"
          )
  
  
  def get_valid_provider_types() -> List[str]:
      """
      Return the valid provider types that are currently supported by
      the mephisto framework
      """
      return list(PROVIDERS.keys())
  
  
  def get_valid_blueprint_types() -> List[str]:
      """
      Return the valid provider types that are currently supported by
      the mephisto framework
      """
      return list(BLUEPRINTS.keys())
  
  
  def get_valid_architect_types() -> List[str]:
      """
      Return the valid provider types that are currently supported by
      the mephisto framework
      """
      return list(ARCHITECTS.keys())
  