def visit_For(self, node): # Python doesn't create a scope for "for", but we will # treat it as if it did because it should union_type = Union(List(Unknown()), Set(Unknown()), Dict(Unknown(), Unknown()), Str()) self.check_type(node.iter, union_type) self.begin_scope() self.check_assign(node, node.target, node.iter, generator=True) self.generic_visit(node) self.end_scope()
def import_module(name, current_filepath, imported, warn): try: source, filepath, is_package = import_source(name, current_filepath) except RuntimeError as error: warn('import-failed', name + ' ' + current_filepath + '\n' + str(error)) return Unknown(), current_filepath, False cache_filename = sha256(filepath + '~' + source).hexdigest() cache_filepath = os.path.join(os.sep, os.environ['HOME'], '.pystarch', __version__, cache_filename) if False and os.path.exists(cache_filepath): with open(cache_filepath, 'rb') as cache_file: return pickle.load(cache_file), filepath, is_package elif filepath in imported: #i = imported.index(filepath) #paths = ' -> '.join(imported[i:] + [filepath]) #print('CIRCULAR: ' + paths) return Instance('object', Scope()), filepath, is_package else: imported.append(filepath) scope, _, _ = analyze(source, filepath, imported=imported) module = Instance('object', scope) #try: os.makedirs(os.path.dirname(cache_filepath)) #except: pass #with open(cache_filepath, 'wb') as cache_file: # import ipdb; ipdb.set_trace() # pickle.dump(module, cache_file, pickle.HIGHEST_PROTOCOL) return module, filepath, is_package
def check_type(self, node, expected_type=Unknown()): computed_type = visit_expression(node, expected_type, self.context(), self._warnings) if (not type_subset(computed_type, expected_type) and not isinstance(computed_type, Unknown)): details = '{0} vs {1}'.format(computed_type, expected_type) self.warn('type-error', node, details) return computed_type
def check_return(self, node, is_yield=False): if node.value is None: value_type = NoneType() else: value_type = self.check_type(node.value, Unknown()) return_type = List(value_type) if is_yield else value_type static_value = self.evaluate(node.value) self._check_return(return_type, static_value)
def visit_FunctionDef(self, node): visitor = ScopeVisitor(self._filepath, self.context(), warnings=self._warnings) function_type = construct_function_type(node, visitor, self._class_instance) self._context.add(Symbol(node.name, function_type)) # now check that all the types are consistent between # the default types, annotated types, and constrained types signature = function_type.signature types = zip(signature.names, signature.types, signature.annotated_types, signature.default_types) for name, _, annotated_type, default_type in types: if (annotated_type != Unknown() and default_type != Unknown() and default_type != annotated_type): self.warn('default-argument-type-error', node, name)
def visit_ImportFrom(self, node): filepath = get_path_for_level(self._filepath, node.level) parts = node.module.split('.') if node.module else [None] warn = lambda category, details: self._warnings.warn( node, category, details) for part in parts: import_type, filepath, is_package = import_module( part, filepath, self._imported, warn) for alias in node.names: symbol_name = alias.asname or alias.name if is_package: symbol_type, _, _ = import_module(alias.name, filepath, self._imported, warn) else: if isinstance(import_type, Instance): symbol_type = import_type.attributes.get_type(alias.name) if symbol_type is None: warn('name-not-found', alias.name) continue else: symbol_type = Unknown() self._context.add(Symbol(symbol_name, symbol_type))
def import_chain(fully_qualified_name, asname, import_scope, current_filepath, imported, warn): scope = import_scope filepath = current_filepath is_package = True names = fully_qualified_name.split('.') if fully_qualified_name else [None] for name in names: if scope is None: warn('import-error', fully_qualified_name) return Unknown() if is_package: import_type, filepath, is_package = import_module( name, filepath, imported, warn) if asname is None: scope.add(Symbol(name, import_type)) scope = (import_type.attributes if isinstance( import_type, Instance) else None) else: import_type = scope.get_type(name) scope = None if asname is not None: import_scope.add(Symbol(asname, import_type)) return import_type
def visit_Expr(self, node): self.check_type(node.value, Unknown())