def get_pedal_type_from_type_literal(value, type_space=None) -> Type: if value == list: return ListType(empty=False) elif value == dict: return DictType(empty=False) elif isinstance(value, list): if value: return ListType(empty=False, subtype=get_pedal_type_from_type_literal( value[0], type_space)) else: return ListType(empty=True) elif isinstance(value, dict): if not value: return DictType(empty=True) if all(isinstance(value, str) for k in value.keys()): return DictType(literals=[LiteralStr(s) for s in value.keys()], values=[ get_pedal_type_from_type_literal( vv, type_space) for vv in value.values() ]) return DictType(keys=[ get_pedal_type_from_type_literal(k, type_space) for k in value.keys() ], values=[ get_pedal_type_from_type_literal(vv, type_space) for vv in value.values() ]) elif isinstance(value, type): return get_pedal_type_from_str(value.__name__) else: return get_pedal_type_from_str(str(value))
def get_literal(self, node): """ Args: node: Returns: """ if isinstance(node, ast.Num): return LiteralNum(node.n) elif isinstance(node, ast.Str): return LiteralStr(node.s) elif isinstance(node, ast.Tuple): values = [] for elt in node.elts: subvalue = self.get_literal(elt) if subvalue is not None: values.append(subvalue) else: return None return LiteralTuple(values) elif isinstance(node, ast.Name): if node.id == "None": return LiteralNone(None) elif node.id == "False": return LiteralBool(False) elif node.id == "True": return LiteralBool(True) return None
def get_pedal_literal_from_pedal_type(type): """ Args: type: Returns: """ if isinstance(type, NumType): return LiteralNum(0) elif isinstance(type, StrType): return LiteralStr("") else: # TODO: Finish the mapping return LiteralStr("")
def test_assert_type_custom_record_passes(self): Dog = DictType(literals=[LiteralStr("Name")], values=[StrType()]) with Execution( 'Dog = {"Name": str}\ndef pet(d: Dog) -> str: return d["Name"]\npet({"Name": "Fido"})' ) as e: f = ensure_function('pet', parameters=('Dog', ), returns=str) self.assertFalse(f) self.assertFeedback(e, SUCCESS_MESSAGE)
def make_record(a_record) -> Type: if isinstance(a_record, dict): return DictType( literals=[LiteralStr(s) for s in a_record.keys()], values=[make_record(value) for value in a_record.values()]) elif isinstance(a_record, list): return ListType(subtype=make_record(a_record[0])) else: return get_pedal_type_from_str(str(a_record))
def test_assert_type_custom_record_fails(self): Dog = DictType(literals=[LiteralStr("Name")], values=[StrType()]) with Execution('def pet(d: str) -> str: return d\npet("Fido")') as e: f = ensure_function('pet', parameters=('Dog', ), returns=str) self.assertTrue(f) self.assertFeedback( e, "Wrong Parameter Type\n" "The function named pet has a parameter named d" " that is a string, but should be Dog.")
def get_pedal_literal_from_json(val): """ Args: val: Returns: """ if val['type'] == 'LiteralStr': return LiteralStr(val['value']) elif val['type'] == 'LiteralNum': return LiteralNum(val['value']) elif val['type'] == 'LiteralBool': return LiteralBool(val['value'])
def get_pedal_type_from_value(value, type_space=None) -> Type: """ Converts the Python value to a Pedal Type """ if isinstance(value, bool): return BoolType() if isinstance(value, (int, float, complex)): return NumType() if isinstance(value, str): return StrType() if isinstance(value, type(None)): return NoneType() if isinstance(value, tuple): return TupleType( (get_pedal_type_from_value(t, type_space) for t in value)) if isinstance(value, set): return SetType( (get_pedal_type_from_value(t, type_space) for t in value)) if isinstance(value, frozenset): return FrozenSetType( (get_pedal_type_from_value(t, type_space) for t in value)) if isinstance(value, list): if value: return ListType(empty=False, subtype=get_pedal_type_from_value(value[0])) else: return ListType(empty=True) if isinstance(value, dict): if not value: return DictType(empty=True) if all(isinstance(value, str) for k in value.keys()): return DictType(literals=[LiteralStr(s) for s in value.keys()], values=[ get_pedal_type_from_value(vv, type_space) for vv in value.values() ]) return DictType(keys=[ get_pedal_type_from_ast(k, type_space) for k in value.keys() ], values=[ get_pedal_type_from_ast(vv, type_space) for vv in value.values() ]) return UnknownType()
def get_pedal_type_from_ast(value: ast.AST, type_space=None) -> Type: """ Determines the Pedal Type from this ast node. Args: value (ast.AST): An AST node. Returns: Type: A Pedal Type """ try: if isinstance(value, ast.Constant): return get_pedal_type_from_value(value.value, type_space) except AttributeError as e: pass if isinstance(value, ast.Name): return get_pedal_type_from_str(value.id, type_space) elif isinstance(value, ast.Str): return StrType(bool(value.s)) elif isinstance(value, ast.List): return ListType(subtype=(get_pedal_type_from_ast( value.elts[0], type_space) if value.elts else None), empty=not bool(value.elts)) elif isinstance(value, ast.Set): return SetType(subtype=(get_pedal_type_from_ast( value.elts[0], type_space) if value.elts else None), empty=not bool(value.elts)) elif isinstance(value, ast.Tuple): return TupleType(subtypes=[ get_pedal_type_from_ast(e, type_space) for e in value.elts ]) elif isinstance(value, ast.Dict): if not value.keys: return DictType(empty=True) if all(isinstance(k, ast.Str) for k in value.keys): return DictType(literals=[LiteralStr(s.s) for s in value.keys], values=[ get_pedal_type_from_ast(vv, type_space) for vv in value.values ]) return DictType( keys=[get_pedal_type_from_ast(k, type_space) for k in value.keys], values=[ get_pedal_type_from_ast(vv, type_space) for vv in value.values ]) # Support new style subscripts (e.g., ``list[int]``) elif ((IS_PYTHON_39 and isinstance(value, ast.Subscript)) or isinstance(value, ast.Subscript) and isinstance(value.slice, ast.Index)): if IS_PYTHON_39: slice = value.slice else: slice = value.slice.value if isinstance(value.value, ast.Name): if isinstance(slice, ast.Name): subtype = get_pedal_type_from_str(slice.id) if value.value.id == "list": return ListType(subtype=subtype, empty=False) if value.value.id == "set": return SetType(subtype=subtype, empty=False) if value.value.id == "tuple": return TupleType(subtypes=(subtype, )) if value.value.id == "frozenset": return FrozenSetType(subtype=subtype, empty=False) elif isinstance(slice, ast.Tuple): subtypes = [ get_pedal_type_from_ast(e, type_space) for e in slice.elts ] if value.value.id == "tuple": return TupleType(subtypes=subtypes) elif value.value.id == "dict" and len(subtypes) == 2: return DictType(keys=subtypes[0], values=subtypes[1]) # Top-level Module, parse it and get it back if isinstance(value, ast.Module) and value.body: if isinstance(value.body[0], ast.Expr): return get_pedal_type_from_ast(value.body[0].value, type_space) return UnknownType()