示例#1
0
    def processMacro(self, element: Element, *args: typing.Any) -> str:
        """
		Process a macro already defined.
		"""

        sequence = element.getNestedSequence("nested")
        assert sequence

        # Build the argument list
        argList = []
        argument = element.getNestedSequence("argument")
        assert argument is not None
        for arg in argument:
            Error.assertHasAttr(element=arg, attr="name")
            argList.append(arg.getAttr("name").value)

        # Sanity check
        Error.assertTrue(
            element=element,
            condition=len(argList) == len(args),
            message="Wrong number of argument(s), expected {}: {}".format(
                len(argList), ", ".join(argList)))

        for i, name in enumerate(argList):
            self.substitutions.register(element=element,
                                        key=name,
                                        value=args[i])

        # Process the template
        result = self._visit(sequence=sequence)

        for name in argList:
            self.substitutions.unregister(name)

        return "".join(result)
示例#2
0
    def visitSubstitution(self, element: Element, result: ResultType) -> None:
        """
		Handle substitution.
		"""
        Error.assertHasAttr(element=element, attr="name")
        name = element.getAttr("name").value

        # Check if callable and if there are arguments
        arguments = element.getNestedSequence("argument")
        if arguments is None:
            value = self.resolveName(name=name)
        else:
            # Resolve all arguments
            args = []
            for arg in arguments:
                args.append(self.readValue(element=arg))
            value = self.resolveName(name, True, *args)

        # Process the pipes if any.
        pipes = element.getNestedSequence("pipe")
        if pipes:
            for pipe in pipes:
                Error.assertHasAttr(element=pipe, attr="name")
                value = self.resolveName(
                    pipe.getAttr("name").value, True, value)

        # Save the output
        assert isinstance(
            value, (int, float, str, pathlib.Path)
        ), "The resulting substitued value must be a number, a string or a path."
        self.appendSubstitution(element=element,
                                result=result,
                                string=str(value))
示例#3
0
    def visitForBlock(self, element: Element) -> ResultType:
        """
		Handle for loop block.
		"""

        Error.assertHasAttr(element=element, attr="value1")
        Error.assertHasAttr(element=element, attr="iterable")
        Error.assertHasSequence(element=element, sequence="nested")

        value1 = element.getAttr("value1").value
        value2 = element.getAttrValue("value2")

        sequence = element.getNestedSequence(kind="nested")
        assert sequence

        block: ResultType = []

        # Loop through the elements
        iterable = self.resolveName(name=element.getAttr("iterable").value)
        if value2 is None:
            for value in iterable:
                self.substitutions.register(element=element,
                                            key=value1,
                                            value=value)
                block += self._visit(sequence=sequence)
                self.substitutions.unregister(value1)
        else:
            iterablePair = iterable.items() if isinstance(
                iterable, dict) else enumerate(iterable)
            for key, value in iterablePair:
                self.substitutions.register(element=element,
                                            key=value1,
                                            value=key)
                self.substitutions.register(element=element,
                                            key=value2,
                                            value=value)
                block += self._visit(sequence=sequence)
                self.substitutions.unregister(value2)
                self.substitutions.unregister(value1)

        return block
示例#4
0
    def visitElement(self, element: Element, result: T) -> T:
        """
		Main visitor, called each time a new element is discovered.
		"""

        entity = elementToEntity(element=element,
                                 extension=self.elementToEntityExtenstion)

        # Handle nested object
        if isinstance(entity, Nested):

            self.level += 1

            for category in CATEGORIES:
                sequence = element.getNestedSequence(category)
                if sequence is not None:
                    self.parents.append(
                        Parent(entity=entity, category=category))
                    nestedResult = self._visit(sequence, result)
                    self.entityToNested(category, entity, nestedResult, result)
                    self.parents.pop()

            self.level -= 1

            self.visitNestedEntities(entity, result)

        # Handle expression
        elif isinstance(entity, Expression):

            self.visitExpression(entity, result)

        # Handle method
        elif isinstance(entity, Method):

            self.visitMethod(entity, result)

        # Handle using
        elif isinstance(entity, Using):

            self.visitUsing(entity, result)

        # Handle using
        elif isinstance(entity, Enum):

            self.visitEnum(entity, result)

        # Handle namespace
        elif isinstance(entity, Namespace):

            Error.assertTrue(
                element=element,
                condition=(self.level == 0),
                message="Namespaces can only be declared at top level.")

            self.visitNamespace(entity, result)

            # Update the current namespace
            self.parents.append(Parent(entity=entity))

        # Handle use
        elif isinstance(entity, Use):

            self.visitUse(entity, result)

        # Should never go here
        else:
            Error.handleFromElement(element=element,
                                    message="Unexpected entity: {}".format(
                                        type(entity)))

        return result