text: 
  
  import logging
  
  from random import choice
  from itertools import repeat
  
  from thanatos.questions.base import Question
  
  _log = logging.getLogger('thanatos')
  
  
  def get_all_question_details():
      """
  
      :return: A dictionary of sets representing the categories and their sub categories.
      :rtype: dict
      """
  
      categories = {}
      subclasses = get_question_subclasses()
      
      for subclass in subclasses:
          if subclass.category is not None and subclass.sub_category is not None:
              name = subclass.__name__.lower()
              category = subclass.category['name'].lower()
              sub_category = subclass.sub_category['name'].lower()
              
              if category not in categories:
                  categories[category] = subclass.category
                  categories[category]['sub_categories'] = {}
              
              if sub_category not in categories[category]['sub_categories']:
                  categories[category]['sub_categories'][sub_category] = subclass.sub_category
                  categories[category]['sub_categories'][sub_category]['questions'] = {}
      
              categories[category]['sub_categories'][sub_category]['questions'][name] = {
                  'name': subclass.name,
                  'description': subclass.description,
                  'weight': subclass.random_weight,
                  'question': subclass.question,
              }
          
      return categories
  
  
  def get_question_subclasses():
      return Question.__subclasses__()
  
  
  def get_random_question():
      questions = []
      subclasses = get_question_subclasses()
  
      for subclass in subclasses:
          questions.extend(repeat(subclass, subclass.random_weight))
  
      return choice(questions)
  
  
  def get_question(question_id):
      subclasses = get_question_subclasses()
      
      for subclass in subclasses:
          if subclass.__name__.lower() == question_id:
              return subclass
      
      raise InvalidQuestionException('The specified question does not exist.')
  
  
  def get_question_from_category(category):
      questions = []
      subclasses = get_question_subclasses()
  
      for question in subclasses:
          if question.category is not None and question.sub_category is not None:
              if question.category['name'].lower() == category:
                  questions.extend(repeat(question, question.random_weight))
  
      if len(questions) > 0:
          return choice(questions)
  
      else:
          raise InvalidQuestionCategoryException('The category specified is invalid.')
  
  
  def get_question_from_sub_category(category, sub_category):
      questions = []
      subclasses = get_question_subclasses()
  
      for question in subclasses:
          if question.category is not None and question.sub_category is not None:
              if question.category['name'].lower() == category:
                  if question.sub_category['name'].lower() == sub_category:
                      questions.extend(repeat(question, question.random_weight))
  
      if len(questions) > 0:
          return choice(questions)
  
      else:
          raise InvalidQuestionCategoryException('Either the category or sub-category specified is invalid.')
  
  
  class InvalidQuestionCategoryException(Exception):
      pass
  
  
  class InvalidQuestionException(Exception):
      pass
  