]> crepu.dev Git - config.git/blame - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/jedi/api/file_name.py
ActualizaciĆ³n de Readme
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / jedi / api / file_name.py
CommitLineData
53e6db90
DC
1import os
2
3from jedi.api import classes
4from jedi.api.strings import StringName, get_quote_ending
5from jedi.api.helpers import match
6from jedi.inference.helpers import get_str_or_none
7
8
9class PathName(StringName):
10 api_type = 'path'
11
12
13def complete_file_name(inference_state, module_context, start_leaf, quote, string,
14 like_name, signatures_callback, code_lines, position, fuzzy):
15 # First we want to find out what can actually be changed as a name.
16 like_name_length = len(os.path.basename(string))
17
18 addition = _get_string_additions(module_context, start_leaf)
19 if string.startswith('~'):
20 string = os.path.expanduser(string)
21 if addition is None:
22 return
23 string = addition + string
24
25 # Here we use basename again, because if strings are added like
26 # `'foo' + 'bar`, it should complete to `foobar/`.
27 must_start_with = os.path.basename(string)
28 string = os.path.dirname(string)
29
30 sigs = signatures_callback(*position)
31 is_in_os_path_join = sigs and all(s.full_name == 'os.path.join' for s in sigs)
32 if is_in_os_path_join:
33 to_be_added = _add_os_path_join(module_context, start_leaf, sigs[0].bracket_start)
34 if to_be_added is None:
35 is_in_os_path_join = False
36 else:
37 string = to_be_added + string
38 base_path = os.path.join(inference_state.project.path, string)
39 try:
40 listed = sorted(os.scandir(base_path), key=lambda e: e.name)
41 # OSError: [Errno 36] File name too long: '...'
42 except (FileNotFoundError, OSError):
43 return
44 quote_ending = get_quote_ending(quote, code_lines, position)
45 for entry in listed:
46 name = entry.name
47 if match(name, must_start_with, fuzzy=fuzzy):
48 if is_in_os_path_join or not entry.is_dir():
49 name += quote_ending
50 else:
51 name += os.path.sep
52
53 yield classes.Completion(
54 inference_state,
55 PathName(inference_state, name[len(must_start_with) - like_name_length:]),
56 stack=None,
57 like_name_length=like_name_length,
58 is_fuzzy=fuzzy,
59 )
60
61
62def _get_string_additions(module_context, start_leaf):
63 def iterate_nodes():
64 node = addition.parent
65 was_addition = True
66 for child_node in reversed(node.children[:node.children.index(addition)]):
67 if was_addition:
68 was_addition = False
69 yield child_node
70 continue
71
72 if child_node != '+':
73 break
74 was_addition = True
75
76 addition = start_leaf.get_previous_leaf()
77 if addition != '+':
78 return ''
79 context = module_context.create_context(start_leaf)
80 return _add_strings(context, reversed(list(iterate_nodes())))
81
82
83def _add_strings(context, nodes, add_slash=False):
84 string = ''
85 first = True
86 for child_node in nodes:
87 values = context.infer_node(child_node)
88 if len(values) != 1:
89 return None
90 c, = values
91 s = get_str_or_none(c)
92 if s is None:
93 return None
94 if not first and add_slash:
95 string += os.path.sep
96 string += s
97 first = False
98 return string
99
100
101def _add_os_path_join(module_context, start_leaf, bracket_start):
102 def check(maybe_bracket, nodes):
103 if maybe_bracket.start_pos != bracket_start:
104 return None
105
106 if not nodes:
107 return ''
108 context = module_context.create_context(nodes[0])
109 return _add_strings(context, nodes, add_slash=True) or ''
110
111 if start_leaf.type == 'error_leaf':
112 # Unfinished string literal, like `join('`
113 value_node = start_leaf.parent
114 index = value_node.children.index(start_leaf)
115 if index > 0:
116 error_node = value_node.children[index - 1]
117 if error_node.type == 'error_node' and len(error_node.children) >= 2:
118 index = -2
119 if error_node.children[-1].type == 'arglist':
120 arglist_nodes = error_node.children[-1].children
121 index -= 1
122 else:
123 arglist_nodes = []
124
125 return check(error_node.children[index + 1], arglist_nodes[::2])
126 return None
127
128 # Maybe an arglist or some weird error case. Therefore checked below.
129 searched_node_child = start_leaf
130 while searched_node_child.parent is not None \
131 and searched_node_child.parent.type not in ('arglist', 'trailer', 'error_node'):
132 searched_node_child = searched_node_child.parent
133
134 if searched_node_child.get_first_leaf() is not start_leaf:
135 return None
136 searched_node = searched_node_child.parent
137 if searched_node is None:
138 return None
139
140 index = searched_node.children.index(searched_node_child)
141 arglist_nodes = searched_node.children[:index]
142 if searched_node.type == 'arglist':
143 trailer = searched_node.parent
144 if trailer.type == 'error_node':
145 trailer_index = trailer.children.index(searched_node)
146 assert trailer_index >= 2
147 assert trailer.children[trailer_index - 1] == '('
148 return check(trailer.children[trailer_index - 1], arglist_nodes[::2])
149 elif trailer.type == 'trailer':
150 return check(trailer.children[0], arglist_nodes[::2])
151 elif searched_node.type == 'trailer':
152 return check(searched_node.children[0], [])
153 elif searched_node.type == 'error_node':
154 # Stuff like `join(""`
155 return check(arglist_nodes[-1], [])