code-intelligence 4.8.2__py3-none-macosx_11_0_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,27 @@
1
+ from .goober import (
2
+ Language,
3
+ Definition_Link,
4
+ scan_file,
5
+ find_symbols_in_text,
6
+ init,
7
+ stop,
8
+ clear,
9
+ )
10
+
11
+ # PROUD - Bump when you are proud of the release.
12
+ # DEFAULT - Just normal/okay releases.
13
+ # SHAME - Bump when fixing things too embarrassing to admit.
14
+ # PROUD.DEFAULT.SHAME
15
+ # \ | /
16
+ __version__ = "4.8.2"
17
+ __version_info__ = tuple(int(i) for i in __version__.split('.'))
18
+
19
+ __all__ = [
20
+ "Language",
21
+ "Definition_Link",
22
+ "scan_file",
23
+ "find_symbols_in_text",
24
+ "init",
25
+ "stop",
26
+ "clear",
27
+ ]
@@ -0,0 +1,265 @@
1
+ import os
2
+ import sys
3
+ import time
4
+ import platform
5
+ import ctypes as C
6
+ from pathlib import Path
7
+ from dataclasses import dataclass, fields
8
+ from enum import IntEnum, IntFlag
9
+ from typing import Callable, TypeVar
10
+
11
+
12
+ DIR = Path(__file__).parent
13
+
14
+ class Str_C(C.Structure):
15
+ _fields_ = [
16
+ ("data" , C.c_char_p),
17
+ ("length", C.c_uint32),
18
+ ]
19
+
20
+ def to_bytes(self) -> bytes:
21
+ return C.string_at(self.data, self.length)
22
+
23
+ def to_str_c(s: str | bytes) -> Str_C:
24
+ if isinstance(s, str):
25
+ s = s.encode()
26
+ return Str_C(s, len(s))
27
+
28
+ _lib = C.CDLL(str(DIR / "libcode_intelligence.so"))
29
+
30
+ SCAN_CALLBACK = C.CFUNCTYPE(None, C.c_void_p)
31
+ _lib.enqueue_scan_file.argtypes = [SCAN_CALLBACK, C.c_void_p, Str_C, C.c_uint64]
32
+ _lib.enqueue_scan_file.restype = None
33
+
34
+ class Definition_Link_C(C.Structure):
35
+ _fields_ = [
36
+ ("start_offset_in_utf8_text", C.c_uint32),
37
+ ("end_offset_in_utf8_text" , C.c_uint32),
38
+ ("source_file" , C.c_char_p),
39
+ ("line_0_based" , C.c_uint32),
40
+ ("column_0_based" , C.c_uint32),
41
+ ]
42
+
43
+ FIND_CALLBACK = C.CFUNCTYPE(None, C.c_void_p, C.POINTER(Definition_Link_C), C.c_int, C.c_void_p)
44
+ _lib.enqueue_find_symbols_in_text.argtypes = [FIND_CALLBACK, C.c_void_p, Str_C, C.c_bool, C.c_bool, C.POINTER(Str_C), C.c_uint32]
45
+ _lib.enqueue_find_symbols_in_text.restype = None
46
+
47
+ _lib.enqueue_stop.argtypes = []
48
+ _lib.enqueue_stop.restype = None
49
+
50
+ _lib.enqueue_clear.argtypes = []
51
+ _lib.enqueue_clear.restype = None
52
+
53
+ _lib.start_workers.argtypes = []
54
+ _lib.start_workers.restype = None
55
+
56
+ _lib.get_pending_tasks_count.argtypes = []
57
+ _lib.get_pending_tasks_count.restype = C.c_uint64
58
+
59
+ _lib.free_memory.argtypes = [C.c_void_p]
60
+ _lib.free_memory.restype = None
61
+
62
+
63
+ T = TypeVar("T")
64
+
65
+
66
+ def positional_repr(cls: type) -> type:
67
+ def __repr__(self):
68
+ values = ', '.join(repr(getattr(self, f.name)) for f in fields(self))
69
+ return f"{cls.__name__}({values})"
70
+ cls.__repr__ = __repr__
71
+ return cls
72
+
73
+
74
+ class Language(IntEnum):
75
+ UNKNOWN = 0
76
+ PYTHON = 1
77
+ JAVASCRIPT = 2
78
+ GOLANG = 3
79
+ PHP = 4
80
+ RUST = 5
81
+ CPP = 6
82
+ JAVA = 7
83
+ C_SHARP = 8
84
+ KOTLIN = 9
85
+ SWIFT = 10
86
+ DART = 11
87
+ R_LANG = 12
88
+ RUBY = 13
89
+ LUA = 14
90
+
91
+
92
+ @dataclass
93
+ @positional_repr
94
+ class Definition_Link:
95
+ start_offset_in_text: int = 0
96
+ end_offset_in_text : int = 0
97
+ source_file : str = ""
98
+ line_0_based : int = 0
99
+ column_0_based : int = 0
100
+
101
+ @classmethod
102
+ def from_c(cls, link: Definition_Link_C) -> "Definition_Link":
103
+ return cls(
104
+ start_offset_in_text=link.start_offset_in_utf8_text,
105
+ end_offset_in_text=link.end_offset_in_utf8_text,
106
+ source_file=link.source_file.decode('utf-8'),
107
+ line_0_based=link.line_0_based,
108
+ column_0_based=link.column_0_based,
109
+ )
110
+
111
+
112
+ # Using ["..."] syntax to create a copy independant of
113
+ # whether any other library sets the signature for those functions.
114
+ Py_IncRef = C.pythonapi["Py_IncRef"]
115
+ Py_IncRef.argtypes = [C.py_object]
116
+ Py_IncRef.restype = None
117
+
118
+ Py_DecRef = C.pythonapi["Py_DecRef"]
119
+ Py_DecRef.argtypes = [C.py_object]
120
+ Py_DecRef.restype = None
121
+
122
+
123
+ # IMPORTANT: KEEP THIS ALIVE FOR GO THREAD WORKER
124
+ C_NO_CALLBACK = SCAN_CALLBACK(0)
125
+
126
+
127
+ def _wrap_data_ptr(tup: T) -> int:
128
+ # MANUALLY INCREMENT THE REFERENCE COUNT
129
+ # We are now responsible for its lifetime
130
+ Py_IncRef(C.py_object(tup))
131
+
132
+ return id(tup)
133
+
134
+
135
+ def _unwrap_data_ptr(data_ptr: int) -> T:
136
+ assert data_ptr, "Received a NULL pointer"
137
+
138
+ tup = C.cast(data_ptr, C.py_object).value
139
+
140
+ # MANUALLY DECREMENT THE REFERENCE COUNT.
141
+ # We are fulfilling our promise
142
+ Py_DecRef(C.py_object(tup))
143
+
144
+ return tup
145
+
146
+
147
+ def scan_file(file: str | Path, language: Language, callback: Callable[[T | None], None] | None = None, data: T | None = None) -> bool:
148
+ if callback is None:
149
+ c_callback, data_ptr = C_NO_CALLBACK, 0
150
+ else:
151
+ c_callback, data_ptr = C_AFTER_SCAN, _wrap_data_ptr((callback, data))
152
+
153
+ # print(f"[PY] sending next request {file}")
154
+ _lib.enqueue_scan_file(c_callback, data_ptr, to_str_c(os.fsencode(file)), language)
155
+
156
+ # never drop the request (it would be a memory leak)
157
+ return True
158
+
159
+
160
+ @SCAN_CALLBACK
161
+ def C_AFTER_SCAN(data_ptr: int) -> None:
162
+ callback, data = _unwrap_data_ptr(data_ptr)
163
+ assert callback is not None, "Don't feed youself NULL callbacks!"
164
+ callback(data)
165
+
166
+
167
+ def find_symbols_in_text(text: str, callback: Callable[[T | None, list[Definition_Link]], None] | None = None, data: T | None = None, ignore_word_like: bool = False, sync: bool = False, first_look_at_these_files: list[Path|str] = []) -> bool:
168
+ if callback is None:
169
+ return True
170
+
171
+ c_callback, data_ptr = C_AFTER_FIND, _wrap_data_ptr((callback, data))
172
+
173
+ first_look_at_these_files_c = (Str_C * len(first_look_at_these_files))()
174
+ for i, it in enumerate(first_look_at_these_files):
175
+ first_look_at_these_files_c[i] = to_str_c(os.fsencode(it))
176
+
177
+ # print("[PY] sending find_symbols_in_text")
178
+ _lib.enqueue_find_symbols_in_text(c_callback, data_ptr, to_str_c(text), ignore_word_like, sync, first_look_at_these_files_c, len(first_look_at_these_files))
179
+
180
+ # never drop the request (it would be a memory leak)
181
+ return True
182
+
183
+
184
+ @FIND_CALLBACK
185
+ def C_AFTER_FIND(data_ptr: int, links_ptr: C.POINTER(Definition_Link_C), count: int, strings_handle: int) -> None:
186
+ callback, data = _unwrap_data_ptr(data_ptr)
187
+ try:
188
+ assert callback is not None, "Don't feed youself NULL callbacks!"
189
+ results = [Definition_Link()] * count
190
+ for i in range(count):
191
+ results[i] = Definition_Link.from_c(links_ptr[i])
192
+ callback(data, results)
193
+ finally:
194
+ if links_ptr: _lib.free_memory(links_ptr)
195
+ if strings_handle: _lib.free_memory(strings_handle)
196
+
197
+
198
+ def pending_tasks() -> int:
199
+ return int(_lib.get_pending_tasks_count())
200
+
201
+
202
+ def init() -> None:
203
+ _lib.start_workers()
204
+
205
+
206
+ def stop() -> None:
207
+ _lib.enqueue_stop()
208
+
209
+
210
+ def clear() -> None:
211
+ _lib.enqueue_clear()
212
+
213
+
214
+ def wait_for_callbacks_in_seconds(timeout_s: float, step_s: float = 0.15) -> bool:
215
+ # print(f"[PY] Waiting for callbacks (~{timeout_s}s)...")
216
+ deadline = time.time() + timeout_s
217
+ while True:
218
+ if pending_tasks() == 0:
219
+ # print("[PY] All pending tasks have completed.")
220
+ return True
221
+
222
+ if time.time() >= deadline:
223
+ print("[PY] Timeout reached.")
224
+ return False
225
+
226
+ # print(f"[PY] pending_tasks={pending_tasks()}")
227
+ time.sleep(step_s)
228
+
229
+
230
+ if __name__ == "__main__":
231
+ if len(sys.argv) <= 2:
232
+ print("usage: python goober.py text folder...")
233
+ exit(1)
234
+
235
+ import atexit
236
+ atexit.register(stop)
237
+
238
+ def scan_callback(data: Path) -> None:
239
+ print(f"[PY] {data}")
240
+
241
+ def find_callback(data: tuple[str, str], links: list[Definition_Link]) -> None:
242
+ text, label = data
243
+ print(f"[PY] Callback for '{label}': Found {len(links)} symbols in text \"{text}\"")
244
+ for res in links:
245
+ matched_symbol = text[res.start_offset_in_text:res.end_offset_in_text]
246
+ print(f" '{matched_symbol}' -> {res.source_file}:{res.line_0_based}:{res.column_0_based}")
247
+
248
+ for folder in sys.argv[2:]:
249
+ path = Path(folder)
250
+ if path.is_dir():
251
+ for file in path.rglob("*.py"):
252
+ scan_file(file, Language.PYTHON, scan_callback, file)
253
+ else:
254
+ scan_file(path, Language.PYTHON, scan_callback, path)
255
+
256
+ text = sys.argv[1]
257
+ find_symbols_in_text(text, find_callback, data=(text, "before"),
258
+ first_look_at_these_files=["hello.py", "yay.so"])
259
+
260
+ print("[PY] WAIT, WAIT, WAIT!")
261
+ wait_for_callbacks_in_seconds(20)
262
+
263
+ find_symbols_in_text(text, find_callback, data=(text, "after"))
264
+
265
+ wait_for_callbacks_in_seconds(1)
File without changes
@@ -0,0 +1,4 @@
1
+ Metadata-Version: 2.1
2
+ Name: code_intelligence
3
+ Version: 4.8.2
4
+ Summary: Code intelligence library
@@ -0,0 +1,7 @@
1
+ code_intelligence-4.8.2.dist-info/METADATA,sha256=vYFdhKMd6QQFE_ofbbj2pRKZe0BU3Avv-HhCacGtkzI,96
2
+ code_intelligence-4.8.2.dist-info/RECORD,,
3
+ code_intelligence-4.8.2.dist-info/WHEEL,sha256=fP6FXRdXCjH8ll6K3YWkkgIJi7DgDAtlR6s0hai6FzM,103
4
+ code_intelligence/__init__.py,sha256=oBt0zByIG6xwSRyhARy9UDEajO818XIvgjaEfzItoyw,560
5
+ code_intelligence/goober.py,sha256=9U3i9wqIZrofwxWM8-GJzyVbFjgHaZ0XX3o9On-0S1c,7909
6
+ code_intelligence/libcode_intelligence.so,sha256=9NjM3S2BI9ATXE7SwFiPbGYaldn_wrizTzVlVkQIKvQ,23748736
7
+ code_intelligence/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: ship.py (manual)
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-macosx_11_0_x86_64