robotcode-robot 0.94.0__py3-none-any.whl → 0.95.1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- robotcode/robot/__version__.py +1 -1
- robotcode/robot/diagnostics/data_cache.py +83 -0
- robotcode/robot/diagnostics/entities.py +3 -3
- robotcode/robot/diagnostics/errors.py +1 -1
- robotcode/robot/diagnostics/imports_manager.py +100 -99
- robotcode/robot/diagnostics/keyword_finder.py +69 -43
- robotcode/robot/diagnostics/library_doc.py +197 -151
- robotcode/robot/diagnostics/model_helper.py +10 -6
- robotcode/robot/diagnostics/namespace.py +17 -28
- robotcode/robot/diagnostics/namespace_analyzer.py +120 -43
- robotcode/robot/utils/ast.py +0 -7
- robotcode/robot/utils/match.py +2 -2
- robotcode/robot/utils/robot_path.py +15 -16
- robotcode/robot/utils/stubs.py +1 -19
- robotcode/robot/utils/variables.py +35 -0
- robotcode/robot/utils/visitor.py +0 -27
- {robotcode_robot-0.94.0.dist-info → robotcode_robot-0.95.1.dist-info}/METADATA +2 -2
- robotcode_robot-0.95.1.dist-info/RECORD +32 -0
- robotcode_robot-0.94.0.dist-info/RECORD +0 -31
- {robotcode_robot-0.94.0.dist-info → robotcode_robot-0.95.1.dist-info}/WHEEL +0 -0
- {robotcode_robot-0.94.0.dist-info → robotcode_robot-0.95.1.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import ast
|
4
|
+
import functools
|
4
5
|
import hashlib
|
5
6
|
import importlib
|
6
7
|
import importlib.util
|
@@ -61,7 +62,6 @@ from robot.variables import Variables
|
|
61
62
|
from robot.variables.filesetter import PythonImporter, YamlImporter
|
62
63
|
from robot.variables.finders import VariableFinder
|
63
64
|
from robot.variables.replacer import VariableReplacer
|
64
|
-
from robot.variables.search import contains_variable
|
65
65
|
from robotcode.core.lsp.types import Position, Range
|
66
66
|
from robotcode.core.utils.path import normalized_path
|
67
67
|
from robotcode.robot.diagnostics.entities import (
|
@@ -76,12 +76,14 @@ from robotcode.robot.utils import get_robot_version
|
|
76
76
|
from robotcode.robot.utils.ast import (
|
77
77
|
cached_isinstance,
|
78
78
|
get_variable_token,
|
79
|
+
iter_nodes,
|
79
80
|
range_from_token,
|
80
81
|
strip_variable_token,
|
81
82
|
)
|
82
83
|
from robotcode.robot.utils.markdownformatter import MarkDownFormatter
|
83
84
|
from robotcode.robot.utils.match import normalize, normalize_namespace
|
84
|
-
|
85
|
+
|
86
|
+
from ..utils.variables import contains_variable
|
85
87
|
|
86
88
|
if get_robot_version() < (7, 0):
|
87
89
|
from robot.running.handlers import _PythonHandler, _PythonInitHandler # pyright: ignore[reportMissingImports]
|
@@ -197,14 +199,29 @@ def convert_from_rest(text: str) -> str:
|
|
197
199
|
return text
|
198
200
|
|
199
201
|
|
202
|
+
if get_robot_version() >= (6, 0):
|
203
|
+
|
204
|
+
@functools.lru_cache(maxsize=None)
|
205
|
+
def _get_embedded_arguments(name: str) -> Any:
|
206
|
+
try:
|
207
|
+
return EmbeddedArguments.from_name(name)
|
208
|
+
except (VariableError, DataError):
|
209
|
+
return ()
|
210
|
+
|
211
|
+
else:
|
212
|
+
|
213
|
+
@functools.lru_cache(maxsize=None)
|
214
|
+
def _get_embedded_arguments(name: str) -> Any:
|
215
|
+
try:
|
216
|
+
return EmbeddedArguments(name)
|
217
|
+
except (VariableError, DataError):
|
218
|
+
return ()
|
219
|
+
|
220
|
+
|
200
221
|
def is_embedded_keyword(name: str) -> bool:
|
201
222
|
try:
|
202
|
-
if
|
203
|
-
|
204
|
-
return True
|
205
|
-
else:
|
206
|
-
if EmbeddedArguments(name):
|
207
|
-
return True
|
223
|
+
if _get_embedded_arguments(name):
|
224
|
+
return True
|
208
225
|
except (VariableError, DataError):
|
209
226
|
return True
|
210
227
|
|
@@ -222,7 +239,11 @@ class KeywordMatcher:
|
|
222
239
|
self._can_have_embedded = can_have_embedded and not is_namespace
|
223
240
|
self._is_namespace = is_namespace
|
224
241
|
self._normalized_name: Optional[str] = None
|
225
|
-
|
242
|
+
|
243
|
+
self.embedded_arguments: Optional[EmbeddedArguments] = (
|
244
|
+
_get_embedded_arguments(self.name) or None if self._can_have_embedded else None
|
245
|
+
)
|
246
|
+
self._match_cache: Dict[str, bool] = {}
|
226
247
|
|
227
248
|
@property
|
228
249
|
def normalized_name(self) -> str:
|
@@ -231,24 +252,18 @@ class KeywordMatcher:
|
|
231
252
|
|
232
253
|
return self._normalized_name
|
233
254
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
try:
|
239
|
-
if get_robot_version() >= (6, 0):
|
240
|
-
self._embedded_arguments = EmbeddedArguments.from_name(self.name)
|
241
|
-
else:
|
242
|
-
self._embedded_arguments = EmbeddedArguments(self.name)
|
243
|
-
except (VariableError, DataError):
|
244
|
-
self._embedded_arguments = ()
|
245
|
-
else:
|
246
|
-
self._embedded_arguments = ()
|
255
|
+
if get_robot_version() >= (6, 0):
|
256
|
+
|
257
|
+
def __match_embedded(self, name: str) -> bool:
|
258
|
+
return self.embedded_arguments is not None and self.embedded_arguments.match(name) is not None
|
247
259
|
|
248
|
-
|
260
|
+
else:
|
261
|
+
|
262
|
+
def __match_embedded(self, name: str) -> bool:
|
263
|
+
return self.embedded_arguments is not None and self.embedded_arguments.name.match(name) is not None
|
249
264
|
|
250
265
|
def __eq__(self, o: object) -> bool:
|
251
|
-
if
|
266
|
+
if type(o) is KeywordMatcher:
|
252
267
|
if self._is_namespace != o._is_namespace:
|
253
268
|
return False
|
254
269
|
|
@@ -257,14 +272,11 @@ class KeywordMatcher:
|
|
257
272
|
|
258
273
|
o = o.name
|
259
274
|
|
260
|
-
if
|
275
|
+
if type(o) is not str:
|
261
276
|
return False
|
262
277
|
|
263
278
|
if self.embedded_arguments:
|
264
|
-
|
265
|
-
return self.embedded_arguments.match(o) is not None
|
266
|
-
|
267
|
-
return self.embedded_arguments.name.match(o) is not None
|
279
|
+
return self.__match_embedded(o)
|
268
280
|
|
269
281
|
return self.normalized_name == str(normalize_namespace(o) if self._is_namespace else normalize(o))
|
270
282
|
|
@@ -649,13 +661,11 @@ class KeywordDoc(SourceEntity):
|
|
649
661
|
def __str__(self) -> str:
|
650
662
|
return f"{self.name}({', '.join(str(arg) for arg in self.arguments)})"
|
651
663
|
|
652
|
-
@
|
664
|
+
@functools.cached_property
|
653
665
|
def matcher(self) -> KeywordMatcher:
|
654
|
-
|
655
|
-
self.__matcher = KeywordMatcher(self.name)
|
656
|
-
return self.__matcher
|
666
|
+
return KeywordMatcher(self.name)
|
657
667
|
|
658
|
-
@
|
668
|
+
@functools.cached_property
|
659
669
|
def is_deprecated(self) -> bool:
|
660
670
|
return self.deprecated or DEPRECATED_PATTERN.match(self.doc) is not None
|
661
671
|
|
@@ -667,13 +677,13 @@ class KeywordDoc(SourceEntity):
|
|
667
677
|
def is_library_keyword(self) -> bool:
|
668
678
|
return self.libtype == "LIBRARY"
|
669
679
|
|
670
|
-
@
|
680
|
+
@functools.cached_property
|
671
681
|
def deprecated_message(self) -> str:
|
672
682
|
if (m := DEPRECATED_PATTERN.match(self.doc)) is not None:
|
673
683
|
return m.group("message").strip()
|
674
684
|
return ""
|
675
685
|
|
676
|
-
@
|
686
|
+
@functools.cached_property
|
677
687
|
def name_range(self) -> Range:
|
678
688
|
if self.name_token is not None:
|
679
689
|
return range_from_token(self.name_token)
|
@@ -691,7 +701,7 @@ class KeywordDoc(SourceEntity):
|
|
691
701
|
|
692
702
|
return "robot:private" in self.normalized_tags()
|
693
703
|
|
694
|
-
@
|
704
|
+
@functools.cached_property
|
695
705
|
def range(self) -> Range:
|
696
706
|
if self.name_token is not None:
|
697
707
|
return range_from_token(self.name_token)
|
@@ -802,7 +812,7 @@ class KeywordDoc(SourceEntity):
|
|
802
812
|
|
803
813
|
return result
|
804
814
|
|
805
|
-
@
|
815
|
+
@functools.cached_property
|
806
816
|
def signature(self) -> str:
|
807
817
|
return (
|
808
818
|
f'({self.type}) "{self.name}": ('
|
@@ -901,20 +911,13 @@ class KeywordStore:
|
|
901
911
|
source_type: Optional[str] = None
|
902
912
|
keywords: List[KeywordDoc] = field(default_factory=list)
|
903
913
|
|
904
|
-
@property
|
905
|
-
def _matchers(self) -> Dict[KeywordMatcher, KeywordDoc]:
|
906
|
-
if not hasattr(self, "__matchers"):
|
907
|
-
self.__matchers = {v.matcher: v for v in self.keywords}
|
908
|
-
return self.__matchers
|
909
|
-
|
910
914
|
def __getitem__(self, key: str) -> KeywordDoc:
|
911
|
-
|
912
|
-
items = [(k, v) for k, v in self._matchers.items() if k == key_matcher]
|
915
|
+
items = [v for v in self.keywords if v.matcher == key]
|
913
916
|
|
914
917
|
if not items:
|
915
918
|
raise KeyError
|
916
919
|
if len(items) == 1:
|
917
|
-
return items[0]
|
920
|
+
return items[0]
|
918
921
|
|
919
922
|
if self.source and self.source_type:
|
920
923
|
file_info = ""
|
@@ -929,16 +932,14 @@ class KeywordStore:
|
|
929
932
|
else:
|
930
933
|
file_info = "File"
|
931
934
|
error = [f"{file_info} contains multiple keywords matching name '{key}':"]
|
932
|
-
names = sorted(
|
935
|
+
names = sorted(v.name for v in items)
|
933
936
|
raise KeywordError(
|
934
937
|
"\n ".join(error + names),
|
935
|
-
multiple_keywords=[v for
|
938
|
+
multiple_keywords=[v for v in items],
|
936
939
|
)
|
937
940
|
|
938
941
|
def __contains__(self, _x: object) -> bool:
|
939
|
-
|
940
|
-
_x = KeywordMatcher(str(_x))
|
941
|
-
return any(k == _x for k in self._matchers.keys())
|
942
|
+
return any(v.matcher == _x for v in self.keywords)
|
942
943
|
|
943
944
|
def __len__(self) -> int:
|
944
945
|
return len(self.keywords)
|
@@ -968,8 +969,7 @@ class KeywordStore:
|
|
968
969
|
return list(self.iter_all(key))
|
969
970
|
|
970
971
|
def iter_all(self, key: str) -> Iterable[KeywordDoc]:
|
971
|
-
|
972
|
-
yield from (v for k, v in self._matchers.items() if k == key_matcher)
|
972
|
+
yield from (v for v in self.keywords if v.matcher == key)
|
973
973
|
|
974
974
|
|
975
975
|
@dataclass
|
@@ -1282,10 +1282,12 @@ class VariablesDoc(LibraryDoc):
|
|
1282
1282
|
return result
|
1283
1283
|
|
1284
1284
|
|
1285
|
+
@functools.lru_cache(maxsize=256)
|
1285
1286
|
def is_library_by_path(path: str) -> bool:
|
1286
1287
|
return path.lower().endswith((".py", "/", os.sep))
|
1287
1288
|
|
1288
1289
|
|
1290
|
+
@functools.lru_cache(maxsize=256)
|
1289
1291
|
def is_variables_by_path(path: str) -> bool:
|
1290
1292
|
if get_robot_version() >= (6, 1):
|
1291
1293
|
return path.lower().endswith((".py", ".yml", ".yaml", ".json", "/", os.sep))
|
@@ -1656,9 +1658,8 @@ def _find_library_internal(
|
|
1656
1658
|
|
1657
1659
|
robot_variables = None
|
1658
1660
|
|
1659
|
-
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
1660
|
-
|
1661
1661
|
if contains_variable(name, "$@&%"):
|
1662
|
+
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
1662
1663
|
try:
|
1663
1664
|
name = robot_variables.replace_string(name, ignore_errors=False)
|
1664
1665
|
except DataError as error:
|
@@ -1711,6 +1712,52 @@ def get_robot_library_html_doc_str(
|
|
1711
1712
|
return output.getvalue()
|
1712
1713
|
|
1713
1714
|
|
1715
|
+
class _Logger(AbstractLogger):
|
1716
|
+
def __init__(self) -> None:
|
1717
|
+
super().__init__()
|
1718
|
+
self.messages: List[Tuple[str, str, bool]] = []
|
1719
|
+
|
1720
|
+
def write(self, message: str, level: str, html: bool = False) -> None:
|
1721
|
+
self.messages.append((message, level, html))
|
1722
|
+
|
1723
|
+
|
1724
|
+
def _import_test_library(name: str) -> Union[Any, Tuple[Any, str]]:
|
1725
|
+
with OutputCapturer(library_import=True):
|
1726
|
+
importer = Importer("test library", LOGGER)
|
1727
|
+
return importer.import_class_or_module(name, return_source=True)
|
1728
|
+
|
1729
|
+
|
1730
|
+
def _get_test_library(
|
1731
|
+
libcode: Any,
|
1732
|
+
source: str,
|
1733
|
+
name: str,
|
1734
|
+
args: Optional[Tuple[Any, ...]] = None,
|
1735
|
+
variables: Optional[Dict[str, Optional[Any]]] = None,
|
1736
|
+
create_handlers: bool = True,
|
1737
|
+
logger: Any = LOGGER,
|
1738
|
+
) -> Any:
|
1739
|
+
if get_robot_version() < (7, 0):
|
1740
|
+
libclass = robot.running.testlibraries._get_lib_class(libcode)
|
1741
|
+
lib = libclass(libcode, name, args or [], source, logger, variables)
|
1742
|
+
if create_handlers:
|
1743
|
+
lib.create_handlers()
|
1744
|
+
else:
|
1745
|
+
lib = robot.running.testlibraries.TestLibrary.from_code(
|
1746
|
+
libcode,
|
1747
|
+
name,
|
1748
|
+
source=Path(source),
|
1749
|
+
args=args or [],
|
1750
|
+
variables=variables,
|
1751
|
+
create_keywords=create_handlers,
|
1752
|
+
logger=logger,
|
1753
|
+
)
|
1754
|
+
|
1755
|
+
return lib
|
1756
|
+
|
1757
|
+
|
1758
|
+
_T = TypeVar("_T")
|
1759
|
+
|
1760
|
+
|
1714
1761
|
def get_library_doc(
|
1715
1762
|
name: str,
|
1716
1763
|
args: Optional[Tuple[Any, ...]] = None,
|
@@ -1719,45 +1766,6 @@ def get_library_doc(
|
|
1719
1766
|
command_line_variables: Optional[Dict[str, Optional[Any]]] = None,
|
1720
1767
|
variables: Optional[Dict[str, Optional[Any]]] = None,
|
1721
1768
|
) -> LibraryDoc:
|
1722
|
-
class Logger(AbstractLogger):
|
1723
|
-
def __init__(self) -> None:
|
1724
|
-
super().__init__()
|
1725
|
-
self.messages: List[Tuple[str, str, bool]] = []
|
1726
|
-
|
1727
|
-
def write(self, message: str, level: str, html: bool = False) -> None:
|
1728
|
-
self.messages.append((message, level, html))
|
1729
|
-
|
1730
|
-
def import_test_library(name: str) -> Union[Any, Tuple[Any, str]]:
|
1731
|
-
with OutputCapturer(library_import=True):
|
1732
|
-
importer = Importer("test library", LOGGER)
|
1733
|
-
return importer.import_class_or_module(name, return_source=True)
|
1734
|
-
|
1735
|
-
def get_test_library(
|
1736
|
-
libcode: Any,
|
1737
|
-
source: str,
|
1738
|
-
name: str,
|
1739
|
-
args: Optional[Tuple[Any, ...]] = None,
|
1740
|
-
variables: Optional[Dict[str, Optional[Any]]] = None,
|
1741
|
-
create_handlers: bool = True,
|
1742
|
-
logger: Any = LOGGER,
|
1743
|
-
) -> Any:
|
1744
|
-
if get_robot_version() < (7, 0):
|
1745
|
-
libclass = robot.running.testlibraries._get_lib_class(libcode)
|
1746
|
-
lib = libclass(libcode, name, args or [], source, logger, variables)
|
1747
|
-
if create_handlers:
|
1748
|
-
lib.create_handlers()
|
1749
|
-
else:
|
1750
|
-
lib = robot.running.testlibraries.TestLibrary.from_code(
|
1751
|
-
libcode,
|
1752
|
-
name,
|
1753
|
-
source=Path(source),
|
1754
|
-
args=args or [],
|
1755
|
-
variables=variables,
|
1756
|
-
create_keywords=create_handlers,
|
1757
|
-
logger=logger,
|
1758
|
-
)
|
1759
|
-
|
1760
|
-
return lib
|
1761
1769
|
|
1762
1770
|
with _std_capture() as std_capturer:
|
1763
1771
|
import_name, robot_variables = _find_library_internal(
|
@@ -1781,7 +1789,7 @@ def get_library_doc(
|
|
1781
1789
|
|
1782
1790
|
source = None
|
1783
1791
|
try:
|
1784
|
-
libcode, source =
|
1792
|
+
libcode, source = _import_test_library(import_name)
|
1785
1793
|
except (SystemExit, KeyboardInterrupt):
|
1786
1794
|
raise
|
1787
1795
|
except BaseException as e:
|
@@ -1821,13 +1829,17 @@ def get_library_doc(
|
|
1821
1829
|
|
1822
1830
|
lib = None
|
1823
1831
|
try:
|
1824
|
-
lib =
|
1832
|
+
lib = _get_test_library(
|
1825
1833
|
libcode,
|
1826
1834
|
source,
|
1827
1835
|
library_name,
|
1828
1836
|
args,
|
1829
1837
|
create_handlers=False,
|
1830
|
-
variables=
|
1838
|
+
variables=(
|
1839
|
+
robot_variables
|
1840
|
+
if robot_variables is not None
|
1841
|
+
else resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
1842
|
+
),
|
1831
1843
|
)
|
1832
1844
|
if get_robot_version() < (7, 0):
|
1833
1845
|
_ = lib.get_instance()
|
@@ -1847,7 +1859,7 @@ def get_library_doc(
|
|
1847
1859
|
|
1848
1860
|
if args:
|
1849
1861
|
try:
|
1850
|
-
lib =
|
1862
|
+
lib = _get_test_library(libcode, source, library_name, (), create_handlers=False)
|
1851
1863
|
if get_robot_version() < (7, 0):
|
1852
1864
|
_ = lib.get_instance()
|
1853
1865
|
else:
|
@@ -1862,6 +1874,10 @@ def get_library_doc(
|
|
1862
1874
|
libdoc = LibraryDoc(
|
1863
1875
|
name=library_name,
|
1864
1876
|
source=real_source,
|
1877
|
+
line_no=lib.lineno if lib is not None else -1,
|
1878
|
+
version=str(lib.version) if lib is not None else "",
|
1879
|
+
scope=str(lib.scope) if lib is not None else ROBOT_DEFAULT_SCOPE,
|
1880
|
+
doc_format=(str(lib.doc_format) or ROBOT_DOC_FORMAT) if lib is not None else ROBOT_DOC_FORMAT,
|
1865
1881
|
module_spec=(
|
1866
1882
|
module_spec
|
1867
1883
|
if module_spec is not None
|
@@ -1870,16 +1886,33 @@ def get_library_doc(
|
|
1870
1886
|
else None
|
1871
1887
|
),
|
1872
1888
|
python_path=sys.path,
|
1873
|
-
line_no=lib.lineno if lib is not None else -1,
|
1874
|
-
doc=str(lib.doc) if lib is not None else "",
|
1875
|
-
version=str(lib.version) if lib is not None else "",
|
1876
|
-
scope=str(lib.scope) if lib is not None else ROBOT_DEFAULT_SCOPE,
|
1877
|
-
doc_format=(str(lib.doc_format) or ROBOT_DOC_FORMAT) if lib is not None else ROBOT_DOC_FORMAT,
|
1878
1889
|
member_name=module_spec.member_name if module_spec is not None else None,
|
1879
1890
|
)
|
1880
1891
|
|
1881
1892
|
if lib is not None:
|
1882
1893
|
try:
|
1894
|
+
|
1895
|
+
def _get(handler: Callable[[], _T]) -> Optional[_T]:
|
1896
|
+
try:
|
1897
|
+
return handler()
|
1898
|
+
except (SystemExit, KeyboardInterrupt):
|
1899
|
+
raise
|
1900
|
+
except BaseException as e:
|
1901
|
+
errors.append(
|
1902
|
+
error_from_exception(
|
1903
|
+
e,
|
1904
|
+
source or module_spec.origin if module_spec is not None else None,
|
1905
|
+
(
|
1906
|
+
1
|
1907
|
+
if source is not None or module_spec is not None and module_spec.origin is not None
|
1908
|
+
else None
|
1909
|
+
),
|
1910
|
+
)
|
1911
|
+
)
|
1912
|
+
return None
|
1913
|
+
|
1914
|
+
libdoc.doc = _get(lambda: str(lib.doc) if lib is not None else "") or ""
|
1915
|
+
|
1883
1916
|
if get_robot_version() < (7, 0):
|
1884
1917
|
libdoc.has_listener = lib.has_listener
|
1885
1918
|
|
@@ -1909,10 +1942,10 @@ def get_library_doc(
|
|
1909
1942
|
keywords=[
|
1910
1943
|
KeywordDoc(
|
1911
1944
|
name=libdoc.name,
|
1912
|
-
arguments=[ArgumentInfo.from_robot(a) for a in kw[0].args],
|
1913
|
-
doc=kw[0].doc,
|
1914
|
-
tags=list(kw[0].tags),
|
1915
|
-
source=kw[0].source,
|
1945
|
+
arguments=_get(lambda: [ArgumentInfo.from_robot(a) for a in kw[0].args]) or [],
|
1946
|
+
doc=_get(lambda: kw[0].doc) or "",
|
1947
|
+
tags=_get(lambda: list(kw[0].tags)) or [],
|
1948
|
+
source=_get(lambda: kw[0].source) or "",
|
1916
1949
|
line_no=kw[0].lineno if kw[0].lineno is not None else -1,
|
1917
1950
|
col_offset=-1,
|
1918
1951
|
end_col_offset=-1,
|
@@ -1923,20 +1956,23 @@ def get_library_doc(
|
|
1923
1956
|
longname=f"{libdoc.name}.{kw[0].name}",
|
1924
1957
|
doc_format=str(lib.doc_format) or ROBOT_DOC_FORMAT,
|
1925
1958
|
is_initializer=True,
|
1926
|
-
arguments_spec=
|
1927
|
-
|
1959
|
+
arguments_spec=_get(
|
1960
|
+
lambda: ArgumentSpec.from_robot_argument_spec(
|
1961
|
+
kw[1].arguments if get_robot_version() < (7, 0) else kw[1].args
|
1962
|
+
)
|
1928
1963
|
),
|
1929
1964
|
)
|
1930
1965
|
for kw in init_keywords
|
1931
1966
|
]
|
1932
1967
|
)
|
1933
1968
|
|
1934
|
-
logger =
|
1935
|
-
lib.logger = logger
|
1969
|
+
logger = _Logger()
|
1936
1970
|
|
1937
1971
|
if get_robot_version() < (7, 0):
|
1972
|
+
lib.logger = logger
|
1938
1973
|
lib.create_handlers()
|
1939
1974
|
else:
|
1975
|
+
lib._logger = logger
|
1940
1976
|
lib.create_keywords()
|
1941
1977
|
|
1942
1978
|
for m in logger.messages:
|
@@ -1969,10 +2005,10 @@ def get_library_doc(
|
|
1969
2005
|
keywords=[
|
1970
2006
|
KeywordDoc(
|
1971
2007
|
name=kw[0].name,
|
1972
|
-
arguments=[ArgumentInfo.from_robot(a) for a in kw[0].args],
|
1973
|
-
doc=kw[0].doc,
|
1974
|
-
tags=list(kw[0].tags),
|
1975
|
-
source=kw[0].source,
|
2008
|
+
arguments=_get(lambda: [ArgumentInfo.from_robot(a) for a in kw[0].args]) or [],
|
2009
|
+
doc=_get(lambda: kw[0].doc) or "",
|
2010
|
+
tags=_get(lambda: list(kw[0].tags)) or [],
|
2011
|
+
source=_get(lambda: kw[0].source) or "",
|
1976
2012
|
line_no=kw[0].lineno if kw[0].lineno is not None else -1,
|
1977
2013
|
col_offset=-1,
|
1978
2014
|
end_col_offset=-1,
|
@@ -1987,21 +2023,26 @@ def get_library_doc(
|
|
1987
2023
|
is_registered_run_keyword=RUN_KW_REGISTER.is_run_keyword(libdoc.name, kw[0].name),
|
1988
2024
|
args_to_process=get_args_to_process(libdoc.name, kw[0].name),
|
1989
2025
|
deprecated=kw[0].deprecated,
|
1990
|
-
arguments_spec=(
|
1991
|
-
|
1992
|
-
|
2026
|
+
arguments_spec=_get(
|
2027
|
+
lambda: (
|
2028
|
+
ArgumentSpec.from_robot_argument_spec(
|
2029
|
+
kw[1].arguments if get_robot_version() < (7, 0) else kw[1].args
|
2030
|
+
)
|
2031
|
+
if not kw[1].is_error_handler
|
2032
|
+
else None
|
1993
2033
|
)
|
1994
|
-
if not kw[1].is_error_handler
|
1995
|
-
else None
|
1996
2034
|
),
|
1997
|
-
return_type=(
|
1998
|
-
(
|
1999
|
-
|
2000
|
-
|
2035
|
+
return_type=_get(
|
2036
|
+
lambda: (
|
2037
|
+
(
|
2038
|
+
str(kw[1].args.return_type)
|
2039
|
+
if kw[1].args.return_type is not None
|
2040
|
+
and kw[1].args.return_type is not type(None)
|
2041
|
+
else None
|
2042
|
+
)
|
2043
|
+
if get_robot_version() >= (7, 0)
|
2001
2044
|
else None
|
2002
2045
|
)
|
2003
|
-
if get_robot_version() >= (7, 0)
|
2004
|
-
else None
|
2005
2046
|
),
|
2006
2047
|
)
|
2007
2048
|
for kw in keyword_docs
|
@@ -2086,9 +2127,8 @@ def _find_variables_internal(
|
|
2086
2127
|
|
2087
2128
|
_update_env(working_dir)
|
2088
2129
|
|
2089
|
-
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
2090
|
-
|
2091
2130
|
if contains_variable(name, "$@&%"):
|
2131
|
+
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
2092
2132
|
try:
|
2093
2133
|
name = robot_variables.replace_string(name, ignore_errors=False)
|
2094
2134
|
except DataError as error:
|
@@ -2109,12 +2149,18 @@ def resolve_args(
|
|
2109
2149
|
command_line_variables: Optional[Dict[str, Optional[Any]]] = None,
|
2110
2150
|
variables: Optional[Dict[str, Optional[Any]]] = None,
|
2111
2151
|
) -> Tuple[Any, ...]:
|
2112
|
-
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
2152
|
+
# robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
2153
|
+
robot_variables: Any = None
|
2113
2154
|
|
2114
2155
|
result = []
|
2115
2156
|
for arg in args:
|
2116
2157
|
if isinstance(arg, str):
|
2117
|
-
|
2158
|
+
if contains_variable(arg, "$@&%"):
|
2159
|
+
if robot_variables is None:
|
2160
|
+
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
2161
|
+
result.append(robot_variables.replace_string(arg, ignore_errors=True))
|
2162
|
+
else:
|
2163
|
+
result.append(arg)
|
2118
2164
|
else:
|
2119
2165
|
result.append(arg)
|
2120
2166
|
|
@@ -2389,8 +2435,8 @@ def find_file(
|
|
2389
2435
|
) -> str:
|
2390
2436
|
_update_env(working_dir)
|
2391
2437
|
|
2392
|
-
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
2393
2438
|
if contains_variable(name, "$@&%"):
|
2439
|
+
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
2394
2440
|
try:
|
2395
2441
|
name = robot_variables.replace_string(name, ignore_errors=False)
|
2396
2442
|
except DataError as error:
|
@@ -2492,7 +2538,7 @@ def complete_library_import(
|
|
2492
2538
|
if e not in DEFAULT_LIBRARIES
|
2493
2539
|
]
|
2494
2540
|
|
2495
|
-
if name is not None:
|
2541
|
+
if name is not None and contains_variable(name, "$@&%"):
|
2496
2542
|
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
2497
2543
|
|
2498
2544
|
name = robot_variables.replace_string(name, ignore_errors=True)
|
@@ -2568,7 +2614,7 @@ def complete_resource_import(
|
|
2568
2614
|
|
2569
2615
|
result: List[CompleteResult] = []
|
2570
2616
|
|
2571
|
-
if name is not None:
|
2617
|
+
if name is not None and contains_variable(name, "$@&%"):
|
2572
2618
|
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
2573
2619
|
|
2574
2620
|
name = robot_variables.replace_string(name, ignore_errors=True)
|
@@ -2608,7 +2654,7 @@ def complete_variables_import(
|
|
2608
2654
|
|
2609
2655
|
result: List[CompleteResult] = []
|
2610
2656
|
|
2611
|
-
if name is not None:
|
2657
|
+
if name is not None and contains_variable(name, "$@&%"):
|
2612
2658
|
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
|
2613
2659
|
|
2614
2660
|
name = robot_variables.replace_string(name, ignore_errors=True)
|
@@ -2656,15 +2702,16 @@ def get_model_doc(
|
|
2656
2702
|
append_model_errors: bool = True,
|
2657
2703
|
) -> LibraryDoc:
|
2658
2704
|
errors: List[Error] = []
|
2659
|
-
keyword_name_nodes:
|
2660
|
-
keywords_nodes:
|
2661
|
-
for node in
|
2662
|
-
if
|
2663
|
-
|
2664
|
-
|
2665
|
-
|
2666
|
-
|
2667
|
-
|
2705
|
+
keyword_name_nodes: Dict[int, KeywordName] = {}
|
2706
|
+
keywords_nodes: Dict[int, Keyword] = {}
|
2707
|
+
for node in iter_nodes(model):
|
2708
|
+
if cached_isinstance(node, Keyword):
|
2709
|
+
node.lineno
|
2710
|
+
keywords_nodes[node.lineno] = node
|
2711
|
+
if cached_isinstance(node, KeywordName):
|
2712
|
+
keyword_name_nodes[node.lineno] = node
|
2713
|
+
|
2714
|
+
error = getattr(node, "error", None)
|
2668
2715
|
if error is not None:
|
2669
2716
|
errors.append(
|
2670
2717
|
Error(
|
@@ -2675,7 +2722,7 @@ def get_model_doc(
|
|
2675
2722
|
)
|
2676
2723
|
)
|
2677
2724
|
if append_model_errors:
|
2678
|
-
node_errors =
|
2725
|
+
node_errors = getattr(node, "errors", None)
|
2679
2726
|
if node_errors is not None:
|
2680
2727
|
for e in node_errors:
|
2681
2728
|
errors.append(
|
@@ -2688,16 +2735,15 @@ def get_model_doc(
|
|
2688
2735
|
)
|
2689
2736
|
|
2690
2737
|
def get_keyword_name_token_from_line(line: int) -> Optional[Token]:
|
2691
|
-
|
2692
|
-
|
2693
|
-
|
2694
|
-
|
2695
|
-
return None
|
2738
|
+
keyword_name = keyword_name_nodes.get(line, None)
|
2739
|
+
if keyword_name is None:
|
2740
|
+
return None
|
2741
|
+
return cast(Token, keyword_name.get_token(RobotToken.KEYWORD_NAME))
|
2696
2742
|
|
2697
2743
|
def get_argument_definitions_from_line(
|
2698
2744
|
line: int,
|
2699
2745
|
) -> List[ArgumentDefinition]:
|
2700
|
-
keyword_node =
|
2746
|
+
keyword_node = keywords_nodes.get(line, None)
|
2701
2747
|
if keyword_node is None:
|
2702
2748
|
return []
|
2703
2749
|
|