robotcode-robot 0.94.0__py3-none-any.whl → 0.95.0__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 +1 -1
- robotcode/robot/diagnostics/errors.py +1 -1
- robotcode/robot/diagnostics/imports_manager.py +100 -99
- robotcode/robot/diagnostics/keyword_finder.py +51 -24
- robotcode/robot/diagnostics/library_doc.py +165 -105
- robotcode/robot/diagnostics/model_helper.py +7 -3
- robotcode/robot/diagnostics/namespace.py +17 -28
- robotcode/robot/diagnostics/namespace_analyzer.py +120 -43
- robotcode/robot/utils/match.py +2 -2
- robotcode/robot/utils/robot_path.py +14 -15
- robotcode/robot/utils/variables.py +35 -0
- {robotcode_robot-0.94.0.dist-info → robotcode_robot-0.95.0.dist-info}/METADATA +2 -2
- robotcode_robot-0.95.0.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.0.dist-info}/WHEEL +0 -0
- {robotcode_robot-0.94.0.dist-info → robotcode_robot-0.95.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -8,7 +8,7 @@ from dataclasses import dataclass
|
|
8
8
|
from io import StringIO
|
9
9
|
from pathlib import Path
|
10
10
|
from tokenize import TokenError, generate_tokens
|
11
|
-
from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Optional, Set, Tuple, Union, cast
|
11
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Union, cast
|
12
12
|
|
13
13
|
from robot.errors import VariableError
|
14
14
|
from robot.parsing.lexer.tokens import Token
|
@@ -28,9 +28,8 @@ from robot.parsing.model.statements import (
|
|
28
28
|
Variable,
|
29
29
|
VariablesImport,
|
30
30
|
)
|
31
|
-
from robot.utils.escaping import
|
31
|
+
from robot.utils.escaping import unescape
|
32
32
|
from robot.variables.finders import NOT_FOUND, NumberFinder
|
33
|
-
from robot.variables.search import contains_variable, is_scalar_assign, is_variable, search_variable
|
34
33
|
from robotcode.core.concurrent import check_current_task_canceled
|
35
34
|
from robotcode.core.lsp.types import (
|
36
35
|
CodeDescription,
|
@@ -43,6 +42,7 @@ from robotcode.core.lsp.types import (
|
|
43
42
|
Range,
|
44
43
|
)
|
45
44
|
from robotcode.core.uri import Uri
|
45
|
+
from robotcode.core.utils.logging import LoggingDescriptor
|
46
46
|
|
47
47
|
from ..utils import get_robot_version
|
48
48
|
from ..utils.ast import (
|
@@ -53,11 +53,13 @@ from ..utils.ast import (
|
|
53
53
|
strip_variable_token,
|
54
54
|
tokenize_variables,
|
55
55
|
)
|
56
|
+
from ..utils.variables import contains_variable, is_scalar_assign, is_variable, search_variable, split_from_equals
|
56
57
|
from ..utils.visitor import Visitor
|
57
58
|
from .entities import (
|
58
59
|
ArgumentDefinition,
|
59
60
|
EnvironmentVariableDefinition,
|
60
61
|
GlobalVariableDefinition,
|
62
|
+
InvalidVariableError,
|
61
63
|
LibraryEntry,
|
62
64
|
LocalVariableDefinition,
|
63
65
|
TestVariableDefinition,
|
@@ -94,6 +96,9 @@ class AnalyzerResult:
|
|
94
96
|
|
95
97
|
|
96
98
|
class NamespaceAnalyzer(Visitor):
|
99
|
+
|
100
|
+
_logger = LoggingDescriptor()
|
101
|
+
|
97
102
|
def __init__(
|
98
103
|
self,
|
99
104
|
model: ast.AST,
|
@@ -126,8 +131,11 @@ class NamespaceAnalyzer(Visitor):
|
|
126
131
|
self._overridden_variables: Dict[VariableDefinition, VariableDefinition] = {}
|
127
132
|
|
128
133
|
self._in_setting = False
|
134
|
+
self._in_block_setting = False
|
129
135
|
|
130
136
|
self._suite_variables = self._variables.copy()
|
137
|
+
self._block_variables: Optional[Dict[VariableMatcher, VariableDefinition]] = None
|
138
|
+
self._end_block_handlers: Optional[List[Callable[[], None]]] = None
|
131
139
|
|
132
140
|
def run(self) -> AnalyzerResult:
|
133
141
|
self._diagnostics = []
|
@@ -146,10 +154,11 @@ class NamespaceAnalyzer(Visitor):
|
|
146
154
|
except BaseException as e:
|
147
155
|
self._append_diagnostics(
|
148
156
|
range_from_node(self._model),
|
149
|
-
message=f"Fatal: can't analyze namespace '{e}'
|
157
|
+
message=f"Fatal: can't analyze namespace '{e}'.",
|
150
158
|
severity=DiagnosticSeverity.ERROR,
|
151
159
|
code=type(e).__qualname__,
|
152
160
|
)
|
161
|
+
self._logger.exception(e)
|
153
162
|
|
154
163
|
return AnalyzerResult(
|
155
164
|
self._diagnostics,
|
@@ -379,6 +388,15 @@ class NamespaceAnalyzer(Visitor):
|
|
379
388
|
finally:
|
380
389
|
self._in_setting = False
|
381
390
|
|
391
|
+
def _visit_block_settings_statement(
|
392
|
+
self, node: Statement, severity: DiagnosticSeverity = DiagnosticSeverity.ERROR
|
393
|
+
) -> None:
|
394
|
+
self._in_block_setting = True
|
395
|
+
try:
|
396
|
+
self._visit_settings_statement(node, severity)
|
397
|
+
finally:
|
398
|
+
self._in_block_setting = False
|
399
|
+
|
382
400
|
def _analyze_token_expression_variables(
|
383
401
|
self, token: Token, severity: DiagnosticSeverity = DiagnosticSeverity.ERROR
|
384
402
|
) -> None:
|
@@ -476,7 +494,7 @@ class NamespaceAnalyzer(Visitor):
|
|
476
494
|
range=range_from_token(var_token),
|
477
495
|
message=f"Environment variable '{var.name}' not found.",
|
478
496
|
severity=severity,
|
479
|
-
code=Error.
|
497
|
+
code=Error.ENVIRONMENT_VARIABLE_NOT_FOUND,
|
480
498
|
)
|
481
499
|
|
482
500
|
if var.type == VariableDefinitionType.ENVIRONMENT_VARIABLE:
|
@@ -531,6 +549,20 @@ class NamespaceAnalyzer(Visitor):
|
|
531
549
|
)
|
532
550
|
)
|
533
551
|
|
552
|
+
KEYWORDS_WITH_EXPRESSIONS = [
|
553
|
+
"BuiltIn.Evaluate",
|
554
|
+
"BuiltIn.Should Be True",
|
555
|
+
"BuiltIn.Should Not Be True",
|
556
|
+
"BuiltIn.Skip If",
|
557
|
+
"BuiltIn.Continue For Loop If",
|
558
|
+
"BuiltIn.Exit For Loop If",
|
559
|
+
"BuiltIn.Return From Keyword If",
|
560
|
+
"BuiltIn.Run Keyword And Return If",
|
561
|
+
"BuiltIn.Pass Execution If",
|
562
|
+
"BuiltIn.Run Keyword If",
|
563
|
+
"BuiltIn.Run Keyword Unless",
|
564
|
+
]
|
565
|
+
|
534
566
|
def _analyze_keyword_call(
|
535
567
|
self,
|
536
568
|
node: ast.AST,
|
@@ -552,13 +584,11 @@ class NamespaceAnalyzer(Visitor):
|
|
552
584
|
if not allow_variables and not is_not_variable_token(keyword_token):
|
553
585
|
return None
|
554
586
|
|
555
|
-
result = self._finder.find_keyword(keyword, raise_keyword_error=False
|
587
|
+
result = self._finder.find_keyword(keyword, raise_keyword_error=False)
|
556
588
|
|
557
|
-
if result is None:
|
589
|
+
if result is not None and self._finder.result_bdd_prefix:
|
558
590
|
keyword_token = ModelHelper.strip_bdd_prefix(self._namespace, keyword_token)
|
559
591
|
|
560
|
-
result = self._finder.find_keyword(keyword, raise_keyword_error=False)
|
561
|
-
|
562
592
|
kw_range = range_from_token(keyword_token)
|
563
593
|
|
564
594
|
if keyword:
|
@@ -710,19 +740,7 @@ class NamespaceAnalyzer(Visitor):
|
|
710
740
|
)
|
711
741
|
|
712
742
|
if result is not None:
|
713
|
-
if result.longname in
|
714
|
-
"BuiltIn.Evaluate",
|
715
|
-
"BuiltIn.Should Be True",
|
716
|
-
"BuiltIn.Should Not Be True",
|
717
|
-
"BuiltIn.Skip If",
|
718
|
-
"BuiltIn.Continue For Loop If",
|
719
|
-
"BuiltIn.Exit For Loop If",
|
720
|
-
"BuiltIn.Return From Keyword If",
|
721
|
-
"BuiltIn.Run Keyword And Return If",
|
722
|
-
"BuiltIn.Pass Execution If",
|
723
|
-
"BuiltIn.Run Keyword If",
|
724
|
-
"BuiltIn.Run Keyword Unless",
|
725
|
-
]:
|
743
|
+
if result.longname in self.KEYWORDS_WITH_EXPRESSIONS:
|
726
744
|
tokens = argument_tokens
|
727
745
|
if tokens and (token := tokens[0]):
|
728
746
|
self._analyze_token_expression_variables(token)
|
@@ -896,7 +914,29 @@ class NamespaceAnalyzer(Visitor):
|
|
896
914
|
|
897
915
|
if keyword_token is not None and keyword_token.value and keyword_token.value.upper() not in ("", "NONE"):
|
898
916
|
self._analyze_token_variables(keyword_token)
|
899
|
-
self.
|
917
|
+
self._visit_block_settings_statement(node)
|
918
|
+
|
919
|
+
self._analyze_keyword_call(
|
920
|
+
node,
|
921
|
+
keyword_token,
|
922
|
+
[e for e in node.get_tokens(Token.ARGUMENT)],
|
923
|
+
allow_variables=True,
|
924
|
+
ignore_errors_if_contains_variables=True,
|
925
|
+
)
|
926
|
+
|
927
|
+
def visit_Teardown(self, node: Fixture) -> None: # noqa: N802
|
928
|
+
keyword_token = node.get_token(Token.NAME)
|
929
|
+
|
930
|
+
# TODO: calculate possible variables in NAME
|
931
|
+
|
932
|
+
if keyword_token is not None and keyword_token.value and keyword_token.value.upper() not in ("", "NONE"):
|
933
|
+
|
934
|
+
def _handler() -> None:
|
935
|
+
self._analyze_token_variables(keyword_token)
|
936
|
+
self._analyze_statement_variables(node)
|
937
|
+
|
938
|
+
if self._end_block_handlers is not None:
|
939
|
+
self._end_block_handlers.append(_handler)
|
900
940
|
|
901
941
|
self._analyze_keyword_call(
|
902
942
|
node,
|
@@ -984,9 +1024,15 @@ class NamespaceAnalyzer(Visitor):
|
|
984
1024
|
self._current_testcase_or_keyword_name = node.name
|
985
1025
|
old_variables = self._variables
|
986
1026
|
self._variables = self._variables.copy()
|
1027
|
+
self._end_block_handlers = []
|
987
1028
|
try:
|
988
1029
|
self.generic_visit(node)
|
1030
|
+
|
1031
|
+
for handler in self._end_block_handlers:
|
1032
|
+
handler()
|
1033
|
+
|
989
1034
|
finally:
|
1035
|
+
self._end_block_handlers = None
|
990
1036
|
self._variables = old_variables
|
991
1037
|
self._current_testcase_or_keyword_name = None
|
992
1038
|
self._template = None
|
@@ -1029,13 +1075,21 @@ class NamespaceAnalyzer(Visitor):
|
|
1029
1075
|
self._current_testcase_or_keyword_name = node.name
|
1030
1076
|
old_variables = self._variables
|
1031
1077
|
self._variables = self._variables.copy()
|
1078
|
+
self._end_block_handlers = []
|
1032
1079
|
try:
|
1033
1080
|
arguments = next((v for v in node.body if isinstance(v, Arguments)), None)
|
1034
1081
|
if arguments is not None:
|
1035
1082
|
self._visit_Arguments(arguments)
|
1083
|
+
self._block_variables = self._variables.copy()
|
1036
1084
|
|
1037
1085
|
self.generic_visit(node)
|
1086
|
+
|
1087
|
+
for handler in self._end_block_handlers:
|
1088
|
+
handler()
|
1089
|
+
|
1038
1090
|
finally:
|
1091
|
+
self._end_block_handlers = None
|
1092
|
+
self._block_variables = None
|
1039
1093
|
self._variables = old_variables
|
1040
1094
|
self._current_testcase_or_keyword_name = None
|
1041
1095
|
self._current_keyword_doc = None
|
@@ -1132,7 +1186,7 @@ class NamespaceAnalyzer(Visitor):
|
|
1132
1186
|
)
|
1133
1187
|
)
|
1134
1188
|
|
1135
|
-
except VariableError:
|
1189
|
+
except (VariableError, InvalidVariableError):
|
1136
1190
|
pass
|
1137
1191
|
|
1138
1192
|
def _analyze_assign_statement(self, node: Statement) -> None:
|
@@ -1172,7 +1226,7 @@ class NamespaceAnalyzer(Visitor):
|
|
1172
1226
|
)
|
1173
1227
|
)
|
1174
1228
|
|
1175
|
-
except VariableError:
|
1229
|
+
except (VariableError, InvalidVariableError):
|
1176
1230
|
pass
|
1177
1231
|
|
1178
1232
|
def visit_InlineIfHeader(self, node: Statement) -> None: # noqa: N802
|
@@ -1186,7 +1240,7 @@ class NamespaceAnalyzer(Visitor):
|
|
1186
1240
|
variables = node.get_tokens(Token.VARIABLE)
|
1187
1241
|
for variable in variables:
|
1188
1242
|
variable_token = self._get_variable_token(variable)
|
1189
|
-
if variable_token is not None:
|
1243
|
+
if variable_token is not None and is_variable(variable_token.value):
|
1190
1244
|
existing_var = self._find_variable(variable_token.value)
|
1191
1245
|
|
1192
1246
|
if existing_var is None or existing_var.type not in [
|
@@ -1248,7 +1302,7 @@ class NamespaceAnalyzer(Visitor):
|
|
1248
1302
|
source=self._namespace.source,
|
1249
1303
|
)
|
1250
1304
|
|
1251
|
-
except VariableError:
|
1305
|
+
except (VariableError, InvalidVariableError):
|
1252
1306
|
pass
|
1253
1307
|
|
1254
1308
|
def _format_template(self, template: str, arguments: Tuple[str, ...]) -> Tuple[str, Tuple[str, ...]]:
|
@@ -1351,7 +1405,7 @@ class NamespaceAnalyzer(Visitor):
|
|
1351
1405
|
self._visit_settings_statement(node, DiagnosticSeverity.HINT)
|
1352
1406
|
|
1353
1407
|
def visit_Timeout(self, node: Statement) -> None: # noqa: N802
|
1354
|
-
self.
|
1408
|
+
self._visit_block_settings_statement(node)
|
1355
1409
|
|
1356
1410
|
def visit_SingleValue(self, node: Statement) -> None: # noqa: N802
|
1357
1411
|
self._visit_settings_statement(node, DiagnosticSeverity.HINT)
|
@@ -1399,19 +1453,35 @@ class NamespaceAnalyzer(Visitor):
|
|
1399
1453
|
code=Error.DEPRECATED_HEADER,
|
1400
1454
|
)
|
1401
1455
|
|
1402
|
-
|
1403
|
-
self._analyze_statement_variables(node)
|
1456
|
+
if get_robot_version() >= (7, 0):
|
1404
1457
|
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
self.
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
)
|
1458
|
+
def visit_ReturnSetting(self, node: Statement) -> None: # noqa: N802
|
1459
|
+
|
1460
|
+
def _handler() -> None:
|
1461
|
+
self._analyze_statement_variables(node)
|
1462
|
+
|
1463
|
+
if self._end_block_handlers is not None:
|
1464
|
+
self._end_block_handlers.append(_handler)
|
1465
|
+
|
1466
|
+
if get_robot_version() >= (7, 0):
|
1467
|
+
token = node.get_token(Token.RETURN_SETTING)
|
1468
|
+
if token is not None and token.error:
|
1469
|
+
self._append_diagnostics(
|
1470
|
+
range=range_from_node_or_token(node, token),
|
1471
|
+
message=token.error,
|
1472
|
+
severity=DiagnosticSeverity.WARNING,
|
1473
|
+
tags=[DiagnosticTag.DEPRECATED],
|
1474
|
+
code=Error.DEPRECATED_RETURN_SETTING,
|
1475
|
+
)
|
1476
|
+
|
1477
|
+
else:
|
1478
|
+
|
1479
|
+
def visit_Return(self, node: Statement) -> None: # noqa: N802
|
1480
|
+
def _handler() -> None:
|
1481
|
+
self._analyze_statement_variables(node)
|
1482
|
+
|
1483
|
+
if self._end_block_handlers is not None:
|
1484
|
+
self._end_block_handlers.append(_handler)
|
1415
1485
|
|
1416
1486
|
def _check_import_name(self, value: Optional[str], node: ast.AST, type: str) -> None:
|
1417
1487
|
if not value:
|
@@ -1540,11 +1610,18 @@ class NamespaceAnalyzer(Visitor):
|
|
1540
1610
|
default_value=default_value or None,
|
1541
1611
|
)
|
1542
1612
|
|
1543
|
-
vars =
|
1613
|
+
vars = (
|
1614
|
+
self._block_variables
|
1615
|
+
if self._block_variables and self._in_block_setting
|
1616
|
+
else self._suite_variables if self._in_setting else self._variables
|
1617
|
+
)
|
1544
1618
|
|
1545
|
-
|
1619
|
+
try:
|
1620
|
+
matcher = VariableMatcher(name)
|
1546
1621
|
|
1547
|
-
|
1622
|
+
return vars.get(matcher, None)
|
1623
|
+
except (VariableError, InvalidVariableError):
|
1624
|
+
return None
|
1548
1625
|
|
1549
1626
|
def _is_number(self, name: str) -> bool:
|
1550
1627
|
if name.startswith("$"):
|
robotcode/robot/utils/match.py
CHANGED
@@ -3,13 +3,13 @@ from functools import lru_cache
|
|
3
3
|
_transform_table = str.maketrans("", "", "_ ")
|
4
4
|
|
5
5
|
|
6
|
-
@lru_cache(maxsize=
|
6
|
+
@lru_cache(maxsize=None)
|
7
7
|
def normalize(text: str) -> str:
|
8
8
|
# return text.lower().replace("_", "").replace(" ", "")
|
9
9
|
return text.casefold().translate(_transform_table)
|
10
10
|
|
11
11
|
|
12
|
-
@lru_cache(maxsize=
|
12
|
+
@lru_cache(maxsize=None)
|
13
13
|
def normalize_namespace(text: str) -> str:
|
14
14
|
return text.lower().replace(" ", "")
|
15
15
|
|
@@ -1,21 +1,11 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
1
|
import sys
|
4
2
|
from os import PathLike
|
5
3
|
from pathlib import Path
|
6
4
|
from typing import Optional, Union
|
7
5
|
|
8
6
|
|
9
|
-
def find_file(
|
10
|
-
path: Union[Path, PathLike[str], str],
|
11
|
-
basedir: Union[Path, PathLike[str], str] = ".",
|
12
|
-
file_type: Optional[str] = None,
|
13
|
-
) -> str:
|
14
|
-
return find_file_ex(path, basedir, file_type)
|
15
|
-
|
16
|
-
|
17
7
|
def find_file_ex(
|
18
|
-
path: Union[Path, PathLike[str], str],
|
8
|
+
path: Union[Path, "PathLike[str]", str],
|
19
9
|
basedir: Union[Path, PathLike[str], str] = ".",
|
20
10
|
file_type: Optional[str] = None,
|
21
11
|
) -> str:
|
@@ -25,6 +15,7 @@ def find_file_ex(
|
|
25
15
|
ret = _find_absolute_path(path) if path.is_absolute() else _find_relative_path(path, basedir)
|
26
16
|
if ret:
|
27
17
|
return str(ret)
|
18
|
+
|
28
19
|
default = file_type or "File"
|
29
20
|
|
30
21
|
file_type = (
|
@@ -40,15 +31,23 @@ def find_file_ex(
|
|
40
31
|
raise DataError("%s '%s' does not exist." % (file_type, path))
|
41
32
|
|
42
33
|
|
43
|
-
def
|
34
|
+
def find_file(
|
35
|
+
path: Union[Path, "PathLike[str]", str],
|
36
|
+
basedir: Union[Path, PathLike[str], str] = ".",
|
37
|
+
file_type: Optional[str] = None,
|
38
|
+
) -> str:
|
39
|
+
return find_file_ex(path, basedir, file_type)
|
40
|
+
|
41
|
+
|
42
|
+
def _find_absolute_path(path: Union[Path, "PathLike[str]", str]) -> Optional[str]:
|
44
43
|
if _is_valid_file(path):
|
45
44
|
return str(path)
|
46
45
|
return None
|
47
46
|
|
48
47
|
|
49
48
|
def _find_relative_path(
|
50
|
-
path: Union[Path, PathLike[str], str],
|
51
|
-
basedir: Union[Path, PathLike[str], str],
|
49
|
+
path: Union[Path, "PathLike[str]", str],
|
50
|
+
basedir: Union[Path, "PathLike[str]", str],
|
52
51
|
) -> Optional[str]:
|
53
52
|
for base in [basedir, *sys.path]:
|
54
53
|
if not base:
|
@@ -65,6 +64,6 @@ def _find_relative_path(
|
|
65
64
|
return None
|
66
65
|
|
67
66
|
|
68
|
-
def _is_valid_file(path: Union[Path, PathLike[str], str]) -> bool:
|
67
|
+
def _is_valid_file(path: Union[Path, "PathLike[str]", str]) -> bool:
|
69
68
|
path = Path(path)
|
70
69
|
return path.is_file() or (path.is_dir() and Path(path, "__init__.py").is_fifo())
|
@@ -1,3 +1,13 @@
|
|
1
|
+
import functools
|
2
|
+
from typing import Optional, Tuple, cast
|
3
|
+
|
4
|
+
from robot.utils.escaping import split_from_equals as robot_split_from_equals
|
5
|
+
from robot.variables.search import VariableMatch as RobotVariableMatch
|
6
|
+
from robot.variables.search import contains_variable as robot_contains_variable
|
7
|
+
from robot.variables.search import is_scalar_assign as robot_is_scalar_assign
|
8
|
+
from robot.variables.search import is_variable as robot_is_variable
|
9
|
+
from robot.variables.search import search_variable as robot_search_variable
|
10
|
+
|
1
11
|
BUILTIN_VARIABLES = [
|
2
12
|
"${CURDIR}",
|
3
13
|
"${EMPTY}",
|
@@ -35,3 +45,28 @@ BUILTIN_VARIABLES = [
|
|
35
45
|
"${DEBUG_FILE}",
|
36
46
|
"${OUTPUT_DIR}",
|
37
47
|
]
|
48
|
+
|
49
|
+
|
50
|
+
@functools.lru_cache(maxsize=512)
|
51
|
+
def contains_variable(string: str, identifiers: str = "$@&") -> bool:
|
52
|
+
return cast(bool, robot_contains_variable(string, identifiers))
|
53
|
+
|
54
|
+
|
55
|
+
@functools.lru_cache(maxsize=512)
|
56
|
+
def is_scalar_assign(string: str, allow_assign_mark: bool = False) -> bool:
|
57
|
+
return cast(bool, robot_is_scalar_assign(string, allow_assign_mark))
|
58
|
+
|
59
|
+
|
60
|
+
@functools.lru_cache(maxsize=512)
|
61
|
+
def is_variable(string: str, identifiers: str = "$@&") -> bool:
|
62
|
+
return cast(bool, robot_is_variable(string, identifiers))
|
63
|
+
|
64
|
+
|
65
|
+
@functools.lru_cache(maxsize=512)
|
66
|
+
def search_variable(string: str, identifiers: str = "$@&%*", ignore_errors: bool = False) -> RobotVariableMatch:
|
67
|
+
return robot_search_variable(string, identifiers, ignore_errors)
|
68
|
+
|
69
|
+
|
70
|
+
@functools.lru_cache(maxsize=512)
|
71
|
+
def split_from_equals(string: str) -> Tuple[str, Optional[str]]:
|
72
|
+
return cast(Tuple[str, Optional[str]], robot_split_from_equals(string))
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: robotcode-robot
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.95.0
|
4
4
|
Summary: Support classes for RobotCode for handling Robot Framework projects.
|
5
5
|
Project-URL: Homepage, https://robotcode.io
|
6
6
|
Project-URL: Donate, https://opencollective.com/robotcode
|
@@ -26,7 +26,7 @@ Classifier: Topic :: Utilities
|
|
26
26
|
Classifier: Typing :: Typed
|
27
27
|
Requires-Python: >=3.8
|
28
28
|
Requires-Dist: platformdirs<4.2.0,>=3.2.0
|
29
|
-
Requires-Dist: robotcode-core==0.
|
29
|
+
Requires-Dist: robotcode-core==0.95.0
|
30
30
|
Requires-Dist: robotframework>=4.1.0
|
31
31
|
Requires-Dist: tomli>=1.1.0; python_version < '3.11'
|
32
32
|
Description-Content-Type: text/markdown
|
@@ -0,0 +1,32 @@
|
|
1
|
+
robotcode/robot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
robotcode/robot/__version__.py,sha256=1KBvo1_4ig2ZeMfCvFApYtfDll8Ysfu6h45ByRERz1E,23
|
3
|
+
robotcode/robot/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
|
4
|
+
robotcode/robot/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
+
robotcode/robot/config/loader.py,sha256=bNJwr_XdCoUzpG2ag0BH33PIfiCwn0GMxn7q_Sw3zOk,8103
|
6
|
+
robotcode/robot/config/model.py,sha256=sgr6-4_E06g-yIXW41Z-NtIXZ_7JMmR5WvUD7kTUqu4,89106
|
7
|
+
robotcode/robot/config/utils.py,sha256=xY-LH31BidWzonpvSrle-4HvKrp02I7IRqU2JwlL4Ls,2931
|
8
|
+
robotcode/robot/diagnostics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
robotcode/robot/diagnostics/data_cache.py,sha256=Wge9HuxSUiBVMmrmlsYSMmG2ad7f3Texwox0Dm8lN7U,2969
|
10
|
+
robotcode/robot/diagnostics/diagnostics_modifier.py,sha256=3dDsu8-ET6weIvv7Sk3IQaPYFNxnXUs8Y7gpGTjfOBs,9796
|
11
|
+
robotcode/robot/diagnostics/document_cache_helper.py,sha256=n903UxVXM4Uq4fPxN5s-dugQAKcWUwf4Nw4q0CJV7aw,23902
|
12
|
+
robotcode/robot/diagnostics/entities.py,sha256=dA5jTt1pSCLvWWC_DkHPjfBZmnS80dVt3gZptASR3Uo,11008
|
13
|
+
robotcode/robot/diagnostics/errors.py,sha256=vRH7HiZOfQIC-L7ys2Bj9ULYxLpUH7I03qJRSkEx08k,1813
|
14
|
+
robotcode/robot/diagnostics/imports_manager.py,sha256=lmwg_wYFZLNx_o0u856_5JihXHPLBei2vfr6Puhlm-c,59127
|
15
|
+
robotcode/robot/diagnostics/keyword_finder.py,sha256=O3EHA93ZGqNI-TocvSYAmWz7INWakhhfBeiXq57wepM,17421
|
16
|
+
robotcode/robot/diagnostics/library_doc.py,sha256=6j_7qy5O-dFAbVmwjn_sDkBHrFvghJwu0fvPcLhJnMw,100901
|
17
|
+
robotcode/robot/diagnostics/model_helper.py,sha256=-dRXt__coz-m2HaMLTqgQEUF6ylH0QZxj5hUv2DBJyQ,31017
|
18
|
+
robotcode/robot/diagnostics/namespace.py,sha256=Y6HDBKIYyCc3qCg2TT-orB9mASd-Ii4fkZuIpcFQMbk,75417
|
19
|
+
robotcode/robot/diagnostics/namespace_analyzer.py,sha256=NlvfAEYH_GyE1ZQ1JH9vR9yPfki3Xmw9TyNEc-B0mtM,74067
|
20
|
+
robotcode/robot/diagnostics/workspace_config.py,sha256=3SoewUj_LZB1Ki5hXM8oxQpJr6vyiog66SUw-ibODSA,2478
|
21
|
+
robotcode/robot/utils/__init__.py,sha256=OjNPMn_XSnfaMCyKd8Kmq6vlRt6mIGlzW4qiiD3ykUg,447
|
22
|
+
robotcode/robot/utils/ast.py,sha256=_ob36KHFY776n9dhljn0xAWVoUDb7pV86fPW40vIirY,11266
|
23
|
+
robotcode/robot/utils/markdownformatter.py,sha256=Cj4NjComTcNZf8uuezvtBbZqPMLjS237RknMopZYETk,11418
|
24
|
+
robotcode/robot/utils/match.py,sha256=Vtz1ueT6DIZZ4hKyXgvTg1A3x2puBwHgvjw1oAYBn5w,632
|
25
|
+
robotcode/robot/utils/robot_path.py,sha256=6XfNjnIVQREwgUR7r0eUMHgLnduXKTpHWy2Dvs_MbPo,1763
|
26
|
+
robotcode/robot/utils/stubs.py,sha256=6-DMI_CQVJHDgG13t-zINKGCRb_Q7MQPm0_AkfhAEvE,748
|
27
|
+
robotcode/robot/utils/variables.py,sha256=XNPUDpghGy_f_Fne9lJ4OST-kFi-72Nrr0yJUu6f_Oc,2169
|
28
|
+
robotcode/robot/utils/visitor.py,sha256=V3ZtpzrCilKpLQfDXUcjapd2uGq12XxbHppNPOl_Jns,3080
|
29
|
+
robotcode_robot-0.95.0.dist-info/METADATA,sha256=ucoFRI1dSKtBhbXI3KtxfGXyEbIXRUHxBoe7LURhGVY,2240
|
30
|
+
robotcode_robot-0.95.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
31
|
+
robotcode_robot-0.95.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
|
32
|
+
robotcode_robot-0.95.0.dist-info/RECORD,,
|
@@ -1,31 +0,0 @@
|
|
1
|
-
robotcode/robot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
robotcode/robot/__version__.py,sha256=BbCpQB0IaKmq_fOtysTb_iVtvqbH-vHS1DoS1eLd4w8,23
|
3
|
-
robotcode/robot/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
|
4
|
-
robotcode/robot/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
-
robotcode/robot/config/loader.py,sha256=bNJwr_XdCoUzpG2ag0BH33PIfiCwn0GMxn7q_Sw3zOk,8103
|
6
|
-
robotcode/robot/config/model.py,sha256=sgr6-4_E06g-yIXW41Z-NtIXZ_7JMmR5WvUD7kTUqu4,89106
|
7
|
-
robotcode/robot/config/utils.py,sha256=xY-LH31BidWzonpvSrle-4HvKrp02I7IRqU2JwlL4Ls,2931
|
8
|
-
robotcode/robot/diagnostics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
robotcode/robot/diagnostics/diagnostics_modifier.py,sha256=3dDsu8-ET6weIvv7Sk3IQaPYFNxnXUs8Y7gpGTjfOBs,9796
|
10
|
-
robotcode/robot/diagnostics/document_cache_helper.py,sha256=n903UxVXM4Uq4fPxN5s-dugQAKcWUwf4Nw4q0CJV7aw,23902
|
11
|
-
robotcode/robot/diagnostics/entities.py,sha256=sNXKBdJEy7elkzc0P2qszHQQosbmcyWrCw3Za4-LSCE,11013
|
12
|
-
robotcode/robot/diagnostics/errors.py,sha256=QpvimvU_-c13i6mNrOiIavr2BeClHThRk8Rh7zIbA1s,1813
|
13
|
-
robotcode/robot/diagnostics/imports_manager.py,sha256=somlZbrkXasgU6KZmnf9Zfm4_3nqXEbi8Er5kSO-48Y,58999
|
14
|
-
robotcode/robot/diagnostics/keyword_finder.py,sha256=KQKZN0lf4D8qRERRx1JUeEdSHFgRfs0wEcu0XH2xJ-A,16809
|
15
|
-
robotcode/robot/diagnostics/library_doc.py,sha256=2qPU1MeD4uiUAipV0U3JUxQAKhr9TH_WwDM_rDdMZuw,98862
|
16
|
-
robotcode/robot/diagnostics/model_helper.py,sha256=9JGZN_dBXMPP06WsAIDz5Q_Fg3F3Rq1n-7Rc72etivo,30864
|
17
|
-
robotcode/robot/diagnostics/namespace.py,sha256=_KNsoQS5UJB6Laa8Ic0FrQZjxngxmaKO36KJ260qyug,76054
|
18
|
-
robotcode/robot/diagnostics/namespace_analyzer.py,sha256=z1AyGQXMoq1up3LrPSLWJHHNUI_j_iwIj9ucLJcg7gU,71399
|
19
|
-
robotcode/robot/diagnostics/workspace_config.py,sha256=3SoewUj_LZB1Ki5hXM8oxQpJr6vyiog66SUw-ibODSA,2478
|
20
|
-
robotcode/robot/utils/__init__.py,sha256=OjNPMn_XSnfaMCyKd8Kmq6vlRt6mIGlzW4qiiD3ykUg,447
|
21
|
-
robotcode/robot/utils/ast.py,sha256=_ob36KHFY776n9dhljn0xAWVoUDb7pV86fPW40vIirY,11266
|
22
|
-
robotcode/robot/utils/markdownformatter.py,sha256=Cj4NjComTcNZf8uuezvtBbZqPMLjS237RknMopZYETk,11418
|
23
|
-
robotcode/robot/utils/match.py,sha256=ofyfXgrvVddl7a064Dk5Kiqp3a-n_6gTIgqDbL3E80Q,632
|
24
|
-
robotcode/robot/utils/robot_path.py,sha256=qKBh1cEnReBBLKkWu4gB9EzM-scAwE4xJc1m6v2LRN0,1786
|
25
|
-
robotcode/robot/utils/stubs.py,sha256=6-DMI_CQVJHDgG13t-zINKGCRb_Q7MQPm0_AkfhAEvE,748
|
26
|
-
robotcode/robot/utils/variables.py,sha256=fEl8S37lb_mD4hn2MZRAlkiuLGBjAOeZVK0r2o2CfPw,742
|
27
|
-
robotcode/robot/utils/visitor.py,sha256=V3ZtpzrCilKpLQfDXUcjapd2uGq12XxbHppNPOl_Jns,3080
|
28
|
-
robotcode_robot-0.94.0.dist-info/METADATA,sha256=ZC2K7aAay0qTvzWb38ymbXwS1Ufd8OvfKZdICK2A1uw,2240
|
29
|
-
robotcode_robot-0.94.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
30
|
-
robotcode_robot-0.94.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
|
31
|
-
robotcode_robot-0.94.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|