Skip to content

Commit 35c9775

Browse files
committed
feat(langserver): support for importing libraries of multiple classes from a module
1 parent 85c3dc1 commit 35c9775

File tree

3 files changed

+26
-16
lines changed

3 files changed

+26
-16
lines changed

packages/language_server/src/robotcode/language_server/robotframework/diagnostics/imports_manager.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -471,22 +471,23 @@ async def get_libdoc(self) -> VariablesDoc:
471471
class LibraryMetaData:
472472
meta_version: str
473473
name: Optional[str]
474+
member_name: Optional[str]
474475
origin: Optional[str]
475476
submodule_search_locations: Optional[List[str]]
476477
by_path: bool
477478

478479
mtimes: Optional[Dict[str, int]] = None
479480

480481
@property
481-
def filepath_base(self) -> Path:
482+
def filepath_base(self) -> str:
482483
if self.by_path:
483484
if self.origin is not None:
484485
p = Path(self.origin)
485486

486-
return Path(f"{zlib.adler32(str(p.parent).encode('utf-8')):08x}_{p.stem}")
487+
return f"{zlib.adler32(str(p.parent).encode('utf-8')):08x}_{p.stem}"
487488
else:
488489
if self.name is not None:
489-
return Path(self.name.replace(".", "/"))
490+
return self.name.replace(".", "/") + (f".{self.member_name}" if self.member_name else "")
490491

491492
raise ValueError("Cannot determine filepath base.")
492493

@@ -832,13 +833,14 @@ async def get_library_meta(
832833
module_spec: Optional[ModuleSpec] = None
833834
if is_library_by_path(import_name):
834835
if (p := Path(import_name)).exists():
835-
result = LibraryMetaData(__version__, p.stem, import_name, None, True)
836+
result = LibraryMetaData(__version__, p.stem, None, import_name, None, True)
836837
else:
837838
module_spec = get_module_spec(import_name)
838839
if module_spec is not None and module_spec.origin is not None:
839840
result = LibraryMetaData(
840841
__version__,
841842
module_spec.name,
843+
module_spec.member_name,
842844
module_spec.origin,
843845
module_spec.submodule_search_locations,
844846
False,
@@ -900,13 +902,14 @@ async def get_variables_meta(
900902
module_spec: Optional[ModuleSpec] = None
901903
if is_variables_by_path(import_name):
902904
if (p := Path(import_name)).exists():
903-
result = LibraryMetaData(__version__, p.stem, import_name, None, True)
905+
result = LibraryMetaData(__version__, p.stem, None, import_name, None, True)
904906
else:
905907
module_spec = get_module_spec(import_name)
906908
if module_spec is not None and module_spec.origin is not None:
907909
result = LibraryMetaData(
908910
__version__,
909911
module_spec.name,
912+
module_spec.member_name,
910913
module_spec.origin,
911914
module_spec.submodule_search_locations,
912915
False,
@@ -1059,15 +1062,16 @@ async def _get_libdoc(name: str, args: Tuple[Any, ...], working_dir: str, base_d
10591062
)
10601063

10611064
self._logger.debug(lambda: f"Load Library {source}{args!r}")
1065+
10621066
if meta is not None:
1063-
meta_file = Path(self.lib_doc_cache_path, meta.filepath_base.with_suffix(".meta.json"))
1067+
meta_file = Path(self.lib_doc_cache_path, meta.filepath_base + ".meta.json")
10641068
if meta_file.exists():
10651069
try:
10661070
try:
10671071
saved_meta = from_json(meta_file.read_text("utf-8"), LibraryMetaData)
10681072
spec_path = None
10691073
if saved_meta == meta:
1070-
spec_path = Path(self.lib_doc_cache_path, meta.filepath_base.with_suffix(".spec.json"))
1074+
spec_path = Path(self.lib_doc_cache_path, meta.filepath_base + ".spec.json")
10711075
return from_json(
10721076
spec_path.read_text("utf-8"),
10731077
LibraryDoc,
@@ -1110,8 +1114,8 @@ async def _get_libdoc(name: str, args: Tuple[Any, ...], working_dir: str, base_d
11101114
self._logger.warning(lambda: f"stdout captured at loading library {name}{args!r}:\n{result.stdout}")
11111115
try:
11121116
if meta is not None:
1113-
meta_file = Path(self.lib_doc_cache_path, meta.filepath_base.with_suffix(".meta.json"))
1114-
spec_file = Path(self.lib_doc_cache_path, meta.filepath_base.with_suffix(".spec.json"))
1117+
meta_file = Path(self.lib_doc_cache_path, meta.filepath_base + ".meta.json")
1118+
spec_file = Path(self.lib_doc_cache_path, meta.filepath_base + ".spec.json")
11151119
spec_file.parent.mkdir(parents=True, exist_ok=True)
11161120

11171121
try:
@@ -1202,16 +1206,14 @@ async def _get_libdoc(name: str, args: Tuple[Any, ...], working_dir: str, base_d
12021206

12031207
self._logger.debug(lambda: f"Load variables {source}{args!r}")
12041208
if meta is not None:
1205-
meta_file = Path(self.variables_doc_cache_path, meta.filepath_base.with_suffix(".meta.json"))
1209+
meta_file = Path(self.variables_doc_cache_path, meta.filepath_base + ".meta.json")
12061210
if meta_file.exists():
12071211
try:
12081212
try:
12091213
saved_meta = from_json(meta_file.read_text("utf-8"), LibraryMetaData)
12101214
spec_path = None
12111215
if saved_meta == meta:
1212-
spec_path = Path(
1213-
self.variables_doc_cache_path, meta.filepath_base.with_suffix(".spec.json")
1214-
)
1216+
spec_path = Path(self.variables_doc_cache_path, meta.filepath_base + ".spec.json")
12151217
return from_json(
12161218
spec_path.read_text("utf-8"),
12171219
VariablesDoc,
@@ -1255,8 +1257,8 @@ async def _get_libdoc(name: str, args: Tuple[Any, ...], working_dir: str, base_d
12551257

12561258
try:
12571259
if meta is not None:
1258-
meta_file = Path(self.variables_doc_cache_path, meta.filepath_base.with_suffix(".meta.json"))
1259-
spec_file = Path(self.variables_doc_cache_path, meta.filepath_base.with_suffix(".spec.json"))
1260+
meta_file = Path(self.variables_doc_cache_path, meta.filepath_base + ".meta.json")
1261+
spec_file = Path(self.variables_doc_cache_path, meta.filepath_base + ".spec.json")
12601262
spec_file.parent.mkdir(parents=True, exist_ok=True)
12611263

12621264
try:

packages/language_server/src/robotcode/language_server/robotframework/diagnostics/library_doc.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,7 @@ class ModuleSpec:
835835
name: str
836836
origin: Optional[str]
837837
submodule_search_locations: Optional[List[str]]
838+
member_name: Optional[str]
838839

839840

840841
class LibraryType(Enum):
@@ -866,6 +867,7 @@ class LibraryDoc:
866867
_keywords: KeywordStore = field(default_factory=KeywordStore, compare=False)
867868
types: List[TypeDoc] = field(default_factory=list)
868869
module_spec: Optional[ModuleSpec] = None
870+
member_name: Optional[str] = None
869871
errors: Optional[List[Error]] = field(default=None, compare=False)
870872
python_path: Optional[List[str]] = None
871873
stdout: Optional[str] = field(default=None, compare=False)
@@ -1149,6 +1151,7 @@ def get_module_spec(module_name: str) -> Optional[ModuleSpec]:
11491151
import importlib.util
11501152

11511153
result = None
1154+
member_name: Optional[str] = None
11521155
while result is None:
11531156
try:
11541157
result = importlib.util.find_spec(module_name)
@@ -1160,7 +1163,9 @@ def get_module_spec(module_name: str) -> Optional[ModuleSpec]:
11601163
splitted = module_name.rsplit(".", 1)
11611164
if len(splitted) <= 1:
11621165
break
1163-
module_name = splitted[0]
1166+
module_name, m = splitted
1167+
if m:
1168+
member_name = m + "." + member_name if m and member_name is not None else m
11641169

11651170
if result is not None:
11661171
return ModuleSpec( # type: ignore
@@ -1169,6 +1174,7 @@ def get_module_spec(module_name: str) -> Optional[ModuleSpec]:
11691174
submodule_search_locations=list(result.submodule_search_locations)
11701175
if result.submodule_search_locations
11711176
else None,
1177+
member_name=member_name,
11721178
)
11731179
return None
11741180

@@ -1651,6 +1657,7 @@ def get_test_library(
16511657
version=str(lib.version) if lib is not None else "",
16521658
scope=str(lib.scope) if lib is not None else ROBOT_DEFAULT_SCOPE,
16531659
doc_format=(str(lib.doc_format) or ROBOT_DOC_FORMAT) if lib is not None else ROBOT_DOC_FORMAT,
1660+
member_name=module_spec.member_name if module_spec is not None else None,
16541661
)
16551662

16561663
if lib is not None:

packages/language_server/src/robotcode/language_server/robotframework/diagnostics/namespace.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,6 +1321,7 @@ async def _import(
13211321
e
13221322
for e in self._libraries.values()
13231323
if e.library_doc.source == entry.library_doc.source
1324+
and e.library_doc.member_name == entry.library_doc.member_name
13241325
and e.alias == entry.alias
13251326
and e.args == entry.args
13261327
]

0 commit comments

Comments
 (0)