# Buggy code
def _ProcessAnalysisPlugins(
    self,
    analysis_plugins,
    analysis_output_queue,
    storage_file,
    counter,
    preferred_encoding="utf-8",
):
    """Runs the analysis plugins.

    Args:
      analysis_plugins: the analysis plugins.
      analysis_output_queue: the analysis output queue (instance of Queue).
      storage_file: a storage file object (instance of StorageFile).
      counter: a counter object (instance of collections.Counter).
      preferred_encoding: optional preferred encoding. The default is "utf-8".
    """
    if not analysis_plugins:
        return

    logging.info("Processing data from analysis plugins.")

    # Wait for all analysis plugins to complete.
    for analysis_process_info in self._analysis_process_info:
        name = analysis_process_info.plugin.name
        if analysis_process_info.plugin.LONG_RUNNING_PLUGIN:
            logging.warning(
                "{0:s} may take a long time to run. It will not be automatically "
                "terminated.".format(name)
            )
            report_wait = None
        else:
            report_wait = self.MAX_ANALYSIS_PLUGIN_REPORT_WAIT
        completion_event = analysis_process_info.completion_event
        process = analysis_process_info.process
        logging.info("Waiting for analysis plugin: {0:s} to complete.".format(name))
        if completion_event.wait(report_wait):
            logging.info("Plugin {0:s} has completed.".format(name))
        else:
            logging.warning(
                "Analysis process {0:s} failed to compile its report in a "
                "reasonable time. No report will be displayed or stored.".format(name)
            )
            process.terminate()

    logging.info("All analysis plugins are now completed.")

    # Go over each output.
    analysis_queue_consumer = PsortAnalysisReportQueueConsumer(
        analysis_output_queue,
        storage_file,
        self._filter_expression,
        preferred_encoding=preferred_encoding,
    )

    analysis_queue_consumer.ConsumeItems()

    if analysis_queue_consumer.tags:
        storage_file.StoreTagging(analysis_queue_consumer.tags)

    # TODO: analysis_queue_consumer.anomalies:

    for item, value in analysis_queue_consumer.counter.iteritems():
        counter[item] = value


# Traceback (AttributeError)
PYTHONPATH=. ./tools/psort.py --analysis list

******************************* Analysis Plugins *******************************
Traceback (most recent call last):
File "./tools/psort.py", line 604, in <module>
if not Main():
File "./tools/psort.py", line 581, in Main
tool.ListAnalysisPlugins()
File "./tools/psort.py", line 297, in ListAnalysisPlugins
analysis_plugins = self._front_end.GetAnalysisPlugins()
File "/home/onager/code/plaso/plaso/frontend/psort.py", line 96, in GetAnalysisPlugins
return analysis_manager.AnalysisPluginManager.ListAllPluginNames()
File "/home/onager/code/plaso/plaso/analysis/manager.py", line 55, in ListAllPluginNames
for cls_obj in interface.AnalysisPlugin.classes.itervalues():
AttributeError: type object 'AnalysisPlugin' has no attribute 'classes'

# Fixed code
def _ProcessAnalysisPlugins(
    self,
    analysis_plugins,
    analysis_output_queue,
    storage_file,
    counter,
    preferred_encoding="utf-8",
):
    """Runs the analysis plugins.

    Args:
      analysis_plugins: the analysis plugins.
      analysis_output_queue: the analysis output queue (instance of Queue).
      storage_file: a storage file object (instance of StorageFile).
      counter: a counter object (instance of collections.Counter).
      preferred_encoding: optional preferred encoding. The default is "utf-8".
    """
    if not analysis_plugins:
        return

    logging.info("Processing data from analysis plugins.")

    # Wait for all analysis plugins to complete.
    for analysis_process_info in self._analysis_process_info:
        name = analysis_process_info.plugin.NAME
        if analysis_process_info.plugin.LONG_RUNNING_PLUGIN:
            logging.warning(
                "{0:s} may take a long time to run. It will not be automatically "
                "terminated.".format(name)
            )
            report_wait = None
        else:
            report_wait = self.MAX_ANALYSIS_PLUGIN_REPORT_WAIT
        completion_event = analysis_process_info.completion_event
        logging.info("Waiting for analysis plugin: {0:s} to complete.".format(name))
        if completion_event.wait(report_wait):
            logging.info("Plugin {0:s} has completed.".format(name))
        else:
            logging.warning(
                "Analysis process {0:s} failed to compile its report in a "
                "reasonable time. No report will be displayed or stored.".format(name)
            )

    logging.info("All analysis plugins are now completed.")

    # Go over each output.
    analysis_queue_consumer = PsortAnalysisReportQueueConsumer(
        analysis_output_queue,
        storage_file,
        self._filter_expression,
        preferred_encoding=preferred_encoding,
    )

    analysis_queue_consumer.ConsumeItems()

    if analysis_queue_consumer.tags:
        storage_file.StoreTagging(analysis_queue_consumer.tags)

    # TODO: analysis_queue_consumer.anomalies:

    for item, value in analysis_queue_consumer.counter.iteritems():
        counter[item] = value