Esempio n. 1
0
class BuiltinPluginLoaderTest (unittest.TestCase):
    def setUp (self):
        super(BuiltinPluginLoaderTest, self).setUp()
        self.project = mock()
        self.loader = BuiltinPluginLoader(mock())
    
    def tearDown (self):
        super(BuiltinPluginLoaderTest, self).tearDown()
        unstub()
    
    def test_should_raise_exception_when_requiring_plugin_and_plugin_is_not_found (self):
        when(builtin_module).__import__("pythonbuilder.plugins.spam_plugin").thenRaise(ImportError())
        
        self.assertRaises(MissingPluginException, self.loader.load_plugin, self.project, "spam")
        
        verify(builtin_module).__import__("pythonbuilder.plugins.spam_plugin")

    def test_should_import_plugin_when_requiring_plugin_and_plugin_is_found_as_builtin (self):
        old_module = sys.modules.get("pythonbuilder.plugins.spam_plugin")
        try:
            plugin_module = mock()
            sys.modules["pythonbuilder.plugins.spam_plugin"] = plugin_module
            when(builtin_module).__import__("pythonbuilder.plugins.spam_plugin").thenReturn(plugin_module)
            
            self.loader.load_plugin(self.project, "spam")
            
            verify(builtin_module).__import__("pythonbuilder.plugins.spam_plugin")
        finally:
            del sys.modules["pythonbuilder.plugins.spam_plugin"]
            if old_module:
                sys.modules["pythonbuilder.plugins.spam_plugin"] = old_module
Esempio n. 2
0
class Reactor(object):
    _current_instance = None

    @staticmethod
    def current_instance():
        return Reactor._current_instance

    def __init__(self, logger, execution_manager, plugin_loader=None):
        self.logger = logger
        self.execution_manager = execution_manager
        if not plugin_loader:
            self.plugin_loader = BuiltinPluginLoader(self.logger)
        else:
            self.plugin_loader = plugin_loader
        self._plugins = []
        self.project = None

    def require_plugin(self, plugin):
        if plugin not in self._plugins:
            try:
                self._plugins.append(plugin)
                self.import_plugin(plugin)
            except:
                self._plugins.remove(plugin)
                raise

    def get_plugins(self):
        return self._plugins

    def get_tasks(self):
        return self.execution_manager.tasks

    def validate_project(self):
        validation_messages = self.project.validate()
        if len(validation_messages) > 0:
            raise ProjectValidationFailedException(validation_messages)

    def prepare_build(self,
                      property_overrides={},
                      project_directory=".",
                      project_descriptor="build.py"):
        Reactor._current_instance = self

        project_directory, project_descriptor =\
        self.verify_project_directory(project_directory, project_descriptor)

        self.logger.debug("Loading project module from %s", project_descriptor)

        self.project = Project(basedir=project_directory)

        self.project_module = self.load_project_module(project_descriptor)

        self.apply_project_attributes()
        self.override_properties(property_overrides)

        self.logger.debug("Have loaded plugins %s", ", ".join(self._plugins))

        self.collect_tasks_and_actions_and_initializers(self.project_module)

        self.execution_manager.resolve_dependencies()

    def build(self, tasks=[], environments=[]):
        Reactor._current_instance = self

        if environments:
            self.logger.info("Activated environments: %s", ", ".join(environments))

        self.execution_manager.execute_initializers(environments, logger=self.logger, project=self.project)

        self.log_project_properties()

        self.validate_project()

        tasks = as_list(tasks)

        if not len(tasks):
            if self.project.default_task:
                tasks += as_list(self.project.default_task)
            else:
                raise PythonbuilderException("No default task given.")

        execution_plan = self.execution_manager.build_execution_plan(tasks)
        self.logger.debug("Execution plan is %s", ", ".join([task.name for task in execution_plan]))

        self.logger.info("Building %s version %s", self.project.name, self.project.version)
        self.logger.info("Executing build in %s", self.project.basedir)
        self.logger.info("Going to execute task%s %s",
            "s" if len(tasks) != 1 else "",
            ", ".join(tasks))

        task_execution_summaries =\
        self.execution_manager.execute_execution_plan(execution_plan,
            logger=self.logger,
            project=self.project,
            reactor=self)

        return BuildSummary(self.project, task_execution_summaries)

    def execute_task(self, task_name):
        execution_plan = self.execution_manager.build_execution_plan(task_name)

        self.execution_manager.execute_execution_plan(execution_plan,
            logger=self.logger,
            project=self.project,
            reactor=self)

    def override_properties(self, property_overrides):
        for property_override in property_overrides:
            self.project.set_property(property_override,
                property_overrides[property_override])

    def log_project_properties(self):
        formatted = ""
        for key in sorted(self.project.properties):
            formatted += "\n%40s : %s" % (key, self.project.get_property(key))
        self.logger.debug("Project properties: %s", formatted)

    def import_plugin(self, plugin):
        self.logger.debug("Loading plugin '%s'", plugin)
        plugin_module = self.plugin_loader.load_plugin(self.project, plugin)
        self.collect_tasks_and_actions_and_initializers(plugin_module)

    def collect_tasks_and_actions_and_initializers(self, project_module):
        for name in dir(project_module):
            candidate = getattr(project_module, name)

            if hasattr(candidate, NAME_ATTRIBUTE):
                name = getattr(candidate, NAME_ATTRIBUTE)
            elif hasattr(candidate, "__name__"):
                name = candidate.__name__
            description = getattr(candidate, DESCRIPTION_ATTRIBUTE) if hasattr(candidate, DESCRIPTION_ATTRIBUTE) else ""

            if hasattr(candidate, TASK_ATTRIBUTE) and getattr(candidate, TASK_ATTRIBUTE):
                dependencies = getattr(candidate, DEPENDS_ATTRIBUTE) if hasattr(candidate, DEPENDS_ATTRIBUTE) else None

                self.logger.debug("Found task %s", name)
                self.execution_manager.register_task(Task(name, candidate, dependencies, description))

            elif hasattr(candidate, ACTION_ATTRIBUTE) and getattr(candidate, ACTION_ATTRIBUTE):
                before = getattr(candidate, BEFORE_ATTRIBUTE) if hasattr(candidate, BEFORE_ATTRIBUTE) else None
                after = getattr(candidate, AFTER_ATTRIBUTE) if hasattr(candidate, AFTER_ATTRIBUTE) else None
                only_once = getattr(candidate, ONLY_ONCE_ATTRIBUTE) if hasattr(candidate,
                    ONLY_ONCE_ATTRIBUTE) else False

                self.logger.debug("Found action %s", name)
                self.execution_manager.register_action(Action(name, candidate, before, after, description, only_once))

            elif hasattr(candidate, INITIALIZER_ATTRIBUTE) and getattr(candidate, INITIALIZER_ATTRIBUTE):
                environments = []
                if hasattr(candidate, ENVIRONMENTS_ATTRIBUTE):
                    environments = getattr(candidate, ENVIRONMENTS_ATTRIBUTE)

                self.execution_manager.register_initializer(Initializer(name, candidate, environments, description))

    def apply_project_attributes(self):
        self.propagate_property("name")
        self.propagate_property("version")
        self.propagate_property("default_task")
        self.propagate_property("summary")
        self.propagate_property("home_page")
        self.propagate_property("description")
        self.propagate_property("authors")
        self.propagate_property("license")
        self.propagate_property("url")

    def propagate_property(self, property):
        if hasattr(self.project_module, property):
            value = getattr(self.project_module, property)
            setattr(self.project, property, value)

    def load_project_module(self, project_descriptor):
        try:
            return imp.load_source("build", project_descriptor)
        except ImportError as e:
            raise PythonbuilderException("Error importing project descriptor %s: %s" % (project_descriptor, e))

    def verify_project_directory(self, project_directory, project_descriptor):
        project_directory = os.path.abspath(project_directory)

        if not os.path.exists(project_directory):
            raise PythonbuilderException("Project directory does not exist: %s", project_directory)
        if not os.path.isdir(project_directory):
            raise PythonbuilderException("Project directory is not a directory: %s", project_directory)

        project_descriptor_full_path = os.path.join(project_directory, project_descriptor)

        if not os.path.exists(project_descriptor_full_path):
            raise PythonbuilderException("Project directory does not contain descriptor file: %s",
                project_descriptor_full_path)
        if not os.path.isfile(project_descriptor_full_path):
            raise PythonbuilderException("Project descriptor is not a file: %s", project_descriptor_full_path)

        return project_directory, project_descriptor_full_path