robotcode 0.91.0__py3-none-any.whl → 0.93.0__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.
robotcode/cli/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  from pathlib import Path
3
- from typing import List, Optional
3
+ from typing import List, Literal, Optional
4
4
 
5
5
  import click
6
6
 
@@ -49,6 +49,21 @@ from .commands import config, profiles
49
49
  If not specified, the default profile is used.
50
50
  """,
51
51
  )
52
+ @click.option(
53
+ "-r",
54
+ "--root",
55
+ "root",
56
+ type=click.Path(exists=True, path_type=Path, dir_okay=True, file_okay=False, resolve_path=True),
57
+ multiple=False,
58
+ show_envvar=True,
59
+ help="Specifies the root path to be used for the project. It will be automatically detected if not provided.",
60
+ )
61
+ @click.option(
62
+ "--no-vcs",
63
+ is_flag=True,
64
+ show_envvar=True,
65
+ help="Ignore version control system directories (e.g., .git, .hg) when detecting the project root.",
66
+ )
52
67
  @click.option(
53
68
  "-f",
54
69
  "--format",
@@ -95,6 +110,22 @@ from .commands import config, profiles
95
110
  show_default=True,
96
111
  show_envvar=True,
97
112
  )
113
+ @click.option(
114
+ "--log-format",
115
+ type=str,
116
+ help="Sets the log format. See python logging documentation for more information.",
117
+ default="%(name)s:%(levelname)s: %(message)s",
118
+ show_default=True,
119
+ show_envvar=True,
120
+ )
121
+ @click.option(
122
+ "--log-style",
123
+ type=click.Choice(["%", "{", "$"]),
124
+ help="Sets the log style. See python logging documentation for more information.",
125
+ default="%",
126
+ show_default=True,
127
+ show_envvar=True,
128
+ )
98
129
  @click.option(
99
130
  "--log-filename",
100
131
  type=click.Path(
@@ -160,6 +191,8 @@ def robotcode(
160
191
  app: Application,
161
192
  config_files: Optional[List[Path]],
162
193
  profiles: Optional[List[str]],
194
+ root: Optional[Path],
195
+ no_vcs: bool,
163
196
  format: Optional[OutputFormat],
164
197
  dry: bool,
165
198
  verbose: bool,
@@ -167,6 +200,8 @@ def robotcode(
167
200
  pager: Optional[bool],
168
201
  log: bool,
169
202
  log_level: str,
203
+ log_format: str,
204
+ log_style: Literal["%", "{", "$"],
170
205
  log_filename: Optional[str],
171
206
  log_calls: bool,
172
207
  default_path: Optional[List[str]],
@@ -189,6 +224,8 @@ def robotcode(
189
224
  app.config.profiles = profiles
190
225
  app.config.dry = dry
191
226
  app.config.verbose = verbose
227
+ app.config.root = root
228
+ app.config.no_vcs = no_vcs
192
229
 
193
230
  if color is None:
194
231
  app.config.colored_output = ColoredOutput.AUTO
@@ -210,7 +247,8 @@ def robotcode(
210
247
 
211
248
  logging.basicConfig(
212
249
  level=log_level,
213
- format="%(name)s:%(levelname)s: %(message)s",
250
+ format=log_format,
251
+ style=log_style,
214
252
  filename=log_filename,
215
253
  )
216
254
 
@@ -240,9 +278,8 @@ def robotcode(
240
278
  robotcode.add_command(config)
241
279
  robotcode.add_command(profiles)
242
280
 
243
- for p in PluginManager().cli_commands:
244
- for c in p:
245
- robotcode.add_command(c)
281
+ for c in PluginManager.instance().cli_commands:
282
+ robotcode.add_command(c)
246
283
 
247
284
 
248
285
  @robotcode.command()
@@ -1 +1 @@
1
- __version__ = "0.91.0"
1
+ __version__ = "0.93.0"
@@ -2,7 +2,7 @@ import dataclasses
2
2
  import os
3
3
  from fnmatch import fnmatchcase
4
4
  from pathlib import Path
5
- from typing import Any, Dict, List, Optional
5
+ from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Type, Union, get_args, get_origin
6
6
 
7
7
  import click
8
8
 
@@ -20,11 +20,9 @@ from robotcode.robot.config.loader import (
20
20
  load_robot_config_from_path,
21
21
  )
22
22
  from robotcode.robot.config.model import (
23
- LibDocProfile,
24
- RebotProfile,
23
+ BaseOptions,
25
24
  RobotConfig,
26
25
  RobotProfile,
27
- TestDocProfile,
28
26
  )
29
27
  from robotcode.robot.config.utils import get_config_files
30
28
 
@@ -66,11 +64,21 @@ def show(app: Application, single: bool, paths: List[Path]) -> None:
66
64
  ```
67
65
  """
68
66
  try:
69
- config_files, _, _ = get_config_files(paths, app.config.config_files, verbose_callback=app.verbose)
67
+ config_files, _, _ = get_config_files(
68
+ paths,
69
+ app.config.config_files,
70
+ root_folder=app.config.root,
71
+ no_vcs=app.config.no_vcs,
72
+ verbose_callback=app.verbose,
73
+ )
70
74
 
71
75
  if single:
72
76
  for file, _ in config_files:
73
- config = load_robot_config_from_path(file)
77
+ config = load_robot_config_from_path(
78
+ file,
79
+ extra_tools={k: v for k, v in PluginManager.instance().tool_config_classes},
80
+ verbose_callback=app.verbose,
81
+ )
74
82
  click.secho(f"File: {file}")
75
83
  app.print_data(
76
84
  config,
@@ -80,7 +88,11 @@ def show(app: Application, single: bool, paths: List[Path]) -> None:
80
88
 
81
89
  return
82
90
 
83
- config = load_robot_config_from_path(*config_files)
91
+ config = load_robot_config_from_path(
92
+ *config_files,
93
+ extra_tools={k: v for k, v in PluginManager.instance().tool_config_classes},
94
+ verbose_callback=app.verbose,
95
+ )
84
96
 
85
97
  app.print_data(
86
98
  config,
@@ -117,7 +129,13 @@ def files(app: Application, paths: List[Path], user: bool = False) -> None:
117
129
  """
118
130
 
119
131
  try:
120
- config_files, _, discovered_by = get_config_files(paths, app.config.config_files, verbose_callback=app.verbose)
132
+ config_files, _, discovered_by = get_config_files(
133
+ paths,
134
+ app.config.config_files,
135
+ root_folder=app.config.root,
136
+ no_vcs=app.config.no_vcs,
137
+ verbose_callback=app.verbose,
138
+ )
121
139
 
122
140
  result: Dict[str, Any] = {"files": [{"path": str(file), "type": type} for file, type in config_files]}
123
141
 
@@ -147,7 +165,7 @@ def files(app: Application, paths: List[Path], user: bool = False) -> None:
147
165
  required=False,
148
166
  )
149
167
  @pass_application
150
- def root(app: Application, paths: List[Path]) -> None:
168
+ def root(app: Application, paths: Tuple[Path, ...]) -> None:
151
169
  """\
152
170
  Searches for the root folder of the project and prints them.
153
171
 
@@ -162,7 +180,9 @@ def root(app: Application, paths: List[Path]) -> None:
162
180
  ```
163
181
  """
164
182
 
165
- root_folder, discovered_by = find_project_root(*(paths or []))
183
+ root_folder, discovered_by = find_project_root(
184
+ *(paths or []), root_folder=app.config.root, no_vcs=app.config.no_vcs
185
+ )
166
186
 
167
187
  if root_folder is None and (app.config.output_format is None or app.config.output_format == OutputFormat.TEXT):
168
188
  raise click.ClickException("Cannot detect root folder. 😥")
@@ -193,55 +213,51 @@ def info(app: Application) -> None:
193
213
  """Shows informations about possible configuration settings."""
194
214
 
195
215
 
196
- def get_config_fields() -> Dict[str, Dict[str, str]]:
197
- result = {}
198
- for field in dataclasses.fields(RobotConfig):
199
- field_name_encoded = encode_case_for_field_name(RobotConfig, field)
200
- result[field_name_encoded] = {
201
- "type": str(field.type),
202
- "description": field.metadata.get("description", "").strip(),
203
- }
216
+ def type_to_str(t: Union[Type[Any], str]) -> str:
217
+ if isinstance(t, str):
218
+ return f"'{t}'"
219
+
220
+ origin = get_origin(t)
221
+ if origin is None:
222
+ return t.__name__
223
+
224
+ if origin is Union:
225
+ return " | ".join(type_to_str(a) for a in get_args(t))
204
226
 
205
- for field in dataclasses.fields(RobotProfile):
206
- field_name_encoded = encode_case_for_field_name(RobotProfile, field)
207
- if field_name_encoded in result:
227
+ return f"{origin.__name__}[{', '.join(type_to_str(a) for a in get_args(t))}]"
228
+
229
+
230
+ def _get_config_fields_for_type(
231
+ prefix: str, cls: Type[Any], filter: Optional[Callable[[str], bool]] = None
232
+ ) -> Dict[str, Dict[str, str]]:
233
+ result = {}
234
+ for field in dataclasses.fields(cls):
235
+ field_name_encoded = encode_case_for_field_name(cls, field)
236
+ if filter and not filter(field_name_encoded):
208
237
  continue
209
238
 
210
- result["[profile]." + field_name_encoded] = {
211
- "type": str(field.type),
239
+ result[prefix + field_name_encoded] = {
240
+ "type": type_to_str(field.type),
212
241
  "description": field.metadata.get("description", "").strip(),
213
242
  }
243
+ args = get_args(field.type)
214
244
 
215
- for field in dataclasses.fields(RebotProfile):
216
- field_name_encoded = encode_case_for_field_name(RebotProfile, field)
217
- result["rebot." + field_name_encoded] = {
218
- "type": str(field.type),
219
- "description": field.metadata.get("description", "").strip(),
220
- }
245
+ p = f"{prefix}{'' if prefix[-1]=='.' else '.'}" if prefix else ""
246
+ for a in args:
247
+ origin = get_origin(a)
248
+ if origin is None and issubclass(a, BaseOptions):
249
+ result.update(_get_config_fields_for_type(f"{p}{field_name_encoded}.", a, filter))
250
+ return result
221
251
 
222
- for field in dataclasses.fields(LibDocProfile):
223
- field_name_encoded = encode_case_for_field_name(LibDocProfile, field)
224
- result["libdoc." + field_name_encoded] = {
225
- "type": str(field.type),
226
- "description": field.metadata.get("description", "").strip(),
227
- }
228
252
 
229
- for field in dataclasses.fields(TestDocProfile):
230
- field_name_encoded = encode_case_for_field_name(TestDocProfile, field)
231
- result["testdoc." + field_name_encoded] = {
232
- "type": str(field.type),
233
- "description": field.metadata.get("description", "").strip(),
234
- }
253
+ def get_config_fields() -> Dict[str, Dict[str, str]]:
254
+ result = {}
255
+ result.update(_get_config_fields_for_type("", RobotConfig))
235
256
 
236
- for entry in PluginManager().config_classes:
237
- for s, cls in entry:
238
- if dataclasses.is_dataclass(cls):
239
- for field in dataclasses.fields(cls):
240
- field_name_encoded = encode_case_for_field_name(TestDocProfile, field)
241
- result[f"{s}." + field_name_encoded] = {
242
- "type": str(field.type),
243
- "description": field.metadata.get("description", "").strip(),
244
- }
257
+ result.update(_get_config_fields_for_type("[profile].", RobotProfile, lambda x: x not in result))
258
+ for entry in PluginManager.instance().tool_config_classes:
259
+ if dataclasses.is_dataclass(entry.config_class):
260
+ result.update(_get_config_fields_for_type(f"tool.{entry.tool_name}.", entry.config_class))
245
261
 
246
262
  return {k: v for k, v in sorted(result.items(), key=lambda item: item[0])}
247
263
 
@@ -275,7 +291,15 @@ def list(app: Application, name: Optional[List[str]] = None) -> None:
275
291
  result.append(field)
276
292
 
277
293
  if app.config.output_format is None or app.config.output_format == OutputFormat.TEXT:
278
- app.echo_via_pager(os.linesep.join(result))
294
+
295
+ def output() -> Iterable[str]:
296
+ for r in result:
297
+ yield r + os.linesep
298
+
299
+ yield os.linesep
300
+ yield f"Total: {len(result)}"
301
+
302
+ app.echo_via_pager(output())
279
303
  else:
280
304
  app.print_data({"names": result})
281
305
 
@@ -40,9 +40,11 @@ def profiles() -> None:
40
40
  def show(app: Application, no_evaluate: bool, paths: List[Path]) -> None:
41
41
  """Shows the given profile configuration."""
42
42
  try:
43
- config_files, _, _ = get_config_files(paths, app.config.config_files, verbose_callback=app.verbose)
43
+ config_files, _, _ = get_config_files(
44
+ paths, app.config.config_files, root_folder=app.config.root, verbose_callback=app.verbose
45
+ )
44
46
 
45
- config = load_robot_config_from_path(*config_files).combine_profiles(
47
+ config = load_robot_config_from_path(*config_files, verbose_callback=app.verbose).combine_profiles(
46
48
  *(app.config.profiles or []), verbose_callback=app.verbose, error_callback=app.error
47
49
  )
48
50
 
@@ -73,9 +75,15 @@ def list(app: Application, paths: List[Path], show_hidden: bool = False, sort_by
73
75
  """Lists the defined profiles in the current configuration."""
74
76
 
75
77
  try:
76
- config_files, _, discovered_by = get_config_files(paths, app.config.config_files, verbose_callback=app.verbose)
78
+ config_files, _, discovered_by = get_config_files(
79
+ paths,
80
+ app.config.config_files,
81
+ root_folder=app.config.root,
82
+ no_vcs=app.config.no_vcs,
83
+ verbose_callback=app.verbose,
84
+ )
77
85
 
78
- config = load_robot_config_from_path(*config_files)
86
+ config = load_robot_config_from_path(*config_files, verbose_callback=app.verbose)
79
87
 
80
88
  _, selected_profiles, enabled_names = config.combine_profiles_ex(
81
89
  *(app.config.profiles or []), verbose_callback=app.verbose, error_callback=app.error
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: robotcode
3
- Version: 0.91.0
3
+ Version: 0.93.0
4
4
  Summary: Command line interface for RobotCode
5
5
  Project-URL: Homepage, https://robotcode.io
6
6
  Project-URL: Donate, https://opencollective.com/robotcode
@@ -33,33 +33,36 @@ Classifier: Topic :: Text Editors :: Integrated Development Environments (IDE)
33
33
  Classifier: Topic :: Utilities
34
34
  Classifier: Typing :: Typed
35
35
  Requires-Python: >=3.8
36
- Requires-Dist: robotcode-core==0.91.0
37
- Requires-Dist: robotcode-plugin==0.91.0
38
- Requires-Dist: robotcode-robot==0.91.0
36
+ Requires-Dist: robotcode-core==0.93.0
37
+ Requires-Dist: robotcode-plugin==0.93.0
38
+ Requires-Dist: robotcode-robot==0.93.0
39
39
  Provides-Extra: all
40
40
  Requires-Dist: docutils; extra == 'all'
41
41
  Requires-Dist: pyyaml>=5.4; extra == 'all'
42
42
  Requires-Dist: rich; extra == 'all'
43
- Requires-Dist: robotcode-analyze==0.91.0; extra == 'all'
44
- Requires-Dist: robotcode-debugger==0.91.0; extra == 'all'
45
- Requires-Dist: robotcode-language-server==0.91.0; extra == 'all'
46
- Requires-Dist: robotcode-runner==0.91.0; extra == 'all'
43
+ Requires-Dist: robotcode-analyze==0.93.0; extra == 'all'
44
+ Requires-Dist: robotcode-debugger==0.93.0; extra == 'all'
45
+ Requires-Dist: robotcode-language-server==0.93.0; extra == 'all'
46
+ Requires-Dist: robotcode-repl==0.93.0; extra == 'all'
47
+ Requires-Dist: robotcode-runner==0.93.0; extra == 'all'
47
48
  Requires-Dist: robotframework-robocop>=2.0.0; extra == 'all'
48
49
  Requires-Dist: robotframework-tidy>=2.0.0; extra == 'all'
49
50
  Provides-Extra: analyze
50
- Requires-Dist: robotcode-analyze==0.91.0; extra == 'analyze'
51
+ Requires-Dist: robotcode-analyze==0.93.0; extra == 'analyze'
51
52
  Provides-Extra: colored
52
53
  Requires-Dist: rich; extra == 'colored'
53
54
  Provides-Extra: debugger
54
- Requires-Dist: robotcode-debugger==0.91.0; extra == 'debugger'
55
+ Requires-Dist: robotcode-debugger==0.93.0; extra == 'debugger'
55
56
  Provides-Extra: languageserver
56
- Requires-Dist: robotcode-language-server==0.91.0; extra == 'languageserver'
57
+ Requires-Dist: robotcode-language-server==0.93.0; extra == 'languageserver'
57
58
  Provides-Extra: lint
58
59
  Requires-Dist: robotframework-robocop>=2.0.0; extra == 'lint'
60
+ Provides-Extra: repl
61
+ Requires-Dist: robotcode-repl==0.93.0; extra == 'repl'
59
62
  Provides-Extra: rest
60
63
  Requires-Dist: docutils; extra == 'rest'
61
64
  Provides-Extra: runner
62
- Requires-Dist: robotcode-runner==0.91.0; extra == 'runner'
65
+ Requires-Dist: robotcode-runner==0.93.0; extra == 'runner'
63
66
  Provides-Extra: tidy
64
67
  Requires-Dist: robotframework-tidy>=2.0.0; extra == 'tidy'
65
68
  Provides-Extra: yaml
@@ -0,0 +1,12 @@
1
+ robotcode/cli/__init__.py,sha256=davaLdB53bWWMqm4BMmjktKlL0AyzOuMObZbNbmhiQE,8226
2
+ robotcode/cli/__main__.py,sha256=hX3nwROMTnsYGT1KS0rXUYrslu9sFzctYdAh66Rcckw,153
3
+ robotcode/cli/__version__.py,sha256=W-KEJT0wpRrG8XJ2aDG4NSyzaUucgZR9y6mwfCTlku4,23
4
+ robotcode/cli/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
5
+ robotcode/cli/commands/__init__.py,sha256=XJHRt_YwMO2Ni2EfL2aj4jkJXMVG6NGFTpzvSVgIRnQ,92
6
+ robotcode/cli/commands/config.py,sha256=84gG4LrIynfPbEQkQDYA3ZClg50ck32NZyUvAWw9g6w,10479
7
+ robotcode/cli/commands/profiles.py,sha256=GAyNsnz4vvybkEfktFTjDm-L4zkcntXZtBt385U9oRo,5897
8
+ robotcode-0.93.0.dist-info/METADATA,sha256=eKwu6UpIwPOazyU3KKtC1bj4TQ23OzHM7CT8Rpdcs-0,6758
9
+ robotcode-0.93.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
10
+ robotcode-0.93.0.dist-info/entry_points.txt,sha256=Pb4DKVVdJb5PboVl48njwk3DkKQHBJOL1A8KkpemqA8,58
11
+ robotcode-0.93.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
12
+ robotcode-0.93.0.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- robotcode/cli/__init__.py,sha256=6c-evRLgJ0NR08YvynBQzKxAesAbXB0fnrzZ7MvBDM0,7115
2
- robotcode/cli/__main__.py,sha256=hX3nwROMTnsYGT1KS0rXUYrslu9sFzctYdAh66Rcckw,153
3
- robotcode/cli/__version__.py,sha256=RBon26SFk4Bs08h0XAmTYW8lrYs3N9ihifF9r6VT4Vc,23
4
- robotcode/cli/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
5
- robotcode/cli/commands/__init__.py,sha256=XJHRt_YwMO2Ni2EfL2aj4jkJXMVG6NGFTpzvSVgIRnQ,92
6
- robotcode/cli/commands/config.py,sha256=fCXhxsotQJl3vMSWpCEM-zwV-tST7sZBH7T-5v9j5EU,10061
7
- robotcode/cli/commands/profiles.py,sha256=HUCsNMaK75AVSG_A6F1I209xtQH2AICaoLcqpIO7Vjs,5660
8
- robotcode-0.91.0.dist-info/METADATA,sha256=IW1fsf7rm_4v9JmF4IWn6BhvmxyTOSqjctFnqROtVuA,6628
9
- robotcode-0.91.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
10
- robotcode-0.91.0.dist-info/entry_points.txt,sha256=Pb4DKVVdJb5PboVl48njwk3DkKQHBJOL1A8KkpemqA8,58
11
- robotcode-0.91.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
12
- robotcode-0.91.0.dist-info/RECORD,,