hypergumbo-lang-scip-python 9.1.0__tar.gz → 9.2.0__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.
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/.gitignore +1 -0
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/PKG-INFO +3 -3
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/pyproject.toml +3 -3
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/src/hypergumbo_lang_scip_python/__init__.py +3 -2
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/src/hypergumbo_lang_scip_python/analyzer.py +8 -2
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/src/hypergumbo_lang_scip_python/invoke.py +29 -5
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/tests/test_scip_python_analyzer.py +5 -1
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/tests/test_scip_python_invoke.py +23 -1
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/README.md +0 -0
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/recorded/recorded_scip_python_0_6_6.py +0 -0
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/recorded/sample_project/index.scip +0 -0
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/recorded/sample_project/pkg/__init__.py +0 -0
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/recorded/sample_project/pkg/app.py +0 -0
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/recorded/sample_project/pkg/shapes.py +0 -0
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/src/hypergumbo_lang_scip_python/gate.py +0 -0
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/src/hypergumbo_lang_scip_python/translate.py +0 -0
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/tests/test_scip_python_gate.py +0 -0
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/tests/test_scip_python_recorded_fixtures.py +0 -0
- {hypergumbo_lang_scip_python-9.1.0 → hypergumbo_lang_scip_python-9.2.0}/tests/test_scip_python_translate.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: hypergumbo-lang-scip-python
|
|
3
|
-
Version: 9.
|
|
3
|
+
Version: 9.2.0
|
|
4
4
|
Summary: SCIP-backed Python analyzer for hypergumbo (scip-python / pyright integration)
|
|
5
5
|
Author: Hypergumbo contributors
|
|
6
6
|
License: AGPL-3.0-or-later
|
|
@@ -10,8 +10,8 @@ Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or l
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
|
-
Requires-Dist: hypergumbo-core==9.
|
|
14
|
-
Requires-Dist: hypergumbo-lang-mainstream==9.
|
|
13
|
+
Requires-Dist: hypergumbo-core==9.2.0
|
|
14
|
+
Requires-Dist: hypergumbo-lang-mainstream==9.2.0
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
|
|
17
17
|
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hypergumbo-lang-scip-python"
|
|
7
|
-
version = "9.
|
|
7
|
+
version = "9.2.0"
|
|
8
8
|
description = "SCIP-backed Python analyzer for hypergumbo (scip-python / pyright integration)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -18,8 +18,8 @@ classifiers = [
|
|
|
18
18
|
"Programming Language :: Python :: 3 :: Only",
|
|
19
19
|
]
|
|
20
20
|
dependencies = [
|
|
21
|
-
"hypergumbo-core==9.
|
|
22
|
-
"hypergumbo-lang-mainstream==9.
|
|
21
|
+
"hypergumbo-core==9.2.0",
|
|
22
|
+
"hypergumbo-lang-mainstream==9.2.0",
|
|
23
23
|
]
|
|
24
24
|
|
|
25
25
|
[project.entry-points."hypergumbo.analyzers"]
|
|
@@ -6,7 +6,8 @@ the analysed repository. Its parts mirror ``hypergumbo_lang_rust_analyzer``:
|
|
|
6
6
|
|
|
7
7
|
- ``invoke.py`` shells out to ``scip-python index`` to produce a SCIP blob.
|
|
8
8
|
- ``translate.py`` turns that blob into ``(symbols, edges)`` through the
|
|
9
|
-
shared importer, plus
|
|
9
|
+
shared importer, plus two things the Rust arm never needed: it drops the
|
|
10
|
+
PARAMETER and META symbols the syntax arm never models, and external
|
|
10
11
|
callees keep the receiver's MODULE.
|
|
11
12
|
- ``gate.py`` answers "did the user ask?" — flag > environment > config
|
|
12
13
|
tiers (a preference, ADR-0045 ruling 5) — and whether the binary is there.
|
|
@@ -23,7 +24,7 @@ from hypergumbo_lang_scip_python.invoke import (
|
|
|
23
24
|
)
|
|
24
25
|
from hypergumbo_lang_scip_python.translate import translate_scip_python_to_hg
|
|
25
26
|
|
|
26
|
-
__version__ = "9.
|
|
27
|
+
__version__ = "9.2.0"
|
|
27
28
|
|
|
28
29
|
#: Module paths for analyzer discovery via entry-points (ADR-0012 Step 1).
|
|
29
30
|
ANALYZER_MODULES = [
|
|
@@ -19,7 +19,11 @@ with ``backend_disabled``, so the orchestrator records an honest
|
|
|
19
19
|
writes no index, the corresponding pass-silence code travels with the skip
|
|
20
20
|
(``dependency_unavailable`` / ``pass_crashed`` / ``unreported``) — the same
|
|
21
21
|
discrimination WI-luvud gave the Rust arm. A completed run that produced
|
|
22
|
-
nothing is NOT a skip: the pass ran, and says so
|
|
22
|
+
nothing is NOT a skip: the pass ran, and says so -- as ``unreported`` when
|
|
23
|
+
the tree holds Python, since an empty index of a Python project says the
|
|
24
|
+
indexer saw no files, not that the files held nothing (WI-nijod: every run
|
|
25
|
+
indexed an empty scratch directory, and ``no_candidate_construct``, a
|
|
26
|
+
routine silence, hid it).
|
|
23
27
|
"""
|
|
24
28
|
from __future__ import annotations
|
|
25
29
|
|
|
@@ -117,7 +121,9 @@ def analyze_python_with_scip_impl(
|
|
|
117
121
|
f"scip-python backend produced no symbols for {repo_root} despite .py "
|
|
118
122
|
f"files being present — likely a project scip-python could not index.",
|
|
119
123
|
)
|
|
120
|
-
|
|
124
|
+
run.silence_reason = UNREPORTED
|
|
125
|
+
else:
|
|
126
|
+
run.silence_reason = silence_reason_for_candidates(symbols)
|
|
121
127
|
return AnalysisResult(run=run, symbols=symbols, edges=edges)
|
|
122
128
|
|
|
123
129
|
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
2
|
"""Shell-out wrapper for ``scip-python index`` (WI-nanom).
|
|
3
3
|
|
|
4
|
-
``scip-python index <project> --project-name NAME --
|
|
5
|
-
SCIP index for a Python project; pyright resolves the project's own
|
|
4
|
+
``scip-python index --cwd <project> --project-name NAME --project-version 0
|
|
5
|
+
--output FILE`` writes a SCIP index for a Python project; pyright resolves the project's own
|
|
6
6
|
modules and whatever is importable from the invoking interpreter's
|
|
7
7
|
environment (so a project analysed inside its own virtualenv gets its
|
|
8
8
|
dependencies typed too). It executes NOTHING from the project — static
|
|
9
9
|
inference only — which is why this backend's opt-in is a preference and
|
|
10
10
|
not a trust grant.
|
|
11
11
|
|
|
12
|
+
The project goes in ``--cwd``. scip-python 0.6.6 takes no positional
|
|
13
|
+
project: handed one, it ignores it, indexes its own working directory and
|
|
14
|
+
exits 0 -- and the subprocess runs in a scratch directory, so until WI-nijod
|
|
15
|
+
every run indexed that empty directory ("Total Project Files 0") and
|
|
16
|
+
returned a valid, empty index. The version is a constant: left out, it is
|
|
17
|
+
the project's git revision, and outside a git checkout the indexer crashes
|
|
18
|
+
on the first module (``normalizeNameOrVersion``). Nothing downstream reads
|
|
19
|
+
it -- translation keys on the descriptors -- and a constant keeps symbol
|
|
20
|
+
strings identical from one commit to the next.
|
|
21
|
+
|
|
12
22
|
:func:`run_scip_python_index` confirms the binary resolves, runs it with
|
|
13
23
|
stdout/stderr captured and a timeout, and returns the index bytes. Failure
|
|
14
24
|
modes map to three exceptions the analyzer turns into pass-silence codes:
|
|
@@ -26,6 +36,14 @@ from typing import Any, Callable, Optional
|
|
|
26
36
|
from hypergumbo_core.scip_python_install import SCIP_PYTHON_BINARY
|
|
27
37
|
|
|
28
38
|
|
|
39
|
+
#: V8's fatal-error text when the heap limit is reached. The default limit
|
|
40
|
+
#: (~4 GB) is too small for a large project: hypergumbo's own tree (1,712
|
|
41
|
+
#: files) aborted at 4.2 GB RSS and indexed in 306 s at 8.4 GB with
|
|
42
|
+
#: ``--max-old-space-size=9000`` (WI-nijod). The limit is the user's to set --
|
|
43
|
+
#: it is memory on their machine -- so the failure names the knob instead.
|
|
44
|
+
_NODE_HEAP_EXHAUSTED = b"JavaScript heap out of memory"
|
|
45
|
+
|
|
46
|
+
|
|
29
47
|
class ScipPythonError(Exception):
|
|
30
48
|
"""Base class for :func:`run_scip_python_index` failures."""
|
|
31
49
|
|
|
@@ -77,8 +95,9 @@ def run_scip_python_index(
|
|
|
77
95
|
)
|
|
78
96
|
output = cwd / "index.scip"
|
|
79
97
|
argv = [
|
|
80
|
-
resolved, "index", str(project),
|
|
98
|
+
resolved, "index", "--cwd", str(project),
|
|
81
99
|
"--project-name", project_name,
|
|
100
|
+
"--project-version", "0",
|
|
82
101
|
"--output", str(output),
|
|
83
102
|
]
|
|
84
103
|
run = runner if runner is not None else subprocess.run
|
|
@@ -92,9 +111,14 @@ def run_scip_python_index(
|
|
|
92
111
|
f"scip-python index timed out after {timeout_sec:.0f}s on {project}", stderr,
|
|
93
112
|
) from exc
|
|
94
113
|
if completed.returncode != 0:
|
|
114
|
+
stderr = completed.stderr or b""
|
|
115
|
+
hint = (
|
|
116
|
+
"; node ran out of heap -- raise it with NODE_OPTIONS=--max-old-space-size=<MB>"
|
|
117
|
+
if _NODE_HEAP_EXHAUSTED in stderr else ""
|
|
118
|
+
)
|
|
95
119
|
raise ScipPythonInvocationFailed(
|
|
96
|
-
f"scip-python index exited {completed.returncode} on {project}",
|
|
97
|
-
|
|
120
|
+
f"scip-python index exited {completed.returncode} on {project}{hint}",
|
|
121
|
+
stderr, returncode=completed.returncode,
|
|
98
122
|
)
|
|
99
123
|
if not output.is_file():
|
|
100
124
|
raise ScipPythonNoOutput(
|
|
@@ -100,7 +100,11 @@ class TestSuccess:
|
|
|
100
100
|
)
|
|
101
101
|
assert result.skipped is False and result.run is not None and result.symbols == []
|
|
102
102
|
assert logged and "produced no symbols" in logged[0]
|
|
103
|
-
|
|
103
|
+
# Not ``no_candidate_construct``: that says the files were read and held
|
|
104
|
+
# nothing, and it is routine, so the [passes] line never names it. An
|
|
105
|
+
# index with no symbols for a tree with Python in it is CANNOT-DETERMINE
|
|
106
|
+
# (WI-nijod: every run indexed an empty scratch dir and looked clean).
|
|
107
|
+
assert result.run.silence_reason == UNREPORTED
|
|
104
108
|
|
|
105
109
|
def test_the_default_warning_channel_is_a_user_warning(self, tmp_path: Path) -> None:
|
|
106
110
|
with pytest.warns(UserWarning, match="did not run"):
|
|
@@ -45,7 +45,13 @@ def test_a_successful_run_returns_the_index_bytes_and_the_argv_is_pinned(tmp_pat
|
|
|
45
45
|
project.mkdir()
|
|
46
46
|
out = run_scip_python_index(project, cwd=tmp_path, project_name="proj", which=_found, runner=runner)
|
|
47
47
|
assert out == b"\x00scip"
|
|
48
|
-
|
|
48
|
+
# The project travels as ``--cwd``: scip-python 0.6.6 takes no positional
|
|
49
|
+
# project and silently indexes its own working directory -- the scratch dir,
|
|
50
|
+
# which is empty -- when handed one. And the version is given: left out,
|
|
51
|
+
# it is read from git, and outside a git checkout the indexer crashes on
|
|
52
|
+
# the first module (WI-nijod).
|
|
53
|
+
assert seen["argv"] == ["/fake/bin/scip-python", "index", "--cwd", str(project),
|
|
54
|
+
"--project-name", "proj", "--project-version", "0",
|
|
49
55
|
"--output", str(tmp_path / "index.scip")]
|
|
50
56
|
assert seen["kwargs"]["cwd"] == str(tmp_path) and seen["kwargs"]["timeout"] == 900.0
|
|
51
57
|
|
|
@@ -69,3 +75,19 @@ def test_a_timeout_is_an_invocation_failure(tmp_path: Path) -> None:
|
|
|
69
75
|
def test_exit_zero_without_an_index_is_no_output(tmp_path: Path) -> None:
|
|
70
76
|
with pytest.raises(ScipPythonNoOutput, match="wrote no"):
|
|
71
77
|
run_scip_python_index(tmp_path, cwd=tmp_path, which=_found, runner=lambda argv, **kw: _Completed())
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_a_node_heap_exhaustion_names_the_remedy(tmp_path: Path) -> None:
|
|
81
|
+
"""V8's default heap (~4 GB) is too small for a large project: indexing
|
|
82
|
+
hypergumbo itself (1,712 files) aborted at 4.2 GB RSS and finished with an
|
|
83
|
+
8 GB heap (WI-nijod). The crash is an exit code 134 and a V8 trace; the
|
|
84
|
+
message says what to set."""
|
|
85
|
+
oom = b"FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory"
|
|
86
|
+
with pytest.raises(ScipPythonInvocationFailed, match="NODE_OPTIONS=--max-old-space-size") as excinfo:
|
|
87
|
+
run_scip_python_index(tmp_path, cwd=tmp_path, which=_found,
|
|
88
|
+
runner=lambda argv, **kw: _Completed(returncode=134, stderr=oom))
|
|
89
|
+
assert excinfo.value.returncode == 134 and excinfo.value.stderr == oom
|
|
90
|
+
with pytest.raises(ScipPythonInvocationFailed) as other:
|
|
91
|
+
run_scip_python_index(tmp_path, cwd=tmp_path, which=_found,
|
|
92
|
+
runner=lambda argv, **kw: _Completed(returncode=1, stderr=b"boom"))
|
|
93
|
+
assert "NODE_OPTIONS" not in str(other.value)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|