FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
pythonVSCode/pythonFiles/preview/jedi/api/__init__.py at codeHealth · sbialobok/pythonVSCode · GitHub
sbialobok
/
pythonVSCode
Public
forked from
DonJayamanne/pythonVSCode
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
pythonVSCode
/
pythonFiles
/
preview
/
jedi
/
api
/
__init__.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
467 lines (387 loc) · 17.7 KB
Breadcrumbs
pythonVSCode
/
pythonFiles
/
preview
/
jedi
/
api
/
__init__.py
Copy path
File metadata and controls
467 lines (387 loc) · 17.7 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
"""
The API basically only provides one class. You can create a :class:`Script` and
use its methods.
Additionally you can add a debug function with :func:`set_debug_function`.
Alternatively, if you don't need a custom function and are happy with printing
debug messages to stdout, simply call :func:`set_debug_function` without
arguments.
.. warning:: Please, note that Jedi is **not thread safe**.
"""
import
os
import
warnings
import
sys
from
jedi
.
_compatibility
import
unicode
from
jedi
.
parser
import
load_grammar
from
jedi
.
parser
import
tree
from
jedi
.
parser
.
fast
import
FastParser
from
jedi
.
parser
.
utils
import
save_parser
from
jedi
import
debug
from
jedi
import
settings
from
jedi
import
common
from
jedi
import
cache
from
jedi
.
api
import
classes
from
jedi
.
api
import
interpreter
from
jedi
.
api
import
usages
from
jedi
.
api
import
helpers
from
jedi
.
api
.
completion
import
Completion
from
jedi
.
evaluate
import
Evaluator
from
jedi
.
evaluate
import
representation
as
er
from
jedi
.
evaluate
import
imports
from
jedi
.
evaluate
.
param
import
try_iter_content
from
jedi
.
evaluate
.
helpers
import
get_module_names
from
jedi
.
evaluate
.
sys_path
import
get_venv_path
from
jedi
.
evaluate
.
iterable
import
unpack_tuple_to_dict
# Jedi uses lots and lots of recursion. By setting this a little bit higher, we
# can remove some "maximum recursion depth" errors.
sys
.
setrecursionlimit
(
2000
)
class
NotFoundError
(
Exception
):
"""A custom error to avoid catching the wrong exceptions.
.. deprecated:: 0.9.0
Not in use anymore, Jedi just returns no goto result if you're not on a
valid name.
.. todo:: Remove!
"""
class
Script
(
object
):
"""
A Script is the base for completions, goto or whatever you want to do with
|jedi|.
You can either use the ``source`` parameter or ``path`` to read a file.
Usually you're going to want to use both of them (in an editor).
The script might be analyzed in a different ``sys.path`` than |jedi|:
- if `sys_path` parameter is not ``None``, it will be used as ``sys.path``
for the script;
- if `sys_path` parameter is ``None`` and ``VIRTUAL_ENV`` environment
variable is defined, ``sys.path`` for the specified environment will be
guessed (see :func:`jedi.evaluate.sys_path.get_venv_path`) and used for
the script;
- otherwise ``sys.path`` will match that of |jedi|.
:param source: The source code of the current file, separated by newlines.
:type source: str
:param line: The line to perform actions on (starting with 1).
:type line: int
:param column: The column of the cursor (starting with 0).
:type column: int
:param path: The path of the file in the file system, or ``''`` if
it hasn't been saved yet.
:type path: str or None
:param encoding: The encoding of ``source``, if it is not a
``unicode`` object (default ``'utf-8'``).
:type encoding: str
:param source_encoding: The encoding of ``source``, if it is not a
``unicode`` object (default ``'utf-8'``).
:type encoding: str
:param sys_path: ``sys.path`` to use during analysis of the script
:type sys_path: list
"""
def
__init__
(
self
,
source
=
None
,
line
=
None
,
column
=
None
,
path
=
None
,
encoding
=
'utf-8'
,
source_path
=
None
,
source_encoding
=
None
,
sys_path
=
None
):
if
source_path
is
not
None
:
warnings
.
warn
(
"Use path instead of source_path."
,
DeprecationWarning
)
path
=
source_path
if
source_encoding
is
not
None
:
warnings
.
warn
(
"Use encoding instead of source_encoding."
,
DeprecationWarning
)
encoding
=
source_encoding
self
.
_orig_path
=
path
# An empty path (also empty string) should always result in no path.
self
.
path
=
os
.
path
.
abspath
(
path
)
if
path
else
None
if
source
is
None
:
# TODO add a better warning than the traceback!
try
:
with
open
(
path
)
as
f
:
source
=
f
.
read
()
except
UnicodeDecodeError
:
with
open
(
path
,
encoding
=
encoding
)
as
f
:
source
=
f
.
read
()
self
.
_source
=
common
.
source_to_unicode
(
source
,
encoding
)
self
.
_code_lines
=
common
.
splitlines
(
self
.
_source
)
line
=
max
(
len
(
self
.
_code_lines
),
1
)
if
line
is
None
else
line
if
not
(
0
<
line
<=
len
(
self
.
_code_lines
)):
raise
ValueError
(
'`line` parameter is not in a valid range.'
)
line_len
=
len
(
self
.
_code_lines
[
line
-
1
])
column
=
line_len
if
column
is
None
else
column
if
not
(
0
<=
column
<=
line_len
):
raise
ValueError
(
'`column` parameter is not in a valid range.'
)
self
.
_pos
=
line
,
column
self
.
_path
=
path
cache
.
clear_time_caches
()
debug
.
reset_time
()
self
.
_grammar
=
load_grammar
(
version
=
'%s.%s'
%
sys
.
version_info
[:
2
])
if
sys_path
is
None
:
venv
=
os
.
getenv
(
'VIRTUAL_ENV'
)
if
venv
:
sys_path
=
list
(
get_venv_path
(
venv
))
self
.
_evaluator
=
Evaluator
(
self
.
_grammar
,
sys_path
=
sys_path
)
debug
.
speed
(
'init'
)
def
_get_module
(
self
):
cache
.
invalidate_star_import_cache
(
self
.
_path
)
parser
=
FastParser
(
self
.
_grammar
,
self
.
_source
,
self
.
path
)
save_parser
(
self
.
path
,
parser
,
pickling
=
False
)
module
=
self
.
_evaluator
.
wrap
(
parser
.
module
)
imports
.
add_module
(
self
.
_evaluator
,
unicode
(
module
.
name
),
module
)
return
parser
.
module
@
property
def
source_path
(
self
):
"""
.. deprecated:: 0.7.0
Use :attr:`.path` instead.
.. todo:: Remove!
"""
warnings
.
warn
(
"Use path instead of source_path."
,
DeprecationWarning
)
return
self
.
path
def
__repr__
(
self
):
return
'<%s: %s>'
%
(
self
.
__class__
.
__name__
,
repr
(
self
.
_orig_path
))
def
completions
(
self
):
"""
Return :class:`classes.Completion` objects. Those objects contain
information about the completions, more than just names.
:return: Completion objects, sorted by name and __ comes last.
:rtype: list of :class:`classes.Completion`
"""
debug
.
speed
(
'completions start'
)
completion
=
Completion
(
self
.
_evaluator
,
self
.
_get_module
(),
self
.
_code_lines
,
self
.
_pos
,
self
.
call_signatures
)
completions
=
completion
.
completions
()
debug
.
speed
(
'completions end'
)
return
completions
def
goto_definitions
(
self
):
"""
Return the definitions of a the path under the cursor. goto function!
This follows complicated paths and returns the end, not the first
definition. The big difference between :meth:`goto_assignments` and
:meth:`goto_definitions` is that :meth:`goto_assignments` doesn't
follow imports and statements. Multiple objects may be returned,
because Python itself is a dynamic language, which means depending on
an option you can have two different versions of a function.
:rtype: list of :class:`classes.Definition`
"""
leaf
=
self
.
_get_module
().
name_for_position
(
self
.
_pos
)
if
leaf
is
None
:
leaf
=
self
.
_get_module
().
get_leaf_for_position
(
self
.
_pos
)
if
leaf
is
None
:
return
[]
definitions
=
helpers
.
evaluate_goto_definition
(
self
.
_evaluator
,
leaf
)
names
=
[
s
.
name
for
s
in
definitions
]
defs
=
[
classes
.
Definition
(
self
.
_evaluator
,
name
)
for
name
in
names
]
# The additional set here allows the definitions to become unique in an
# API sense. In the internals we want to separate more things than in
# the API.
return
helpers
.
sorted_definitions
(
set
(
defs
))
def
goto_assignments
(
self
,
follow_imports
=
False
):
"""
Return the first definition found, while optionally following imports.
Multiple objects may be returned, because Python itself is a
dynamic language, which means depending on an option you can have two
different versions of a function.
:rtype: list of :class:`classes.Definition`
"""
def
filter_follow_imports
(
names
):
for
name
in
names
:
definition
=
name
.
get_definition
()
if
definition
.
type
in
(
'import_name'
,
'import_from'
):
imp
=
imports
.
ImportWrapper
(
self
.
_evaluator
,
name
)
for
name
in
filter_follow_imports
(
imp
.
follow
(
is_goto
=
True
)):
yield
name
else
:
yield
name
names
=
self
.
_goto
()
if
follow_imports
:
names
=
filter_follow_imports
(
names
)
defs
=
[
classes
.
Definition
(
self
.
_evaluator
,
d
)
for
d
in
set
(
names
)]
return
helpers
.
sorted_definitions
(
defs
)
def
_goto
(
self
):
"""
Used for goto_assignments and usages.
"""
name
=
self
.
_get_module
().
name_for_position
(
self
.
_pos
)
if
name
is
None
:
return
[]
return
list
(
self
.
_evaluator
.
goto
(
name
))
def
usages
(
self
,
additional_module_paths
=
()):
"""
Return :class:`classes.Definition` objects, which contain all
names that point to the definition of the name under the cursor. This
is very useful for refactoring (renaming), or to show all usages of a
variable.
.. todo:: Implement additional_module_paths
:rtype: list of :class:`classes.Definition`
"""
temp
,
settings
.
dynamic_flow_information
=
\
settings
.
dynamic_flow_information
,
False
try
:
user_stmt
=
self
.
_get_module
().
get_statement_for_position
(
self
.
_pos
)
definitions
=
self
.
_goto
()
if
not
definitions
and
isinstance
(
user_stmt
,
tree
.
Import
):
# For not defined imports (goto doesn't find something, we take
# the name as a definition. This is enough, because every name
# points to it.
name
=
user_stmt
.
name_for_position
(
self
.
_pos
)
if
name
is
None
:
# Must be syntax
return
[]
definitions
=
[
name
]
if
not
definitions
:
# Without a definition for a name we cannot find references.
return
[]
if
not
isinstance
(
user_stmt
,
tree
.
Import
):
# import case is looked at with add_import_name option
definitions
=
usages
.
usages_add_import_modules
(
self
.
_evaluator
,
definitions
)
module
=
set
([
d
.
get_parent_until
()
for
d
in
definitions
])
module
.
add
(
self
.
_get_module
())
names
=
usages
.
usages
(
self
.
_evaluator
,
definitions
,
module
)
for
d
in
set
(
definitions
):
names
.
append
(
classes
.
Definition
(
self
.
_evaluator
,
d
))
finally
:
settings
.
dynamic_flow_information
=
temp
return
helpers
.
sorted_definitions
(
set
(
names
))
def
call_signatures
(
self
):
"""
Return the function object of the call you're currently in.
E.g. if the cursor is here::
abs(# <-- cursor is here
This would return the ``abs`` function. On the other hand::
abs()# <-- cursor is here
This would return an empty list..
:rtype: list of :class:`classes.CallSignature`
"""
call_signature_details
=
\
helpers
.
get_call_signature_details
(
self
.
_get_module
(),
self
.
_pos
)
if
call_signature_details
is
None
:
return
[]
with
common
.
scale_speed_settings
(
settings
.
scale_call_signatures
):
definitions
=
helpers
.
cache_call_signatures
(
self
.
_evaluator
,
call_signature_details
.
bracket_leaf
,
self
.
_code_lines
,
self
.
_pos
)
debug
.
speed
(
'func_call followed'
)
return
[
classes
.
CallSignature
(
self
.
_evaluator
,
d
.
name
,
call_signature_details
.
bracket_leaf
.
start_pos
,
call_signature_details
.
call_index
,
call_signature_details
.
keyword_name_str
)
for
d
in
definitions
if
hasattr
(
d
,
'py__call__'
)]
def
_analysis
(
self
):
self
.
_evaluator
.
is_analysis
=
True
self
.
_evaluator
.
analysis_modules
=
[
self
.
_get_module
()]
try
:
for
node
in
self
.
_get_module
().
nodes_to_execute
():
if
node
.
type
in
(
'funcdef'
,
'classdef'
):
if
node
.
type
==
'classdef'
:
continue
raise
NotImplementedError
er
.
Function
(
self
.
_evaluator
,
node
).
get_decorated_func
()
elif
isinstance
(
node
,
tree
.
Import
):
import_names
=
set
(
node
.
get_defined_names
())
if
node
.
is_nested
():
import_names
|=
set
(
path
[
-
1
]
for
path
in
node
.
paths
())
for
n
in
import_names
:
imports
.
ImportWrapper
(
self
.
_evaluator
,
n
).
follow
()
elif
node
.
type
==
'expr_stmt'
:
types
=
self
.
_evaluator
.
eval_element
(
node
)
for
testlist
in
node
.
children
[:
-
1
:
2
]:
# Iterate tuples.
unpack_tuple_to_dict
(
self
.
_evaluator
,
types
,
testlist
)
else
:
try_iter_content
(
self
.
_evaluator
.
goto_definitions
(
node
))
self
.
_evaluator
.
reset_recursion_limitations
()
ana
=
[
a
for
a
in
self
.
_evaluator
.
analysis
if
self
.
path
==
a
.
path
]
return
sorted
(
set
(
ana
),
key
=
lambda
x
:
x
.
line
)
finally
:
self
.
_evaluator
.
is_analysis
=
False
class
Interpreter
(
Script
):
"""
Jedi API for Python REPLs.
In addition to completion of simple attribute access, Jedi
supports code completion based on static code analysis.
Jedi can complete attributes of object which is not initialized
yet.
>>> from os.path import join
>>> namespace = locals()
>>> script = Interpreter('join("").up', [namespace])
>>> print(script.completions()[0].name)
upper
"""
def
__init__
(
self
,
source
,
namespaces
,
**
kwds
):
"""
Parse `source` and mixin interpreted Python objects from `namespaces`.
:type source: str
:arg source: Code to parse.
:type namespaces: list of dict
:arg namespaces: a list of namespace dictionaries such as the one
returned by :func:`locals`.
Other optional arguments are same as the ones for :class:`Script`.
If `line` and `column` are None, they are assumed be at the end of
`source`.
"""
try
:
namespaces
=
[
dict
(
n
)
for
n
in
namespaces
]
except
Exception
:
raise
TypeError
(
"namespaces must be a non-empty list of dicts."
)
super
(
Interpreter
,
self
).
__init__
(
source
,
**
kwds
)
self
.
namespaces
=
namespaces
parser_module
=
super
(
Interpreter
,
self
).
_get_module
()
self
.
_module
=
interpreter
.
MixedModule
(
self
.
_evaluator
,
parser_module
,
self
.
namespaces
)
def
_get_module
(
self
):
return
self
.
_module
def
defined_names
(
source
,
path
=
None
,
encoding
=
'utf-8'
):
"""
Get all definitions in `source` sorted by its position.
This functions can be used for listing functions, classes and
data defined in a file. This can be useful if you want to list
them in "sidebar". Each element in the returned list also has
`defined_names` method which can be used to get sub-definitions
(e.g., methods in class).
:rtype: list of classes.Definition
.. deprecated:: 0.9.0
Use :func:`names` instead.
.. todo:: Remove!
"""
warnings
.
warn
(
"Use call_signatures instead."
,
DeprecationWarning
)
return
names
(
source
,
path
,
encoding
)
def
names
(
source
=
None
,
path
=
None
,
encoding
=
'utf-8'
,
all_scopes
=
False
,
definitions
=
True
,
references
=
False
):
"""
Returns a list of `Definition` objects, containing name parts.
This means you can call ``Definition.goto_assignments()`` and get the
reference of a name.
The parameters are the same as in :py:class:`Script`, except or the
following ones:
:param all_scopes: If True lists the names of all scopes instead of only
the module namespace.
:param definitions: If True lists the names that have been defined by a
class, function or a statement (``a = b`` returns ``a``).
:param references: If True lists all the names that are not listed by
``definitions=True``. E.g. ``a = b`` returns ``b``.
"""
def
def_ref_filter
(
_def
):
is_def
=
_def
.
is_definition
()
return
definitions
and
is_def
or
references
and
not
is_def
# Set line/column to a random position, because they don't matter.
script
=
Script
(
source
,
line
=
1
,
column
=
0
,
path
=
path
,
encoding
=
encoding
)
defs
=
[
classes
.
Definition
(
script
.
_evaluator
,
name_part
)
for
name_part
in
get_module_names
(
script
.
_get_module
(),
all_scopes
)]
return
sorted
(
filter
(
def_ref_filter
,
defs
),
key
=
lambda
x
: (
x
.
line
,
x
.
column
))
def
preload_module
(
*
modules
):
"""
Preloading modules tells Jedi to load a module now, instead of lazy parsing
of modules. Usful for IDEs, to control which modules to load on startup.
:param modules: different module names, list of string.
"""
for
m
in
modules
:
s
=
"import %s as x; x."
%
m
Script
(
s
,
1
,
len
(
s
),
None
).
completions
()
def
set_debug_function
(
func_cb
=
debug
.
print_to_stdout
,
warnings
=
True
,
notices
=
True
,
speed
=
True
):
"""
Define a callback debug function to get all the debug messages.
If you don't specify any arguments, debug messages will be printed to stdout.
:param func_cb: The callback function for debug messages, with n params.
"""
debug
.
debug_function
=
func_cb
debug
.
enable_warning
=
warnings
debug
.
enable_notice
=
notices
debug
.
enable_speed
=
speed
Back
|
FazBrowse Home
|
New Git URL