Skip to content

Commit 4f9f2eb

Browse files
Fix PythonPlugin builtin module discovery
1 parent c961e8a commit 4f9f2eb

4 files changed

Lines changed: 29 additions & 17 deletions

File tree

plugins/python/parser/pyparser/parserconfig.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class ParserConfig:
88
sys_path: List[str]
99
venv_path: str | None = None
1010
project: Project | None = None
11-
debug: bool = False
11+
debug: bool = True
1212
stack_trace: bool = False
1313
safe_env: bool = False
1414
type_hint: bool = False

plugins/python/parser/pyparser/pybuiltin.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,44 @@
22
import os
33
import importlib.util
44
import traceback
5+
import sysconfig
56
from jedi.api.classes import Name
67
from parserlog import log, bcolors
78
from parserconfig import ParserConfig
89

910
class PYBuiltin:
1011
builtin = {}
1112

13+
@staticmethod
14+
def __searchDirectory(directory: str):
15+
for root, dirs, files in os.walk(directory):
16+
for file in files:
17+
p = os.path.join(root, file)
18+
ext = os.path.splitext(p)[1]
19+
20+
if ext and ext.lower() == '.py':
21+
PYBuiltin.builtin[p] = True
22+
1223
@staticmethod
1324
def findBuiltins(config: ParserConfig):
1425
try:
26+
# Consider all Python modules in the stdlib directory builtin
27+
sysconfig_paths = sysconfig.get_paths()
28+
if "stdlib" in sysconfig_paths:
29+
PYBuiltin.__searchDirectory(sysconfig_paths["stdlib"])
30+
31+
# Locate module paths via ModuleSpec
32+
# However, this can return "frozen" and "built-in" as module origin and not the actual file
1533
# Note: Python 3.10+ required
1634
stdlib_modules = sys.stdlib_module_names
17-
1835
for e in stdlib_modules:
1936
spec = importlib.util.find_spec(e)
20-
if spec and spec.origin:
37+
if spec and spec.origin and spec.origin != "frozen" and spec.origin != "built-in":
2138
PYBuiltin.builtin[spec.origin] = True
2239

2340
if spec and spec.submodule_search_locations:
2441
for submodule_dir in spec.submodule_search_locations:
25-
for root, dirs, files in os.walk(submodule_dir):
26-
for file in files:
27-
p = os.path.join(root, file)
28-
ext = os.path.splitext(p)[1]
29-
30-
if ext and ext.lower() == '.py':
31-
PYBuiltin.builtin[p] = True
32-
42+
PYBuiltin.__searchDirectory(submodule_dir)
3343
except:
3444
log(f"{bcolors.FAIL}Failed to find Python builtins!")
3545
if config.stack_trace:

plugins/python/parser/pyparser/pyname.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ def getNodeInfo(self) -> NodeInfo:
9898
node.is_definition = self.name.is_definition()
9999
node.file_id = self.__getFileId()
100100
node.type_hint = self.__getNameTypeHint()
101+
node.type_hint = str(self.path) + ":" + str(list(map(lambda x : x.path, self.defs)))
101102
node.is_builtin = PYBuiltin.isBuiltin(self.name) or any(list(map(lambda x : PYBuiltin.isBuiltin(x.name), self.defs)))
102103

103104
parent = self.name.parent()

plugins/python/test/src/pythonparsertest.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,14 @@ class PythonParserTest : public ::testing::Test
2626

2727
model::PYName queryFile(const std::string& filename, const odb::query<model::PYName>& odb_query)
2828
{
29-
model::PYName pyname;
30-
if (m_files.count(filename))
29+
if(!m_files.count(filename))
3130
{
32-
_transaction([&, this]() {
33-
pyname = _db->query_value<model::PYName>(odb_query && odb::query<model::PYName>::file_id == m_files[filename]);
34-
});
31+
throw std::runtime_error("File " + filename + " not found!");
3532
}
3633

37-
return pyname;
34+
return _transaction([&, this]() {
35+
return _db->query_value<model::PYName>(odb_query && odb::query<model::PYName>::file_id == m_files[filename]);
36+
});
3837
}
3938

4039
private:
@@ -422,6 +421,8 @@ TEST_F(PythonParserTest, BuiltinVariable)
422421
(odb::query<model::PYName>::line_start == 6 &&
423422
odb::query<model::PYName>::value == "print"));
424423

424+
LOG(info) << pyname.type_hint;
425+
425426
EXPECT_EQ(pyname.is_builtin, true);
426427

427428
pyname = queryFile("imports.py",

0 commit comments

Comments
 (0)