descry-codegraph 0.3.2__py3-none-any.whl → 0.3.4__py3-none-any.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.
- descry/__init__.py +1 -1
- descry/cli.py +10 -2
- descry/embeddings.py +14 -2
- descry/generate.py +19 -3
- descry/handlers.py +6 -6
- descry/query.py +36 -36
- {descry_codegraph-0.3.2.dist-info → descry_codegraph-0.3.4.dist-info}/METADATA +3 -3
- {descry_codegraph-0.3.2.dist-info → descry_codegraph-0.3.4.dist-info}/RECORD +12 -12
- {descry_codegraph-0.3.2.dist-info → descry_codegraph-0.3.4.dist-info}/WHEEL +0 -0
- {descry_codegraph-0.3.2.dist-info → descry_codegraph-0.3.4.dist-info}/entry_points.txt +0 -0
- {descry_codegraph-0.3.2.dist-info → descry_codegraph-0.3.4.dist-info}/licenses/LICENSE +0 -0
- {descry_codegraph-0.3.2.dist-info → descry_codegraph-0.3.4.dist-info}/licenses/THIRD-PARTY-NOTICES.md +0 -0
descry/__init__.py
CHANGED
descry/cli.py
CHANGED
|
@@ -308,7 +308,9 @@ def main():
|
|
|
308
308
|
default=3,
|
|
309
309
|
help="Levels of calls below the start (default: 3)",
|
|
310
310
|
)
|
|
311
|
-
sub.add_argument(
|
|
311
|
+
sub.add_argument(
|
|
312
|
+
"--target", default=None, help="Symbol to reach, by name or node ID"
|
|
313
|
+
)
|
|
312
314
|
sub.add_argument(
|
|
313
315
|
"--inline-threshold",
|
|
314
316
|
type=int,
|
|
@@ -329,7 +331,13 @@ def main():
|
|
|
329
331
|
sub.add_argument("--limit", type=int, default=10, help="Max results (default: 10)")
|
|
330
332
|
sub.add_argument("--lang", default=None, help="Filter by language")
|
|
331
333
|
sub.add_argument("--crate", default=None, help="Filter by crate")
|
|
332
|
-
sub.add_argument(
|
|
334
|
+
sub.add_argument(
|
|
335
|
+
"--type",
|
|
336
|
+
default=None,
|
|
337
|
+
type=str.lower,
|
|
338
|
+
choices=["function", "class", "method", "constant", "file", "all"],
|
|
339
|
+
help="Filter by symbol type",
|
|
340
|
+
)
|
|
333
341
|
sub.add_argument(
|
|
334
342
|
"--exclude-tests", action="store_true", help="Exclude test symbols"
|
|
335
343
|
)
|
descry/embeddings.py
CHANGED
|
@@ -774,7 +774,9 @@ class SemanticSearcher:
|
|
|
774
774
|
self.embeddings = embeddings / np.where(norms == 0, 1, norms)
|
|
775
775
|
logger.info("Embeddings generated successfully")
|
|
776
776
|
|
|
777
|
-
def search(
|
|
777
|
+
def search(
|
|
778
|
+
self, query: str, limit: int = 10, min_score: float = 0.3, keep=None
|
|
779
|
+
) -> list:
|
|
778
780
|
"""Search for nodes semantically similar to the query.
|
|
779
781
|
|
|
780
782
|
Args:
|
|
@@ -782,6 +784,7 @@ class SemanticSearcher:
|
|
|
782
784
|
limit: Maximum number of results
|
|
783
785
|
min_score: Minimum final score, i.e. cosine similarity after
|
|
784
786
|
the in-degree and type boosts are added (may exceed 1).
|
|
787
|
+
keep: The node IDs results may have, None for any.
|
|
785
788
|
|
|
786
789
|
Returns:
|
|
787
790
|
List of (node, score) tuples sorted by relevance
|
|
@@ -826,10 +829,19 @@ class SemanticSearcher:
|
|
|
826
829
|
np.linalg.norm(self.embeddings, axis=1) * np.linalg.norm(query_embedding)
|
|
827
830
|
)
|
|
828
831
|
|
|
832
|
+
if keep is not None:
|
|
833
|
+
# Nodes outside `keep` never enter the pool
|
|
834
|
+
kept = np.fromiter(
|
|
835
|
+
(n["id"] in keep for n in self.nodes), bool, len(self.nodes)
|
|
836
|
+
)
|
|
837
|
+
similarities = np.where(kept, similarities, -np.inf)
|
|
838
|
+
if not kept.any():
|
|
839
|
+
return []
|
|
840
|
+
|
|
829
841
|
# Take a candidate pool by base score, then apply min_score to the
|
|
830
842
|
# final score, so a node whose boosts (worth up to +0.17) lift it over
|
|
831
843
|
# the threshold is kept.
|
|
832
|
-
pool = min(len(similarities), limit * 3)
|
|
844
|
+
pool = min(len(similarities) if keep is None else int(kept.sum()), limit * 3)
|
|
833
845
|
top_indices = np.argpartition(-similarities, pool - 1)[:pool]
|
|
834
846
|
top_indices = top_indices[np.argsort(-similarities[top_indices])]
|
|
835
847
|
|
descry/generate.py
CHANGED
|
@@ -18650,6 +18650,15 @@ class CallResolver:
|
|
|
18650
18650
|
if self.standard[lang].key(callee, source_id) == callee:
|
|
18651
18651
|
held = self._returned_type(constructed, source_id)
|
|
18652
18652
|
self._result = held or self._result
|
|
18653
|
+
elif verdict[1] == _EXTERNAL and not origin and lang == "dart":
|
|
18654
|
+
# Dart constructs without `new`: a call of a standard type's
|
|
18655
|
+
# name gives an instance of it.
|
|
18656
|
+
library = self.standard[lang]
|
|
18657
|
+
if (
|
|
18658
|
+
callee in library.data["types"]
|
|
18659
|
+
and library.key(callee, source_id) == callee
|
|
18660
|
+
):
|
|
18661
|
+
self._result = self._returned_type(callee, source_id) or self._result
|
|
18653
18662
|
elif verdict[1] == _EXTERNAL and not origin and lang == "typescript":
|
|
18654
18663
|
known, value = self._js_global(callee, source_id)
|
|
18655
18664
|
if known:
|
|
@@ -24878,12 +24887,19 @@ class CodeGraphBuilder:
|
|
|
24878
24887
|
for root, dirs, files in os.walk(self.root_dir, followlinks=False):
|
|
24879
24888
|
dirs.sort()
|
|
24880
24889
|
files.sort()
|
|
24881
|
-
# Filter by name first (excluded dirs, dotfiles
|
|
24882
|
-
# ignores.
|
|
24890
|
+
# Filter by name first (excluded dirs, dotfiles, the build output
|
|
24891
|
+
# of a .NET or an Eclipse project), and by what git ignores.
|
|
24892
|
+
# `bin` holds sources in Dart and Rust.
|
|
24893
|
+
built = any(
|
|
24894
|
+
f.endswith((".csproj", ".vbproj", ".fsproj")) or f == ".classpath"
|
|
24895
|
+
for f in files
|
|
24896
|
+
)
|
|
24883
24897
|
dirs[:] = [
|
|
24884
24898
|
d
|
|
24885
24899
|
for d in kept(root, dirs)
|
|
24886
|
-
if not d.startswith(".")
|
|
24900
|
+
if not d.startswith(".")
|
|
24901
|
+
and d not in self.excluded_dirs
|
|
24902
|
+
and not (built and d == "bin")
|
|
24887
24903
|
]
|
|
24888
24904
|
# Then filter by realpath containment — drop directories that are
|
|
24889
24905
|
# symlinks pointing outside the project root.
|
descry/handlers.py
CHANGED
|
@@ -92,8 +92,8 @@ _DEFAULT_EXCLUDED_DIRS = {
|
|
|
92
92
|
"venv",
|
|
93
93
|
# Go
|
|
94
94
|
"vendor",
|
|
95
|
-
# .NET
|
|
96
|
-
|
|
95
|
+
# .NET (its `bin`, and an Eclipse project's, is skipped beside the
|
|
96
|
+
# project file)
|
|
97
97
|
"obj",
|
|
98
98
|
# Dart / Flutter
|
|
99
99
|
".dart_tool",
|
|
@@ -2086,23 +2086,23 @@ class DescryService:
|
|
|
2086
2086
|
# and respects the cache lock).
|
|
2087
2087
|
searcher = await self._get_semantic_searcher()
|
|
2088
2088
|
if searcher is not None:
|
|
2089
|
+
# Under the filters the keyword side has
|
|
2089
2090
|
semantic_results = await asyncio.to_thread(
|
|
2090
2091
|
searcher.search,
|
|
2091
2092
|
" ".join(terms),
|
|
2092
2093
|
limit=limit * 2,
|
|
2093
2094
|
min_score=0.25,
|
|
2095
|
+
keep=q.filtered_ids(lang, crate, symbol_type, exclude_tests),
|
|
2094
2096
|
)
|
|
2095
2097
|
except Exception as e: # noqa: BLE001 — boundary over the embedding backend; search degrades to keyword-only
|
|
2096
2098
|
logger.warning(f"Semantic search failed, using keyword only: {e}")
|
|
2097
2099
|
|
|
2098
|
-
if semantic_results
|
|
2100
|
+
if semantic_results:
|
|
2099
2101
|
combined = reciprocal_rank_fusion(tfidf_results, semantic_results)
|
|
2100
2102
|
results = [node for node, _ in combined[:limit]]
|
|
2101
2103
|
method = "hybrid"
|
|
2102
|
-
elif tfidf_results:
|
|
2103
|
-
results = tfidf_results[:limit]
|
|
2104
2104
|
else:
|
|
2105
|
-
results = []
|
|
2105
|
+
results = tfidf_results[:limit]
|
|
2106
2106
|
|
|
2107
2107
|
return {"ok": True, "error": None, "results": results, "method": method}
|
|
2108
2108
|
|
descry/query.py
CHANGED
|
@@ -1318,7 +1318,8 @@ class GraphQuerier:
|
|
|
1318
1318
|
once, at the first level that reaches it, and met again as `seen`,
|
|
1319
1319
|
the level of that entry (the start is level 0).
|
|
1320
1320
|
Returns ``(root, path, cut)``: the tree, the node IDs from the start
|
|
1321
|
-
to the first node
|
|
1321
|
+
to the first node ``target`` names, by name or node ID, and why it
|
|
1322
|
+
stopped early
|
|
1322
1323
|
("timeout", "node limit") or None."""
|
|
1323
1324
|
start_time = time.time()
|
|
1324
1325
|
|
|
@@ -1353,7 +1354,7 @@ class GraphQuerier:
|
|
|
1353
1354
|
|
|
1354
1355
|
root = tree_node(start_id, None)
|
|
1355
1356
|
paths = {start_id: [start_id]}
|
|
1356
|
-
if target
|
|
1357
|
+
if target in (root["name"], root["id"]):
|
|
1357
1358
|
return root, paths[start_id], None
|
|
1358
1359
|
level = [root]
|
|
1359
1360
|
for _ in range(depth):
|
|
@@ -1378,7 +1379,7 @@ class GraphQuerier:
|
|
|
1378
1379
|
child = tree_node(child_id, marks.get(child_id))
|
|
1379
1380
|
paths[child_id] = [*paths[parent["id"]], child_id]
|
|
1380
1381
|
parent["children"].append(child)
|
|
1381
|
-
if target
|
|
1382
|
+
if target in (child["name"], child["id"]):
|
|
1382
1383
|
return root, paths[child_id], None
|
|
1383
1384
|
next_level.append(child)
|
|
1384
1385
|
level = next_level
|
|
@@ -1500,7 +1501,7 @@ class GraphQuerier:
|
|
|
1500
1501
|
cut (why the trace stopped early, when it did). Each tree node has: id,
|
|
1501
1502
|
name, type, tokens, file, line, code, lang, candidates, children,
|
|
1502
1503
|
more, more_possible, and `seen`, the level its entry is at, where it
|
|
1503
|
-
is placed there already. The trace stops at the first node
|
|
1504
|
+
is placed there already. The trace stops at the first node `target` names, by name or node ID.
|
|
1504
1505
|
"""
|
|
1505
1506
|
if timeout_ms is None:
|
|
1506
1507
|
timeout_ms = self._timeout_ms
|
|
@@ -1666,6 +1667,33 @@ class GraphQuerier:
|
|
|
1666
1667
|
idf[term] = math.log((total_docs + 1) / (df + 1)) + 1
|
|
1667
1668
|
return idf
|
|
1668
1669
|
|
|
1670
|
+
def filtered_ids(
|
|
1671
|
+
self, lang=None, crate=None, symbol_type=None, exclude_tests=False
|
|
1672
|
+
):
|
|
1673
|
+
"""The IDs of the nodes `search_docs`'s filters keep, None when none
|
|
1674
|
+
is given: the language, the crate or module, the type, and no tests."""
|
|
1675
|
+
if not (lang or crate or symbol_type or exclude_tests):
|
|
1676
|
+
return None
|
|
1677
|
+
self._ensure_filter_indices()
|
|
1678
|
+
kept = set(self.nodes.keys())
|
|
1679
|
+
if exclude_tests and self._index_is_test:
|
|
1680
|
+
kept -= self._index_is_test
|
|
1681
|
+
if crate:
|
|
1682
|
+
kept &= self._index_by_crate.get(crate, set())
|
|
1683
|
+
if lang and lang != "all":
|
|
1684
|
+
lang = _LANG_ALIASES.get(lang.lower(), lang.lower())
|
|
1685
|
+
kept &= self._index_by_lang.get(lang, set())
|
|
1686
|
+
if symbol_type and symbol_type != "all":
|
|
1687
|
+
type_map = {
|
|
1688
|
+
"function": "Function",
|
|
1689
|
+
"class": "Class",
|
|
1690
|
+
"method": "Method",
|
|
1691
|
+
"constant": "Constant",
|
|
1692
|
+
"file": "File",
|
|
1693
|
+
}
|
|
1694
|
+
kept &= self._index_by_type.get(type_map.get(symbol_type.lower()), set())
|
|
1695
|
+
return kept
|
|
1696
|
+
|
|
1669
1697
|
def search_docs(
|
|
1670
1698
|
self, query_terms, lang=None, crate=None, symbol_type=None, exclude_tests=False
|
|
1671
1699
|
):
|
|
@@ -1695,38 +1723,10 @@ class GraphQuerier:
|
|
|
1695
1723
|
if num_terms == 0:
|
|
1696
1724
|
return []
|
|
1697
1725
|
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
self.
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
# Filter out test files and functions if requested
|
|
1704
|
-
if exclude_tests and self._index_is_test:
|
|
1705
|
-
candidate_ids -= self._index_is_test
|
|
1706
|
-
|
|
1707
|
-
if crate:
|
|
1708
|
-
# If crate filter specified but doesn't exist, return empty results
|
|
1709
|
-
if crate not in self._index_by_crate:
|
|
1710
|
-
return []
|
|
1711
|
-
candidate_ids &= self._index_by_crate[crate]
|
|
1712
|
-
if lang and lang != "all":
|
|
1713
|
-
lang = _LANG_ALIASES.get(lang.lower(), lang.lower())
|
|
1714
|
-
candidate_ids &= self._index_by_lang.get(lang, set())
|
|
1715
|
-
if symbol_type and symbol_type != "all":
|
|
1716
|
-
type_map = {
|
|
1717
|
-
"function": "Function",
|
|
1718
|
-
"class": "Class",
|
|
1719
|
-
"method": "Method",
|
|
1720
|
-
"constant": "Constant",
|
|
1721
|
-
"file": "File",
|
|
1722
|
-
}
|
|
1723
|
-
type_key = type_map.get(symbol_type.lower())
|
|
1724
|
-
if type_key and type_key in self._index_by_type:
|
|
1725
|
-
candidate_ids &= self._index_by_type[type_key]
|
|
1726
|
-
|
|
1727
|
-
candidates = [self.nodes[nid] for nid in candidate_ids]
|
|
1728
|
-
else:
|
|
1729
|
-
candidates = self.data["nodes"]
|
|
1726
|
+
kept = self.filtered_ids(lang, crate, symbol_type, exclude_tests)
|
|
1727
|
+
candidates = (
|
|
1728
|
+
self.data["nodes"] if kept is None else [self.nodes[nid] for nid in kept]
|
|
1729
|
+
)
|
|
1730
1730
|
|
|
1731
1731
|
for node in candidates:
|
|
1732
1732
|
score = 0.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: descry-codegraph
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: Codebase knowledge graph: polyglot indexer, semantic search, call-graph analysis
|
|
5
5
|
Project-URL: Homepage, https://github.com/06chaynes/descry
|
|
6
6
|
Project-URL: Repository, https://github.com/06chaynes/descry
|
|
@@ -267,7 +267,7 @@ For customization, add a `.descry.toml` to your project root.
|
|
|
267
267
|
|
|
268
268
|
```toml
|
|
269
269
|
[project]
|
|
270
|
-
# OPTIONAL — REPLACES the
|
|
270
|
+
# OPTIONAL — REPLACES the 24-element default. Leave unset to keep defaults
|
|
271
271
|
# (.git, .gradle, .next, .svelte-kit, .venv, node_modules, target, build, …).
|
|
272
272
|
# excluded_dirs = ["target", "node_modules", "dist", "build", "vendor"]
|
|
273
273
|
# OPTIONAL — in a git repository, files git ignores are not indexed.
|
|
@@ -393,7 +393,7 @@ Share of project calls resolved without SCIP, measured on public repositories at
|
|
|
393
393
|
| C# | serilog `bebc771`, Newtonsoft.Json `52fa3ae` (`Src/Newtonsoft.Json`) | 94%, 91% |
|
|
394
394
|
| C | jq `a19efdd`, libuv `954c1d1` | 99%, 79% |
|
|
395
395
|
| C++ | leveldb `7ee830d`, fmt `c4927e6` | 97%, 86% |
|
|
396
|
-
| Dart | shelf `b2cb503`, riverpod `1efba1c` (`packages/riverpod`) |
|
|
396
|
+
| Dart | shelf `b2cb503`, riverpod `1efba1c` (`packages/riverpod`) | 95%, 91% |
|
|
397
397
|
| Ruby | rack `a9833c8`, sinatra `cb22afd` | 70%, 39% |
|
|
398
398
|
|
|
399
399
|
The remainder is unresolved, not wrong: of 450 resolved edges drawn at random from these repositories and read against the source, every one reaches the definition the call reaches. Ruby is low because the language declares no types and calls inside DSL blocks run with another `self`; libuv because most of its functions exist once for Unix and once for Windows, and the build files, not the source, choose between them.
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
descry/__init__.py,sha256=
|
|
1
|
+
descry/__init__.py,sha256=wF1DadE3KUESLtSaENhYMj5JL-jXyNJP8GSF_l-S7NE,148
|
|
2
2
|
descry/_comments.py,sha256=CCL0ywnHTWDZE2zKRpQwgbU2Re7B979XdbLyLIZooHc,2499
|
|
3
3
|
descry/_env.py,sha256=xme87ibczJ0wBvFUlZGXeyqO6lFs0Xk2hg6Uxi1mVJU,251
|
|
4
4
|
descry/_files.py,sha256=1fcXCw-tLXs9JOq67H0qHcKa0j538f65ZysH9op1HXM,1826
|
|
5
5
|
descry/_graph.py,sha256=y3PExZ2XddHo__y-X9_uTtLD9rpGuHxcE7VtJUUvkoQ,5237
|
|
6
6
|
descry/_stdlib.py,sha256=xA0hiCCspqeqD79znB6ADSMd3TjZvGkgsZlGUPqhrjI,3141
|
|
7
7
|
descry/clang_parser.py,sha256=SImFWXPRIN81mZzHOwkJkWH8JV68ihJ75Wo9kyhV35I,76089
|
|
8
|
-
descry/cli.py,sha256=
|
|
8
|
+
descry/cli.py,sha256=IY-2aDksq7Yw-mRWGYVoPG7Njqdj6Z0D6X8_lKvjDm4,14576
|
|
9
9
|
descry/cross_lang.py,sha256=tGBhUrkt3EPu0A2J8Fwi3RgneLtTbZjWiIaPlqk4tuI,14906
|
|
10
10
|
descry/dart_parser.py,sha256=yOFLNqUdSSF1tS4YPuYGZLyY5o3xKUIh5QwFQDhcI30,77634
|
|
11
11
|
descry/dotnet_parser.py,sha256=kzH28pmY6XXpOnFcghta_srarojrMmz7_I3887v0Yfo,57094
|
|
12
|
-
descry/embeddings.py,sha256=
|
|
13
|
-
descry/generate.py,sha256=
|
|
12
|
+
descry/embeddings.py,sha256=VyXynjY54soASnDcSehzvVgGW4q5ucSUOSVpmCJ1WsI,37677
|
|
13
|
+
descry/generate.py,sha256=lQLjvQoaIOk3WUfnU5LnaABbA1Lq25W_VAVIrEapyD4,1073512
|
|
14
14
|
descry/git_history.py,sha256=EGBzjorPBT3ZyUdYuCBqvb2aoueoH2X5vOd83P67Mb0,67277
|
|
15
15
|
descry/go_parser.py,sha256=j2rMjgERA1A7Ma8sS1ha-QtoD4_EipUPVqs3XbsQRrE,40802
|
|
16
|
-
descry/handlers.py,sha256=
|
|
16
|
+
descry/handlers.py,sha256=LVeMuxPodte7bwh2qGvBPl2BKTDL0sIQTHTWUpnGpJ4,114135
|
|
17
17
|
descry/java_parser.py,sha256=SK78X_Ykwkb9iLVpq9IemWLURZRF_l1XX6RFaHNkKuA,41424
|
|
18
18
|
descry/mcp_server.py,sha256=W6dLKBBB5FJ8wcuzXc_FbjOcvcvIs1ZEABoYAUDsW9I,14216
|
|
19
19
|
descry/php_parser.py,sha256=CUrfMO4lnYCmUGXR-FqkQ9kaoPsH8Gu13q3MwIMjsw4,56739
|
|
20
|
-
descry/query.py,sha256=
|
|
20
|
+
descry/query.py,sha256=Q3nuaGaW9Lr3IUCHs85Rzyf8Jjmfu2iaTM-E6GmQF8A,96195
|
|
21
21
|
descry/ruby_parser.py,sha256=LGpPaQX6QWKnPiRy9oUrDTg41QGmCWNvZ-m5tg6gF58,66233
|
|
22
22
|
descry/scip/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
23
|
descry/scip/adapter.py,sha256=vLEQrO7MDqZipDlp6xsB_-86eAKwJhUk9aVKZfXceFI,7762
|
|
@@ -54,9 +54,9 @@ descry/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
54
54
|
descry/web/server.py,sha256=ESWuPSwXA0LtCo1bwWqiQN1wjvMDbXhJ3byqlPg99FU,38475
|
|
55
55
|
descry/web/web/index.html,sha256=WvcTTkJSpdgDzYLk79YWlx2PG8d7CqwFwi2xgBH3-oc,151183
|
|
56
56
|
descry/web/web/style.css,sha256=VTQ1mC-n0BYuDlI1ghozfDG-azLqhJcpWnA0eZtts1o,35816
|
|
57
|
-
descry_codegraph-0.3.
|
|
58
|
-
descry_codegraph-0.3.
|
|
59
|
-
descry_codegraph-0.3.
|
|
60
|
-
descry_codegraph-0.3.
|
|
61
|
-
descry_codegraph-0.3.
|
|
62
|
-
descry_codegraph-0.3.
|
|
57
|
+
descry_codegraph-0.3.4.dist-info/METADATA,sha256=DDgtb-9GJ_ke43N709Q6EO_qstv411baeBP1ZRsmmlI,24021
|
|
58
|
+
descry_codegraph-0.3.4.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
59
|
+
descry_codegraph-0.3.4.dist-info/entry_points.txt,sha256=qz8s4CwO8y8SAryD9PibrMPDgAbFV2L3sIafvl91_HQ,154
|
|
60
|
+
descry_codegraph-0.3.4.dist-info/licenses/LICENSE,sha256=V8lsocOdIekq2MluAKSu-wGZBsWPBNHCgG7OBfUMlt0,1073
|
|
61
|
+
descry_codegraph-0.3.4.dist-info/licenses/THIRD-PARTY-NOTICES.md,sha256=igEI8prnwdkwsNBWpIZGKDoTs-wuGD6ijhpDLI6ks2g,1944
|
|
62
|
+
descry_codegraph-0.3.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|