def _ast_mod_source_from_module_and_name(self, module, name):
        """ Retreive the AST and module source for a function given its module
            and name.

            If it fails to find the module or find the function within
            the module, set the load_error appropriately and return None.
            Otherwise, return the FuncDef ast for the function.
            Additionally, return the module source for use with other parsers.
        """
        # Find the source code for the specified module.
        try:
            loader = _pkgutil.get_loader(module)
        except:
            # A variety of exceptions can be thrown from getting the loader,
            # mostly dealing with a failure to parse an __init__.py file
            self.load_error = "failed to find module '%s'" % self.module
            return None, None

        if loader is None:
            self.load_error = "failed to find module '%s'" % self.module
            return None, None

        # fixme: Can this fail if the above succeeded?
        module_source = loader.get_source()


        # Convert it to an ast, and find all function asts defined in it.
        try:
            module_ast = compiler.parse(module_source)
        except:
            # This catches parse errors in the python source
            self.load_error = "failed to parse module '%s'" % self.module
            return None, None

        # fixme: find_local_defs is a bit primitive.  If we have problems,
        #        with finding the wrong function, this is the place to look.
        funcs = parse_tools.find_local_defs(module_ast)
        ast = funcs.get(name, None)

        if ast is None:
            # fixme much better error handling here.
            self.load_error = "failed to find '%s' in module '%s'" % \
                (self.name, self.module)

        return ast, module_source
    def _ast_mod_source_from_module_and_name(self, module, name):
        """ Retreive the AST and module source for a function given its module
            and name.

            If it fails to find the module or find the function within
            the module, set the load_error appropriately and return None.
            Otherwise, return the FuncDef ast for the function.
            Additionally, return the module source for use with other parsers.
        """
        # Find the source code for the specified module.
        try:
            loader = _pkgutil.get_loader(module)
        except:
            # A variety of exceptions can be thrown from getting the loader,
            # mostly dealing with a failure to parse an __init__.py file
            self.load_error = "failed to find module '%s'" % self.module
            return None, None

        if loader is None:
            self.load_error = "failed to find module '%s'" % self.module
            return None, None

        # fixme: Can this fail if the above succeeded?
        module_source = loader.get_source()


        # Convert it to an ast, and find all function asts defined in it.
        try:
            module_ast = compiler.parse(module_source)
        except:
            # This catches parse errors in the python source
            self.load_error = "failed to parse module '%s'" % self.module
            return None, None

        # fixme: find_local_defs is a bit primitive.  If we have problems,
        #        with finding the wrong function, this is the place to look.
        funcs = parse_tools.find_local_defs(module_ast)
        ast = funcs.get(name, None)

        if ast is None:
            # fixme much better error handling here.
            self.load_error = "failed to find '%s' in module '%s'" % \
                (self.name, self.module)

        return ast, module_source
    def _code_changed(self):
        """ Whenever the code changes, try and update the input and output
            arguments.

            fixme: We only handle one function definition in the code.
                   Fix this to where we allow local functions, and we
                   are defined by the first function in the file.
        """

        # If we fail to parse the ast, our current behavior is to reset
        # all our values to empty and set our invalid flag.
        try:
            ast = compiler.parse(self.code)
        except:
            # If the code failed to load, invalidate all traits,
            # set the load error based on the exception that happened,
            # and set ast to None so that we don't do any further
            # processing.
            ast = None

        if ast is not None:
            functions = find_local_defs(ast)
            if functions.items():
                # Use the first function we find as the one used for this
                # local function.
                # fixme: Should we raise an error if we find more?
                # fixme: find_local_defs will loose a function def if there are
                #        two versions with same name.
                name, function_ast = functions.items()[0]
                self._initialize_from_ast(function_ast)
                self.load_error = ""
            else:
                # There weren't any functions found to initialize from.
                self._initialize_as_invalid()
                self.load_error = "No function definition found."
        else:
            self._initialize_as_invalid()
            # fixme: For now we just report the type of error.  This
            #        should be improved.
            self.load_error = "%s" % exception_info()[0]
    def _code_changed(self):
        """ Whenever the code changes, try and update the input and output
            arguments.

            fixme: We only handle one function definition in the code.
                   Fix this to where we allow local functions, and we
                   are defined by the first function in the file.
        """

        # If we fail to parse the ast, our current behavior is to reset
        # all our values to empty and set our invalid flag.
        try:
            ast = compiler.parse(self.code)
        except:
            # If the code failed to load, invalidate all traits,
            # set the load error based on the exception that happened,
            # and set ast to None so that we don't do any further
            # processing.
            ast = None

        if ast is not None:
            functions = find_local_defs(ast)
            if functions.items():
                # Use the first function we find as the one used for this
                # local function.
                # fixme: Should we raise an error if we find more?
                # fixme: find_local_defs will loose a function def if there are
                #        two versions with same name.
                name, function_ast = functions.items()[0]
                self._initialize_from_ast(function_ast)
                self.load_error = ""
            else:
                # There weren't any functions found to initialize from.
                self._initialize_as_invalid()
                self.load_error = "No function definition found."
        else:
            self._initialize_as_invalid()
            # fixme: For now we just report the type of error.  This
            #        should be improved.
            self.load_error = "%s" % exception_info()[0]