robotcode-robot 0.94.0__py3-none-any.whl → 0.95.1__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,3 +1,5 @@
1
+ import functools
2
+ import re
1
3
  from itertools import chain
2
4
  from typing import TYPE_CHECKING, Dict, Iterable, Iterator, List, NamedTuple, Optional, Sequence, Tuple
3
5
 
@@ -42,6 +44,8 @@ class KeywordFinder:
42
44
  self.self_library_doc = library_doc
43
45
 
44
46
  self.diagnostics: List[DiagnosticsEntry] = []
47
+ self.result_bdd_prefix: Optional[str] = None
48
+
45
49
  self.multiple_keywords_result: Optional[List[KeywordDoc]] = None
46
50
  self._cache: Dict[
47
51
  Tuple[Optional[str], bool],
@@ -49,17 +53,20 @@ class KeywordFinder:
49
53
  Optional[KeywordDoc],
50
54
  List[DiagnosticsEntry],
51
55
  Optional[List[KeywordDoc]],
56
+ Optional[str],
52
57
  ],
53
58
  ] = {}
54
- self.handle_bdd_style = True
59
+
55
60
  self._all_keywords: Optional[List[LibraryEntry]] = None
56
- self._resource_keywords: Optional[List[ResourceEntry]] = None
57
- self._library_keywords: Optional[List[LibraryEntry]] = None
61
+ self._resource_imports: Optional[List[ResourceEntry]] = None
62
+ self._library_imports: Optional[List[LibraryEntry]] = None
58
63
 
59
64
  def reset_diagnostics(self) -> None:
60
65
  self.diagnostics = []
61
66
  self.multiple_keywords_result = None
67
+ self.result_bdd_prefix = None
62
68
 
69
+ # TODO: make this threadsafe
63
70
  def find_keyword(
64
71
  self,
65
72
  name: Optional[str],
@@ -70,17 +77,16 @@ class KeywordFinder:
70
77
  try:
71
78
  self.reset_diagnostics()
72
79
 
73
- self.handle_bdd_style = handle_bdd_style
74
-
75
- cached = self._cache.get((name, self.handle_bdd_style), None)
80
+ cached = self._cache.get((name, handle_bdd_style), None)
76
81
 
77
82
  if cached is not None:
78
83
  self.diagnostics = cached[1]
79
84
  self.multiple_keywords_result = cached[2]
85
+ self.result_bdd_prefix = cached[3]
80
86
  return cached[0]
81
87
 
82
88
  try:
83
- result = self._find_keyword(name)
89
+ result = self._find_keyword(name, handle_bdd_style)
84
90
  if result is None:
85
91
  self.diagnostics.append(
86
92
  DiagnosticsEntry(
@@ -99,17 +105,22 @@ class KeywordFinder:
99
105
  result = None
100
106
  self.diagnostics.append(DiagnosticsEntry(str(e), DiagnosticSeverity.ERROR, Error.KEYWORD_ERROR))
101
107
 
102
- self._cache[(name, self.handle_bdd_style)] = (
108
+ self._cache[(name, handle_bdd_style)] = (
103
109
  result,
104
110
  self.diagnostics,
105
111
  self.multiple_keywords_result,
112
+ self.result_bdd_prefix,
106
113
  )
107
114
 
108
115
  return result
109
116
  except CancelSearchError:
110
117
  return None
111
118
 
112
- def _find_keyword(self, name: Optional[str]) -> Optional[KeywordDoc]:
119
+ def _find_keyword(
120
+ self,
121
+ name: Optional[str],
122
+ handle_bdd_style: bool = True,
123
+ ) -> Optional[KeywordDoc]:
113
124
  if not name:
114
125
  self.diagnostics.append(
115
126
  DiagnosticsEntry(
@@ -129,14 +140,21 @@ class KeywordFinder:
129
140
  )
130
141
  raise CancelSearchError
131
142
 
132
- result = self._get_keyword_from_self(name)
143
+ result: Optional[KeywordDoc] = None
144
+
145
+ if get_robot_version() >= (7, 0) and handle_bdd_style:
146
+ result = self._get_bdd_style_keyword(name)
147
+
148
+ if not result:
149
+ result = self._get_keyword_from_self(name)
150
+
133
151
  if not result and "." in name:
134
152
  result = self._get_explicit_keyword(name)
135
153
 
136
154
  if not result:
137
155
  result = self._get_implicit_keyword(name)
138
156
 
139
- if not result and self.handle_bdd_style:
157
+ if get_robot_version() < (7, 0) and not result and handle_bdd_style:
140
158
  return self._get_bdd_style_keyword(name)
141
159
 
142
160
  return result
@@ -264,6 +282,9 @@ class KeywordFinder:
264
282
  def _select_best_matches(
265
283
  self, entries: List[Tuple[Optional[LibraryEntry], KeywordDoc]]
266
284
  ) -> List[Tuple[Optional[LibraryEntry], KeywordDoc]]:
285
+ if len(entries) < 2:
286
+ return entries
287
+
267
288
  normal = [hand for hand in entries if not hand[1].is_embedded]
268
289
  if normal:
269
290
  return normal
@@ -291,23 +312,23 @@ class KeywordFinder:
291
312
  other: Tuple[Optional[LibraryEntry], KeywordDoc],
292
313
  ) -> bool:
293
314
  return (
294
- other[1].matcher.embedded_arguments.match(candidate[1].name) is not None
315
+ other[1].matcher.embedded_arguments is not None
316
+ and candidate[1].matcher.embedded_arguments is not None
317
+ and other[1].matcher.embedded_arguments.match(candidate[1].name) is not None
295
318
  and candidate[1].matcher.embedded_arguments.match(other[1].name) is None
296
319
  )
297
320
 
298
321
  def _get_keyword_from_resource_files(self, name: str) -> Optional[KeywordDoc]:
299
- if self._resource_keywords is None:
300
- self._resource_keywords = list(chain(self.namespace._resources.values()))
322
+ if self._resource_imports is None:
323
+ self._resource_imports = list(chain(self.namespace._resources.values()))
301
324
 
302
325
  if get_robot_version() >= (6, 0):
303
- found: List[Tuple[Optional[LibraryEntry], KeywordDoc]] = []
304
- for v in self._resource_keywords:
305
- r = v.library_doc.keywords.get_all(name)
306
- if r:
307
- found.extend([(v, k) for k in r])
326
+ found: List[Tuple[Optional[LibraryEntry], KeywordDoc]] = [
327
+ (v, k) for v in self._resource_imports for k in v.library_doc.keywords.iter_all(name)
328
+ ]
308
329
  else:
309
330
  found = []
310
- for k in self._resource_keywords:
331
+ for k in self._resource_imports:
311
332
  s = k.library_doc.keywords.get(name, None)
312
333
  if s is not None:
313
334
  found.append((k, s))
@@ -352,19 +373,18 @@ class KeywordFinder:
352
373
  return entries
353
374
 
354
375
  def _get_keyword_from_libraries(self, name: str) -> Optional[KeywordDoc]:
355
- if self._library_keywords is None:
356
- self._library_keywords = list(chain(self.namespace._libraries.values()))
376
+ if self._library_imports is None:
377
+ self._library_imports = list(chain(self.namespace._libraries.values()))
357
378
 
358
379
  if get_robot_version() >= (6, 0):
359
- found: List[Tuple[Optional[LibraryEntry], KeywordDoc]] = []
360
- for v in self._library_keywords:
361
- r = v.library_doc.keywords.get_all(name)
362
- if r:
363
- found.extend([(v, k) for k in r])
380
+ found: List[Tuple[Optional[LibraryEntry], KeywordDoc]] = [
381
+ (v, k) for v in self._library_imports for k in v.library_doc.keywords.iter_all(name)
382
+ ]
383
+
364
384
  else:
365
385
  found = []
366
386
 
367
- for k in self._library_keywords:
387
+ for k in self._library_imports:
368
388
  s = k.library_doc.keywords.get(name, None)
369
389
  if s is not None:
370
390
  found.append((k, s))
@@ -438,21 +458,27 @@ class KeywordFinder:
438
458
  f"or '{'' if standard[0] is None else standard[0].alias or standard[0].name}.{standard[1].name}'."
439
459
  )
440
460
 
461
+ @functools.cached_property
462
+ def bdd_prefix_regexp(self) -> "re.Pattern[str]":
463
+ prefixes = (
464
+ "|".join(
465
+ self.namespace.languages.bdd_prefixes
466
+ if self.namespace.languages is not None
467
+ else ["given", "when", "then", "and", "but"]
468
+ )
469
+ .replace(" ", r"\s")
470
+ .lower()
471
+ )
472
+ return re.compile(rf"({prefixes})\s", re.IGNORECASE)
473
+
441
474
  def _get_bdd_style_keyword(self, name: str) -> Optional[KeywordDoc]:
442
- if get_robot_version() < (6, 0):
443
- lower = name.lower()
444
- for prefix in ["given ", "when ", "then ", "and ", "but "]:
445
- if lower.startswith(prefix):
446
- return self._find_keyword(name[len(prefix) :])
447
- return None
475
+ match = self.bdd_prefix_regexp.match(name)
476
+ if match:
477
+ result = self._find_keyword(
478
+ name[match.end() :], handle_bdd_style=False if get_robot_version() >= (7, 0) else True
479
+ )
480
+ if result:
481
+ self.result_bdd_prefix = str(match.group(0))
448
482
 
449
- parts = name.split()
450
- if len(parts) < 2:
451
- return None
452
- for index in range(1, len(parts)):
453
- prefix = " ".join(parts[:index]).title()
454
- if prefix.title() in (
455
- self.namespace.languages.bdd_prefixes if self.namespace.languages is not None else DEFAULT_BDD_PREFIXES
456
- ):
457
- return self._find_keyword(" ".join(parts[index:]))
483
+ return result
458
484
  return None