def test_import(self): nms = names('from json import load', references=True) assert nms[0].name == 'json' assert nms[0].type == 'import' n = nms[0].goto_assignments()[0] assert n.name == 'json' assert n.type == 'module' assert nms[1].name == 'load' assert nms[1].type == 'import' n = nms[1].goto_assignments()[0] assert n.name == 'load' assert n.type == 'function' nms = names('import os; os.path', references=True) assert nms[0].name == 'os' assert nms[0].type == 'import' n = nms[0].goto_assignments()[0] assert n.name == 'os' assert n.type == 'module' n = nms[2].goto_assignments()[0] assert n.name == 'path' assert n.type == 'import' nms = names('import os.path', references=True) n = nms[0].goto_assignments()[0] assert n.name == 'os' assert n.type == 'module' n = nms[1].goto_assignments()[0] # This is very special, normally the name doesn't chance, but since # os.path is a sys.modules hack, it does. assert n.name in ('ntpath', 'posixpath') assert n.type == 'module'
def test_import(self): nms = names('from json import load', references=True) assert nms[0].name == 'json' assert nms[0].type == 'import' n = nms[0].goto_assignments()[0] assert n.name == 'json' assert n.type == 'module' assert nms[1].name == 'load' assert nms[1].type == 'import' n = nms[1].goto_assignments()[0] assert n.name == 'load' assert n.type == 'function' nms = names('import os; os.path', references=True) assert nms[0].name == 'os' assert nms[0].type == 'import' n = nms[0].goto_assignments()[0] assert n.name == 'os' assert n.type == 'module' n = nms[2].goto_assignments()[0] assert n.name == 'path' assert n.type == 'import' nms = names('import os.path', references=True) n = nms[0].goto_assignments()[0] assert n.name == 'os' assert n.type == 'module' n = nms[1].goto_assignments()[0] assert n.name == 'path' assert n.type == 'import'
def test_import(self): nms = names("from json import load", references=True) assert nms[0].name == "json" assert nms[0].type == "import" n = nms[0].goto_assignments()[0] assert n.name == "json" assert n.type == "module" assert nms[1].name == "load" assert nms[1].type == "import" n = nms[1].goto_assignments()[0] assert n.name == "load" assert n.type == "function" nms = names("import os; os.path", references=True) assert nms[0].name == "os" assert nms[0].type == "import" n = nms[0].goto_assignments()[0] assert n.name == "os" assert n.type == "module" n = nms[2].goto_assignments()[0] assert n.name == "path" assert n.type == "import" nms = names("import os.path", references=True) n = nms[0].goto_assignments()[0] assert n.name == "os" assert n.type == "module" n = nms[1].goto_assignments()[0] assert n.name == "path" assert n.type == "import"
def test_import(self): nms = names('from json import load', references=True) assert nms[0].name == 'json' assert nms[0].type == 'module' n = nms[0].goto_assignments()[0] assert n.name == 'json' assert n.type == 'module' assert nms[1].name == 'load' assert nms[1].type == 'function' n = nms[1].goto_assignments()[0] assert n.name == 'load' assert n.type == 'function' nms = names('import os; os.path', references=True) assert nms[0].name == 'os' assert nms[0].type == 'module' n = nms[0].goto_assignments()[0] assert n.name == 'os' assert n.type == 'module' n = nms[2].goto_assignments()[0] assert n.name == 'path' assert n.type == 'module' nms = names('import os.path', references=True) n = nms[0].goto_assignments()[0] assert n.name == 'os' assert n.type == 'module' n = nms[1].goto_assignments()[0] # This is very special, normally the name doesn't chance, but since # os.path is a sys.modules hack, it does. assert n.name in ('ntpath', 'posixpath', 'os2emxpath') assert n.type == 'module'
def _def(self, source, index=-1): return names( dedent(source), references=True, all_scopes=True, environment=self.environment )[index]
def get_defs_refs(file_path): defs, refs = [], [] # Get a clean UTF8 source. linecoler = LineColToOffConverter(jedi.Script(path=file_path).source) names = jedi.names(path=file_path, all_scopes=True, references=True) for name in names: if name.is_definition(): def_ = jedi_def_to_def(name, file_path, linecoler) defs.append(def_) else: try: full_name = full_name_of_def(name, from_ref=True) if full_name == '': raise Exception('full_name is empty') start = linecoler.convert(name.line, name.column) refs.append(Ref( DefPath=full_name.replace('.', '/'), DefFile=path.relpath(name.module_path), Def=False, File=file_path, Start=start, End=start + len(name.name), ToBuiltin=name.in_builtin_module(), )) except Exception as e: error('failed to convert ref (%s) in source file %s: %s' % (name, file_path, e)) return defs, refs
def test_class_call(self): src = 'from threading import Thread; Thread(group=1)' n = names(src, references=True)[-1] assert n.name == 'group' param_def = n.goto_assignments()[0] assert param_def.name == 'group' assert param_def.type == 'param'
def imports(filename): import jedi for n in jedi.names(path=filename): node = n._name.tree_name if node.parent.type in IMPORT_TYPES: yield node
def test_repetition(self): defs = names('a = 1; a', references=True, definitions=False) # Repeat on the same variable. Shouldn't change once we're on a # definition. for _ in range(3): assert len(defs) == 1 ass = defs[0].goto_assignments() assert ass[0].description == 'a = 1'
def test_names_twice(): source = dedent(''' def lol(): pass ''') defs = names(source=source) assert defs[0].defined_names() == []
def test_names_twice(environment): source = dedent(''' def lol(): pass ''') defs = names(source=source, environment=environment) assert defs[0].defined_names() == []
def imports_apis(script, apis): if apis is None or len(apis) == 0: return True names = jedi.names(script["source"]) imports = [n for n in names if n.description.startswith("module")] for imp in imports: if imp.full_name.startswith(apis): return True return False
def _extract_var_names(filename): if not filename.endswith(".py"): return [] try: var_names = jedi.names(path=filename) return var_names except: return []
def search_references(script, content, name_string): global use_score global use_magnitude result = [] to_search = [] # replace("return","_____return_value=" ) to force jedi analyse return and print command # also use += to replace append content = content.replace("return", "_____return_value=").replace("print", "_____print=").replace(".append", "+=") all_names = jedi.names(content, all_scopes=True, definitions=True, references=False) for name in all_names: if not name.full_name: continue if len(name.full_name) <=0: continue if name_string in name.description: # reduce some false postives if is_appear(name.description, name_string): left_value = name.description.strip().split('=')[0].strip() if left_value == name_string: continue result.append(name) if not "_____return_value" == name.full_name: to_search.append(left_value) use_score, use_magnitude = search_score_mag(name.description, use_score, use_magnitude) # if find two variables, then quit if use_score and use_magnitude: return result while True: len1 = len(result) to_search_new = [] for search_item in to_search: for name in all_names: if not name.full_name: continue if len(name.full_name) <=0: continue if search_item in name.description: if is_appear(name.description, search_item): left_value = name.description.strip().split('=')[0].strip() if left_value == search_item: continue result.append(name) to_search_new.append(left_value) use_score, use_magnitude = search_score_mag(name.description, use_score, use_magnitude) if use_score and use_magnitude: return result to_search = to_search_new if len1 == len(result): return result return result
def test_call_of_leaf_in_brackets(): s = dedent(""" x = 1 type(x) """) last_x = names(s, references=True, definitions=False)[-1] name = last_x._name call = helpers.call_of_leaf(name) assert call == name
def test_named_params(self): src = """\ def foo(a=1, bar=2): pass foo(bar=1) """ bar = names(dedent(src), references=True)[-1] param = bar.goto_assignments()[0] assert param.start_pos == (1, 13) assert param.type == 'param'
def test_named_params(self): src = """\ def foo(a=1, bar=2): pass foo(bar=1) """ bar = names(dedent(src), references=True)[-1] param = bar.goto_assignments()[0] assert (param.line, param.column) == (1, 13) assert param.type == 'param'
def is_appear(content, variable): all_names = jedi.names(content, all_scopes=True, definitions=True, references=True) for name in all_names: if not name.full_name: continue if len(name.full_name) <=0: continue if name.full_name.endswith("."+variable): return True return False
def test_goto_assignments_named_params(environment): src = """\ def foo(a=1, bar=2): pass foo(bar=1) """ bar = names(dedent(src), references=True, environment=environment)[-1] param = bar.goto_assignments()[0] assert (param.line, param.column) == (1, 13) assert param.type == 'param'
def get_names(source, filename): """ Retrieve a list of Name objects for the given source. """ definitions = jedi.names( source, path=filename, all_scopes=True, references=True, ) return [Name(d) for d in definitions]
def test_extract_def(): code = """ import pyqode.python.widgets import PyQt5.QtWidgets as QtWidgets app = QtWidgets.QApplication([]) editor = pyqode.python.widgets.PyCyodeEdit() editor.file.open(__file__) editor.show() app.exec() """ for definition in jedi.names(code): result = workers._extract_def(definition, "") assert result
def test_parent_on_comprehension(): ns = jedi.names('''\ def spam(): return [i for i in range(5)] ''', all_scopes=True) assert [name.name for name in ns] == ['spam', 'i'] assert ns[0].parent().name == '' assert ns[0].parent().type == 'module' assert ns[1].parent().name == 'spam' assert ns[1].parent().type == 'function'
def test_import_alias(self): nms = names("import json as foo", references=True) assert nms[0].name == "json" assert nms[0].type == "import" n = nms[0].goto_assignments()[0] assert n.name == "json" assert n.type == "module" assert nms[1].name == "foo" assert nms[1].type == "import" ass = nms[1].goto_assignments() assert len(ass) == 1 assert ass[0].name == "json" assert ass[0].type == "module"
def test_import_alias(self): nms = names('import json as foo', references=True) assert nms[0].name == 'json' assert nms[0].type == 'import' n = nms[0].goto_assignments()[0] assert n.name == 'json' assert n.type == 'module' assert nms[1].name == 'foo' assert nms[1].type == 'import' ass = nms[1].goto_assignments() assert len(ass) == 1 assert ass[0].name == 'json' assert ass[0].type == 'module'
def analyse(source_path=None, code=None): """ Analyse a Python source code file with Jedi. Returns a mapping from (scope-name, (line, column)) pairs to a name-types mapping. """ if not source_path and code is None: raise ValueError("Either 'source_path' or 'code' is required.") scoped_names = {} statement_iter = jedi.names(source=code, path=source_path, all_scopes=True) for statement in statement_iter: parent = statement.parent() scope = parent._definition evaluator = statement._evaluator # skip function/generator definitions, class definitions, and module imports if any( isinstance(statement._definition, t) for t in [Function, Class, ImportName]): continue key = (None if isinstance(scope, Module) else str(parent.name), scope.start_pos) try: names = scoped_names[key] except KeyError: names = scoped_names[key] = defaultdict(set) position = statement.start_pos if statement.name in names else None for name_type in evaluator.find_types(scope, statement.name, position=position, search_global=True): if isinstance(name_type, Instance): if isinstance(name_type.base, Class): type_name = 'object' else: type_name = name_type.base.obj.__name__ elif isinstance(name_type, ArrayMixin): type_name = name_type.type elif isinstance(name_type, GeneratorComprehension): type_name = None else: try: type_name = type(name_type.obj).__name__ except AttributeError as error: type_name = None if type_name is not None: names[str(statement.name)].add(type_name) return scoped_names
def defined_names(request_data): """ Returns the list of defined names for the document. """ global _old_definitions ret_val = [] path = request_data['path'] toplvl_definitions = jedi.names(request_data['code'], path, 'utf-8') for d in toplvl_definitions: definition = _extract_def(d, path) if d.type != 'import': ret_val.append(definition) ret_val = [d.to_dict() for d in ret_val] return ret_val
def test_no_error(environment): code = dedent(""" def foo(a, b): if a == 10: if b is None: print("foo") a = 20 """) func_name, = names(code) a, b, a20 = func_name.defined_names() assert a.name == 'a' assert b.name == 'b' assert a20.name == 'a' assert a20.goto_assignments() == [a20]
def test_no_error(environment): code = dedent(""" def foo(a, b): if a == 10: if b is None: print("foo") a = 20 """) func_name, = names(code) print(func_name.defined_names()) a, b, a20 = func_name.defined_names() assert a.name == 'a' assert b.name == 'b' assert a20.name == 'a' assert a20.goto_assignments() == [a20]
def test_import_alias(self): nms = names('import json as foo', references=True) assert nms[0].name == 'json' assert nms[0].type == 'module' assert nms[0]._name.tree_name.get_definition().type == 'import_name' n = nms[0].goto_assignments()[0] assert n.name == 'json' assert n.type == 'module' assert n._name.tree_name.get_definition().type == 'file_input' assert nms[1].name == 'foo' assert nms[1].type == 'module' assert nms[1]._name.tree_name.get_definition().type == 'import_name' ass = nms[1].goto_assignments() assert len(ass) == 1 assert ass[0].name == 'json' assert ass[0].type == 'module' assert ass[0]._name.tree_name.get_definition().type == 'file_input'
def test_import_alias(self): nms = names('import json as foo', references=True) assert nms[0].name == 'json' assert nms[0].type == 'module' assert nms[0]._name.tree_name.get_definition().type == 'import_name' n = nms[0].goto_assignments()[0] assert n.name == 'json' assert n.type == 'module' assert n._name._context.tree_node.type == 'file_input' assert nms[1].name == 'foo' assert nms[1].type == 'module' assert nms[1]._name.tree_name.get_definition().type == 'import_name' ass = nms[1].goto_assignments() assert len(ass) == 1 assert ass[0].name == 'json' assert ass[0].type == 'module' assert ass[0]._name._context.tree_node.type == 'file_input'
def test_import_alias(environment): nms = names('import json as foo', references=True, environment=environment) assert nms[0].name == 'json' assert nms[0].type == 'module' assert nms[0]._name.tree_name.parent.type == 'dotted_as_name' n = nms[0].goto_assignments()[0] assert n.name == 'json' assert n.type == 'module' assert n._name._context.tree_node.type == 'file_input' assert nms[1].name == 'foo' assert nms[1].type == 'module' assert nms[1]._name.tree_name.parent.type == 'dotted_as_name' ass = nms[1].goto_assignments() assert len(ass) == 1 assert ass[0].name == 'json' assert ass[0].type == 'module' assert ass[0]._name._context.tree_node.type == 'file_input'
def get_assigned_calls(source, api_basenames=None): skip = ( "class", "module", "def", ) assignments = [ n for n in jedi.names(source) if not n.description.startswith(skip) ] trees = [get_ast_subtree(n.description) for n in assignments] trees = [t for t in trees if t is not None] calls_trees = [t.value for t in trees if is_assign(t) and is_call(t.value)] if api_basenames is not None: calls_trees = [ c for c in calls_trees if get_func_str(c).split(".")[-1] in api_basenames ] return calls_trees
def analyse(source_path=None, code=None): """ Analyse a Python source code file with Jedi. Returns a mapping from (scope-name, (line, column)) pairs to a name-types mapping. """ if not source_path and code is None: raise ValueError("Either 'source_path' or 'code' is required.") scoped_names = {} statement_iter = jedi.names(source=code, path=source_path, all_scopes=True) for statement in statement_iter: parent = statement.parent() scope = parent._definition evaluator = statement._evaluator # skip function/generator definitions, class definitions, and module imports if any(isinstance(statement._definition, t) for t in [Function, Class, ImportName]): continue key = (None if isinstance(scope, Module) else str(parent.name), scope.start_pos) try: names = scoped_names[key] except KeyError: names = scoped_names[key] = defaultdict(set) position = statement.start_pos if statement.name in names else None for name_type in evaluator.find_types(scope, statement.name, position=position ,search_global=True): if isinstance(name_type, Instance): if isinstance(name_type.base, Class): type_name = 'object' else: type_name = name_type.base.obj.__name__ elif isinstance(name_type, ArrayMixin): type_name = name_type.type elif isinstance(name_type, GeneratorComprehension): type_name = None else: try: type_name = type(name_type.obj).__name__ except AttributeError as error: type_name = None if type_name is not None: names[str(statement.name)].add(type_name) return scoped_names
def _get_positions_simple_but_incorrect(self): # goto_assignments only gives you last assignment to given node import jedi defs = jedi.names(self.text.get('1.0', 'end'), path="", all_scopes=True, definitions=True, references=True) result = set() for definition in defs: if definition.parent( ).type == "function": # is located in a function ass = definition.goto_assignments() if len(ass) > 0 and ass[0].parent( ).type == "function": # is assigned to in a function pos = ("%d.%d" % (definition.line, definition.column), "%d.%d" % (definition.line, definition.column + len(definition.name))) result.add(pos) return result
def make_definitions(): """ Return a list of definitions for parametrized tests. :rtype: [jedi.api_classes.BaseDefinition] """ source = dedent(""" import sys class C: pass x = C() def f(): pass def g(): yield h = lambda: None """) definitions = [] definitions += names(source, environment=environment) source += dedent(""" variable = sys or C or x or f or g or g() or h""") lines = source.splitlines() script = Script(source, len(lines), len('variable'), None) definitions += script.goto_definitions() script2 = Script(source, 4, len('class C'), None) definitions += script2.usages() source_param = "def f(a): return a" script_param = Script(source_param, 1, len(source_param), None) definitions += script_param.goto_assignments() return definitions
def transform(file_name, debug=False): """ Takes a file name returns the transformed text. """ if debug: jedi.set_debug_function() names = jedi.names(path=file_name, all_scopes=True) param_names = [p for p in names if p.type == 'param'] for param in param_names: # This is all very complicated and basically should just be replaced # with param.goto_definition(), once that api is being added (it's # planned). e = param._evaluator jedi_obj = param._definition types = _eval_param(e, jedi_obj, jedi_obj.get_parent_scope()) if types and param.name != 'self': # Now refactor, Jedi has a round-trippable parser, yay! annotation = types_to_string(types, abspath(file_name)) jedi_obj.name.value += ': ' + annotation # Get the module and generate the code. return jedi_obj.get_parent_until().get_code()
def test_parentheses(self): n = names('("").upper', references=True)[-1] assert n.goto_assignments()[0].name == 'upper'
def _def(self, source, index=-1): return names(dedent(source), references=True, all_scopes=True)[index]
def _bool_is_definitions(self, source): ns = names(dedent(source), references=True, all_scopes=True) # Assure that names are definitely sorted. ns = sorted(ns, key=lambda name: (name.line, name.column)) return [name.is_definition() for name in ns]
def _GetJediNames( request_data ): return jedi.names( source = request_data[ 'source' ], path = request_data[ 'path' ], all_scopes = request_data.get( 'all_scopes', False ), definitions = request_data.get( 'definitions', True ), references = request_data.get( 'references', False ) )
def check_defined_names(self, source, names_): definitions = names(dedent(source), environment=self.environment) self.assert_definition_names(definitions, names_) return definitions
def test_simple_name(environment): defs = names('foo', references=True, environment=environment) assert not defs[0]._name.infer()
def graph(self): # Add module/package defs. module = os.path.splitext(self._file)[0] if os.path.basename(self._file) == '__init__.py': module = os.path.normpath(os.path.dirname(self._file)) self._add_def(self.Def( Path=module, Kind='module', Name=module.split('/')[-1], File=self._file, DefStart=0, DefEnd=0, Exported=True, # TODO(MaikuMori): extract module/package-level doc. Docstring='', Data=None, )) # Get occurrences of names via Jedi. try: jedi_names = jedi.names(source=self._source, path=self._file, all_scopes=True, references=True) except Exception as e: raise FileGrapherException('failed to parse {}: {}'.format(self._file, str(e))) jedi_defs, jedi_refs = [], [] for jedi_name in jedi_names: # Imports should be refs. if jedi_name.is_definition() and jedi_name.type != 'import': jedi_defs.append(jedi_name) else: jedi_refs.append(jedi_name) # Defs. for jedi_def in jedi_defs: self._log.debug( '\nProcessing def: %s | %s | %s', jedi_def.desc_with_module, jedi_def.name, jedi_def.type, ) try: self._add_def(self._jedi_def_to_def(jedi_def)) except Exception as e: self._log.error( u'\nFailed to process def `%s`: %s', jedi_def.name, e, ) continue # Refs. for jedi_ref in jedi_refs: self._log.debug( '\nProcessing ref: %s | %s | %s', jedi_ref.desc_with_module, jedi_ref.name, jedi_ref.type, ) ref_def = self._find_def_for_ref(jedi_ref) # We found nothing. if ref_def is None: continue try: sg_def = self._jedi_def_to_def_key(ref_def) except Exception as e: self._log.error( u'\nFailed to process def to def-key `%s`: %s', ref_def.name, e, ) continue self._log.debug( 'Ref-Def: %s | %s | %s | %s \n', sg_def.Name, sg_def.Path, sg_def.Kind, sg_def.File, ) ref_start = self._to_offset(jedi_ref.line, jedi_ref.column) ref_end = ref_start + len(jedi_ref.name) self._add_ref(self.Ref( DefPath=sg_def.Path, DefFile=sg_def.File, Def=False, File=self._file, Start=ref_start, End=ref_end, ToBuiltin=ref_def.in_builtin_module(), )) return self._defs, self._refs
def test_follow_imports(environment): # github issue #344 imp = names('import datetime', environment=environment)[0] assert imp.name == 'datetime' datetime_names = [str(d.name) for d in imp.defined_names()] assert 'timedelta' in datetime_names
def check(self, source, desired): definitions = jedi.names(textwrap.dedent(source)) full_names = [d.full_name for d in definitions] self.assertEqual(full_names, desired)
def graph(self): # Add module/package defs. basic_module_path = normalize(os.path.relpath(self._file, self._base_dir)) if basic_module_path.startswith('./'): basic_module_path = basic_module_path[2:] if os.path.basename(self._file) == '__init__.py': dot_path = normalize(os.path.dirname(basic_module_path)).replace('/', '.') else: dot_path = normalize(os.path.splitext(basic_module_path)[0]).replace('/', '.') module_path = '{}/{}.{}'.format(basic_module_path, dot_path, dot_path.split('.')[-1]) self._add_def(Def( Repo="", Unit=self._unit, UnitType=self._unit_type, Path=module_path, Kind='module', Name=os.path.basename(basic_module_path), File=normalize(self._file), DefStart=0, DefEnd=0, Exported=True, Data=DefFormatData( Name=os.path.basename(basic_module_path), Keyword='', Type='', Kind='module', Separator='', ), )) # TODO(beyang): extract module/package-level doc. # Get occurrences of names via Jedi. try: jedi_names = jedi.names(source=self._source, path=self._file, all_scopes=True, references=True) except Exception as e: raise FileGrapherException('failed to parse {}: {}'.format(self._file, str(e))) jedi_defs, jedi_refs = [], [] for jedi_name in jedi_names: # Imports should be refs. if jedi_name.is_definition() and jedi_name.type != 'import': jedi_defs.append(jedi_name) else: jedi_refs.append(jedi_name) # Defs and docs. for jedi_def in jedi_defs: self._log.debug( 'processing def: %s | %s | %s', jedi_def.desc_with_module, jedi_def.name, jedi_def.type, ) try: def_, doc = self._jedi_def_to_def(jedi_def) self._add_def(def_) if doc is not None and doc.Data is not None and len(doc.Data) > 0: self._add_doc(doc) except Exception as e: self._log.error( u'failed to process def `%s`: %s', jedi_def.name, e, ) continue # Refs. for jedi_ref in jedi_refs: self._log.debug( 'processing ref: %s | %s | %s', jedi_ref.desc_with_module, jedi_ref.name, jedi_ref.type, ) ref_def = self._find_def_for_ref(jedi_ref) # We found nothing. if ref_def is None: continue try: sg_def = self._jedi_def_to_def_key(ref_def) except Exception as e: self._log.error( u'failed to process def to def-key `%s`: %s', ref_def.name, e, ) continue ref_start = self._to_offset(jedi_ref.line, jedi_ref.column) ref_end = ref_start + len(jedi_ref.name) self._add_ref(Ref( DefRepo=sg_def.Repo, DefUnit=sg_def.Unit, DefUnitType=sg_def.UnitType, DefPath=sg_def.Path, Unit=self._unit, UnitType=self._unit_type, Def=False, File=normalize(self._file), Start=ref_start, End=ref_end, ToBuiltin=ref_def.in_builtin_module(), )) return self._defs, self._refs, self._docs