robotcode-robot 0.96.0__py3-none-any.whl → 0.98.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- __version__ = "0.96.0"
1
+ __version__ = "0.98.0"
@@ -55,14 +55,36 @@ class ConfigTypeError(TypeError):
55
55
  _ConfigType = TypeVar("_ConfigType", bound=BaseOptions)
56
56
 
57
57
 
58
+ class InvalidTomlError(ValueError):
59
+ pass
60
+
61
+
62
+ class InvalidTomlFileError(ValueError):
63
+ pass
64
+
65
+
66
+ def _load_toml(data: Union[str, Path]) -> Dict[str, Any]:
67
+ file = None
68
+ if isinstance(data, Path):
69
+ file = data
70
+ data = data.read_text("utf-8")
71
+
72
+ try:
73
+ return tomllib.loads(data)
74
+ except tomllib.TOMLDecodeError as e:
75
+ if file:
76
+ raise InvalidTomlFileError(f"Invalid TOML file'{file.absolute()}': {e}") from e
77
+ raise InvalidTomlError(f"Invalid TOML: {e}") from e
78
+
79
+
58
80
  def load_robot_config_from_robot_toml_str(__s: str) -> RobotConfig:
59
81
  return load_config_from_robot_toml_str(RobotConfig, __s)
60
82
 
61
83
 
62
84
  def load_config_from_robot_toml_str(
63
- config_type: Type[_ConfigType], data: Union[str, Dict[str, Any]], tool_name: Optional[str] = None
85
+ config_type: Type[_ConfigType], data: Union[str, Dict[str, Any], Path], tool_name: Optional[str] = None
64
86
  ) -> _ConfigType:
65
- dict_data = tomllib.loads(data) if isinstance(data, str) else data
87
+ dict_data = _load_toml(data) if isinstance(data, (str, Path)) else data
66
88
 
67
89
  if tool_name:
68
90
  try:
@@ -76,9 +98,9 @@ def load_config_from_robot_toml_str(
76
98
 
77
99
 
78
100
  def load_config_from_pyproject_toml_str(
79
- config_type: Type[_ConfigType], tool_name: str, data: Union[str, Dict[str, Any]]
101
+ config_type: Type[_ConfigType], tool_name: str, data: Union[str, Dict[str, Any], Path]
80
102
  ) -> _ConfigType:
81
- dict_data = tomllib.loads(data) if isinstance(data, str) else data
103
+ dict_data = _load_toml(data) if isinstance(data, (str, Path)) else data
82
104
 
83
105
  return from_dict(dict_data.get("tool", {}).get(tool_name, {}), config_type)
84
106
 
@@ -93,13 +115,13 @@ def _load_config_data_from_path(
93
115
  try:
94
116
  if path.name == PYPROJECT_TOML:
95
117
  return load_config_from_pyproject_toml_str(
96
- config_type, pyproject_toml_tool_name, path.read_text("utf-8") if data is None else data
118
+ config_type, pyproject_toml_tool_name, path if data is None else data
97
119
  )
98
120
 
99
121
  if path.name == ROBOT_TOML or path.name == LOCAL_ROBOT_TOML or path.suffix == ".toml":
100
122
  return load_config_from_robot_toml_str(
101
123
  config_type,
102
- path.read_text("utf-8") if data is None else data,
124
+ path if data is None else data,
103
125
  tool_name=robot_toml_tool_name,
104
126
  )
105
127
  raise TypeError("Unknown config file type.")
@@ -143,7 +165,7 @@ def load_config_from_path(
143
165
  verbose_callback(f"Load configuration from {__path if isinstance(__path, Path) else __path[0]}")
144
166
 
145
167
  p = __path if isinstance(__path, Path) else __path[0]
146
- data = tomllib.loads(p.read_text("utf-8"))
168
+ data = _load_toml(p)
147
169
 
148
170
  result.add_options(
149
171
  _load_config_data_from_path(
@@ -25,6 +25,7 @@ from typing import (
25
25
  final,
26
26
  )
27
27
 
28
+ from robot.errors import RobotError
28
29
  from robot.libraries import STDLIBS
29
30
  from robot.utils.text import split_args_from_name_or_path
30
31
  from robotcode.core.concurrent import RLock, run_as_task
@@ -32,7 +33,16 @@ from robotcode.core.documents_manager import DocumentsManager
32
33
  from robotcode.core.event import event
33
34
  from robotcode.core.filewatcher import FileWatcherEntry, FileWatcherManagerBase, FileWatcherManagerDummy
34
35
  from robotcode.core.language import language_id
35
- from robotcode.core.lsp.types import DocumentUri, FileChangeType, FileEvent
36
+ from robotcode.core.lsp.types import (
37
+ Diagnostic,
38
+ DiagnosticRelatedInformation,
39
+ DiagnosticSeverity,
40
+ DocumentUri,
41
+ FileChangeType,
42
+ FileEvent,
43
+ Location,
44
+ Range,
45
+ )
36
46
  from robotcode.core.text_document import TextDocument
37
47
  from robotcode.core.uri import Uri
38
48
  from robotcode.core.utils.caching import SimpleLRUCache
@@ -577,6 +587,8 @@ class ImportsManager:
577
587
  weakref.WeakKeyDictionary()
578
588
  )
579
589
 
590
+ self._diagnostics: List[Diagnostic] = []
591
+
580
592
  def __del__(self) -> None:
581
593
  try:
582
594
  if self._executor is not None:
@@ -584,6 +596,12 @@ class ImportsManager:
584
596
  except RuntimeError:
585
597
  pass
586
598
 
599
+ @property
600
+ def diagnostics(self) -> List[Diagnostic]:
601
+ self.get_command_line_variables()
602
+
603
+ return self._diagnostics
604
+
587
605
  @property
588
606
  def environment(self) -> Mapping[str, str]:
589
607
  return self._environment
@@ -647,18 +665,54 @@ class ImportsManager:
647
665
  ]
648
666
 
649
667
  if lib_doc.errors:
650
- # TODO add diagnostics
651
668
  for error in lib_doc.errors:
652
- self._logger.error(
653
- lambda: f"{error.type_name}: {error.message} in {error.source}:{error.line_no}"
669
+ self._diagnostics.append(
670
+ Diagnostic(
671
+ Range.zero(),
672
+ f"Processing variable file variable file '{name}({', '.join(args)})' failed"
673
+ + ("" if error.source is not None else f": {error.message}"),
674
+ DiagnosticSeverity.ERROR,
675
+ error.type_name,
676
+ related_information=(
677
+ [
678
+ DiagnosticRelatedInformation(
679
+ Location(
680
+ str(Uri.from_path(os.path.abspath(error.source))),
681
+ Range.from_int_range(
682
+ (error.line_no - 1) if error.line_no is not None else -1
683
+ ),
684
+ ),
685
+ error.message,
686
+ )
687
+ ]
688
+ if error.source is not None
689
+ else None
690
+ ),
691
+ )
654
692
  )
693
+ except RobotError as e:
694
+ self._diagnostics.append(
695
+ Diagnostic(
696
+ Range.zero(),
697
+ f"Error in command line variable file '{name}({', '.join(args)})': {e}",
698
+ DiagnosticSeverity.ERROR,
699
+ type(e).__name__,
700
+ )
701
+ )
655
702
  except (SystemExit, KeyboardInterrupt):
656
703
  raise
657
704
  except BaseException as e:
658
- # TODO add diagnostics
705
+ self._diagnostics.append(
706
+ Diagnostic(
707
+ Range.zero(),
708
+ f"Error in command line variable file '{name}({', '.join(args)})': {e}",
709
+ DiagnosticSeverity.ERROR,
710
+ type(e).__name__,
711
+ )
712
+ )
659
713
  ex = e
660
714
  self._logger.exception(
661
- lambda: f"Error getting command line variables: {ex}",
715
+ lambda: f"Error in command line variable file '{name}({', '.join(args)})'",
662
716
  exc_info=ex,
663
717
  )
664
718
 
@@ -44,6 +44,7 @@ from robotcode.core.lsp.types import (
44
44
  from robotcode.core.text_document import TextDocument
45
45
  from robotcode.core.uri import Uri
46
46
  from robotcode.core.utils.logging import LoggingDescriptor
47
+ from robotcode.core.utils.path import same_file
47
48
 
48
49
  from ..utils.ast import (
49
50
  range_from_node,
@@ -1242,8 +1243,37 @@ class Namespace:
1242
1243
 
1243
1244
  source = self.imports_manager.find_resource(value.name, base_dir, variables=variables)
1244
1245
 
1245
- if source in self._resources_files:
1246
+ allread_imported_resource = next(
1247
+ (
1248
+ v
1249
+ for k, v in self._resources.items()
1250
+ if v.library_doc.source is not None and same_file(v.library_doc.source, source)
1251
+ ),
1252
+ None,
1253
+ )
1254
+ if allread_imported_resource is not None:
1246
1255
  self._logger.debug(lambda: f"Resource '{value.name}' already imported.", context_name="import")
1256
+ if top_level:
1257
+ self.append_diagnostics(
1258
+ range=value.range,
1259
+ message=f"Resource '{value.name}' already imported.",
1260
+ severity=DiagnosticSeverity.INFORMATION,
1261
+ source=DIAGNOSTICS_SOURCE_NAME,
1262
+ related_information=(
1263
+ [
1264
+ DiagnosticRelatedInformation(
1265
+ location=Location(
1266
+ uri=str(Uri.from_path(allread_imported_resource.import_source)),
1267
+ range=allread_imported_resource.import_range,
1268
+ ),
1269
+ message="",
1270
+ )
1271
+ ]
1272
+ if allread_imported_resource.import_source
1273
+ else None
1274
+ ),
1275
+ code=Error.RESOURCE_ALREADY_IMPORTED,
1276
+ )
1247
1277
  return None
1248
1278
 
1249
1279
  if self.source == source:
@@ -1453,7 +1483,7 @@ class Namespace:
1453
1483
  allread_imported_resource = self._resources_files.get(entry.library_doc.source, None)
1454
1484
 
1455
1485
  if allread_imported_resource is None and entry.library_doc.source != self.source:
1456
- self._resources[entry.import_name] = entry
1486
+ self._resources[entry.library_doc.source] = entry
1457
1487
  self._resources_files[entry.library_doc.source] = entry
1458
1488
  if entry.variables:
1459
1489
  variables = self.get_suite_variables()
@@ -75,6 +75,7 @@ class WorkspaceConfig(ConfigBase):
75
75
 
76
76
  @dataclass
77
77
  class WorkspaceAnalysisConfig:
78
+ exclude_patterns: List[str] = field(default_factory=list)
78
79
  cache: CacheConfig = field(default_factory=CacheConfig)
79
80
  robot: AnalysisRobotConfig = field(default_factory=AnalysisRobotConfig)
80
81
  modifiers: AnalysisDiagnosticModifiersConfig = field(default_factory=AnalysisDiagnosticModifiersConfig)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: robotcode-robot
3
- Version: 0.96.0
3
+ Version: 0.98.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
@@ -10,7 +10,6 @@ Project-URL: Issues, https://github.com/robotcodedev/robotcode/issues
10
10
  Project-URL: Source, https://github.com/robotcodedev/robotcode
11
11
  Author-email: Daniel Biehl <dbiehl@live.de>
12
12
  License: Apache-2.0
13
- License-File: LICENSE.txt
14
13
  Classifier: Development Status :: 5 - Production/Stable
15
14
  Classifier: Framework :: Robot Framework
16
15
  Classifier: Framework :: Robot Framework :: Tool
@@ -26,7 +25,7 @@ Classifier: Topic :: Utilities
26
25
  Classifier: Typing :: Typed
27
26
  Requires-Python: >=3.8
28
27
  Requires-Dist: platformdirs<4.4.0,>=3.2.0
29
- Requires-Dist: robotcode-core==0.96.0
28
+ Requires-Dist: robotcode-core==0.98.0
30
29
  Requires-Dist: robotframework>=4.1.0
31
30
  Requires-Dist: tomli>=1.1.0; python_version < '3.11'
32
31
  Description-Content-Type: text/markdown
@@ -1,8 +1,8 @@
1
1
  robotcode/robot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- robotcode/robot/__version__.py,sha256=B-kjJajURz8O11CWqC3d4KQ5aeL4lukk9XP51Xbpo8o,23
2
+ robotcode/robot/__version__.py,sha256=wDatk6DOlwcbppXlUNCn5v8i6SpKrbGGBYEGlrqUork,23
3
3
  robotcode/robot/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
4
4
  robotcode/robot/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- robotcode/robot/config/loader.py,sha256=bNJwr_XdCoUzpG2ag0BH33PIfiCwn0GMxn7q_Sw3zOk,8103
5
+ robotcode/robot/config/loader.py,sha256=tLPzeyHl4ELBIVSj2JtU2wVqlurouKTdfxHy0T5HxRE,8584
6
6
  robotcode/robot/config/model.py,sha256=sgr6-4_E06g-yIXW41Z-NtIXZ_7JMmR5WvUD7kTUqu4,89106
7
7
  robotcode/robot/config/utils.py,sha256=xY-LH31BidWzonpvSrle-4HvKrp02I7IRqU2JwlL4Ls,2931
8
8
  robotcode/robot/diagnostics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -11,13 +11,13 @@ robotcode/robot/diagnostics/diagnostics_modifier.py,sha256=3dDsu8-ET6weIvv7Sk3IQ
11
11
  robotcode/robot/diagnostics/document_cache_helper.py,sha256=n903UxVXM4Uq4fPxN5s-dugQAKcWUwf4Nw4q0CJV7aw,23902
12
12
  robotcode/robot/diagnostics/entities.py,sha256=b4u2yQN8MDg90RoTMaW7iLogiDNwOAtK180KCB94RfE,10970
13
13
  robotcode/robot/diagnostics/errors.py,sha256=vRH7HiZOfQIC-L7ys2Bj9ULYxLpUH7I03qJRSkEx08k,1813
14
- robotcode/robot/diagnostics/imports_manager.py,sha256=zMHqs8WGis9r74FR6Jb4AqpR15EmGtdBWpMq9R_GZMA,58604
14
+ robotcode/robot/diagnostics/imports_manager.py,sha256=jaEE7iUzEA4Rp-KXP3nfn0JyUGyp-0BMfNi8_DsQ6KE,61169
15
15
  robotcode/robot/diagnostics/keyword_finder.py,sha256=dm4BA0ccp5V4C65CkSYUJUNXegSmvG24uu09T3eL6a4,17319
16
16
  robotcode/robot/diagnostics/library_doc.py,sha256=VPCX7xp-0LJiYSFLO68y8MuNAMIYcnhJTIHRmWPpl30,100507
17
17
  robotcode/robot/diagnostics/model_helper.py,sha256=ltuUNWwZJFBmMFXIomMmW1IP5v7tMpQSoC1YbncgoNI,30985
18
- robotcode/robot/diagnostics/namespace.py,sha256=lJOkaS_yCp8SVhURqh5NqAsm394s0cHZUMQwVeh9nno,75159
18
+ robotcode/robot/diagnostics/namespace.py,sha256=nP2Nr388yw91tkd5L6DE9Yn8lb9Y4ML6c5hFn9qq4O4,76705
19
19
  robotcode/robot/diagnostics/namespace_analyzer.py,sha256=MgEoEGH7FvwVYoR3wA0JEGQxMWJTUUHq10NrorJV5LY,74183
20
- robotcode/robot/diagnostics/workspace_config.py,sha256=0QLcjyyDHsirH0Y6o1RvBEi3_jgJxcp2zvHT1dSQuWU,2627
20
+ robotcode/robot/diagnostics/workspace_config.py,sha256=gyKR5z-HpnjxPAui3YujgeZqXX7RYBO_ErGVlk7vnGc,2689
21
21
  robotcode/robot/utils/__init__.py,sha256=OjNPMn_XSnfaMCyKd8Kmq6vlRt6mIGlzW4qiiD3ykUg,447
22
22
  robotcode/robot/utils/ast.py,sha256=eqAVVquoRbMw3WvGmK6FnkUjZzAxHAitVjqK-vx-HSY,10764
23
23
  robotcode/robot/utils/markdownformatter.py,sha256=SdHFfK9OdBnljWMP5r5Jy2behtHy-_Myd7GV4hiH-kI,11688
@@ -26,7 +26,7 @@ robotcode/robot/utils/robot_path.py,sha256=Z-GVBOPA_xeD20bCJi4_AWaU0eQWvCym-YFty
26
26
  robotcode/robot/utils/stubs.py,sha256=umugZYAyneFNgqRJBRMJPzm0u0B_TH8Sx_y-ykXnxpw,351
27
27
  robotcode/robot/utils/variables.py,sha256=-ldL8mRRSYYW2pwlm8IpoDeQcG6LYBqaYyV_7U3xsIc,2174
28
28
  robotcode/robot/utils/visitor.py,sha256=nP3O0qh3YYuxR6S8wYJRBFfNwIVgsgohURBlrnFkRYQ,2299
29
- robotcode_robot-0.96.0.dist-info/METADATA,sha256=PPFZwhpqJldo2MUkr0Kg4Qa_hx4EkAbJIZCqsG124UE,2240
30
- robotcode_robot-0.96.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
31
- robotcode_robot-0.96.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
32
- robotcode_robot-0.96.0.dist-info/RECORD,,
29
+ robotcode_robot-0.98.0.dist-info/METADATA,sha256=uHcW1ePx5mWUf9_sVG8Gdkc6Fr1kPyxlpmKF1Zj674c,2214
30
+ robotcode_robot-0.98.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
31
+ robotcode_robot-0.98.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
32
+ robotcode_robot-0.98.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.25.0
2
+ Generator: hatchling 1.26.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any