robotcode-runner 0.85.0__tar.gz → 0.86.0__tar.gz

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,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: robotcode-runner
3
- Version: 0.85.0
3
+ Version: 0.86.0
4
4
  Summary: RobotCode runner plugin for Robot Framework
5
5
  Project-URL: Homepage, https://robotcode.io
6
6
  Project-URL: Donate, https://opencollective.com/robotcode
@@ -25,10 +25,10 @@ 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: robotcode-modifiers==0.85.0
29
- Requires-Dist: robotcode-plugin==0.85.0
30
- Requires-Dist: robotcode-robot==0.85.0
31
- Requires-Dist: robotcode==0.85.0
28
+ Requires-Dist: robotcode-modifiers==0.86.0
29
+ Requires-Dist: robotcode-plugin==0.86.0
30
+ Requires-Dist: robotcode-robot==0.86.0
31
+ Requires-Dist: robotcode==0.86.0
32
32
  Requires-Dist: robotframework>=4.1.0
33
33
  Description-Content-Type: text/markdown
34
34
 
@@ -28,10 +28,10 @@ classifiers = [
28
28
  dynamic = ["version"]
29
29
  dependencies = [
30
30
  "robotframework>=4.1.0",
31
- "robotcode-robot==0.85.0",
32
- "robotcode-modifiers==0.85.0",
33
- "robotcode-plugin==0.85.0",
34
- "robotcode==0.85.0",
31
+ "robotcode-robot==0.86.0",
32
+ "robotcode-modifiers==0.86.0",
33
+ "robotcode-plugin==0.86.0",
34
+ "robotcode==0.86.0",
35
35
  ]
36
36
 
37
37
  [project.entry-points.robotcode]
@@ -0,0 +1 @@
1
+ __version__ = "0.86.0"
@@ -70,7 +70,7 @@ def _patch() -> None:
70
70
  return
71
71
  __patched = True
72
72
 
73
- if get_robot_version() <= (6, 1):
73
+ if get_robot_version() < (6, 1):
74
74
  if get_robot_version() > (5, 0) and get_robot_version() < (6, 0) or get_robot_version() < (5, 0):
75
75
  from robot.running.builder.testsettings import ( # pyright: ignore[reportMissingImports]
76
76
  TestDefaults,
@@ -1,23 +1,148 @@
1
1
  import os
2
2
  import sys
3
+ import weakref
3
4
  from pathlib import Path
4
- from typing import Any, List, Optional, Set, Tuple, Union, cast
5
+ from typing import Any, Dict, List, Optional, Set, Tuple, Union, cast
5
6
 
6
7
  import click
7
8
  from robot.errors import DataError, Information
8
9
  from robot.run import USAGE, RobotFramework
10
+ from robot.running.builder.builders import SuiteStructureBuilder
9
11
  from robot.version import get_full_version
10
12
 
11
13
  import robotcode.modifiers
14
+ from robotcode.core.ignore_spec import DEFAULT_SPEC_RULES, GIT_IGNORE_FILE, ROBOT_IGNORE_FILE, IgnoreSpec
15
+ from robotcode.core.utils.path import path_is_relative_to
12
16
  from robotcode.plugin import Application, pass_application
13
17
  from robotcode.plugin.click_helper.aliases import AliasedCommand
14
18
  from robotcode.plugin.click_helper.types import add_options
15
19
  from robotcode.robot.config.loader import load_robot_config_from_path
16
20
  from robotcode.robot.config.model import RobotBaseProfile
17
21
  from robotcode.robot.config.utils import get_config_files
22
+ from robotcode.robot.utils import get_robot_version
18
23
 
19
24
  from ..__version__ import __version__
20
25
 
26
+ _app: Optional[Application] = None
27
+
28
+ __patched = False
29
+
30
+
31
+ def _patch() -> None:
32
+ global __patched
33
+ if __patched:
34
+ return
35
+ __patched = True
36
+
37
+ if get_robot_version() < (6, 1):
38
+ old_is_included = SuiteStructureBuilder._is_included
39
+
40
+ def _is_included_lt_61(self: SuiteStructureBuilder, path: str, base: str, ext: Any, incl_suites: Any) -> bool:
41
+ if not old_is_included(self, path, base, ext, incl_suites):
42
+ return False
43
+
44
+ return not _is_ignored(self, Path(path))
45
+
46
+ SuiteStructureBuilder._is_included = _is_included_lt_61
47
+ elif get_robot_version() >= (6, 1):
48
+ old_is_included = SuiteStructureBuilder._is_included
49
+
50
+ def _is_included(self: SuiteStructureBuilder, path: Path) -> bool:
51
+ if not old_is_included(self, path):
52
+ return False
53
+
54
+ return not _is_ignored(self, path)
55
+
56
+ SuiteStructureBuilder._is_included = _is_included
57
+
58
+
59
+ class BuilderCacheData:
60
+ def __init__(self) -> None:
61
+ self.spec: Optional[IgnoreSpec] = None
62
+ self.ignore_files: List[str] = [ROBOT_IGNORE_FILE, GIT_IGNORE_FILE]
63
+
64
+
65
+ class BuilderCache:
66
+ def __init__(self) -> None:
67
+ self.data: Dict[Path, BuilderCacheData] = {}
68
+ self.base_path: Path = _app.root_folder if _app is not None else Path.cwd()
69
+
70
+
71
+ _BuilderCache: "weakref.WeakKeyDictionary[SuiteStructureBuilder, BuilderCache]" = weakref.WeakKeyDictionary()
72
+
73
+
74
+ def _is_ignored(builder: SuiteStructureBuilder, path: Path) -> bool:
75
+ if builder not in _BuilderCache:
76
+ _BuilderCache[builder] = BuilderCache()
77
+
78
+ cache_data = _BuilderCache[builder]
79
+
80
+ curr_dir = path.parent
81
+
82
+ curr_dir = Path(os.path.abspath(curr_dir))
83
+
84
+ if curr_dir not in cache_data.data:
85
+
86
+ parent_data: Optional[BuilderCacheData] = None
87
+ parent_spec_dir: Optional[Path] = None
88
+
89
+ dir = curr_dir
90
+
91
+ if path_is_relative_to(curr_dir, cache_data.base_path):
92
+ while True:
93
+ if dir in cache_data.data:
94
+ parent_data = cache_data.data[dir]
95
+ parent_spec_dir = dir
96
+ break
97
+ dir = dir.parent
98
+ if not path_is_relative_to(dir, cache_data.base_path):
99
+ break
100
+ else:
101
+ # TODO: we are in a different folder
102
+ if curr_dir.parent in cache_data.data:
103
+ parent_data = cache_data.data[curr_dir.parent]
104
+ parent_spec_dir = curr_dir.parent
105
+ else:
106
+ parent_spec_dir = curr_dir
107
+ if parent_spec_dir in cache_data.data:
108
+ parent_data = cache_data.data[parent_spec_dir]
109
+
110
+ if parent_spec_dir is None:
111
+ parent_spec_dir = cache_data.base_path
112
+
113
+ if parent_data is None:
114
+ parent_data = BuilderCacheData()
115
+ parent_data.spec = IgnoreSpec.from_list(DEFAULT_SPEC_RULES, parent_spec_dir)
116
+
117
+ ignore_file = next(
118
+ (parent_spec_dir / f for f in parent_data.ignore_files if (parent_spec_dir / f).is_file()), None
119
+ )
120
+
121
+ if ignore_file is not None:
122
+ parent_data.ignore_files = [ignore_file.name]
123
+
124
+ parent_data.spec = parent_data.spec + IgnoreSpec.from_gitignore(parent_spec_dir / ignore_file)
125
+ cache_data.data[parent_spec_dir] = parent_data
126
+
127
+ if parent_data is not None and parent_data.spec is not None and parent_spec_dir != curr_dir:
128
+ ignore_file = next((curr_dir / f for f in parent_data.ignore_files if (curr_dir / f).is_file()), None)
129
+
130
+ if ignore_file is not None:
131
+ curr_data = BuilderCacheData()
132
+
133
+ curr_data.spec = parent_data.spec + IgnoreSpec.from_gitignore(curr_dir / ignore_file)
134
+ curr_data.ignore_files = [ignore_file.name]
135
+
136
+ cache_data.data[curr_dir] = curr_data
137
+ else:
138
+ cache_data.data[curr_dir] = parent_data
139
+
140
+ spec = cache_data.data[curr_dir].spec
141
+ if spec is not None and spec.matches(path):
142
+ return True
143
+
144
+ return False
145
+
21
146
 
22
147
  class RobotFrameworkEx(RobotFramework):
23
148
  def __init__(
@@ -109,6 +234,12 @@ ROBOT_OPTIONS: Set[click.Command] = {
109
234
  def handle_robot_options(
110
235
  app: Application, robot_options_and_args: Tuple[str, ...]
111
236
  ) -> Tuple[Optional[Path], RobotBaseProfile, List[str]]:
237
+
238
+ global _app
239
+ _app = app
240
+
241
+ _patch()
242
+
112
243
  robot_arguments: Optional[List[Union[str, Path]]] = None
113
244
  old_sys_path = sys.path.copy()
114
245
  try:
@@ -137,6 +268,9 @@ def handle_robot_options(
137
268
  + " ".join(f'"{o}"' for o in (cmd_options + list(robot_options_and_args)))
138
269
  )
139
270
 
271
+ if root_folder is not None:
272
+ app.root_folder = root_folder
273
+
140
274
  return root_folder, profile, cmd_options
141
275
 
142
276
 
@@ -1 +0,0 @@
1
- __version__ = "0.85.0"