Skip to content

Commit 70ed86b

Browse files
committed
Disable loading of all modules in astroid
1 parent 5366763 commit 70ed86b

3 files changed

Lines changed: 18 additions & 23 deletions

File tree

src/backend/workers/python/papyros/linting.py

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,18 @@
77
from pylint.lint import Run
88
from pylint.reporters.text import TextReporter
99

10-
# Workaround for Pyodide + Python 3.12 + astroid 2.15.8: pylint hangs
11-
# indefinitely when analyzing code that imports `re` because astroid
12-
# recursively parses the stdlib `re` package. Short-circuit astroid's
13-
# module loading for `re` (and related stdlib modules) to return a
14-
# tiny synthetic module instead.
10+
# Workaround for Pyodide + astroid: pylint hangs indefinitely when astroid
11+
# tries to recursively parse imported modules' ASTs (e.g. re, pandas).
12+
# Since we run in a single-threaded WebAssembly environment, this causes an
13+
# infinite hang. We short-circuit ALL module resolution to return synthetic
14+
# empty modules. This preserves core linting (syntax errors, undefined
15+
# variables, unused imports, style checks, custom checkers) while only
16+
# losing type-inference-based checks on imported symbols.
1517
from astroid.manager import AstroidManager as _AstroidManager
1618
from astroid.builder import AstroidBuilder as _AstroidBuilder
1719

18-
_BLOCKED_MODULES = {
19-
"re",
20-
"re._compiler",
21-
"re._parser",
22-
"re._constants",
23-
"re._casefix",
24-
"sre_compile",
25-
"sre_parse",
26-
"sre_constants",
27-
}
28-
29-
_orig_ast_from_module_name = _AstroidManager.ast_from_module_name
30-
3120
def _patched_ast_from_module_name(self, modname, context_file=None, use_cache=True):
32-
if modname in _BLOCKED_MODULES:
33-
# Return an empty synthetic module so astroid's inference short-circuits.
34-
return _AstroidBuilder(self).string_build("", modname=modname)
35-
return _orig_ast_from_module_name(self, modname, context_file=context_file, use_cache=use_cache)
21+
return _AstroidBuilder(self).string_build("", modname=modname)
3622

3723
_AstroidManager.ast_from_module_name = _patched_ast_from_module_name
3824

src/backend/workers/python/papyros/pylint_config.rc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,5 @@ const-rgx=[_A-Za-z0-9]{1,30}$
4343
# I0011 Warning locally suppressed using disable-msg
4444
# I0012 Warning locally suppressed using disable-msg
4545
# old version: disable=I0011,I0012,W0704,W0142,W0212,W0232,W0702,R0201,W0614,R0914,R0912,R0915,R0913,R0904,R0801,C0303,C0111,C0304,R0903,W0141,W0621,C0301,W0631,R0911,C1001
46-
disable=W0311,W0621,W0622,R0902,R0903,C0111,C0301,C0303,C0304,C0413,I0011
46+
disable=W0311,W0621,W0622,R0902,R0903,C0111,C0301,C0303,C0304,C0413,I0011,E0401,E0611,E1101
4747
evaluation=max(10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10), 0)

test/__tests__/state/Runner.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ const c = a + b;`;
7171
expect(Array.isArray(diagnostics)).toBe(true);
7272
}, 60000);
7373

74+
it("should lint code that uses pandas without hanging", async () => {
75+
const papyros = new Papyros();
76+
await papyros.launch();
77+
papyros.runner.programmingLanguage = ProgrammingLanguage.Python;
78+
papyros.runner.code = "import pandas as pd\ndf = pd.DataFrame({'a': [1, 2, 3]})\n";
79+
const diagnostics = await papyros.runner.lintSource();
80+
expect(Array.isArray(diagnostics)).toBe(true);
81+
}, 60000);
82+
7483
it("should be able to handle sleep", async () => {
7584
const papyros = new Papyros();
7685
await papyros.launch();

0 commit comments

Comments
 (0)