robotcode-robot 0.68.0__py3-none-any.whl → 0.68.2__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,8 +1,7 @@
1
1
  from typing import Optional
2
2
 
3
- from robotcode.core.utils.version import Version, create_version_from_str
4
-
5
3
  import robot.version
4
+ from robotcode.core.utils.version import Version, create_version_from_str
6
5
 
7
6
  _robot_version: Optional[Version] = None
8
7
 
@@ -2,24 +2,15 @@ from __future__ import annotations
2
2
 
3
3
  import ast
4
4
  import itertools
5
- from typing import (
6
- Any,
7
- AsyncIterator,
8
- Iterator,
9
- List,
10
- Optional,
11
- Sequence,
12
- Set,
13
- Tuple,
14
- )
15
-
16
- from robotcode.core.lsp.types import Position, Range
5
+ from typing import Any, Iterator, List, Optional, Sequence, Set, Tuple
17
6
 
18
7
  from robot.errors import VariableError
19
8
  from robot.parsing.lexer.tokens import Token
20
9
  from robot.parsing.model.statements import EmptyLine, Statement
10
+ from robotcode.core.lsp.types import Position, Range
21
11
 
22
- from . import get_robot_version, visitors
12
+ from . import get_robot_version
13
+ from .visitor import Visitor
23
14
 
24
15
  if get_robot_version() < (7, 0):
25
16
  from robot.variables.search import VariableIterator
@@ -45,14 +36,11 @@ def iter_nodes(node: ast.AST, descendants: bool = True) -> Iterator[ast.AST]:
45
36
  def range_from_token(token: Token) -> Range:
46
37
  return Range(
47
38
  start=Position(line=token.lineno - 1, character=token.col_offset),
48
- end=Position(
49
- line=token.lineno - 1,
50
- character=token.end_col_offset,
51
- ),
39
+ end=Position(line=token.lineno - 1, character=token.end_col_offset),
52
40
  )
53
41
 
54
42
 
55
- class FirstAndLastRealStatementFinder(visitors.Visitor):
43
+ class FirstAndLastRealStatementFinder(Visitor):
56
44
  def __init__(self) -> None:
57
45
  super().__init__()
58
46
  self.first_statement: Optional[ast.AST] = None
@@ -113,12 +101,18 @@ def _get_non_data_range_from_node(
113
101
  None,
114
102
  )
115
103
  if start_token is not None and end_token is not None:
116
- return Range(start=range_from_token(start_token).start, end=range_from_token(end_token).end)
104
+ return Range(
105
+ start=range_from_token(start_token).start,
106
+ end=range_from_token(end_token).end,
107
+ )
117
108
  return None
118
109
 
119
110
 
120
111
  def range_from_node(
121
- node: ast.AST, skip_non_data: bool = False, only_start: bool = False, allow_comments: bool = False
112
+ node: ast.AST,
113
+ skip_non_data: bool = False,
114
+ only_start: bool = False,
115
+ allow_comments: bool = False,
122
116
  ) -> Range:
123
117
  if skip_non_data:
124
118
  if isinstance(node, Statement) and node.tokens:
@@ -206,20 +200,20 @@ def get_tokens_at_position(node: Statement, position: Position, include_end: boo
206
200
  ]
207
201
 
208
202
 
209
- def iter_nodes_at_position(node: ast.AST, position: Position, include_end: bool = False) -> AsyncIterator[ast.AST]:
203
+ def iter_nodes_at_position(node: ast.AST, position: Position, include_end: bool = False) -> Iterator[ast.AST]:
210
204
  return (
211
205
  n
212
- async for n in visitors.iter_nodes(node)
206
+ for n in iter_nodes(node)
213
207
  if position.is_in_range(range := range_from_node(n), include_end) or include_end and range.end == position
214
208
  )
215
209
 
216
210
 
217
- async def get_nodes_at_position(node: ast.AST, position: Position, include_end: bool = False) -> List[ast.AST]:
218
- return [n async for n in iter_nodes_at_position(node, position, include_end)]
211
+ def get_nodes_at_position(node: ast.AST, position: Position, include_end: bool = False) -> List[ast.AST]:
212
+ return [n for n in iter_nodes_at_position(node, position, include_end)]
219
213
 
220
214
 
221
- async def get_node_at_position(node: ast.AST, position: Position, include_end: bool = False) -> Optional[ast.AST]:
222
- result_nodes = await get_nodes_at_position(node, position, include_end)
215
+ def get_node_at_position(node: ast.AST, position: Position, include_end: bool = False) -> Optional[ast.AST]:
216
+ result_nodes = get_nodes_at_position(node, position, include_end)
223
217
  if not result_nodes:
224
218
  return None
225
219
 
@@ -231,7 +225,11 @@ def _tokenize_no_variables(token: Token) -> Iterator[Token]:
231
225
 
232
226
 
233
227
  def tokenize_variables(
234
- token: Token, identifiers: str = "$@&%", ignore_errors: bool = False, *, extra_types: Optional[Set[str]] = None
228
+ token: Token,
229
+ identifiers: str = "$@&%",
230
+ ignore_errors: bool = False,
231
+ *,
232
+ extra_types: Optional[Set[str]] = None,
235
233
  ) -> Iterator[Token]:
236
234
  if token.type not in {
237
235
  *Token.ALLOW_VARIABLES,
@@ -281,7 +279,9 @@ else:
281
279
  yield Token(token.type, after, lineno, col_offset)
282
280
 
283
281
 
284
- def iter_over_keyword_names_and_owners(full_name: str) -> Iterator[Tuple[Optional[str], ...]]:
282
+ def iter_over_keyword_names_and_owners(
283
+ full_name: str,
284
+ ) -> Iterator[Tuple[Optional[str], ...]]:
285
285
  yield None, full_name
286
286
 
287
287
  tokens = full_name.split(".")
@@ -301,7 +301,12 @@ def strip_variable_token(token: Token) -> Token:
301
301
 
302
302
  stripped_value = value.lstrip()
303
303
  stripped_offset = len(value) - len(stripped_value)
304
- return Token(token.type, stripped_value.rstrip(), token.lineno, token.col_offset + 2 + stripped_offset)
304
+ return Token(
305
+ token.type,
306
+ stripped_value.rstrip(),
307
+ token.lineno,
308
+ token.col_offset + 2 + stripped_offset,
309
+ )
305
310
 
306
311
  return token
307
312
 
@@ -150,7 +150,7 @@ class LinkFormatter:
150
150
  return "".join(f(t) for f, t in zip(formatters, tokens))
151
151
 
152
152
  def _format_link(self, text: str) -> str:
153
- link, content = [t.strip() for t in text.split("|", 1)]
153
+ link, content = (t.strip() for t in text.split("|", 1))
154
154
  if self._is_image(content):
155
155
  content = self._get_image(content, link)
156
156
  elif self._is_image(link):
@@ -171,7 +171,7 @@ class LinkFormatter:
171
171
  if "|" not in text:
172
172
  return text
173
173
 
174
- link, content = [t.strip() for t in text.split("|", 1)]
174
+ link, content = (t.strip() for t in text.split("|", 1))
175
175
  if self._is_image(content):
176
176
  return self._get_image(content, link)
177
177
 
@@ -0,0 +1,23 @@
1
+ from functools import lru_cache
2
+
3
+
4
+ @lru_cache(maxsize=5000)
5
+ def normalize(text: str) -> str:
6
+ return text.lower().replace("_", "").replace(" ", "")
7
+
8
+
9
+ @lru_cache(maxsize=5000)
10
+ def normalize_namespace(text: str) -> str:
11
+ return text.lower().replace(" ", "")
12
+
13
+
14
+ def eq(str1: str, str2: str) -> bool:
15
+ str1 = normalize(str1)
16
+ str2 = normalize(str2)
17
+ return str1 == str2
18
+
19
+
20
+ def eq_namespace(str1: str, str2: str) -> bool:
21
+ str1 = normalize_namespace(str1)
22
+ str2 = normalize_namespace(str2)
23
+ return str1 == str2
@@ -0,0 +1,70 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from os import PathLike
5
+ from pathlib import Path
6
+ from typing import Optional, Union
7
+
8
+
9
+ def find_file(
10
+ path: Union[Path, PathLike[str], str],
11
+ basedir: Union[Path, PathLike[str], str] = ".",
12
+ file_type: Optional[str] = None,
13
+ ) -> str:
14
+ return find_file_ex(path, basedir, file_type)
15
+
16
+
17
+ def find_file_ex(
18
+ path: Union[Path, PathLike[str], str],
19
+ basedir: Union[Path, PathLike[str], str] = ".",
20
+ file_type: Optional[str] = None,
21
+ ) -> str:
22
+ from robot.errors import DataError
23
+
24
+ path = Path(path)
25
+ ret = _find_absolute_path(path) if path.is_absolute() else _find_relative_path(path, basedir)
26
+ if ret:
27
+ return str(ret)
28
+ default = file_type or "File"
29
+
30
+ file_type = (
31
+ {
32
+ "Library": "Test library",
33
+ "Variables": "Variable file",
34
+ "Resource": "Resource file",
35
+ }.get(file_type, default)
36
+ if file_type
37
+ else default
38
+ )
39
+
40
+ raise DataError("%s '%s' does not exist." % (file_type, path))
41
+
42
+
43
+ def _find_absolute_path(path: Union[Path, PathLike[str], str]) -> Optional[str]:
44
+ if _is_valid_file(path):
45
+ return str(path)
46
+ return None
47
+
48
+
49
+ def _find_relative_path(
50
+ path: Union[Path, PathLike[str], str],
51
+ basedir: Union[Path, PathLike[str], str],
52
+ ) -> Optional[str]:
53
+ for base in [basedir, *sys.path]:
54
+ if not base:
55
+ continue
56
+ base_path = Path(base)
57
+
58
+ if not base_path.is_dir():
59
+ continue
60
+
61
+ ret = Path(base, path).absolute()
62
+
63
+ if _is_valid_file(ret):
64
+ return str(ret)
65
+ return None
66
+
67
+
68
+ def _is_valid_file(path: Union[Path, PathLike[str], str]) -> bool:
69
+ path = Path(path)
70
+ return path.is_file() or (path.is_dir() and Path(path, "__init__.py").is_fifo())
@@ -0,0 +1,24 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, List, Optional, Protocol, runtime_checkable
4
+
5
+
6
+ @runtime_checkable
7
+ class HasError(Protocol):
8
+ error: Optional[str]
9
+
10
+
11
+ @runtime_checkable
12
+ class HasErrors(Protocol):
13
+ errors: Optional[List[str]]
14
+
15
+
16
+ @runtime_checkable
17
+ class HeaderAndBodyBlock(Protocol):
18
+ header: Any
19
+ body: List[Any]
20
+
21
+
22
+ @runtime_checkable
23
+ class BodyBlock(Protocol):
24
+ body: List[Any]
@@ -0,0 +1,37 @@
1
+ BUILTIN_VARIABLES = [
2
+ "${CURDIR}",
3
+ "${EMPTY}",
4
+ "${TEMPDIR}",
5
+ "${EXECDIR}",
6
+ "${/}",
7
+ "${:}",
8
+ "${\\n}",
9
+ "${SPACE}",
10
+ "${True}",
11
+ "${False}",
12
+ "${None}",
13
+ "${null}",
14
+ "${OPTIONS}",
15
+ "${TEST_NAME}",
16
+ "@{TEST_TAGS}",
17
+ "${TEST_DOCUMENTATION}",
18
+ "${TEST_STATUS}",
19
+ "${TEST_MESSAGE}",
20
+ "${PREV_TEST_NAME}",
21
+ "${PREV_TEST_STATUS}",
22
+ "${PREV_TEST_MESSAGE}",
23
+ "${SUITE_NAME}",
24
+ "${SUITE_SOURCE}",
25
+ "${SUITE_DOCUMENTATION}",
26
+ "&{SUITE_METADATA}",
27
+ "${SUITE_STATUS}",
28
+ "${SUITE_MESSAGE}",
29
+ "${KEYWORD_STATUS}",
30
+ "${KEYWORD_MESSAGE}",
31
+ "${LOG_LEVEL}",
32
+ "${OUTPUT_FILE}",
33
+ "${LOG_FILE}",
34
+ "${REPORT_FILE}",
35
+ "${DEBUG_FILE}",
36
+ "${OUTPUT_DIR}",
37
+ ]
@@ -1,13 +1,19 @@
1
1
  import ast
2
2
  from abc import ABC
3
3
  from collections import defaultdict
4
-
5
- from typing_extensions import Any, AsyncIterator, Callable, Dict, Iterator, Optional, Type, Union
4
+ from typing import (
5
+ Any,
6
+ AsyncIterator,
7
+ Callable,
8
+ Dict,
9
+ Iterator,
10
+ Optional,
11
+ Type,
12
+ Union,
13
+ )
6
14
 
7
15
  from robot.parsing.model.statements import Statement
8
16
 
9
- __all__ = ["iter_fields", "iter_child_nodes", "AsyncVisitor"]
10
-
11
17
 
12
18
  def _patch_robot() -> None:
13
19
  if hasattr(Statement, "_fields"):
@@ -93,23 +99,6 @@ class VisitorFinder(ABC):
93
99
  return result # type: ignore[return-value]
94
100
 
95
101
 
96
- class AsyncVisitor(VisitorFinder):
97
- async def visit(self, node: ast.AST) -> None:
98
- visitor = self._find_visitor(type(node)) or self.__class__.generic_visit
99
- await visitor(self, node)
100
-
101
- async def generic_visit(self, node: ast.AST) -> None:
102
- for value in iter_field_values(node):
103
- if value is None:
104
- continue
105
- if isinstance(value, ast.AST):
106
- await self.visit(value)
107
- elif isinstance(value, list):
108
- for item in value:
109
- if isinstance(item, ast.AST):
110
- await self.visit(item)
111
-
112
-
113
102
  class Visitor(VisitorFinder):
114
103
  def visit(self, node: ast.AST) -> None:
115
104
  visitor = self._find_visitor(type(node)) or self.__class__.generic_visit
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: robotcode-robot
3
- Version: 0.68.0
3
+ Version: 0.68.2
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://github.com/sponsors/d-biehl
@@ -9,7 +9,7 @@ Project-URL: Changelog, https://github.com/d-biehl/robotcode/blob/main/CHANGELOG
9
9
  Project-URL: Issues, https://github.com/d-biehl/robotcode/issues
10
10
  Project-URL: Source, https://github.com/d-biehl/robotcode
11
11
  Author-email: Daniel Biehl <dbiehl@live.de>
12
- License-Expression: Apache-2.0
12
+ License: Apache-2.0
13
13
  License-File: LICENSE.txt
14
14
  Classifier: Development Status :: 5 - Production/Stable
15
15
  Classifier: Framework :: Robot Framework
@@ -25,8 +25,8 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
25
25
  Classifier: Topic :: Utilities
26
26
  Classifier: Typing :: Typed
27
27
  Requires-Python: >=3.8
28
- Requires-Dist: platformdirs<3.12.0,>=3.2.0
29
- Requires-Dist: robotcode-core==0.68.0
28
+ Requires-Dist: platformdirs<4.2.0,>=3.2.0
29
+ Requires-Dist: robotcode-core==0.68.2
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
@@ -0,0 +1,22 @@
1
+ robotcode/robot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ robotcode/robot/__version__.py,sha256=L1uo5mxlPb32TYSeQYo02HehpkMuc4yGjlhnwLOypps,23
3
+ robotcode/robot/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
4
+ robotcode/robot/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ robotcode/robot/config/loader.py,sha256=RvFjU3fu5U4VlTSVDa0uUzZNAnpVdZwIy_4a0sXh6d0,5777
6
+ robotcode/robot/config/model.py,sha256=MsLye21oCpjSeaaeU1VqhKomGX3GUqZ43eaFgf3OVXg,81856
7
+ robotcode/robot/config/utils.py,sha256=mNNE8Uq5U78_OPwhOdZjtt1HufczyEHogGMB0azRcC4,2651
8
+ robotcode/robot/diagnostics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ robotcode/robot/diagnostics/entities.py,sha256=nyItwiHQVHOAmocvCS6C0lQZhNTdt_L7CUzYQQEHsus,10456
10
+ robotcode/robot/diagnostics/library_doc.py,sha256=tPssawTnT9fLS7c28T9Wb63DThiBpjIMlil8gqvXJ-s,96906
11
+ robotcode/robot/utils/__init__.py,sha256=OjNPMn_XSnfaMCyKd8Kmq6vlRt6mIGlzW4qiiD3ykUg,447
12
+ robotcode/robot/utils/ast.py,sha256=FlRFAUtBYEKLlT7N7T2kpK0UuZ-uL5ayYZ_MBG39NqY,10119
13
+ robotcode/robot/utils/markdownformatter.py,sha256=h4s18lQ8auHLxsMKYIgJQ2p5d_K_PTaJuCtG-xdS-cg,11653
14
+ robotcode/robot/utils/match.py,sha256=jxKXVpv0SHw_LxsDc1vgOxSGGtcV_9eO9cOVj4MAgIo,527
15
+ robotcode/robot/utils/robot_path.py,sha256=qKBh1cEnReBBLKkWu4gB9EzM-scAwE4xJc1m6v2LRN0,1786
16
+ robotcode/robot/utils/stubs.py,sha256=zFMAAl3xitfVW4tS2AMNpS8KAG9IRp6pZ8AQLL9FT_4,417
17
+ robotcode/robot/utils/variables.py,sha256=fEl8S37lb_mD4hn2MZRAlkiuLGBjAOeZVK0r2o2CfPw,742
18
+ robotcode/robot/utils/visitor.py,sha256=uYLqEhGPmzWKWI3SSrmCaYMwtKvNShvbiPZ4b3FavX8,3241
19
+ robotcode_robot-0.68.2.dist-info/METADATA,sha256=LX0RWrOvcWul8q1fX1L_71yNZ8w2c2C8xo_LBs0wYcE,2209
20
+ robotcode_robot-0.68.2.dist-info/WHEEL,sha256=mRYSEL3Ih6g5a_CVMIcwiF__0Ae4_gLYh01YFNwiq1k,87
21
+ robotcode_robot-0.68.2.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
22
+ robotcode_robot-0.68.2.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- robotcode/robot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- robotcode/robot/__version__.py,sha256=HxxTcUQtaiYOEEtr3P4K4pOTRoC_pmpqzV7TOSUOpSQ,23
3
- robotcode/robot/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
4
- robotcode/robot/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- robotcode/robot/config/loader.py,sha256=7HSpMU5uCSOVzg9cIuKPShiwmbdvL7ITH6G6P1iHKzY,5661
6
- robotcode/robot/config/model.py,sha256=ijjwhSgo-k7fvBnomxw-jGs9LR1mwZuNNb64tnoWjEo,80958
7
- robotcode/robot/config/utils.py,sha256=hX-bMn9CFqxrcwQo-WPnRXh1PK434HYbLQgZp89ZHeE,2447
8
- robotcode/robot/utils/__init__.py,sha256=aW_jxCqt1PR1LYu2LLWsm8lIqIqAi2ZBinACGdiLelE,448
9
- robotcode/robot/utils/ast.py,sha256=qeTq6Em8bjE6urAZR5HlLDuqz-XNP6yG1eq-lVeay90,10098
10
- robotcode/robot/utils/markdownformatter.py,sha256=3RHkP8JCg0IzeIY6iIp533V6ZQTaonpTqKdYaAjscpM,11653
11
- robotcode/robot/utils/visitors.py,sha256=YuQuW228cxhUAdsI1TEXz0vT4QNubD037RDEftQ1FDg,3898
12
- robotcode_robot-0.68.0.dist-info/METADATA,sha256=R1J4EUYoUqJM3GrtP8CLsNHM1FyCpCY3o17UpyO18qc,2221
13
- robotcode_robot-0.68.0.dist-info/WHEEL,sha256=mRYSEL3Ih6g5a_CVMIcwiF__0Ae4_gLYh01YFNwiq1k,87
14
- robotcode_robot-0.68.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
15
- robotcode_robot-0.68.0.dist-info/RECORD,,