# Path: lib/python/asterisk/test_runner.py
# def load_and_parse_module(type_name):
#     """Take a qualified module/object name, load the module, and return
#     a typename specifying the object
# 
#     Keyword Arguments:
#     type_name A fully qualified module/object to load into memory
# 
#     Returns:
#     An object type that to be instantiated
#     None on error
#     """
# 
#     LOGGER.debug("Importing %s" % type_name)
# 
#     # Split the object typename into its constituent parts - the module name
#     # and the actual type of the object in that module
#     parts = type_name.split('.')
#     module_name = ".".join(parts[:-1])
# 
#     if not len(module_name):
#         LOGGER.error("No module specified: %s" % typename)
#         return None
# 
#     if os.path.exists('lib/python/asterisk/%s.py' % module_name):
#         # This is convoluted but required.  lib/python/asterisk packages
#         # must be loaded using absolute package names and 'asterisk' must
#         # be included in the list of parts.  We cannot simply prepend
#         # type_name from the start because this blocks load of modules
#         # that are local to the test (add-test-to-search-path: 'True').
#         module_name = 'asterisk.' + module_name
#         parts = ['asterisk'] + parts
# 
#     module = __import__(module_name)
#     for comp in parts[1:]:
#         module = getattr(module, comp)
#     return module
# 
# Path: lib/python/asterisk/pluggable_registry.py
# PLUGGABLE_ACTION_REGISTRY = PluggableRegistry()
# 
# PLUGGABLE_EVENT_REGISTRY = PluggableRegistry()
# 
# class PluggableRegistry(object):
#     """Registry for pluggable modules"""
# 
#     def __init__(self):
#         self.registry = {}
# 
#     def register(self, key, factory):
#         """Register a module"""
#         self.registry[key] = factory
# 
#     def check(self, key):
#         """Check whether a module factory exists for the given key"""
#         if key in self.registry:
#             return True
#         return False
# 
#     def get_class(self, key):
#         """Get the class for a module"""
#         return self.registry[key]


import os
import sys
import logging
import shutil
import re
from .ami import AMIEventInstance
from twisted.internet import reactor
from starpy import fastagi
from .test_runner import load_and_parse_module
from .pluggable_registry import PLUGGABLE_ACTION_REGISTRY,\
    PLUGGABLE_EVENT_REGISTRY,\
    PluggableRegistry
from . import matcher

class AMIPrivateCallbackInstance(AMIEventInstance):
    """Subclass of AMIEventInstance that operates by calling a user-defined
    callback function. The callback function returns the current disposition
    of the test (i.e. whether the test is currently passing or failing).
    """

    def __init__(self, instance_config, test_object, callback):
        """Constructor"""
        super(AMIPrivateCallbackInstance, self).__init__(instance_config,
                                                         test_object)
        self.callback = callback
        if 'start' in instance_config:
            self.passed = True if instance_config['start'] == 'pass' else False

    def event_callback(self, ami, event):
        """Generic AMI event handler"""
        self.passed = self.callback(ami, event)
        return (ami, event)

    def check_result(self, callback_param):
        """Set the test status based on the result of self.callback"""
        self.test_object.set_passed(self.passed)
        return callback_param


class AMIChannelHangup(AMIEventInstance):
    """An AMIEventInstance derived class that hangs up a channel when an
    event is matched."""


# Path: lib/python/asterisk/test_runner.py
# def load_and_parse_module(type_name):
#     """Take a qualified module/object name, load the module, and return
#     a typename specifying the object
# 
#     Keyword Arguments:
#     type_name A fully qualified module/object to load into memory
# 
#     Returns:
#     An object type that to be instantiated
#     None on error
#     """
# 
#     LOGGER.debug("Importing %s" % type_name)
# 
#     # Split the object typename into its constituent parts - the module name
#     # and the actual type of the object in that module
#     parts = type_name.split('.')
#     module_name = ".".join(parts[:-1])
# 
#     if not len(module_name):
#         LOGGER.error("No module specified: %s" % typename)
#         return None
# 
#     if os.path.exists('lib/python/asterisk/%s.py' % module_name):
#         # This is convoluted but required.  lib/python/asterisk packages
#         # must be loaded using absolute package names and 'asterisk' must
#         # be included in the list of parts.  We cannot simply prepend
#         # type_name from the start because this blocks load of modules
#         # that are local to the test (add-test-to-search-path: 'True').
#         module_name = 'asterisk.' + module_name
#         parts = ['asterisk'] + parts
# 
#     module = __import__(module_name)
#     for comp in parts[1:]:
#         module = getattr(module, comp)
#     return module
# 
# Path: lib/python/asterisk/pluggable_registry.py
# PLUGGABLE_ACTION_REGISTRY = PluggableRegistry()
# 
# PLUGGABLE_EVENT_REGISTRY = PluggableRegistry()
# 
# class PluggableRegistry(object):
#     """Registry for pluggable modules"""
# 
#     def __init__(self):
#         self.registry = {}
# 
#     def register(self, key, factory):
#         """Register a module"""
#         self.registry[key] = factory
# 
#     def check(self, key):
#         """Check whether a module factory exists for the given key"""
#         if key in self.registry:
#             return True
#         return False
# 
#     def get_class(self, key):
#         """Get the class for a module"""
#         return self.registry[key]


# Path: lib/python/asterisk/pluggable_modules.py
import os
import sys
import logging
import shutil
import re
from .ami import AMIEventInstance
from twisted.internet import reactor
from starpy import fastagi
from .test_runner import load_and_parse_module
from .pluggable_registry import PLUGGABLE_ACTION_REGISTRY,\
    PLUGGABLE_EVENT_REGISTRY,\
    PluggableRegistry
from . import matcher


class AMIPrivateCallbackInstance(AMIEventInstance):
    """Subclass of AMIEventInstance that operates by calling a user-defined
    callback function. The callback function returns the current disposition
    of the test (i.e. whether the test is currently passing or failing).
    """

    def __init__(self, instance_config, test_object, callback):
        """Constructor"""
        super(AMIPrivateCallbackInstance, self).__init__(instance_config,
                                                         test_object)
        self.callback = callback
        if 'start' in instance_config:
            self.passed = True if instance_config['start'] == 'pass' else False

    def event_callback(self, ami, event):
        """Generic AMI event handler"""
        self.passed = self.callback(ami, event)
        return (ami, event)

    def check_result(self, callback_param):
        """Set the test status based on the result of self.callback"""
        self.test_object.set_passed(self.passed)
        return callback_param


class AMIChannelHangup(AMIEventInstance):
    """An AMIEventInstance derived class that hangs up a channel when an
    event is matched."""


    def __init__(self, instance_config, test_object):