robotcode-robot 0.93.1__py3-none-any.whl → 0.94.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.
@@ -1 +1 @@
1
- __version__ = "0.93.1"
1
+ __version__ = "0.94.0"
@@ -118,8 +118,7 @@ class DocumentsCacheHelper:
118
118
  except ValueError as e:
119
119
  ex = e
120
120
  self._logger.exception(
121
- lambda: f"Language configuration is not valid: {ex}"
122
- "\nPlease check your 'robotcode.robot.language' configuration.",
121
+ lambda: f"Language configuration is not valid: {ex}",
123
122
  exc_info=ex,
124
123
  level=CRITICAL,
125
124
  )
@@ -410,7 +409,16 @@ class DocumentsCacheHelper:
410
409
  return document.get_cache(self.__get_namespace)
411
410
 
412
411
  def __get_namespace(self, document: TextDocument) -> Namespace:
413
- return self.__get_namespace_for_document_type(document, None)
412
+ document_type = self.get_document_type(document)
413
+
414
+ if document_type == DocumentType.INIT:
415
+ return self.get_init_namespace(document)
416
+ if document_type == DocumentType.RESOURCE:
417
+ return self.get_resource_namespace(document)
418
+ if document_type == DocumentType.GENERAL:
419
+ return self.get_general_namespace(document)
420
+
421
+ return self.__get_namespace_for_document_type(document, document_type)
414
422
 
415
423
  def get_resource_namespace(self, document: TextDocument) -> Namespace:
416
424
  return document.get_cache(self.__get_resource_namespace)
@@ -448,9 +456,6 @@ class DocumentsCacheHelper:
448
456
 
449
457
  def __namespace_initialized(self, sender: Namespace) -> None:
450
458
  if sender.document is not None:
451
- self._logger.debug(
452
- lambda: f"Save initialized Namespace: {sender.document.uri if sender.document else None}"
453
- )
454
459
  sender.document.set_data(self.INITIALIZED_NAMESPACE, sender)
455
460
  self.namespace_initialized(self, sender)
456
461
 
@@ -246,7 +246,7 @@ class GlobalVariableDefinition(VariableDefinition):
246
246
 
247
247
 
248
248
  @dataclass
249
- class BuiltInVariableDefinition(VariableDefinition):
249
+ class BuiltInVariableDefinition(GlobalVariableDefinition):
250
250
  type: VariableDefinitionType = VariableDefinitionType.BUILTIN_VARIABLE
251
251
  resolvable: bool = True
252
252
 
@@ -266,7 +266,7 @@ class CommandLineVariableDefinition(GlobalVariableDefinition):
266
266
 
267
267
 
268
268
  @dataclass
269
- class ArgumentDefinition(VariableDefinition):
269
+ class ArgumentDefinition(LocalVariableDefinition):
270
270
  type: VariableDefinitionType = VariableDefinitionType.ARGUMENT
271
271
  keyword_doc: Optional["KeywordDoc"] = field(default=None, compare=False, metadata={"nosave": True})
272
272
 
@@ -1,6 +1,6 @@
1
1
  from typing import final
2
2
 
3
- DIAGNOSTICS_SOURCE_NAME = "robotcode.namespace"
3
+ DIAGNOSTICS_SOURCE_NAME = "robotcode"
4
4
 
5
5
 
6
6
  @final
@@ -35,3 +35,8 @@ class Error:
35
35
  CONFLICTING_LIBRARY_KEYWORDS = "ConflictingLibraryKeywords"
36
36
  INVALID_HEADER = "InvalidHeader"
37
37
  DEPRECATED_HEADER = "DeprecatedHeader"
38
+ OVERRIDDEN_BY_COMMANDLINE = "OverriddenByCommandLine"
39
+ VARIABLE_ALREADY_DEFINED = "VariableAlreadyDefined"
40
+ VARIABLE_OVERRIDDEN = "VariableOverridden"
41
+ MODEL_ERROR = "ModelError"
42
+ TOKEN_ERROR = "TokenError"
@@ -9,7 +9,7 @@ import weakref
9
9
  import zlib
10
10
  from abc import ABC, abstractmethod
11
11
  from collections import OrderedDict
12
- from concurrent.futures import ProcessPoolExecutor
12
+ from concurrent.futures import ProcessPoolExecutor, TimeoutError
13
13
  from dataclasses import dataclass
14
14
  from pathlib import Path
15
15
  from typing import (
@@ -25,6 +25,7 @@ from typing import (
25
25
  final,
26
26
  )
27
27
 
28
+ from robot.utils.text import split_args_from_name_or_path
28
29
  from robotcode.core.concurrent import RLock, run_as_task
29
30
  from robotcode.core.documents_manager import DocumentsManager
30
31
  from robotcode.core.event import event
@@ -82,9 +83,8 @@ RESOURCE_EXTENSIONS = (
82
83
  REST_EXTENSIONS = (".rst", ".rest")
83
84
 
84
85
 
85
- LOAD_LIBRARY_TIME_OUT = 30
86
- FIND_FILE_TIME_OUT = 10
87
- COMPLETE_LIBRARY_IMPORT_TIME_OUT = COMPLETE_RESOURCE_IMPORT_TIME_OUT = COMPLETE_VARIABLES_IMPORT_TIME_OUT = 10
86
+ LOAD_LIBRARY_TIME_OUT = 10
87
+ COMPLETE_LIBRARY_IMPORT_TIME_OUT = COMPLETE_RESOURCE_IMPORT_TIME_OUT = COMPLETE_VARIABLES_IMPORT_TIME_OUT = 5
88
88
 
89
89
 
90
90
  class _EntryKey:
@@ -578,6 +578,10 @@ class ImportsManager:
578
578
  self._resource_document_changed_timer_interval = 1
579
579
  self._resource_document_changed_documents: Set[TextDocument] = set()
580
580
 
581
+ self._resource_libdoc_cache: "weakref.WeakKeyDictionary[ast.AST, Dict[Tuple[str, bool], LibraryDoc]]" = (
582
+ weakref.WeakKeyDictionary()
583
+ )
584
+
581
585
  def __del__(self) -> None:
582
586
  try:
583
587
  if self._executor is not None:
@@ -599,8 +603,6 @@ class ImportsManager:
599
603
 
600
604
  @_logger.call
601
605
  def get_command_line_variables(self) -> List[VariableDefinition]:
602
- from robot.utils.text import split_args_from_name_or_path
603
-
604
606
  with self._command_line_variables_lock:
605
607
  if self._command_line_variables is None:
606
608
  command_line_vars: List[VariableDefinition] = []
@@ -659,7 +661,11 @@ class ImportsManager:
659
661
  raise
660
662
  except BaseException as e:
661
663
  # TODO add diagnostics
662
- self._logger.exception(e)
664
+ ex = e
665
+ self._logger.exception(
666
+ lambda: f"Error getting command line variables: {ex}",
667
+ exc_info=ex,
668
+ )
663
669
 
664
670
  self._command_line_variables = command_line_vars
665
671
 
@@ -854,7 +860,7 @@ class ImportsManager:
854
860
  ) -> None:
855
861
  try:
856
862
  if len(entry.references) == 0 or now:
857
- self._logger.debug(lambda: f"Remove Va riables Entry {entry_key}")
863
+ self._logger.debug(lambda: f"Remove Variables Entry {entry_key}")
858
864
  with self._variables_lock:
859
865
  if len(entry.references) == 0:
860
866
  e1 = self._variables.get(entry_key, None)
@@ -1148,6 +1154,7 @@ class ImportsManager:
1148
1154
  meta, _source, ignore_arguments = self.get_library_meta(name, base_dir, variables)
1149
1155
 
1150
1156
  if meta is not None and not meta.has_errors:
1157
+
1151
1158
  meta_file = Path(self.lib_doc_cache_path, meta.filepath_base + ".meta.json")
1152
1159
  if meta_file.exists():
1153
1160
  try:
@@ -1157,7 +1164,8 @@ class ImportsManager:
1157
1164
  if saved_meta.has_errors:
1158
1165
  self._logger.debug(
1159
1166
  lambda: "Saved library spec for {name}{args!r} is not used "
1160
- "due to errors in meta data"
1167
+ "due to errors in meta data",
1168
+ context_name="import",
1161
1169
  )
1162
1170
 
1163
1171
  if not saved_meta.has_errors and saved_meta == meta:
@@ -1165,6 +1173,10 @@ class ImportsManager:
1165
1173
  self.lib_doc_cache_path,
1166
1174
  meta.filepath_base + ".spec.json",
1167
1175
  )
1176
+
1177
+ self._logger.debug(
1178
+ lambda: f"Use cached library meta data for {name}", context_name="import"
1179
+ )
1168
1180
  return from_json(spec_path.read_text("utf-8"), LibraryDoc)
1169
1181
 
1170
1182
  except (SystemExit, KeyboardInterrupt):
@@ -1178,17 +1190,22 @@ class ImportsManager:
1178
1190
  except BaseException as e:
1179
1191
  self._logger.exception(e)
1180
1192
 
1193
+ self._logger.debug(lambda: f"Load library in process {name}{args!r}", context_name="import")
1181
1194
  executor = ProcessPoolExecutor(max_workers=1, mp_context=mp.get_context("spawn"))
1182
1195
  try:
1183
- result = executor.submit(
1184
- get_library_doc,
1185
- name,
1186
- args if not ignore_arguments else (),
1187
- working_dir,
1188
- base_dir,
1189
- self.get_resolvable_command_line_variables(),
1190
- variables,
1191
- ).result(LOAD_LIBRARY_TIME_OUT)
1196
+ try:
1197
+ result = executor.submit(
1198
+ get_library_doc,
1199
+ name,
1200
+ args if not ignore_arguments else (),
1201
+ working_dir,
1202
+ base_dir,
1203
+ self.get_resolvable_command_line_variables(),
1204
+ variables,
1205
+ ).result(LOAD_LIBRARY_TIME_OUT)
1206
+
1207
+ except TimeoutError as e:
1208
+ raise RuntimeError(f"Timeout loading library {name}({args!r})") from e
1192
1209
 
1193
1210
  except (SystemExit, KeyboardInterrupt):
1194
1211
  raise
@@ -1273,17 +1290,29 @@ class ImportsManager:
1273
1290
  self,
1274
1291
  model: ast.AST,
1275
1292
  source: str,
1276
- model_type: str = "RESOURCE",
1277
- scope: str = "GLOBAL",
1278
1293
  append_model_errors: bool = True,
1279
1294
  ) -> LibraryDoc:
1280
- return get_model_doc(
1295
+ key = (source, append_model_errors)
1296
+
1297
+ entry = None
1298
+ if model in self._resource_libdoc_cache:
1299
+ entry = self._resource_libdoc_cache.get(model, None)
1300
+
1301
+ if entry and key in entry:
1302
+ return entry[key]
1303
+
1304
+ result = get_model_doc(
1281
1305
  model=model,
1282
1306
  source=source,
1283
- model_type=model_type,
1284
- scope=scope,
1285
1307
  append_model_errors=append_model_errors,
1286
1308
  )
1309
+ if entry is None:
1310
+ entry = {}
1311
+ self._resource_libdoc_cache[model] = entry
1312
+
1313
+ entry[key] = result
1314
+
1315
+ return result
1287
1316
 
1288
1317
  def _get_variables_libdoc_handler(
1289
1318
  self,
@@ -1350,15 +1379,20 @@ class ImportsManager:
1350
1379
 
1351
1380
  executor = ProcessPoolExecutor(max_workers=1, mp_context=mp.get_context("spawn"))
1352
1381
  try:
1353
- result = executor.submit(
1354
- get_variables_doc,
1355
- name,
1356
- args,
1357
- working_dir,
1358
- base_dir,
1359
- self.get_resolvable_command_line_variables() if resolve_command_line_vars else None,
1360
- variables,
1361
- ).result(LOAD_LIBRARY_TIME_OUT)
1382
+ try:
1383
+ result = executor.submit(
1384
+ get_variables_doc,
1385
+ name,
1386
+ args,
1387
+ working_dir,
1388
+ base_dir,
1389
+ self.get_resolvable_command_line_variables() if resolve_command_line_vars else None,
1390
+ variables,
1391
+ ).result(LOAD_LIBRARY_TIME_OUT)
1392
+
1393
+ except TimeoutError as e:
1394
+ raise RuntimeError(f"Timeout loading library {name}({args!r})") from e
1395
+
1362
1396
  except (SystemExit, KeyboardInterrupt):
1363
1397
  raise
1364
1398
  except BaseException as e:
@@ -1489,9 +1523,15 @@ class ImportsManager:
1489
1523
  variables: Optional[Dict[str, Any]] = None,
1490
1524
  ) -> Tuple["Namespace", LibraryDoc]:
1491
1525
  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)
1526
+ with self._logger.measure_time(lambda: f"getting resource entry {name}", context_name="import"):
1527
+ entry = self._get_entry_for_resource_import(name, base_dir, sentinel, variables)
1528
+
1529
+ with self._logger.measure_time(lambda: f"getting namespace {name}", context_name="import"):
1530
+ namespace = entry.get_namespace()
1531
+ with self._logger.measure_time(lambda: f"getting libdoc {name}", context_name="import"):
1532
+ libdoc = entry.get_libdoc()
1493
1533
 
1494
- return entry.get_namespace(), entry.get_libdoc()
1534
+ return namespace, libdoc
1495
1535
 
1496
1536
  def get_namespace_for_resource_import(
1497
1537
  self,
@@ -1528,7 +1568,7 @@ class ImportsManager:
1528
1568
  base_dir,
1529
1569
  self.get_resolvable_command_line_variables(),
1530
1570
  variables,
1531
- ).result(LOAD_LIBRARY_TIME_OUT)
1571
+ ).result(COMPLETE_LIBRARY_IMPORT_TIME_OUT)
1532
1572
 
1533
1573
  def complete_resource_import(
1534
1574
  self,
@@ -1543,7 +1583,7 @@ class ImportsManager:
1543
1583
  base_dir,
1544
1584
  self.get_resolvable_command_line_variables(),
1545
1585
  variables,
1546
- ).result(LOAD_LIBRARY_TIME_OUT)
1586
+ ).result(COMPLETE_RESOURCE_IMPORT_TIME_OUT)
1547
1587
 
1548
1588
  def complete_variables_import(
1549
1589
  self,
@@ -1558,7 +1598,7 @@ class ImportsManager:
1558
1598
  base_dir,
1559
1599
  self.get_resolvable_command_line_variables(),
1560
1600
  variables,
1561
- ).result(LOAD_LIBRARY_TIME_OUT)
1601
+ ).result(COMPLETE_VARIABLES_IMPORT_TIME_OUT)
1562
1602
 
1563
1603
  def resolve_variable(
1564
1604
  self,