robotcode-robot 0.91.0__py3-none-any.whl → 0.93.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,8 @@ import functools
2
2
  import re as re
3
3
  from ast import AST
4
4
  from collections import defaultdict
5
- from dataclasses import dataclass
5
+ from dataclasses import dataclass, field
6
+ from enum import Enum
6
7
  from typing import Dict, List, Optional, Set, Union
7
8
 
8
9
  from robot.parsing.lexer.tokens import Token
@@ -12,15 +13,32 @@ from robotcode.core.lsp.types import Diagnostic, DiagnosticSeverity
12
13
 
13
14
  from ..utils.visitor import Visitor
14
15
 
15
- ACTIONS = ["ignore", "error", "warn", "information", "hint", "reset"]
16
+ ACTIONS = ["ignore", "error", "warn", "warning", "info", "information", "hint", "reset"]
16
17
 
17
18
  ROBOTCODE_ACTION_AND_CODES_PATTERN = re.compile(rf"(?P<action>{'|'.join(ACTIONS)})(\[(?P<codes>[^\]]*?)\])?")
18
19
 
19
20
 
21
+ class ModifierAction(Enum):
22
+ IGNORE = "ignore"
23
+ ERROR = "error"
24
+ WARNING = "warning"
25
+ INFORMATION = "information"
26
+ HINT = "hint"
27
+ RESET = "reset"
28
+
29
+ @classmethod
30
+ def from_str(cls, value: str) -> "ModifierAction":
31
+ if value == "warn":
32
+ value = "warning"
33
+ elif value == "info":
34
+ value = "information"
35
+ return cls(value)
36
+
37
+
20
38
  @dataclass
21
39
  class RulesAndCodes:
22
40
  codes: Dict[Union[str, int], Set[int]]
23
- actions: Dict[int, Dict[Union[str, int], str]]
41
+ actions: Dict[int, Dict[Union[str, int], ModifierAction]]
24
42
 
25
43
 
26
44
  _translation_table = str.maketrans("", "", "_- ")
@@ -28,7 +46,7 @@ _translation_table = str.maketrans("", "", "_- ")
28
46
  ROBOTCODE_MARKER = "robotcode:"
29
47
 
30
48
 
31
- class DisablersVisitor(Visitor):
49
+ class ModifiersVisitor(Visitor):
32
50
 
33
51
  def __init__(self) -> None:
34
52
  super().__init__()
@@ -65,8 +83,8 @@ class DisablersVisitor(Visitor):
65
83
  self._handle_statement_comments(node)
66
84
  self.generic_visit(node)
67
85
 
68
- def _parse_robotcode_disabler(self, comment: str) -> Dict[str, List[str]]:
69
- result: Dict[str, List[str]] = {}
86
+ def _parse_robotcode_disabler(self, comment: str) -> Dict[ModifierAction, List[str]]:
87
+ result: Dict[ModifierAction, List[str]] = {}
70
88
 
71
89
  comment = comment.strip()
72
90
  m = ROBOTCODE_ACTION_AND_CODES_PATTERN.match(comment)
@@ -74,7 +92,8 @@ class DisablersVisitor(Visitor):
74
92
  return result
75
93
 
76
94
  for m in ROBOTCODE_ACTION_AND_CODES_PATTERN.finditer(comment):
77
- action = m.group("action")
95
+ action_str = m.group("action")
96
+ action = ModifierAction.from_str(action_str)
78
97
  messages = m.group("codes")
79
98
  result[action] = (
80
99
  [m.strip().translate(_translation_table).lower() for m in messages.split(",")]
@@ -153,19 +172,36 @@ class DisablersVisitor(Visitor):
153
172
  self.rules_and_codes.actions[i][code] = action
154
173
 
155
174
 
175
+ @dataclass
176
+ class DiagnosticModifiersConfig:
177
+ ignore: List[str] = field(default_factory=list)
178
+ error: List[str] = field(default_factory=list)
179
+ warning: List[str] = field(default_factory=list)
180
+ information: List[str] = field(default_factory=list)
181
+ hint: List[str] = field(default_factory=list)
182
+
183
+
156
184
  class DiagnosticsModifier:
157
- def __init__(self, model: AST) -> None:
185
+ def __init__(self, model: AST, config: Optional[DiagnosticModifiersConfig] = None) -> None:
186
+ self.config = config or DiagnosticModifiersConfig()
187
+
188
+ self.config.ignore = [i.translate(_translation_table).lower() for i in self.config.ignore]
189
+ self.config.error = [i.translate(_translation_table).lower() for i in self.config.error]
190
+ self.config.warning = [i.translate(_translation_table).lower() for i in self.config.warning]
191
+ self.config.information = [i.translate(_translation_table).lower() for i in self.config.information]
192
+ self.config.hint = [i.translate(_translation_table).lower() for i in self.config.hint]
193
+
158
194
  self.model = model
159
195
 
160
196
  @functools.cached_property
161
197
  def rules_and_codes(self) -> RulesAndCodes:
162
- visitor = DisablersVisitor()
198
+ visitor = ModifiersVisitor()
163
199
  visitor.visit(self.model)
164
200
  return visitor.rules_and_codes
165
201
 
166
202
  def modify_diagnostic(self, diagnostic: Diagnostic) -> Optional[Diagnostic]:
167
203
  if diagnostic.code is not None:
168
- code = (
204
+ code = orig_code = (
169
205
  str(diagnostic.code).translate(_translation_table).lower()
170
206
  if diagnostic.code is not None
171
207
  else "unknowncode"
@@ -177,24 +213,51 @@ class DiagnosticsModifier:
177
213
  code = "*"
178
214
  lines = self.rules_and_codes.codes.get(code)
179
215
 
216
+ modified = False
180
217
  if lines is not None and diagnostic.range.start.line in lines:
181
218
  actions = self.rules_and_codes.actions.get(diagnostic.range.start.line)
182
219
  if actions is not None:
183
220
  action = actions.get(code)
184
221
  if action is not None:
185
- if action == "ignore":
222
+ if action == ModifierAction.IGNORE:
186
223
  return None
187
- if action == "reset":
188
- pass # do nothing
189
- elif action == "error":
224
+ if action == ModifierAction.RESET:
225
+ pass
226
+ elif action == ModifierAction.ERROR:
227
+ modified = True
190
228
  diagnostic.severity = DiagnosticSeverity.ERROR
191
- elif action == "warn":
229
+ elif action == ModifierAction.WARNING:
230
+ modified = True
192
231
  diagnostic.severity = DiagnosticSeverity.WARNING
193
- elif action == "information":
232
+ elif action == ModifierAction.INFORMATION:
233
+ modified = True
194
234
  diagnostic.severity = DiagnosticSeverity.INFORMATION
195
- elif action == "hint":
235
+ elif action == ModifierAction.HINT:
236
+ modified = True
196
237
  diagnostic.severity = DiagnosticSeverity.HINT
197
238
 
239
+ if not modified:
240
+ if orig_code in self.config.ignore:
241
+ return None
242
+ if orig_code in self.config.error:
243
+ diagnostic.severity = DiagnosticSeverity.ERROR
244
+ elif orig_code in self.config.warning:
245
+ diagnostic.severity = DiagnosticSeverity.WARNING
246
+ elif orig_code in self.config.information:
247
+ diagnostic.severity = DiagnosticSeverity.INFORMATION
248
+ elif orig_code in self.config.hint:
249
+ diagnostic.severity = DiagnosticSeverity.HINT
250
+ elif "*" in self.config.hint:
251
+ diagnostic.severity = DiagnosticSeverity.HINT
252
+ elif "*" in self.config.information:
253
+ diagnostic.severity = DiagnosticSeverity.INFORMATION
254
+ elif "*" in self.config.warning:
255
+ diagnostic.severity = DiagnosticSeverity.WARNING
256
+ elif "*" in self.config.error:
257
+ diagnostic.severity = DiagnosticSeverity.ERROR
258
+ elif "*" in self.config.ignore:
259
+ return None
260
+
198
261
  return diagnostic
199
262
 
200
263
  def modify_diagnostics(self, diagnostics: List[Diagnostic]) -> List[Diagnostic]:
@@ -26,7 +26,7 @@ from robotcode.core.text_document import TextDocument
26
26
  from robotcode.core.uri import Uri
27
27
  from robotcode.core.utils.logging import LoggingDescriptor
28
28
  from robotcode.core.workspace import Workspace, WorkspaceFolder
29
- from robotcode.robot.diagnostics.diagnostics_modifier import DiagnosticsModifier
29
+ from robotcode.robot.diagnostics.diagnostics_modifier import DiagnosticModifiersConfig, DiagnosticsModifier
30
30
 
31
31
  from ..config.model import RobotBaseProfile
32
32
  from ..utils import get_robot_version
@@ -34,7 +34,13 @@ from ..utils.stubs import Languages
34
34
  from .imports_manager import ImportsManager
35
35
  from .library_doc import LibraryDoc
36
36
  from .namespace import DocumentType, Namespace
37
- from .workspace_config import AnalysisRobotConfig, CacheConfig, RobotConfig
37
+ from .workspace_config import (
38
+ AnalysisDiagnosticModifiersConfig,
39
+ AnalysisRobotConfig,
40
+ CacheConfig,
41
+ RobotConfig,
42
+ WorkspaceAnalysisConfig,
43
+ )
38
44
 
39
45
 
40
46
  class UnknownFileTypeError(Exception):
@@ -54,6 +60,7 @@ class DocumentsCacheHelper:
54
60
  documents_manager: DocumentsManager,
55
61
  file_watcher_manager: FileWatcherManagerBase,
56
62
  robot_profile: Optional[RobotBaseProfile],
63
+ analysis_config: Optional[WorkspaceAnalysisConfig],
57
64
  ) -> None:
58
65
  self.INITIALIZED_NAMESPACE = _CacheEntry()
59
66
 
@@ -62,6 +69,7 @@ class DocumentsCacheHelper:
62
69
  self.file_watcher_manager = file_watcher_manager
63
70
 
64
71
  self.robot_profile = robot_profile or RobotBaseProfile()
72
+ self.analysis_config = analysis_config or WorkspaceAnalysisConfig()
65
73
 
66
74
  self._imports_managers_lock = threading.RLock()
67
75
  self._imports_managers: weakref.WeakKeyDictionary[WorkspaceFolder, ImportsManager] = weakref.WeakKeyDictionary()
@@ -514,10 +522,10 @@ class DocumentsCacheHelper:
514
522
  variables,
515
523
  variable_files,
516
524
  environment,
517
- cache_config.ignored_libraries,
518
- cache_config.ignored_variables,
519
- cache_config.ignore_arguments_for_library,
520
- analysis_config.global_library_search_order,
525
+ self.analysis_config.cache.ignored_libraries + cache_config.ignored_libraries,
526
+ self.analysis_config.cache.ignored_variables + cache_config.ignored_variables,
527
+ self.analysis_config.cache.ignore_arguments_for_library + cache_config.ignore_arguments_for_library,
528
+ self.analysis_config.robot.global_library_search_order + analysis_config.global_library_search_order,
521
529
  cache_base_path,
522
530
  )
523
531
 
@@ -583,4 +591,14 @@ class DocumentsCacheHelper:
583
591
  return document.get_cache(self.__get_diagnostic_modifier)
584
592
 
585
593
  def __get_diagnostic_modifier(self, document: TextDocument) -> DiagnosticsModifier:
586
- return DiagnosticsModifier(self.get_model(document, False))
594
+ modifiers_config = self.workspace.get_configuration(AnalysisDiagnosticModifiersConfig, document.uri)
595
+ return DiagnosticsModifier(
596
+ self.get_model(document, False),
597
+ DiagnosticModifiersConfig(
598
+ ignore=self.analysis_config.modifiers.ignore + modifiers_config.ignore,
599
+ error=self.analysis_config.modifiers.error + modifiers_config.error,
600
+ warning=self.analysis_config.modifiers.warning + modifiers_config.warning,
601
+ information=self.analysis_config.modifiers.information + modifiers_config.information,
602
+ hint=self.analysis_config.modifiers.hint + modifiers_config.hint,
603
+ ),
604
+ )
@@ -160,7 +160,7 @@ class VariableMatcher:
160
160
  return False
161
161
 
162
162
  def __hash__(self) -> int:
163
- return hash(self.name)
163
+ return hash(self.normalized_name)
164
164
 
165
165
  def __str__(self) -> str:
166
166
  return self.name
@@ -252,7 +252,7 @@ class BuiltInVariableDefinition(VariableDefinition):
252
252
 
253
253
  @single_call
254
254
  def __hash__(self) -> int:
255
- return hash((type(self), self.name, self.type))
255
+ return hash((type(self), self.name, self.type, None, None))
256
256
 
257
257
 
258
258
  @dataclass
@@ -64,6 +64,7 @@ from .library_doc import (
64
64
  get_variables_doc,
65
65
  is_library_by_path,
66
66
  is_variables_by_path,
67
+ replace_variables_scalar,
67
68
  resolve_args,
68
69
  resolve_variable,
69
70
  )
@@ -905,7 +906,8 @@ class ImportsManager:
905
906
  ):
906
907
  self._logger.debug(
907
908
  lambda: f"Ignore library {result.name or '' if result is not None else ''}"
908
- f" {result.origin or '' if result is not None else ''} for caching."
909
+ f" {result.origin or '' if result is not None else ''} for caching.",
910
+ context_name="import",
909
911
  )
910
912
  return None, import_name, ignore_arguments
911
913
 
@@ -1143,9 +1145,7 @@ class ImportsManager:
1143
1145
  base_dir: str,
1144
1146
  variables: Optional[Dict[str, Any]] = None,
1145
1147
  ) -> LibraryDoc:
1146
- meta, source, ignore_arguments = self.get_library_meta(name, base_dir, variables)
1147
-
1148
- self._logger.debug(lambda: f"Load Library {source}{args!r}")
1148
+ meta, _source, ignore_arguments = self.get_library_meta(name, base_dir, variables)
1149
1149
 
1150
1150
  if meta is not None and not meta.has_errors:
1151
1151
  meta_file = Path(self.lib_doc_cache_path, meta.filepath_base + ".meta.json")
@@ -1219,7 +1219,7 @@ class ImportsManager:
1219
1219
 
1220
1220
  meta_file.write_text(as_json(meta), "utf-8")
1221
1221
  else:
1222
- self._logger.debug(lambda: f"Skip caching library {name}{args!r}")
1222
+ self._logger.debug(lambda: f"Skip caching library {name}{args!r}", context_name="import")
1223
1223
  except (SystemExit, KeyboardInterrupt):
1224
1224
  raise
1225
1225
  except BaseException as e:
@@ -1236,37 +1236,37 @@ class ImportsManager:
1236
1236
  sentinel: Any = None,
1237
1237
  variables: Optional[Dict[str, Any]] = None,
1238
1238
  ) -> LibraryDoc:
1239
+ with self._logger.measure_time(lambda: f"loading library {name}{args!r}", context_name="import"):
1240
+ source = self.find_library(name, base_dir, variables)
1239
1241
 
1240
- source = self.find_library(name, base_dir, variables)
1241
-
1242
- resolved_args = resolve_args(
1243
- args,
1244
- str(self.root_folder),
1245
- base_dir,
1246
- self.get_resolvable_command_line_variables(),
1247
- variables,
1248
- )
1249
- entry_key = _LibrariesEntryKey(source, resolved_args)
1250
-
1251
- with self._libaries_lock:
1252
- if entry_key not in self._libaries:
1253
- self._libaries[entry_key] = _LibrariesEntry(
1254
- self,
1255
- name,
1256
- args,
1257
- str(self.root_folder),
1258
- base_dir,
1259
- self._get_library_libdoc_handler(variables),
1260
- ignore_reference=sentinel is None,
1261
- )
1242
+ resolved_args = resolve_args(
1243
+ args,
1244
+ str(self.root_folder),
1245
+ base_dir,
1246
+ self.get_resolvable_command_line_variables(),
1247
+ variables,
1248
+ )
1249
+ entry_key = _LibrariesEntryKey(source, resolved_args)
1250
+
1251
+ with self._libaries_lock:
1252
+ if entry_key not in self._libaries:
1253
+ self._libaries[entry_key] = _LibrariesEntry(
1254
+ self,
1255
+ name,
1256
+ args,
1257
+ str(self.root_folder),
1258
+ base_dir,
1259
+ self._get_library_libdoc_handler(variables),
1260
+ ignore_reference=sentinel is None,
1261
+ )
1262
1262
 
1263
- entry = self._libaries[entry_key]
1263
+ entry = self._libaries[entry_key]
1264
1264
 
1265
- if not entry.ignore_reference and sentinel is not None and sentinel not in entry.references:
1266
- weakref.finalize(sentinel, self.__remove_library_entry, entry_key, entry)
1267
- entry.references.add(sentinel)
1265
+ if not entry.ignore_reference and sentinel is not None and sentinel not in entry.references:
1266
+ weakref.finalize(sentinel, self.__remove_library_entry, entry_key, entry)
1267
+ entry.references.add(sentinel)
1268
1268
 
1269
- return entry.get_libdoc()
1269
+ return entry.get_libdoc()
1270
1270
 
1271
1271
  @_logger.call
1272
1272
  def get_libdoc_from_model(
@@ -1313,7 +1313,7 @@ class ImportsManager:
1313
1313
  resolve_variables: bool = True,
1314
1314
  resolve_command_line_vars: bool = True,
1315
1315
  ) -> VariablesDoc:
1316
- meta, source = self.get_variables_meta(
1316
+ meta, _source = self.get_variables_meta(
1317
1317
  name,
1318
1318
  base_dir,
1319
1319
  variables,
@@ -1321,7 +1321,6 @@ class ImportsManager:
1321
1321
  resolve_command_line_vars=resolve_command_line_vars,
1322
1322
  )
1323
1323
 
1324
- self._logger.debug(lambda: f"Load variables {source}{args!r}")
1325
1324
  if meta is not None:
1326
1325
  meta_file = Path(
1327
1326
  self.variables_doc_cache_path,
@@ -1391,7 +1390,7 @@ class ImportsManager:
1391
1390
  raise RuntimeError(f"Cannot write spec file for variables '{name}' to '{spec_file}'") from e
1392
1391
  meta_file.write_text(as_json(meta), "utf-8")
1393
1392
  else:
1394
- self._logger.debug(lambda: f"Skip caching variables {name}{args!r}")
1393
+ self._logger.debug(lambda: f"Skip caching variables {name}{args!r}", context_name="import")
1395
1394
  except (SystemExit, KeyboardInterrupt):
1396
1395
  raise
1397
1396
  except BaseException as e:
@@ -1410,39 +1409,40 @@ class ImportsManager:
1410
1409
  resolve_variables: bool = True,
1411
1410
  resolve_command_line_vars: bool = True,
1412
1411
  ) -> VariablesDoc:
1413
- source = self.find_variables(name, base_dir, variables, resolve_variables, resolve_command_line_vars)
1414
-
1415
- if args:
1416
- resolved_args = resolve_args(
1417
- args,
1418
- str(self.root_folder),
1419
- base_dir,
1420
- self.get_resolvable_command_line_variables() if resolve_command_line_vars else None,
1421
- variables,
1422
- )
1423
- else:
1424
- resolved_args = ()
1412
+ with self._logger.measure_time(lambda: f"getting libdoc for variables import {name}", context_name="import"):
1413
+ source = self.find_variables(name, base_dir, variables, resolve_variables, resolve_command_line_vars)
1425
1414
 
1426
- entry_key = _VariablesEntryKey(source, resolved_args)
1427
-
1428
- with self._variables_lock:
1429
- if entry_key not in self._variables:
1430
- self._variables[entry_key] = _VariablesEntry(
1431
- name,
1432
- resolved_args,
1415
+ if args:
1416
+ resolved_args = resolve_args(
1417
+ args,
1433
1418
  str(self.root_folder),
1434
1419
  base_dir,
1435
- self,
1436
- self._get_variables_libdoc_handler(variables, resolve_variables, resolve_command_line_vars),
1420
+ self.get_resolvable_command_line_variables() if resolve_command_line_vars else None,
1421
+ variables,
1437
1422
  )
1423
+ else:
1424
+ resolved_args = ()
1425
+
1426
+ entry_key = _VariablesEntryKey(source, resolved_args)
1427
+
1428
+ with self._variables_lock:
1429
+ if entry_key not in self._variables:
1430
+ self._variables[entry_key] = _VariablesEntry(
1431
+ name,
1432
+ resolved_args,
1433
+ str(self.root_folder),
1434
+ base_dir,
1435
+ self,
1436
+ self._get_variables_libdoc_handler(variables, resolve_variables, resolve_command_line_vars),
1437
+ )
1438
1438
 
1439
- entry = self._variables[entry_key]
1439
+ entry = self._variables[entry_key]
1440
1440
 
1441
- if sentinel is not None and sentinel not in entry.references:
1442
- entry.references.add(sentinel)
1443
- weakref.finalize(sentinel, self.__remove_variables_entry, entry_key, entry)
1441
+ if sentinel is not None and sentinel not in entry.references:
1442
+ entry.references.add(sentinel)
1443
+ weakref.finalize(sentinel, self.__remove_variables_entry, entry_key, entry)
1444
1444
 
1445
- return entry.get_libdoc()
1445
+ return entry.get_libdoc()
1446
1446
 
1447
1447
  @_logger.call
1448
1448
  def _get_entry_for_resource_import(
@@ -1455,7 +1455,7 @@ class ImportsManager:
1455
1455
  source = self.find_resource(name, base_dir, variables=variables)
1456
1456
 
1457
1457
  def _get_document() -> TextDocument:
1458
- self._logger.debug(lambda: f"Load resource {name} from source {source}")
1458
+ self._logger.debug(lambda: f"Load resource {name} from source {source}", context_name="import")
1459
1459
 
1460
1460
  source_path = normalized_path(Path(source))
1461
1461
  extension = source_path.suffix
@@ -1488,9 +1488,10 @@ class ImportsManager:
1488
1488
  sentinel: Any = None,
1489
1489
  variables: Optional[Dict[str, Any]] = None,
1490
1490
  ) -> Tuple["Namespace", LibraryDoc]:
1491
- entry = self._get_entry_for_resource_import(name, base_dir, sentinel, variables)
1491
+ with self._logger.measure_time(lambda: f"getting namespace and libdoc for {name}", context_name="import"):
1492
+ entry = self._get_entry_for_resource_import(name, base_dir, sentinel, variables)
1492
1493
 
1493
- return entry.get_namespace(), entry.get_libdoc()
1494
+ return entry.get_namespace(), entry.get_libdoc()
1494
1495
 
1495
1496
  def get_namespace_for_resource_import(
1496
1497
  self,
@@ -1572,3 +1573,17 @@ class ImportsManager:
1572
1573
  self.get_resolvable_command_line_variables(),
1573
1574
  variables,
1574
1575
  )
1576
+
1577
+ def replace_variables_scalar(
1578
+ self,
1579
+ scalar: str,
1580
+ base_dir: str = ".",
1581
+ variables: Optional[Dict[str, Any]] = None,
1582
+ ) -> Any:
1583
+ return replace_variables_scalar(
1584
+ scalar,
1585
+ str(self.root_folder),
1586
+ base_dir,
1587
+ self.get_resolvable_command_line_variables(),
1588
+ variables,
1589
+ )
@@ -45,12 +45,8 @@ from robot.parsing.lexer.tokens import Token
45
45
  from robot.parsing.lexer.tokens import Token as RobotToken
46
46
  from robot.parsing.model.blocks import Keyword
47
47
  from robot.parsing.model.statements import Arguments, KeywordName
48
- from robot.running.arguments.argumentresolver import (
49
- ArgumentResolver,
50
- DictToKwargs,
51
- NamedArgumentResolver,
52
- VariableReplacer,
53
- )
48
+ from robot.running.arguments.argumentresolver import ArgumentResolver, DictToKwargs, NamedArgumentResolver
49
+ from robot.running.arguments.argumentresolver import VariableReplacer as ArgumentsVariableReplacer
54
50
  from robot.running.arguments.argumentspec import ArgInfo
55
51
  from robot.running.arguments.argumentspec import (
56
52
  ArgumentSpec as RobotArgumentSpec,
@@ -64,6 +60,7 @@ from robot.utils.robotpath import find_file as robot_find_file
64
60
  from robot.variables import Variables
65
61
  from robot.variables.filesetter import PythonImporter, YamlImporter
66
62
  from robot.variables.finders import VariableFinder
63
+ from robot.variables.replacer import VariableReplacer
67
64
  from robot.variables.search import contains_variable
68
65
  from robotcode.core.lsp.types import Position, Range
69
66
  from robotcode.core.utils.path import normalized_path
@@ -578,9 +575,9 @@ class ArgumentSpec:
578
575
 
579
576
  positional, named = MyNamedArgumentResolver(self.__robot_arguments).resolve(arguments, variables)
580
577
  if get_robot_version() < (7, 0):
581
- positional, named = VariableReplacer(resolve_variables_until).replace(positional, named, variables)
578
+ positional, named = ArgumentsVariableReplacer(resolve_variables_until).replace(positional, named, variables)
582
579
  else:
583
- positional, named = VariableReplacer(self.__robot_arguments, resolve_variables_until).replace(
580
+ positional, named = ArgumentsVariableReplacer(self.__robot_arguments, resolve_variables_until).replace(
584
581
  positional, named, variables
585
582
  )
586
583
  positional, named = DictToKwargs(self.__robot_arguments, dict_to_kwargs).handle(positional, named)
@@ -1585,6 +1582,26 @@ def resolve_variable(
1585
1582
  return name.replace("\\", "\\\\")
1586
1583
 
1587
1584
 
1585
+ def replace_variables_scalar(
1586
+ scalar: str,
1587
+ working_dir: str = ".",
1588
+ base_dir: str = ".",
1589
+ command_line_variables: Optional[Dict[str, Optional[Any]]] = None,
1590
+ variables: Optional[Dict[str, Optional[Any]]] = None,
1591
+ ) -> Any:
1592
+
1593
+ _update_env(working_dir)
1594
+
1595
+ if contains_variable(scalar, "$@&%"):
1596
+ robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
1597
+ if get_robot_version() >= (6, 1):
1598
+ return VariableReplacer(robot_variables).replace_scalar(scalar.replace("\\", "\\\\"))
1599
+
1600
+ return VariableReplacer(robot_variables.store).replace_scalar(scalar.replace("\\", "\\\\"))
1601
+
1602
+ return scalar.replace("\\", "\\\\")
1603
+
1604
+
1588
1605
  @contextmanager
1589
1606
  def _std_capture() -> Iterator[io.StringIO]:
1590
1607
  old__stdout__ = sys.__stdout__