Example #1
0
class ParseProject(object):
    """ Parse an x2p project
    """
    def __init__(self, project_file, sdk=None, wsroot=None):
        self.xml = parsers.get_xml(project_file)
        self.aliases = Aliases(project_file, sdk=sdk, wsroot=wsroot)
        self.xml_tree = self.xml.parse()
        self.files = self._parse_files()
        self.configurations = self._parse_configurations()

    def _parse_files(self):
        files = []
        for file_element in self.xml_tree.iter(file_xpath):
            file_path = file_element.get(path_attr_str)
            file_path = self.aliases.expand(file_path)
            if not os.path.isabs(file_path):
                file_path = os.path.normpath(
                    os.path.join(self.xml.base_dir, file_path))
            if not os.path.isfile(file_path):
                print(
                    "WARN: File listed in project {} doesn't exist: {}".format(
                        self.xml.filename, file_path))
            files.append(file_path)
        return files

    def _parse_configurations(self):
        configurations_elements = self.xml_tree.findall(configurations_xpath)
        if len(configurations_elements) > 1:
            raise InvalidProjectElement(
                "Multiple <configurations> elements in {}".format(
                    self.xml.filename))
        elif len(configurations_elements) < 1:
            raise InvalidProjectElement(
                "No <configurations> elements found in {}".format(
                    self.xml.filename))

        configurations = {}
        for config in configurations_elements[0].findall(configuration_xpath):
            configuration = Configuration(config)
            configurations[configuration.name] = configuration
        return configurations

    def parse(self):
        return self.files, self.configurations
class ParseWorkspace(object):
    """Parse an x2w workspace"""
    def __init__(self, workspace_file):
        self.workspace_xml = parsers.get_xml(workspace_file)
        self.aliases = Aliases(workspace_file)
        self.default_project = None

    def __repr__(self):
        return self.workspace_xml

    def __call__(self):
        return self.workspace_xml

    def _join_workspace_path_with_relative_project_path(self, relative_project_path):
        return os.path.abspath(os.path.join(self.workspace_xml.base_dir, relative_project_path))

    def _get_absolute_project_path(self, project_xml):
        project_path = self._parse_project_path(project_xml)
        if not os.path.isabs(project_path):
            return self._join_workspace_path_with_relative_project_path(project_path)
        return project_path

    def _parse_project_path(self, element):
        if element is not None:
            return self.aliases.expand(element.get(path_attr_str))
        else:
            raise InvalidProjectElement("Project element has no name or path attribute")

    def _parse_project_attributes(self, element):
        if element is not None:
            name = element.get(name_attr_str)
            path = element.get(path_attr_str)
            return name, path
        else:
            raise InvalidProjectElement("Project element has no name or path attribute")

    def _get_project_id_from_path(self, element):
        project_path = self._parse_project_path(element)
        return os.path.splitext(os.path.basename(project_path))[0]

    def _parse_project_name(self, element):
        project_id = element.get(name_attr_str)
        if project_id is None:
            project_id = self._get_project_id_from_path(element)
        return project_id

    def _parse_dependent_projects(self, parsed_project_xpath):
        dependencies = []
        for dependency in parsed_project_xpath.findall(dependencies_xpath):
            dependencies.append(self._parse_project_name(dependency))
        return dependencies

    def _update_project_dependencies(self, parsed_project_xpath, projects):
        for project_xml in parsed_project_xpath:
            project_id = self._parse_project_name(project_xml)
            dependencies = self._parse_dependent_projects(project_xml)
            for dependency in dependencies:
                projects[project_id].dependencies.append(projects[dependency])

    def _parse_project(self, project_name, project_xml):
        project_file = self._get_absolute_project_path(project_xml)
        project = Project(project_name, project_file, sdk=self.aliases.sdk, wsroot=self.aliases.wsroot)
        return project

    @staticmethod
    def _project_is_default(element):
        return element.get(default_attr_str) == "yes"

    def _parse_projects_from_xml_source(self, parsed_project_xpath):
        projects = {}
        for project_xml in parsed_project_xpath:
            project_id = self._parse_project_name(project_xml)
            project = self._parse_project(project_id, project_xml)
            if self._project_is_default(project_xml):
                if self.default_project:
                    raise InvalidProjectElement((
                        "More than one default project in: {ws}.\n"
                        "Found: {new}\n"
                        "Already had: {old}\n"
                    ).format(ws=self.workspace_xml.filename, old=self.default_project.name, new=project.name))
                self.default_project = project
            projects[project_id] = project
        if not self.default_project:
            raise ParseError("Default project not found in workspace: {}".format(self.workspace_xml.filename))
        return projects

    def parse(self):
        # This is a 2 stage process: 1. Parse all projects. 2. determine dependent projects

        parsed_project_xpath = self.workspace_xml.parse().findall(project_xpath)
        projects = self._parse_projects_from_xml_source(parsed_project_xpath)
        self._update_project_dependencies(parsed_project_xpath, projects)
        return projects