def assign_single_target(target, assigned_type, static_value, context): target_token = expr.get_token(target) if target_token == 'Name': old_symbol = context.get(target.id) new_symbol = Symbol(target.id, assigned_type, static_value) context.add(new_symbol) return (target.id, old_symbol, new_symbol) elif target_token == 'Subscript': _ = expr.expression_type(target.value, context) # TODO: implement this return ('Subscript', None, None) elif target_token == 'Attribute': instance = expr.expression_type(target.value, context) if not isinstance(instance, Instance): return (target.attr, None, None) else: old_symbol = instance.attributes.get(target.attr) new_symbol = Symbol(target.attr, assigned_type, static_value) instance.attributes.add(new_symbol) return (target.attr, old_symbol, new_symbol) elif target_token == 'Tuple': # TODO: implement this return ('Tuple', None, None) else: raise RuntimeError('Unrecognized assignment target: ' + target_token)
def __init__(self, name=None, arguments=None, context=None, decorator_list=[]): self.name = name if arguments is None: self.names = [] self.types = [] self.default_types = [] self.annotated_types = [] self.vararg_name = None self.kwarg_name = None self.min_count = 0 return # only for copy constructor below assert context is not None self.names = [arg.id for arg in arguments.args] self.min_count = len(arguments.args) - len(arguments.defaults) default_types = [expr.expression_type(d, context) for d in arguments.defaults] self.default_types = ([Unknown()] * self.min_count) + default_types self.annotated_types = self._get_annotated_types( decorator_list, context) self.types = [annotated if annotated != Unknown() else default for annotated, default in zip(self.annotated_types, self.default_types)] self.vararg_name = arguments.vararg self.kwarg_name = arguments.kwarg
def static_evaluate(node, context): token = get_token(node) recur = partial(static_evaluate, context=context) if token == 'Num': return node.n if token == 'Str': return node.s if token == 'Name': symbol = context.get(node.id) return symbol.get_value() if symbol else UnknownValue() if token == 'BoolOp': operator = get_token(node.op) return operator_evaluate(operator, *map(recur, node.values)) if token == 'UnaryOp': operator = get_token(node.op) return operator_evaluate(operator, recur(node.operand)) if token == 'BinOp': operator = get_token(node.op) return operator_evaluate(operator, recur(node.left), recur(node.right)) if token == 'Compare': operands = [node.left] + node.comparators operators = map(get_token, node.ops) assert len(operands) == len(operators) + 1 values = map(recur, operands) types = map(partial(expr.expression_type, context=context), operands) params = zip(values, types) results = [ comparison_evaluate(operators[i], params[i], params[i + 1]) for i in range(len(operators)) ] return operator_evaluate('And', *results) if token == 'List': return list(map(recur, node.elts)) if token == 'Set': return set(map(recur, node.elts)) if token == 'Dict': return dict(zip(map(recur, node.keys), map(recur, node.values))) if token == 'Tuple': return tuple(map(recur, node.elts)) if token == 'IfExp': test = recur(node.test) if test is True: return recur(node.body) if test is False: return recur(node.orelse) if token == 'Attribute': value_type = expr.expression_type(node.value, context) if isinstance(value_type, Instance): # pylint: disable=maybe-no-member symbol = value_type.attributes.get(node.attr) return symbol.get_value() if symbol else UnknownValue() return UnknownValue()
def static_evaluate(node, context): token = get_token(node) recur = partial(static_evaluate, context=context) if token == 'Num': return node.n if token == 'Str': return node.s if token == 'Name': symbol = context.get(node.id) return symbol.get_value() if symbol else UnknownValue() if token == 'BoolOp': operator = get_token(node.op) return operator_evaluate(operator, *map(recur, node.values)) if token == 'UnaryOp': operator = get_token(node.op) return operator_evaluate(operator, recur(node.operand)) if token == 'BinOp': operator = get_token(node.op) return operator_evaluate(operator, recur(node.left), recur(node.right)) if token == 'Compare': operands = [node.left] + node.comparators operators = map(get_token, node.ops) assert len(operands) == len(operators) + 1 values = map(recur, operands) types = map(partial(expr.expression_type, context=context), operands) params = zip(values, types) results = [comparison_evaluate(operators[i], params[i], params[i+1]) for i in range(len(operators))] return operator_evaluate('And', *results) if token == 'List': return list(map(recur, node.elts)) if token == 'Set': return set(map(recur, node.elts)) if token == 'Dict': return dict(zip(map(recur, node.keys), map(recur, node.values))) if token == 'Tuple': return tuple(map(recur, node.elts)) if token == 'IfExp': test = recur(node.test) if test is True: return recur(node.body) if test is False: return recur(node.orelse) if token == 'Attribute': value_type = expr.expression_type(node.value, context) if isinstance(value_type, Instance): # pylint: disable=maybe-no-member symbol = value_type.attributes.get(node.attr) return symbol.get_value() if symbol else UnknownValue() return UnknownValue()
def _get_annotated_types(self, decorator_list, context): types_decorator = [d for d in decorator_list if get_token(d) == 'Call' and d.func.id == 'types'] return ([expr.expression_type(arg, context) for arg in types_decorator[0].args] if len(types_decorator) == 1 else repeat(Unknown()))