Example #1
0
File: run.py Project: jackqu7/Facio
    def run(self):
        """ Run the Facio processes. """

        interface = CommandLineInterface()
        interface.start()

        config = ConfigurationFile()
        parsed = config.read()

        settings = Settings(interface, parsed)
        state.update_context_variables(settings.get_variables())

        template = Template(settings.get_template_path())
        template.update_copy_ignore_globs(settings.copy_ignore_globs())
        template.update_render_ignore_globs(settings.render_ignore_globs())
        template.copy()

        pipeline = Hook()
        pipeline.load(os.path.join(
            state.get_project_root(),
            HOOKS_FILE_NAME))

        if pipeline.has_before():
            pipeline.run_before()

        template.rename()
        template.render()

        if pipeline.has_after():
            pipeline.run_after()

        self.success('Done')
Example #2
0
    def run(self):
        """ Runs the python setup.py command.

        :returns: bool -- Based on return code subprocess call return code
        """

        project_root = state.get_project_root()
        working_dir = state.get_working_directory()

        python = self.get_path_to_python()
        setup = os.path.join(project_root, 'setup.py')
        arg = self.get_install_arg()

        self.out('Running: {0} ...'.format(' '.join([python, setup, arg])))

        os.chdir(project_root)
        call = subprocess.Popen([python, setup, arg],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        output, errors = call.communicate()
        os.chdir(working_dir)

        if call.returncode:
            self.log_errors(errors)
            return False

        return True
Example #3
0
    def run(self):
        """ Run the Facio processes. """

        interface = CommandLineInterface()
        interface.start()

        config = ConfigurationFile()
        parsed = config.read()

        settings = Settings(interface, parsed)
        state.update_context_variables(settings.get_variables())

        template = Template(settings.get_template_path())
        template.update_copy_ignore_globs(settings.copy_ignore_globs())
        template.update_render_ignore_globs(settings.render_ignore_globs())
        template.copy()

        pipeline = Hook()
        pipeline.load(os.path.join(state.get_project_root(), HOOKS_FILE_NAME))

        if pipeline.has_before():
            pipeline.run_before()

        template.rename()
        template.render()

        if pipeline.has_after():
            pipeline.run_after()

        self.success('Done')
Example #4
0
    def test_copy_callback_call(self, mock_copy_tree, mock_pwd):
        from facio.state import state
        instance = Template('/foo/bar')
        callback = MagicMock()

        self.assertTrue(instance.copy(callback=callback))
        callback.assert_called_once_with(
            origin=instance.origin,
            destination=state.get_project_root())
Example #5
0
    def rename_direcories(self):
        """ Renames directories that are named after context variables, for
        example: ``{{PROJECT_NAME}}``.

        :returns: generator
        """

        for root, dirs, files in os.walk(state.get_project_root()):
            for directory in fnmatch.filter(dirs, '*{{*}}*'):
                var_name = get_var_name_pattern.findall(directory)[0]
                var_value = state.get_context_variable(var_name)
                if var_value:
                    old_path = os.path.join(root, directory)
                    new_path = os.path.join(root, var_value)
                    shutil.move(old_path, new_path)
                    yield (old_path, new_path)
Example #6
0
    def log_errors(self, errors):
        """ Called with errors are encountered running setup.py and are logged
        to a setup.error.log.

        :param errors: Errors from setup.py
        :type errors: str
        """

        project_root = state.get_project_root()
        log_path = os.path.join(project_root, 'setup.error.log')

        with open(log_path, 'a') as handler:
            handler.write(errors)

        self.error('Errors detected with running setup.py, '
                   'please check {0}'.format(log_path))
Example #7
0
    def rename_direcories(self):
        """ Renames directories that are named after context variables, for
        example: ``{{PROJECT_NAME}}``.

        :returns: generator
        """

        for root, dirs, files in os.walk(state.get_project_root()):
            for directory in fnmatch.filter(dirs, '*{{*}}*'):
                var_name = get_var_name_pattern.findall(directory)[0]
                var_value = state.get_context_variable(var_name)
                if var_value:
                    old_path = os.path.join(root, directory)
                    new_path = os.path.join(root, var_value)
                    shutil.move(old_path, new_path)
                    yield (old_path, new_path)
Example #8
0
    def rename_files(self):
        """ Rename files that are named after context variables, for example:
        ``{{PROJECT_NAME}}.py``

        :returns: generator
        """

        for root, dirs, files in os.walk(state.get_project_root()):
            for filename in fnmatch.filter(files, '*{{*}}*'):
                var_name = get_var_name_pattern.findall(filename)[0]
                var_value = state.get_context_variable(var_name)
                if var_value:
                    name, ext = os.path.splitext(filename)
                    old_path = os.path.join(root, filename)
                    new_path = os.path.join(root,
                                            '{0}{1}'.format(var_value, ext))
                    shutil.move(old_path, new_path)
                    yield (old_path, new_path)
Example #9
0
    def rename_files(self):
        """ Rename files that are named after context variables, for example:
        ``{{PROJECT_NAME}}.py``

        :returns: generator
        """

        for root, dirs, files in os.walk(state.get_project_root()):
            for filename in fnmatch.filter(files, '*{{*}}*'):
                var_name = get_var_name_pattern.findall(filename)[0]
                var_value = state.get_context_variable(var_name)
                if var_value:
                    name, ext = os.path.splitext(filename)
                    old_path = os.path.join(root, filename)
                    new_path = os.path.join(root, '{0}{1}'.format(
                        var_value, ext))
                    shutil.move(old_path, new_path)
                    yield (old_path, new_path)
Example #10
0
    def render(self):
        """ Reads the template and uses Jinja 2 to replace context variables
        with their real values.
        """

        variables = state.get_context_variables()
        for root, dirs, files in os.walk(state.get_project_root()):
            jinja_loader = FileSystemLoader(root)
            jinja_environment = Environment(loader=jinja_loader)
            ignores = self.get_render_ignore_files(files)
            for filename in files:
                if filename not in ignores:
                    path = os.path.join(root, filename)
                    try:
                        template = jinja_environment.get_template(filename)
                        rendered = template.render(variables)
                    except:
                        import sys
                        e = sys.exc_info()[1]
                        self.warning('Failed to render {0}: {1}'.format(
                            path, e))
                    else:
                        with open(path, 'w', encoding='utf8') as handler:
                            handler.write(rendered)
Example #11
0
    def render(self):
        """ Reads the template and uses Jinja 2 to replace context variables
        with their real values.
        """

        variables = state.get_context_variables()
        for root, dirs, files in os.walk(state.get_project_root()):
            jinja_loader = FileSystemLoader(root)
            jinja_environment = Environment(loader=jinja_loader)
            ignores = self.get_render_ignore_files(files)
            for filename in files:
                if filename not in ignores:
                    path = os.path.join(root, filename)
                    try:
                        template = jinja_environment.get_template(filename)
                        rendered = template.render(variables)
                    except:
                        import sys
                        e = sys.exc_info()[1]
                        self.warning('Failed to render {0}: {1}'.format(
                            path, e))
                    else:
                        with open(path, 'w', encoding='utf8') as handler:
                            handler.write(rendered)
Example #12
0
    def copy(self, callback=None):
        """ Copy template from origin path to ``state.get_project_root()``.

        :param callback: A callback function to be called after
                         copy is complete
        :type callback: function -- default None

        :returns: bool
        """

        self.out('Copying {0} to {1}'.format(self.origin,
                                             state.get_project_root()))

        ignore = shutil.ignore_patterns(*self.get_copy_ignore_globs())
        try:
            shutil.copytree(self.origin,
                            state.get_project_root(),
                            ignore=ignore)
        except shutil.Error:
            raise FacioException('Failed to copy {0} to {1}'.format(
                self.origin, state.get_project_root()))
        except OSError:
            # If we get an OSError either the template path does not exist or
            # the project root already exists. Check the later first and then
            # check if the template path is git+ or hg+ and clone, finally
            # raising exceptions

            if not os.path.isdir(state.get_project_root()):

                supported_vcs = [
                    ('git+', GitVCS),
                    ('hg+', MercurialVCS),
                ]

                for prefix, cls in supported_vcs:
                    if self.origin.startswith(prefix):
                        vcs = cls(self.origin)
                        new_path = vcs.clone()
                        if not new_path:
                            raise FacioException(
                                'New path to template not returned by '
                                '{0}.clone()'.format(vcs.__class__.__name__))
                        self.origin = new_path
                        break
                else:
                    # Loop feel through so path is not prefixed with git+ or
                    # +hg so it must be a path that does not exist
                    raise FacioException('{0} does not exist'.format(
                        self.origin))

                # The loop broke so we can call self.copy again
                if self.COPY_ATTEMPT <= self.COPY_ATTEMPT_LIMIT:
                    self.COPY_ATTEMPT += 1
                    self.copy(callback=vcs.remove_tmp_dir)
                else:
                    raise FacioException('Failed to copy template after '
                                         '{0} attempts'.format(
                                             self.COPY_ATTEMPT))

            else:
                # project root exists, raise exception
                raise FacioException('{0} already exists'.format(
                    state.get_project_root()))

        # Call callback if callable
        if callable(callback):
            callback(origin=self.origin, destination=state.get_project_root())

        return True
Example #13
0
    def copy(self, callback=None):
        """ Copy template from origin path to ``state.get_project_root()``.

        :param callback: A callback function to be called after
                         copy is complete
        :type callback: function -- default None

        :returns: bool
        """

        self.out('Copying {0} to {1}'.format(
            self.origin,
            state.get_project_root()))

        ignore = shutil.ignore_patterns(*self.get_copy_ignore_globs())
        try:
            shutil.copytree(self.origin, state.get_project_root(),
                            ignore=ignore)
        except shutil.Error:
            raise FacioException('Failed to copy {0} to {1}'.format(
                self.origin,
                state.get_project_root()))
        except OSError:
            # If we get an OSError either the template path does not exist or
            # the project root already exists. Check the later first and then
            # check if the template path is git+ or hg+ and clone, finally
            # raising exceptions

            if not os.path.isdir(state.get_project_root()):

                supported_vcs = [
                    ('git+', GitVCS),
                    ('hg+', MercurialVCS),
                ]

                for prefix, cls in supported_vcs:
                    if self.origin.startswith(prefix):
                        vcs = cls(self.origin)
                        new_path = vcs.clone()
                        if not new_path:
                            raise FacioException(
                                'New path to template not returned by '
                                '{0}.clone()'.format(vcs.__class__.__name__))
                        self.origin = new_path
                        break
                else:
                    # Loop feel through so path is not prefixed with git+ or
                    # +hg so it must be a path that does not exist
                    raise FacioException('{0} does not exist'.format(
                        self.origin))

                # The loop broke so we can call self.copy again
                if self.COPY_ATTEMPT <= self.COPY_ATTEMPT_LIMIT:
                    self.COPY_ATTEMPT += 1
                    self.copy(callback=vcs.remove_tmp_dir)
                else:
                    raise FacioException('Failed to copy template after '
                                         '{0} attempts'.format(
                                             self.COPY_ATTEMPT))

            else:
                # project root exists, raise exception
                raise FacioException('{0} already exists'.format(
                    state.get_project_root()))

        # Call callback if callable
        if callable(callback):
            callback(
                origin=self.origin,
                destination=state.get_project_root())

        return True