robotcode-robot 0.93.1__tar.gz → 0.94.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/PKG-INFO +2 -2
  2. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/pyproject.toml +1 -1
  3. robotcode_robot-0.94.0/src/robotcode/robot/__version__.py +1 -0
  4. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/diagnostics/document_cache_helper.py +11 -6
  5. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/diagnostics/entities.py +2 -2
  6. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/diagnostics/errors.py +6 -1
  7. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/diagnostics/imports_manager.py +77 -37
  8. robotcode_robot-0.94.0/src/robotcode/robot/diagnostics/keyword_finder.py +458 -0
  9. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/diagnostics/library_doc.py +20 -14
  10. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/diagnostics/model_helper.py +42 -27
  11. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/diagnostics/namespace.py +142 -552
  12. robotcode_robot-0.94.0/src/robotcode/robot/diagnostics/namespace_analyzer.py +1725 -0
  13. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/utils/markdownformatter.py +8 -11
  14. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/utils/visitor.py +7 -13
  15. robotcode_robot-0.93.1/src/robotcode/robot/__version__.py +0 -1
  16. robotcode_robot-0.93.1/src/robotcode/robot/diagnostics/namespace_analyzer.py +0 -1235
  17. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/.gitignore +0 -0
  18. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/LICENSE.txt +0 -0
  19. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/README.md +0 -0
  20. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/__init__.py +0 -0
  21. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/config/__init__.py +0 -0
  22. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/config/loader.py +0 -0
  23. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/config/model.py +0 -0
  24. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/config/utils.py +0 -0
  25. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/diagnostics/__init__.py +0 -0
  26. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/diagnostics/diagnostics_modifier.py +0 -0
  27. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/diagnostics/workspace_config.py +0 -0
  28. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/py.typed +0 -0
  29. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/utils/__init__.py +0 -0
  30. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/utils/ast.py +0 -0
  31. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/utils/match.py +0 -0
  32. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/utils/robot_path.py +0 -0
  33. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/utils/stubs.py +0 -0
  34. {robotcode_robot-0.93.1 → robotcode_robot-0.94.0}/src/robotcode/robot/utils/variables.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: robotcode-robot
3
- Version: 0.93.1
3
+ Version: 0.94.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.93.1
29
+ Requires-Dist: robotcode-core==0.94.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
@@ -29,7 +29,7 @@ dependencies = [
29
29
  "robotframework>=4.1.0",
30
30
  "tomli>=1.1.0; python_version < '3.11'",
31
31
  "platformdirs>=3.2.0,<4.2.0",
32
- "robotcode-core==0.93.1",
32
+ "robotcode-core==0.94.0",
33
33
  ]
34
34
  dynamic = ["version"]
35
35
 
@@ -0,0 +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,