def test_faulty_nested_class(self): code = 'class oops(object):\n class return: pass' tree, errors = frilouz.parse(ast.parse, code) self.assertTrue(errors) self.assertEqual( astunparse.unparse(tree).strip(), 'class oops(object):\n' ' pass')
def test_faulty_class(self): code = 'def foo():pass\nclass oops(): def\ndef bar():pass' tree, errors = frilouz.parse(ast.parse, code) self.assertEqual(len(errors), 1) self.assertEqual( astunparse.unparse(tree).strip(), 'def foo():\n pass\n' 'pass\n\n' 'def bar():\n pass')
def test_faulty_nested_func_multiline(self): code = 'def foo():\n\tx = 1\n\tdef oops(): return return' tree, errors = frilouz.parse(ast.parse, code) self.assertEqual(len(errors), 1) self.assertEqual( astunparse.unparse(tree).strip(), 'def foo():\n' ' x = 1\n' ' pass')
def test_faulty_func_multiline(self): code = 'def foo():pass\ndef oops():\n return return\ndef bar():pass' tree, errors = frilouz.parse(ast.parse, code) self.assertEqual(len(errors), 1) self.assertEqual( astunparse.unparse(tree).strip(), 'def foo():\n pass\n\n' 'def oops():\n pass\n\n' 'def bar():\n pass')
def test_stmt(self): code = 'def foo():\n if 1\n pass\n' tree, errors = frilouz.parse(ast.parse, code) self.assertEqual(len(errors), 1) self.assertEqual( astunparse.unparse(tree).strip(), 'def foo():\n' ' pass\n' ' pass')
def test_multiple_errors(self): code = 'return def\ndef (x):pass\nreturn def' tree, errors = frilouz.parse(ast.parse, code) self.assertEqual(len(errors), 3) self.assertEqual( astunparse.unparse(tree).strip(), 'pass\n' 'pass\n' 'pass')
def test_mutliple_top_level_stmt(self): code = 'def ok():pass\ndef ko(): &^$\n ok()\nok()\nko()' tree, errors = frilouz.parse(ast.parse, code) self.assertEqual(len(errors), 2) self.assertEqual( astunparse.unparse(tree).strip(), 'def ok():\n pass\n' 'pass\npass\n' 'ok()\n' 'ko()')
def test_def(self): code = 'def foo():pass\ndef oops()\n pass\ndef bar(): pass' tree, errors = frilouz.parse(ast.parse, code) self.assertEqual(len(errors), 2) self.assertEqual( astunparse.unparse(tree).strip(), 'def foo():\n pass\n' 'pass\n' 'pass\n\n' 'def bar():\n pass')
def test_faulty_after_dedent(self): code = 'if 1:\n if 2:\n pass\n pass\n ! return' tree, errors = frilouz.parse(ast.parse, code) self.assertEqual(len(errors), 1) self.assertEqual( astunparse.unparse(tree).strip(), 'if 1:\n' ' if 2:\n' ' pass\n' ' pass\n' ' pass')
def memestra(file_descriptor, decorator, reason_keyword, search_paths=None, recursive=False, cache_dir=None): ''' Parse `file_descriptor` and returns a list of (function, filename, line, colno) tuples. Each elements represents a code location where a deprecated function is used. A deprecated function is a function flagged by `decorator`, where `decorator` is a tuple representing an import path, e.g. (module, attribute) If `recursive` is set to `True`, deprecated use are checked recursively throughout the *whole* module import tree. Otherwise, only one level of import is checked. ''' assert not isinstance(decorator, str) and \ len(decorator) > 1, "decorator is at least (module, attribute)" module, syntax_errors = frilouz.parse(ast.parse, file_descriptor.read()) # Collect deprecated functions resolver = ImportResolver(decorator, reason_keyword, search_paths, recursive, cache_dir=cache_dir) resolver.visit(module) ancestors = resolver.ancestors duc = resolver.def_use_chains # Find their users formated_deprecated = [] for deprecated_info in resolver.get_deprecated_users(duc, ancestors): deprecated_node, user_node, _, reason = deprecated_info formated_deprecated.append((prettyname(deprecated_node), getattr(file_descriptor, 'name', '<>'), user_node.lineno, user_node.col_offset, reason)) formated_deprecated.sort() return formated_deprecated
def test_fine(self): code = 'def foo(): pass' tree, errors = frilouz.parse(ast.parse, code) self.assertFalse(errors) self.assertEqual( astunparse.unparse(tree).strip(), 'def foo():\n pass')
def test_faulty_top(self): code = 'return def' tree, errors = frilouz.parse(ast.parse, code) self.assertTrue(errors) self.assertEqual(astunparse.unparse(tree).strip(), 'pass')
def load_deprecated_from_module(self, module_name, level=None): # level may be none when it's taken from the ImportFrom node if level is None: level = 0 # update module/pkg based on level rmodule_name = '.' * level + module_name # perform the module lookup try: module_name = resolve_name(rmodule_name, self.pkg_name) except (ImportError, ValueError): return None module_path = resolve_module(module_name, self.search_paths) # hopefully a module was found if module_path is None: return None module_key = self.key_factory(module_path, name_hint=module_name) # either find it in the cache if module_key in self.cache: data = self.cache[module_key] if data['version'] == Format.version: return dict(load_deprecated(entry) for entry in data['deprecated']) elif data['generator'] == 'manual': warnings.warn( ("skipping module {} because it has an obsolete, " "manually generated, cache file: {}") .format(module_name, module_key.module_hash)) return {} # or fill a new entry # To avoid loop, mark the key as in process self.cache[module_key] = {'generator': 'manual', 'deprecated': []} with open(module_path) as fd: try: module, syntax_errors = frilouz.parse(ast.parse, fd.read()) except UnicodeDecodeError: return [] duc = SilentDefUseChains() duc.visit(module) anc = beniget.Ancestors() anc.visit(module) # Collect deprecated functions if self.recursive and module_path not in self.visited: self.visited.add(module_path) current_pkg = ".".join(module_name.split('.')[:-1]) resolver = ImportResolver(self.decorator, self.reason_keyword, self.search_paths, self.recursive, parent=self, pkg_name=current_pkg) resolver.visit(module) deprecated_imports = [make_deprecated(d, reason) for _, _, d, reason in resolver.get_deprecated_users(duc, anc)] else: deprecated_imports = [] deprecated = self.collect_deprecated(module, duc, anc, pkg_name=module_name) deprecated.update(deprecated_imports) dl = {symbol_name(d[0]): d[1] for d in deprecated if d is not None} data = {'generator': 'memestra', 'deprecated': [store_deprecated(d, dl[d]) for d in sorted(dl)]} self.cache[module_key] = data return dl