Esempio n. 1
0
    def test_integer_list_constant(self):
        input = [1, 2, 3]
        node = ast.parse(str(input)).body[0].value
        expected_output = ListType(Type.int)

        typeanalyser = TypeAnalyser(Analyser(node), {})
        output = typeanalyser.get_type(input)

        self.assertEqual(expected_output, output)
Esempio n. 2
0
    def test_boolean_list_constant(self):
        input = [True, False]
        node = ast.parse(str(input)).body[0].value
        expected_output = ListType(Type.bool)

        typeanalyser = TypeAnalyser(Analyser(node), {})
        output = typeanalyser.get_type(input)

        self.assertEqual(expected_output, output)
Esempio n. 3
0
    def test_any_list_constant(self):
        input = [1, '2', False]
        node = ast.parse(str(input)).body[0].value
        expected_output = ListType(UnionType.build([Type.int, Type.str]))

        typeanalyser = TypeAnalyser(Analyser(node), {})
        output = typeanalyser.get_type(input)

        self.assertEqual(expected_output, output)
Esempio n. 4
0
class Type:
    @classmethod
    def builtin_types(cls) -> Dict[str, IType]:
        """
        Gets a dictionary that maps each type with its name

        :return: A dictionary that maps each Python builtin type representation with its name
        """
        builtin_types = [
            Type.int, Type.bool, Type.str, Type.list, Type.tuple, Type.dict,
            Type.range, Type.bytes, Type.bytearray, Type.none
        ]
        return {
            tpe._identifier: tpe
            for tpe in builtin_types if isinstance(tpe, IType)
        }

    @classmethod
    def all_types(cls) -> Dict[str, IType]:
        return {
            tpe._identifier: tpe
            for tpe in vars(cls).values() if isinstance(tpe, IType)
        }

    @classmethod
    def get_type(cls, value: Any) -> IType:
        """
        Returns the type of the given value.

        :param value: value to get the type
        :return: Returns the type of the value. `Type.none` by default.
        """
        val: IType = None
        for type in vars(cls).values():
            if isinstance(type, IType) and type.is_type_of(value):
                val = type.build(value)
                break

        if val is not None:
            return val
        return cls.none

    @classmethod
    def get_generic_type(cls, *types: IType) -> IType:
        """
        Returns the common generic type between the given values.

        :param types: list of type to be compared
        :return: Returns the common generic type of the values if exist. `Type.any` otherwise.
        """
        generic = cls.any
        if len(types) > 0:
            generic_types = [cls.mutableSequence, cls.mapping, cls.sequence]
            generic_types.append(
                generic)  # any type must be the last value in the list

            generic = types[0]
            for tpe in types[1:]:
                if generic == tpe or generic.is_type_of(tpe):
                    continue
                if tpe.is_type_of(generic):
                    generic = tpe
                    continue

                for gen in generic_types:
                    if gen.is_type_of(generic) and gen.is_type_of(tpe):
                        generic = gen
                        break

                if generic is Type.any:
                    break
        return generic

    # Builtin Types
    int = IntType()
    bool = BoolType()
    str = StrType()
    none = NoneType()
    bytes = BytesType()
    bytearray = ByteArrayType()
    tuple = TupleType()
    list = ListType()
    dict = DictType()
    range = RangeType(int)

    # Generic types
    sequence = GenericSequenceType()
    mutableSequence = GenericMutableSequenceType()
    mapping = GenericMappingType()
    exception = BaseExceptionType()
    any = anyType