Exemple #1
0
def toType(pat):
    """Convert a pattern to a type, if possible (wildcards can't be converted to types).

    :type pat: titus.P
    :param pat: pattern to convert
    :rtype: titus.datatype.Type
    :return: corresponding type (titus.datatype.Type rather than titus.datatype.AvroType to allow for titus.datatype.FcnType)
    """

    if isinstance(pat, Null): return AvroNull()
    elif isinstance(pat, Boolean): return AvroBoolean()
    elif isinstance(pat, Int): return AvroInt()
    elif isinstance(pat, Long): return AvroLong()
    elif isinstance(pat, Float): return AvroFloat()
    elif isinstance(pat, Double): return AvroDouble()
    elif isinstance(pat, Bytes): return AvroBytes()
    elif isinstance(pat, String): return AvroString()

    elif isinstance(pat, Array): return AvroArray(toType(pat.items))
    elif isinstance(pat, Map): return AvroMap(toType(pat.values))
    elif isinstance(pat, Union):
        return AvroUnion([toType(x) for x in pat.types])

    elif isinstance(pat, Fixed) and pat.fullName is not None:
        namebits = pat.fullName.split(".")
        if len(namebits) == 1:
            return AvroFixed(pat.size, namebits[-1], None)
        else:
            return AvroFixed(pat.size, namebits[-1], ".".join(namebits[:-1]))
    elif isinstance(pat, Fixed):
        return AvroFixed(pat.size)

    elif isinstance(pat, Enum) and pat.fullName is not None:
        namebits = pat.fullName.split(".")
        if len(namebits) == 1:
            return AvroEnum(pat.symbols, namebits[-1], None)
        else:
            return AvroEnum(pat.symbols, namebits[-1], ".".join(namebits[:-1]))
    elif isinstance(pat, Enum):
        return AvroEnum(pat.symbols)

    elif isinstance(pat, Record) and pat.fullName is not None:
        namebits = pat.fullName.split(".")
        if len(namebits) == 1:
            return AvroRecord(
                [AvroField(k, toType(v)) for k, v in list(pat.fields.items())],
                namebits[-1], None)
        else:
            return AvroRecord(
                [AvroField(k, toType(v)) for k, v in list(pat.fields.items())],
                namebits[-1], ".".join(namebits[:-1]))
    elif isinstance(pat, Record):
        return AvroRecord(
            [AvroField(k, toType(v)) for k, v in list(pat.fields.items())])

    elif isinstance(pat, Fcn):
        return FcnType([toType(x) for x in pat.params()], toType(pat.ret()))

    else:
        raise Exception
Exemple #2
0
    def assignRet(self, pat, assignments):
        """Apply the label assignments (e.g. "A" matched to "int", "B" matched to "string" etc.) to the return pattern.

        :type pat: titus.P
        :param pat: original return pattern
        :type assignments: dict from label letters to titus.datatype.AvroType
        :param assignments: assigned types to apply
        :rtype: titus.datatype.AvroType
        :return: resolved type for the return value of the signature
        """

        if isinstance(pat, P.Null):
            return AvroNull()
        elif isinstance(pat, P.Boolean):
            return AvroBoolean()
        elif isinstance(pat, P.Int):
            return AvroInt()
        elif isinstance(pat, P.Long):
            return AvroLong()
        elif isinstance(pat, P.Float):
            return AvroFloat()
        elif isinstance(pat, P.Double):
            return AvroDouble()
        elif isinstance(pat, P.Bytes):
            return AvroBytes()
        elif isinstance(pat, P.String):
            return AvroString()

        elif isinstance(pat, P.Array):
            return AvroArray(self.assignRet(pat.items, assignments))
        elif isinstance(pat, P.Map):
            return AvroMap(self.assignRet(pat.values, assignments))
        elif isinstance(pat, P.Union):
            return AvroUnion(
                [self.assignRet(x, assignments) for x in pat.types])

        elif isinstance(pat, P.Fixed):
            return P.toType(pat)
        elif isinstance(pat, P.Enum):
            return P.toType(pat)
        elif isinstance(pat, P.Record):
            return P.toType(pat)
        elif isinstance(pat, P.Fcn):
            return P.toType(pat)

        elif isinstance(pat, P.Wildcard):
            return assignments[pat.label]
        elif isinstance(pat, P.WildRecord):
            return assignments[pat.label]
        elif isinstance(pat, P.WildEnum):
            return assignments[pat.label]
        elif isinstance(pat, P.WildFixed):
            return assignments[pat.label]
        elif isinstance(pat, P.EnumFields):
            return assignments[pat.label]

        else:
            raise Exception(repr(pat))
Exemple #3
0
    def assign(self, pat, arg, assignments):
        """Apply the label assignments (e.g. "A" matched to "int", "B" matched to "string", etc.) to each parameter of the signature.

        :type pat: titus.P
        :param pat: original parameter pattern
        :type arg: titus.datatype.AvroType
        :param arg: supplied argument type
        :type assignments: dict from label letters to titus.datatype.AvroType
        :param assignments: assigned types to apply
        :rtype: titus.datatype.AvroType
        :return: resolved type for one parameter of the signature
        """

        if isinstance(pat, P.Null) and isinstance(arg, AvroNull):
            return arg
        elif isinstance(pat, P.Boolean) and isinstance(arg, AvroBoolean):
            return arg

        elif isinstance(pat, P.Int) and isinstance(arg, AvroInt):
            return AvroInt()
        elif isinstance(pat, P.Long) and (isinstance(arg, AvroInt)
                                          or isinstance(arg, AvroLong)):
            return AvroLong()
        elif isinstance(pat, P.Float) and (isinstance(arg, AvroInt)
                                           or isinstance(arg, AvroLong)
                                           or isinstance(arg, AvroFloat)):
            return AvroFloat()
        elif isinstance(pat, P.Double) and (isinstance(arg, AvroInt)
                                            or isinstance(arg, AvroLong)
                                            or isinstance(arg, AvroFloat)
                                            or isinstance(arg, AvroDouble)):
            return AvroDouble()

        elif isinstance(pat, P.Bytes) and isinstance(arg, AvroBytes):
            return arg
        elif isinstance(pat, P.String) and isinstance(arg, AvroString):
            return arg

        elif isinstance(pat, P.Array) and isinstance(arg, AvroArray):
            return AvroArray(
                P.mustBeAvro(self.assign(pat.items, arg.items, assignments)))
        elif isinstance(pat, P.Map) and isinstance(arg, AvroMap):
            return AvroMap(
                P.mustBeAvro(self.assign(pat.values, arg.values, assignments)))
        elif isinstance(pat, P.Union) and isinstance(arg, AvroUnion):
            return arg
        elif isinstance(pat, P.Union) and isinstance(arg, AvroType):
            return arg

        elif isinstance(pat, P.Fixed) and isinstance(arg, AvroFixed):
            return arg
        elif isinstance(pat, P.Enum) and isinstance(arg, AvroEnum):
            return arg
        elif isinstance(pat, P.Record) and isinstance(arg, AvroRecord):
            return arg

        elif isinstance(pat, P.Fcn) and isinstance(arg, FcnType):
            return arg

        elif isinstance(pat, P.Wildcard):
            return assignments[pat.label]
        elif isinstance(pat, P.WildRecord):
            return assignments[pat.label]
        elif isinstance(pat, P.WildEnum):
            return assignments[pat.label]
        elif isinstance(pat, P.WildFixed):
            return assignments[pat.label]
        elif isinstance(pat, P.EnumFields):
            return assignments[pat.label]

        else:
            raise Exception
Exemple #4
0
    def broadestType(candidates):
        """Compute the narrowest possible supertype of a set of types.

        :type candidates: list of titus.datatype.AvroType
        :param candidates: set of types for which to find the narrowest possible supertype
        :rtype: titus.datatype.AvroType
        :return: narrowest possible supertype, usually a union of the candidates
        """

        realCandidates = [
            x for x in candidates if not isinstance(x, ExceptionType)
        ]

        if len(candidates) == 0:
            return ValueError("empty list of types")
        elif len(realCandidates) == 0:
            return ValueError("list of types consists only of exception type")

        elif all(isinstance(x, AvroNull) for x in realCandidates):
            return realCandidates[0]
        elif all(isinstance(x, AvroBoolean) for x in realCandidates):
            return realCandidates[0]

        elif all(isinstance(x, AvroInt) for x in realCandidates):
            return AvroInt()
        elif all(
                isinstance(x, AvroInt) or isinstance(x, AvroLong)
                for x in realCandidates):
            return AvroLong()
        elif all(
                isinstance(x, AvroInt) or isinstance(x, AvroLong)
                or isinstance(x, AvroFloat) for x in realCandidates):
            return AvroFloat()
        elif all(
                isinstance(x, AvroInt) or isinstance(x, AvroLong)
                or isinstance(x, AvroFloat) or isinstance(x, AvroDouble)
                for x in realCandidates):
            return AvroDouble()

        elif all(isinstance(x, AvroBytes) for x in realCandidates):
            return realCandidates[0]
        elif all(isinstance(x, AvroString) for x in realCandidates):
            return realCandidates[0]

        elif all(isinstance(x, AvroArray) for x in realCandidates):
            return AvroArray(
                P.mustBeAvro(
                    LabelData.broadestType([x.items for x in realCandidates])))

        elif all(isinstance(x, AvroMap) for x in realCandidates):
            return AvroMap(
                P.mustBeAvro(
                    LabelData.broadestType([x.values
                                            for x in realCandidates])))

        elif all(isinstance(x, AvroFixed) for x in realCandidates):
            fullName = realCandidates[0].fullName
            if all(x.fullName == fullName for x in realCandidates[1:]):
                return realCandidates[0]
            else:
                raise IncompatibleTypes("incompatible fixed types: " +
                                        " ".join(map(repr, realCandidates)))

        elif all(isinstance(x, AvroEnum) for x in realCandidates):
            fullName = realCandidates[0].fullName
            if all(x.fullName == fullName for x in realCandidates[1:]):
                return realCandidates[0]
            else:
                raise IncompatibleTypes("incompatible enum types: " +
                                        " ".join(map(repr, realCandidates)))

        elif all(isinstance(x, AvroRecord) for x in realCandidates):
            fullName = realCandidates[0].fullName
            if all(x.fullName == fullName for x in realCandidates[1:]):
                return realCandidates[0]
            else:
                raise IncompatibleTypes("incompatible record types: " +
                                        " ".join(map(repr, realCandidates)))

        elif all(isinstance(x, FcnType) for x in realCandidates):
            params = realCandidates[0].params
            ret = realCandidates[0].ret

            if all(x.params == params and x.ret == ret
                   for x in realCandidates[1:]):
                return realCandidates[0]
            else:
                raise IncompatibleTypes("incompatible function types: " +
                                        " ".join(map(repr, realCandidates)))

        elif not any(isinstance(x, FcnType) for x in realCandidates):
            types = LabelData.distinctTypes(realCandidates)
            types = [P.mustBeAvro(x) for x in types]

            countFixed = 0
            countEnum = 0
            for t in types:
                if isinstance(t, AvroFixed):
                    countFixed += 1
                if isinstance(t, AvroEnum):
                    countEnum += 1

            if countFixed > 1:
                raise IncompatibleTypes("incompatible fixed types")
            if countEnum > 1:
                raise IncompatibleTypes("incompatible enum types")

            return AvroUnion(types)

        else:
            raise IncompatibleTypes(
                "incompatible function/non-function types: " +
                " ".join(map(repr, realCandidates)))