]> crepu.dev Git - config.git/blame - djavu-asus/emacs/elpa/elpy-20230803.1455/elpy/server.py
Reorganización de directorios
[config.git] / djavu-asus / emacs / elpa / elpy-20230803.1455 / elpy / server.py
CommitLineData
53e6db90
DC
1"""Method implementations for the Elpy JSON-RPC server.
2
3This file implements the methods exported by the JSON-RPC server. It
4handles backend selection and passes methods on to the selected
5backend.
6
7"""
8import io
9import os
10import pydoc
11
12from elpy.pydocutils import get_pydoc_completions
13from elpy.rpc import JSONRPCServer, Fault
14from elpy.auto_pep8 import fix_code
15from elpy.yapfutil import fix_code as fix_code_with_yapf
16from elpy.blackutil import fix_code as fix_code_with_black
17
18
19try:
20 from elpy import jedibackend
21except ImportError: # pragma: no cover
22 jedibackend = None
23
24
25class ElpyRPCServer(JSONRPCServer):
26 """The RPC server for elpy.
27
28 See the rpc_* methods for exported method documentation.
29
30 """
31 def __init__(self, *args, **kwargs):
32 super(ElpyRPCServer, self).__init__(*args, **kwargs)
33 self.backend = None
34 self.project_root = None
35
36 def _call_backend(self, method, default, *args, **kwargs):
37 """Call the backend method with args.
38
39 If there is currently no backend, return default."""
40 meth = getattr(self.backend, method, None)
41 if meth is None:
42 return default
43 else:
44 return meth(*args, **kwargs)
45
46 def rpc_echo(self, *args):
47 """Return the arguments.
48
49 This is a simple test method to see if the protocol is
50 working.
51
52 """
53 return args
54
55 def rpc_init(self, options):
56 self.project_root = options["project_root"]
57 self.env = options["environment"]
58
59 if jedibackend:
60 self.backend = jedibackend.JediBackend(self.project_root, self.env)
61 else:
62 self.backend = None
63
64 return {
65 'jedi_available': (self.backend is not None)
66 }
67
68 def rpc_get_calltip(self, filename, source, offset):
69 """Get the calltip for the function at the offset.
70
71 """
72 return self._call_backend("rpc_get_calltip", None, filename,
73 get_source(source), offset)
74
75 def rpc_get_oneline_docstring(self, filename, source, offset):
76 """Get a oneline docstring for the symbol at the offset.
77
78 """
79 return self._call_backend("rpc_get_oneline_docstring", None, filename,
80 get_source(source), offset)
81
82 def rpc_get_calltip_or_oneline_docstring(self, filename, source, offset):
83 """Get a calltip or a oneline docstring for the symbol at the offset.
84
85 """
86 return self._call_backend("rpc_get_calltip_or_oneline_docstring",
87 None, filename,
88 get_source(source), offset)
89
90 def rpc_get_completions(self, filename, source, offset):
91 """Get a list of completion candidates for the symbol at offset.
92
93 """
94 results = self._call_backend("rpc_get_completions", [], filename,
95 get_source(source), offset)
96 # Uniquify by name
97 results = list(dict((res['name'], res) for res in results)
98 .values())
99 results.sort(key=lambda cand: _pysymbol_key(cand["name"]))
100 return results
101
102 def rpc_get_completion_docstring(self, completion):
103 """Return documentation for a previously returned completion.
104
105 """
106 return self._call_backend("rpc_get_completion_docstring",
107 None, completion)
108
109 def rpc_get_completion_location(self, completion):
110 """Return the location for a previously returned completion.
111
112 This returns a list of [file name, line number].
113
114 """
115 return self._call_backend("rpc_get_completion_location", None,
116 completion)
117
118 def rpc_get_definition(self, filename, source, offset):
119 """Get the location of the definition for the symbol at the offset.
120
121 """
122 return self._call_backend("rpc_get_definition", None, filename,
123 get_source(source), offset)
124
125 def rpc_get_assignment(self, filename, source, offset):
126 """Get the location of the assignment for the symbol at the offset.
127
128 """
129 return self._call_backend("rpc_get_assignment", None, filename,
130 get_source(source), offset)
131
132 def rpc_get_docstring(self, filename, source, offset):
133 """Get the docstring for the symbol at the offset.
134
135 """
136 return self._call_backend("rpc_get_docstring", None, filename,
137 get_source(source), offset)
138
139 def rpc_get_pydoc_completions(self, name=None):
140 """Return a list of possible strings to pass to pydoc.
141
142 If name is given, the strings are under name. If not, top
143 level modules are returned.
144
145 """
146 return get_pydoc_completions(name)
147
148 def rpc_get_pydoc_documentation(self, symbol):
149 """Get the Pydoc documentation for the given symbol.
150
151 Uses pydoc and can return a string with backspace characters
152 for bold highlighting.
153
154 """
155 try:
156 docstring = pydoc.render_doc(str(symbol),
157 "Elpy Pydoc Documentation for %s",
158 False)
159 except (ImportError, pydoc.ErrorDuringImport):
160 return None
161 else:
162 if isinstance(docstring, bytes):
163 docstring = docstring.decode("utf-8", "replace")
164 return docstring
165
166 def rpc_get_usages(self, filename, source, offset):
167 """Get usages for the symbol at point.
168
169 """
170 source = get_source(source)
171
172 return self._call_backend("rpc_get_usages",
173 None, filename, source, offset)
174
175 def rpc_get_names(self, filename, source, offset):
176 """Get all possible names
177
178 """
179 source = get_source(source)
180 return self._call_backend("rpc_get_names",
181 None, filename, source, offset)
182
183 def rpc_get_rename_diff(self, filename, source, offset, new_name):
184 """Get the diff resulting from renaming the thing at point
185
186 """
187 source = get_source(source)
188
189 return self._call_backend("rpc_get_rename_diff",
190 None, filename, source, offset, new_name)
191
192 def rpc_get_extract_variable_diff(self, filename, source, offset, new_name,
193 line_beg, line_end, col_beg, col_end):
194 """Get the diff resulting from extracting the selected code
195
196 """
197 source = get_source(source)
198 return self._call_backend("rpc_get_extract_variable_diff",
199 None, filename, source, offset,
200 new_name, line_beg, line_end, col_beg,
201 col_end)
202
203 def rpc_get_extract_function_diff(self, filename, source, offset, new_name,
204 line_beg, line_end, col_beg, col_end):
205 """Get the diff resulting from extracting the selected code
206
207 """
208 source = get_source(source)
209 return self._call_backend("rpc_get_extract_function_diff",
210 None, filename, source, offset, new_name,
211 line_beg, line_end, col_beg, col_end)
212
213 def rpc_get_inline_diff(self, filename, source, offset):
214 """Get the diff resulting from inlining the thing at point.
215
216 """
217 source = get_source(source)
218 return self._call_backend("rpc_get_inline_diff",
219 None, filename, source, offset)
220
221 def rpc_fix_code(self, source, directory):
222 """Formats Python code to conform to the PEP 8 style guide.
223
224 """
225 source = get_source(source)
226 return fix_code(source, directory)
227
228 def rpc_fix_code_with_yapf(self, source, directory):
229 """Formats Python code to conform to the PEP 8 style guide.
230
231 """
232 source = get_source(source)
233 return fix_code_with_yapf(source, directory)
234
235 def rpc_fix_code_with_black(self, source, directory):
236 """Formats Python code to conform to the PEP 8 style guide.
237
238 """
239 source = get_source(source)
240 return fix_code_with_black(source, directory)
241
242
243def get_source(fileobj):
244 """Translate fileobj into file contents.
245
246 fileobj is either a string or a dict. If it's a string, that's the
247 file contents. If it's a string, then the filename key contains
248 the name of the file whose contents we are to use.
249
250 If the dict contains a true value for the key delete_after_use,
251 the file should be deleted once read.
252
253 """
254 if not isinstance(fileobj, dict):
255 return fileobj
256 else:
257 try:
258 with io.open(fileobj["filename"], encoding="utf-8",
259 errors="ignore") as f:
260 return f.read()
261 finally:
262 if fileobj.get('delete_after_use'):
263 try:
264 os.remove(fileobj["filename"])
265 except: # pragma: no cover
266 pass
267
268
269def _pysymbol_key(name):
270 """Return a sortable key index for name.
271
272 Sorting is case-insensitive, with the first underscore counting as
273 worse than any character, but subsequent underscores do not. This
274 means that dunder symbols (like __init__) are sorted after symbols
275 that start with an alphabetic character, but before those that
276 start with only a single underscore.
277
278 """
279 if name.startswith("_"):
280 name = "~" + name[1:]
281 return name.lower()