lscope 0.1.0__tar.gz → 0.1.2__tar.gz

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.
@@ -1,15 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lscope
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: ast-grep using ladybug
5
5
  Requires-Python: >=3.14
6
6
  Description-Content-Type: text/markdown
7
7
  Requires-Dist: icebug>=12.9
8
- Requires-Dist: ladybug>=0.17.1
9
- Requires-Dist: polars>=1.41.2
8
+ Requires-Dist: ladybug>=0.18.0
10
9
  Requires-Dist: pyarrow>=24.0.0
11
10
  Requires-Dist: tqdm>=4.68.3
12
- Requires-Dist: tree-sitter>=0.25.2
11
+ Requires-Dist: tree-sitter==0.25.2
13
12
  Requires-Dist: tree-sitter-c-sharp>=0.23.1
14
13
  Requires-Dist: tree-sitter-cpp>=0.23.4
15
14
  Requires-Dist: tree-sitter-go>=0.23.4
@@ -0,0 +1 @@
1
+ # lscope — semantic code-graph extractor (tree-sitter → Ladybug)
@@ -0,0 +1,10 @@
1
+ """Allow running lscope as ``python -m lscope``."""
2
+ import sys
3
+ import traceback
4
+ from lscope.main import main
5
+
6
+ try:
7
+ sys.exit(main())
8
+ except Exception:
9
+ traceback.print_exc()
10
+ sys.exit(1)
@@ -15,6 +15,7 @@ non-sensical flag combinations are rejected up-front with a clear message.
15
15
  """
16
16
 
17
17
  import argparse
18
+ import importlib.resources
18
19
  import os
19
20
  import sys
20
21
  import threading
@@ -259,7 +260,12 @@ _REQUIRED_REL_CONNECTIONS = (
259
260
 
260
261
 
261
262
  def _default_schema_path() -> str:
262
- return os.path.join(os.path.dirname(os.path.abspath(__file__)), "schema.cypher")
263
+ try:
264
+ # When installed as a package, schema.cypher is bundled as package data.
265
+ return str(importlib.resources.files("lscope").joinpath("schema.cypher"))
266
+ except (ModuleNotFoundError, TypeError):
267
+ # Fallback when running directly (e.g. python lscope/main.py)
268
+ return os.path.join(os.path.dirname(os.path.abspath(__file__)), "schema.cypher")
263
269
 
264
270
 
265
271
  def _load_schema_text(schema_path: str | None) -> str | None:
@@ -293,8 +299,8 @@ def apply_schema(conn, schema_text: str | None) -> None:
293
299
 
294
300
  def ensure_schema(conn, schema_path: str | None = None) -> None:
295
301
  """Create the semantic schema when the database has no graph tables."""
296
- tables = conn.execute("CALL show_tables() RETURN name").get_as_pl()
297
- existing = set(tables["name"].to_list()) if tables.height else set()
302
+ tables = conn.execute("CALL show_tables() RETURN name").get_as_arrow()
303
+ existing = set(tables.column("name").to_pylist()) if tables.num_rows else set()
298
304
  if _REQUIRED_SCHEMA_TABLES <= existing:
299
305
  for source, target in _REQUIRED_REL_CONNECTIONS:
300
306
  if source in existing and target in existing:
@@ -754,7 +760,7 @@ def ingest_analyses_parallel(
754
760
  # --------------------------------------------------------------------------- #
755
761
  def _run_query(conn, query: str, params: dict | None = None):
756
762
  qr = conn.execute(query, params or {})
757
- return qr.get_as_pl()
763
+ return qr.get_as_arrow()
758
764
 
759
765
 
760
766
  def find_functions(conn, pattern: str, languages: list[str] | None = None):
@@ -777,7 +783,7 @@ def find_functions(conn, pattern: str, languages: list[str] | None = None):
777
783
  {"pattern": pattern},
778
784
  )
779
785
  )
780
- return pl.concat(frames, how="vertical")
786
+ return pa.concat_tables(frames)
781
787
 
782
788
 
783
789
  def find_callers(conn, func_name: str):
@@ -803,7 +809,7 @@ def find_callers(conn, func_name: str):
803
809
  {"func_name": func_name},
804
810
  )
805
811
  )
806
- return pl.concat(frames, how="vertical")
812
+ return pa.concat_tables(frames)
807
813
 
808
814
 
809
815
  # --------------------------------------------------------------------------- #
@@ -1036,16 +1042,23 @@ def main(argv: list[str] | None = None) -> int:
1036
1042
  args = parser.parse_args(argv)
1037
1043
  action = _resolve_actions(args)
1038
1044
 
1039
- if action == "index":
1040
- return run_index(args)
1041
- if action == "find-functions":
1042
- return run_find_functions(args)
1043
- if action == "find-callers":
1044
- return run_find_callers(args)
1045
- if action == "schema-only":
1046
- return run_schema_only(args)
1047
- parser.error(f"Unhandled action {action!r}")
1048
- return 2 # unreachable
1045
+ try:
1046
+ if action == "index":
1047
+ return run_index(args)
1048
+ if action == "find-functions":
1049
+ return run_find_functions(args)
1050
+ if action == "find-callers":
1051
+ return run_find_callers(args)
1052
+ if action == "schema-only":
1053
+ return run_schema_only(args)
1054
+ parser.error(f"Unhandled action {action!r}")
1055
+ return 2 # unreachable
1056
+ except SystemExit:
1057
+ raise
1058
+ except Exception:
1059
+ import traceback
1060
+ traceback.print_exc()
1061
+ return 1
1049
1062
 
1050
1063
 
1051
1064
  if __name__ == "__main__":
@@ -0,0 +1,329 @@
1
+ CALL disable_default_hash_index=true;
2
+ CALL debug_enable_multi_writes=true;
3
+
4
+ // Semantic code-graph schema.
5
+ //
6
+ // Every relationship is stored in the CodeRelation relationship-table group.
7
+ // The `type` property contains one of:
8
+ // CONTAINS, DEFINES, CALLS, IMPORTS, EXTENDS, IMPLEMENTS, HAS_METHOD,
9
+ // HAS_PROPERTY, ACCESSES, METHOD_OVERRIDES, METHOD_IMPLEMENTS, MEMBER_OF,
10
+ // STEP_IN_PROCESS, HANDLES_ROUTE, FETCHES, HANDLES_TOOL, ENTRY_POINT_OF.
11
+ //
12
+ // For ACCESSES, `reason` records the access mode (for example "read" or
13
+ // "write"). For STEP_IN_PROCESS, `step` records the zero-based execution order.
14
+
15
+ CREATE NODE TABLE File (
16
+ id STRING,
17
+ name STRING,
18
+ path STRING,
19
+ filePath STRING,
20
+ language STRING,
21
+ PRIMARY KEY (id)
22
+ );
23
+
24
+ CREATE NODE TABLE Folder (
25
+ id STRING,
26
+ name STRING,
27
+ path STRING,
28
+ PRIMARY KEY (id)
29
+ );
30
+
31
+ CREATE NODE TABLE Function (
32
+ id STRING,
33
+ name STRING,
34
+ qualifiedName STRING,
35
+ filePath STRING,
36
+ language STRING,
37
+ signature STRING,
38
+ parameterCount INT32,
39
+ returnType STRING,
40
+ visibility STRING,
41
+ isAsync BOOLEAN,
42
+ startLine INT32,
43
+ endLine INT32,
44
+ PRIMARY KEY (id)
45
+ );
46
+
47
+ CREATE NODE TABLE Class (
48
+ id STRING,
49
+ name STRING,
50
+ qualifiedName STRING,
51
+ filePath STRING,
52
+ language STRING,
53
+ visibility STRING,
54
+ isAbstract BOOLEAN,
55
+ startLine INT32,
56
+ endLine INT32,
57
+ PRIMARY KEY (id)
58
+ );
59
+
60
+ CREATE NODE TABLE Interface (
61
+ id STRING,
62
+ name STRING,
63
+ qualifiedName STRING,
64
+ filePath STRING,
65
+ language STRING,
66
+ visibility STRING,
67
+ startLine INT32,
68
+ endLine INT32,
69
+ PRIMARY KEY (id)
70
+ );
71
+
72
+ CREATE NODE TABLE Method (
73
+ id STRING,
74
+ name STRING,
75
+ qualifiedName STRING,
76
+ filePath STRING,
77
+ language STRING,
78
+ signature STRING,
79
+ parameterCount INT32,
80
+ returnType STRING,
81
+ visibility STRING,
82
+ isAsync BOOLEAN,
83
+ isStatic BOOLEAN,
84
+ startLine INT32,
85
+ endLine INT32,
86
+ PRIMARY KEY (id)
87
+ );
88
+
89
+ CREATE NODE TABLE Property (
90
+ id STRING,
91
+ name STRING,
92
+ qualifiedName STRING,
93
+ filePath STRING,
94
+ language STRING,
95
+ declaredType STRING,
96
+ visibility STRING,
97
+ isStatic BOOLEAN,
98
+ isMutable BOOLEAN,
99
+ startLine INT32,
100
+ endLine INT32,
101
+ PRIMARY KEY (id)
102
+ );
103
+
104
+ CREATE NODE TABLE CodeElement (
105
+ id STRING,
106
+ name STRING,
107
+ qualifiedName STRING,
108
+ kind STRING,
109
+ filePath STRING,
110
+ language STRING,
111
+ startLine INT32,
112
+ endLine INT32,
113
+ PRIMARY KEY (id)
114
+ );
115
+
116
+ CREATE NODE TABLE Community (
117
+ id STRING,
118
+ heuristicLabel STRING,
119
+ cohesion DOUBLE,
120
+ symbolCount INT32,
121
+ keywords STRING[],
122
+ description STRING,
123
+ enrichedBy STRING,
124
+ PRIMARY KEY (id)
125
+ );
126
+
127
+ CREATE NODE TABLE Process (
128
+ id STRING,
129
+ heuristicLabel STRING,
130
+ processType STRING,
131
+ stepCount INT32,
132
+ communities STRING[],
133
+ entryPointId STRING,
134
+ terminalId STRING,
135
+ PRIMARY KEY (id)
136
+ );
137
+
138
+ CREATE NODE TABLE Route (
139
+ id STRING,
140
+ name STRING,
141
+ path STRING,
142
+ httpMethod STRING,
143
+ filePath STRING,
144
+ startLine INT32,
145
+ endLine INT32,
146
+ PRIMARY KEY (id)
147
+ );
148
+
149
+ CREATE NODE TABLE Tool (
150
+ id STRING,
151
+ name STRING,
152
+ description STRING,
153
+ toolType STRING,
154
+ filePath STRING,
155
+ PRIMARY KEY (id)
156
+ );
157
+
158
+ // Language-specific semantic node types.
159
+ CREATE NODE TABLE Struct (
160
+ id STRING,
161
+ name STRING,
162
+ qualifiedName STRING,
163
+ filePath STRING,
164
+ language STRING,
165
+ visibility STRING,
166
+ startLine INT32,
167
+ endLine INT32,
168
+ PRIMARY KEY (id)
169
+ );
170
+
171
+ CREATE NODE TABLE Enum (
172
+ id STRING,
173
+ name STRING,
174
+ qualifiedName STRING,
175
+ filePath STRING,
176
+ language STRING,
177
+ visibility STRING,
178
+ startLine INT32,
179
+ endLine INT32,
180
+ PRIMARY KEY (id)
181
+ );
182
+
183
+ CREATE NODE TABLE Trait (
184
+ id STRING,
185
+ name STRING,
186
+ qualifiedName STRING,
187
+ filePath STRING,
188
+ language STRING,
189
+ visibility STRING,
190
+ startLine INT32,
191
+ endLine INT32,
192
+ PRIMARY KEY (id)
193
+ );
194
+
195
+ CREATE NODE TABLE Impl (
196
+ id STRING,
197
+ name STRING,
198
+ qualifiedName STRING,
199
+ filePath STRING,
200
+ language STRING,
201
+ startLine INT32,
202
+ endLine INT32,
203
+ PRIMARY KEY (id)
204
+ );
205
+
206
+ CREATE REL TABLE GROUP CodeRelation (
207
+ // Filesystem containment and definitions.
208
+ FROM Folder TO Folder,
209
+ FROM Folder TO File,
210
+ FROM File TO Function,
211
+ FROM File TO Method,
212
+ FROM File TO Class,
213
+ FROM File TO Interface,
214
+ FROM File TO Property,
215
+ FROM File TO CodeElement,
216
+ FROM File TO Route,
217
+ FROM File TO Tool,
218
+ FROM File TO Struct,
219
+ FROM File TO Enum,
220
+ FROM File TO Trait,
221
+ FROM File TO Impl,
222
+
223
+ // Nested declarations and members.
224
+ FROM Class TO Class,
225
+ FROM Class TO Struct,
226
+ FROM Class TO Impl,
227
+ FROM Class TO Method,
228
+ FROM Class TO Function,
229
+ FROM Class TO Property,
230
+ FROM Interface TO Class,
231
+ FROM Interface TO Struct,
232
+ FROM Interface TO Trait,
233
+ FROM Interface TO Impl,
234
+ FROM Interface TO Method,
235
+ FROM Interface TO Property,
236
+ FROM Struct TO Class,
237
+ FROM Struct TO Struct,
238
+ FROM Struct TO Impl,
239
+ FROM Struct TO Method,
240
+ FROM Struct TO Property,
241
+ FROM Enum TO Method,
242
+ FROM Enum TO Property,
243
+ FROM Trait TO Class,
244
+ FROM Trait TO Struct,
245
+ FROM Trait TO Interface,
246
+ FROM Trait TO Impl,
247
+ FROM Trait TO Method,
248
+ FROM Trait TO Property,
249
+ FROM Impl TO Method,
250
+ FROM Impl TO Property,
251
+ FROM Impl TO Class,
252
+ FROM Impl TO Struct,
253
+ FROM Impl TO Enum,
254
+ FROM Impl TO Trait,
255
+ FROM Impl TO Interface,
256
+ FROM Impl TO Impl,
257
+ FROM Function TO Class,
258
+ FROM Function TO Interface,
259
+ FROM Function TO Struct,
260
+ FROM Function TO Trait,
261
+ FROM Function TO Impl,
262
+ FROM Method TO Class,
263
+ FROM Method TO Interface,
264
+ FROM Method TO Struct,
265
+ FROM Method TO Trait,
266
+ FROM Method TO Impl,
267
+
268
+ // Imports, inheritance, implementation, calls, and property access.
269
+ FROM File TO File,
270
+ FROM Function TO Function,
271
+ FROM Function TO Method,
272
+ FROM Function TO Property,
273
+ FROM Method TO Function,
274
+ FROM Method TO Method,
275
+ FROM Method TO Property,
276
+ FROM Class TO Interface,
277
+ FROM Class TO Trait,
278
+ FROM Struct TO Interface,
279
+ FROM Struct TO Trait,
280
+ FROM Enum TO Interface,
281
+ FROM Enum TO Trait,
282
+ FROM Interface TO Interface,
283
+ FROM Trait TO Trait,
284
+
285
+ // Communities and process traces.
286
+ FROM File TO Community,
287
+ FROM Function TO Community,
288
+ FROM Class TO Community,
289
+ FROM Interface TO Community,
290
+ FROM Method TO Community,
291
+ FROM Property TO Community,
292
+ FROM CodeElement TO Community,
293
+ FROM Route TO Community,
294
+ FROM Tool TO Community,
295
+ FROM Struct TO Community,
296
+ FROM Enum TO Community,
297
+ FROM Trait TO Community,
298
+ FROM Impl TO Community,
299
+ FROM File TO Process,
300
+ FROM Function TO Process,
301
+ FROM Class TO Process,
302
+ FROM Interface TO Process,
303
+ FROM Method TO Process,
304
+ FROM Property TO Process,
305
+ FROM CodeElement TO Process,
306
+ FROM Route TO Process,
307
+ FROM Tool TO Process,
308
+ FROM Struct TO Process,
309
+ FROM Enum TO Process,
310
+ FROM Trait TO Process,
311
+ FROM Impl TO Process,
312
+
313
+ // Framework routes, external fetches, and tool handlers.
314
+ FROM Function TO Route,
315
+ FROM Method TO Route,
316
+ FROM Class TO Route,
317
+ FROM Route TO Route,
318
+ FROM Function TO Tool,
319
+ FROM Method TO Tool,
320
+ FROM Class TO Tool,
321
+ FROM Tool TO Function,
322
+ FROM Tool TO Method,
323
+ FROM Tool TO Class,
324
+
325
+ type STRING,
326
+ confidence DOUBLE,
327
+ reason STRING,
328
+ step INT32
329
+ );
@@ -1,15 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lscope
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: ast-grep using ladybug
5
5
  Requires-Python: >=3.14
6
6
  Description-Content-Type: text/markdown
7
7
  Requires-Dist: icebug>=12.9
8
- Requires-Dist: ladybug>=0.17.1
9
- Requires-Dist: polars>=1.41.2
8
+ Requires-Dist: ladybug>=0.18.0
10
9
  Requires-Dist: pyarrow>=24.0.0
11
10
  Requires-Dist: tqdm>=4.68.3
12
- Requires-Dist: tree-sitter>=0.25.2
11
+ Requires-Dist: tree-sitter==0.25.2
13
12
  Requires-Dist: tree-sitter-c-sharp>=0.23.1
14
13
  Requires-Dist: tree-sitter-cpp>=0.23.4
15
14
  Requires-Dist: tree-sitter-go>=0.23.4
@@ -1,6 +1,9 @@
1
1
  README.md
2
- main.py
3
2
  pyproject.toml
3
+ lscope/__init__.py
4
+ lscope/__main__.py
5
+ lscope/main.py
6
+ lscope/schema.cypher
4
7
  lscope.egg-info/PKG-INFO
5
8
  lscope.egg-info/SOURCES.txt
6
9
  lscope.egg-info/dependency_links.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ lscope = lscope.main:main
@@ -1,9 +1,8 @@
1
1
  icebug>=12.9
2
- ladybug>=0.17.1
3
- polars>=1.41.2
2
+ ladybug>=0.18.0
4
3
  pyarrow>=24.0.0
5
4
  tqdm>=4.68.3
6
- tree-sitter>=0.25.2
5
+ tree-sitter==0.25.2
7
6
  tree-sitter-c-sharp>=0.23.1
8
7
  tree-sitter-cpp>=0.23.4
9
8
  tree-sitter-go>=0.23.4
@@ -0,0 +1 @@
1
+ lscope
@@ -1,16 +1,15 @@
1
1
  [project]
2
2
  name = "lscope"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  description = "ast-grep using ladybug"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.14"
7
7
  dependencies = [
8
8
  "icebug>=12.9",
9
- "ladybug>=0.17.1",
10
- "polars>=1.41.2",
9
+ "ladybug>=0.18.0",
11
10
  "pyarrow>=24.0.0",
12
11
  "tqdm>=4.68.3",
13
- "tree-sitter>=0.25.2",
12
+ "tree-sitter==0.25.2",
14
13
  "tree-sitter-c-sharp>=0.23.1",
15
14
  "tree-sitter-cpp>=0.23.4",
16
15
  "tree-sitter-go>=0.23.4",
@@ -24,10 +23,11 @@ dependencies = [
24
23
  ]
25
24
 
26
25
  [project.scripts]
27
- lscope = "main:main"
26
+ lscope = "lscope.main:main"
28
27
 
29
28
  [tool.setuptools]
30
- py-modules = ["main"]
29
+ packages = ["lscope"]
30
+ package-data = {"lscope" = ["*.cypher"]}
31
31
 
32
32
  [dependency-groups]
33
33
  dev = [
@@ -1,6 +1,12 @@
1
1
  import ladybug
2
2
 
3
- from main import LanguageRegistry, analyze_file, ensure_schema, ingest_analysis
3
+ from lscope.main import (
4
+ LanguageRegistry,
5
+ _ingest_chunk_edges,
6
+ analyze_file,
7
+ ensure_schema,
8
+ ingest_analyses_parallel,
9
+ )
4
10
 
5
11
 
6
12
  NESTED_TYPES = """\
@@ -32,7 +38,9 @@ def test_ingests_classes_nested_in_functions_and_methods(tmp_path):
32
38
  ensure_schema(conn)
33
39
  analysis = _analyze_nested_types()
34
40
 
35
- assert ingest_analysis(conn, analysis) == 6
41
+ total_nodes, def_edges = ingest_analyses_parallel(db, [analysis], 1)
42
+ _ingest_chunk_edges(conn, def_edges)
43
+ assert total_nodes == 6
36
44
  rows = conn.execute(
37
45
  """
38
46
  MATCH (owner)-[r:CodeRelation]->(nested:Class)
@@ -40,8 +48,8 @@ def test_ingests_classes_nested_in_functions_and_methods(tmp_path):
40
48
  RETURN label(owner) AS owner_label, nested.name AS nested_name
41
49
  ORDER BY nested_name
42
50
  """
43
- ).get_as_pl()
44
- assert rows.to_dicts() == [
51
+ ).get_as_arrow()
52
+ assert [dict(zip(rows.column_names, row)) for row in zip(*(rows.column(c).to_pylist() for c in rows.column_names))] == [
45
53
  {"owner_label": "Function", "nested_name": "Inner"},
46
54
  {"owner_label": "Method", "nested_name": "Local"},
47
55
  ]
@@ -62,7 +70,11 @@ def test_ensure_schema_migrates_existing_relation_group(tmp_path):
62
70
 
63
71
  ensure_schema(conn)
64
72
 
65
- assert ingest_analysis(conn, _analyze_nested_types()) == 6
73
+ total_nodes, def_edges = ingest_analyses_parallel(
74
+ db, [_analyze_nested_types()], 1
75
+ )
76
+ _ingest_chunk_edges(conn, def_edges)
77
+ assert total_nodes == 6
66
78
  finally:
67
79
  conn.close()
68
80
  db.close()
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- lscope = main:main
@@ -1 +0,0 @@
1
- main
File without changes
File without changes