Esempio n. 1
0
    def fill_details_from_code(self, code: str) -> None:
        # Number of parsed fields of metadata. Overrides anything set previously (the code is considered authoritative).
        # For now:
        # __Comment__
        # __Web__
        # __Version__
        # __Files__
        # __Author__
        # __Date__
        # __Icon__
        max_lines_to_search = 200
        line_counter = 0

        string_search_mapping = {
            "__comment__": "comment",
            "__web__": "url",
            "__version__": "version",
            "__files__": "other_files",
            "__author__": "author",
            "__date__": "date",
            "__icon__": "icon",
            "__xpm__": "xpm",
        }

        string_search_regex = re.compile(r"\s*(['\"])(.*)\1")
        f = io.StringIO(code)
        while f and line_counter < max_lines_to_search:
            line = f.readline()
            if not line:
                break
            if QtCore.QThread.currentThread().isInterruptionRequested():
                return
            line_counter += 1
            if not line.startswith("__"):
                # Speed things up a bit... this comparison is very cheap
                continue

            lowercase_line = line.lower()
            for key, value in string_search_mapping.items():
                if lowercase_line.startswith(key):
                    _, _, after_equals = line.partition("=")
                    match = re.match(string_search_regex, after_equals)
                    # We do NOT support triple-quoted strings, except for the icon XPM data
                    if match and '"""' not in after_equals:
                        if type(self.__dict__[value]) == str:
                            self.__dict__[value] = match.group(2)
                        elif type(self.__dict__[value]) == list:
                            self.__dict__[value] = [
                                of.strip() for of in match.group(2).split(",")
                            ]
                        string_search_mapping.pop(key)
                        break
                    else:
                        # Macro authors are supposed to be providing strings here, but in some
                        # cases they are not doing so. If this is the "__version__" tag, try
                        # to apply some special handling to accepts numbers, and "__date__"
                        if key == "__version__":
                            if "__date__" in after_equals.lower():
                                FreeCAD.Console.PrintLog(
                                    translate(
                                        "AddonsInstaller",
                                        "In macro {}, string literal not found for {} element. Guessing at intent and using string from date element.",
                                    ).format(self.name, key) + "\n")
                                self.version = self.date
                                break
                            elif is_float(after_equals):
                                FreeCAD.Console.PrintLog(
                                    translate(
                                        "AddonsInstaller",
                                        "In macro {}, string literal not found for {} element. Guessing at intent and using string representation of contents.",
                                    ).format(self.name, key) + "\n")
                                self.version = str(after_equals).strip()
                                break
                        elif key == "__icon__" or key == "__xpm__":
                            # If this is an icon, it's possible that the icon was actually directly specified
                            # in the file as XPM data. This data **must** be between triple double quotes in
                            # order for the Addon Manager to recognize it.
                            if '"""' in after_equals:
                                _, _, xpm_data = after_equals.partition('"""')
                                while True:
                                    line = f.readline()
                                    if not line:
                                        FreeCAD.Console.PrintError(
                                            translate(
                                                "AddonsInstaller",
                                                "Syntax error while reading {} from macro {}",
                                            ).format(key, self.name) + "\n")
                                        break
                                    if '"""' in line:
                                        last_line, _, _ = line.partition('"""')
                                        xpm_data += last_line
                                        break
                                    else:
                                        xpm_data += line
                                self.xpm = xpm_data
                                break

                        FreeCAD.Console.PrintError(
                            translate(
                                "AddonsInstaller",
                                "Syntax error while reading {} from macro {}",
                            ).format(key, self.name) + "\n")
                        FreeCAD.Console.PrintError(line + "\n")
                        continue

        # Do some cleanup of the values:
        if self.comment:
            self.comment = re.sub("<.*?>", "",
                                  self.comment)  # Strip any HTML tags

        # Truncate long comments to speed up searches, and clean up display
        if len(self.comment) > 512:
            self.comment = self.comment[:511] + "…"
        self.parsed = True
Esempio n. 2
0
    def fill_details_from_code(self, code: str) -> None:
        # Number of parsed fields of metadata. Overrides anything set previously (the code is considered authoritative).
        # For now:
        # __Comment__
        # __Web__
        # __Version__
        # __Files__
        # __Author__
        # __Date__
        max_lines_to_search = 200
        line_counter = 0
        ic = re.IGNORECASE  # Shorten the line for Black

        string_search_mapping = {
            "__comment__": "comment",
            "__web__": "url",
            "__version__": "version",
            "__files__": "other_files",
            "__author__": "author",
            "__date__": "date",
            "__icon__": "icon",
        }

        string_search_regex = re.compile(r"\s*(['\"])(.*)\1")
        f = io.StringIO(code)
        while f and line_counter < max_lines_to_search:
            line = f.readline()
            line_counter += 1
            # if not line.startswith("__"):
            #    # Speed things up a bit... this comparison is very cheap
            #    continue

            lowercase_line = line.lower()
            for key, value in string_search_mapping.items():
                if lowercase_line.startswith(key):
                    _, _, after_equals = line.partition("=")
                    match = re.match(string_search_regex, after_equals)
                    if match:
                        if type(self.__dict__[value]) == str:
                            self.__dict__[value] = match.group(2)
                        elif type(self.__dict__[value]) == list:
                            self.__dict__[value] = [
                                of.strip() for of in match.group(2).split(",")
                            ]
                        string_search_mapping.pop(key)
                        break
                    else:
                        # Macro authors are supposed to be providing strings here, but in some
                        # cases they are not doing so. If this is the "__version__" tag, try
                        # to apply some special handling to accepts numbers, and "__date__"
                        if key == "__version__":
                            if "__date__" in after_equals.lower():
                                FreeCAD.Console.PrintLog(
                                    translate(
                                        "AddonsInstaller",
                                        "In macro {}, string literal not found for {} element. Guessing at intent and using string from date element.",
                                    ).format(self.name, key) + "\n")
                                self.version = self.date
                                break
                            elif is_float(after_equals):
                                FreeCAD.Console.PrintLog(
                                    translate(
                                        "AddonsInstaller",
                                        "In macro {}, string literal not found for {} element. Guessing at intent and using string representation of contents.",
                                    ).format(self.name, key) + "\n")
                                self.version = str(after_equals).strip()
                                break
                        FreeCAD.Console.PrintError(
                            translate(
                                "AddonsInstaller",
                                "Syntax error while reading {} from macro {}",
                            ).format(key, self.name) + "\n")
                        FreeCAD.Console.PrintError(line + "\n")
                        continue

        # Do some cleanup of the values:
        if self.comment:
            self.comment = re.sub("<.*?>", "",
                                  self.comment)  # Strip any HTML tags

        # Truncate long comments to speed up searches, and clean up display
        if len(self.comment) > 512:
            self.comment = self.comment[:511] + "…"
        self.parsed = True