robotcode-robot 0.78.0__tar.gz → 0.78.1__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/PKG-INFO +2 -2
  2. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/pyproject.toml +1 -1
  3. robotcode_robot-0.78.1/src/robotcode/robot/__version__.py +1 -0
  4. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/config/model.py +65 -14
  5. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/diagnostics/entities.py +3 -0
  6. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/diagnostics/namespace.py +24 -0
  7. robotcode_robot-0.78.0/src/robotcode/robot/__version__.py +0 -1
  8. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/.gitignore +0 -0
  9. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/LICENSE.txt +0 -0
  10. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/README.md +0 -0
  11. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/__init__.py +0 -0
  12. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/config/__init__.py +0 -0
  13. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/config/loader.py +0 -0
  14. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/config/utils.py +0 -0
  15. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/diagnostics/__init__.py +0 -0
  16. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/diagnostics/document_cache_helper.py +0 -0
  17. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/diagnostics/errors.py +0 -0
  18. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/diagnostics/imports_manager.py +0 -0
  19. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/diagnostics/library_doc.py +0 -0
  20. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/diagnostics/model_helper.py +0 -0
  21. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/diagnostics/namespace_analyzer.py +0 -0
  22. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/diagnostics/workspace_config.py +0 -0
  23. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/py.typed +0 -0
  24. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/utils/__init__.py +0 -0
  25. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/utils/ast.py +0 -0
  26. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/utils/markdownformatter.py +0 -0
  27. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/utils/match.py +0 -0
  28. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/utils/robot_path.py +0 -0
  29. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/utils/stubs.py +0 -0
  30. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/utils/variables.py +0 -0
  31. {robotcode_robot-0.78.0 → robotcode_robot-0.78.1}/src/robotcode/robot/utils/visitor.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: robotcode-robot
3
- Version: 0.78.0
3
+ Version: 0.78.1
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
@@ -26,7 +26,7 @@ Classifier: Topic :: Utilities
26
26
  Classifier: Typing :: Typed
27
27
  Requires-Python: >=3.8
28
28
  Requires-Dist: platformdirs<4.2.0,>=3.2.0
29
- Requires-Dist: robotcode-core==0.78.0
29
+ Requires-Dist: robotcode-core==0.78.1
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
@@ -29,7 +29,7 @@ dependencies = [
29
29
  "robotframework>=4.1.0",
30
30
  "tomli>=1.1.0; python_version < '3.11'",
31
31
  "platformdirs>=3.2.0,<4.2.0",
32
- "robotcode-core==0.78.0",
32
+ "robotcode-core==0.78.1",
33
33
  ]
34
34
  dynamic = ["version"]
35
35
 
@@ -0,0 +1 @@
1
+ __version__ = "0.78.1"
@@ -16,6 +16,7 @@ from typing import (
16
16
  List,
17
17
  Literal,
18
18
  Optional,
19
+ Set,
19
20
  Tuple,
20
21
  Union,
21
22
  get_type_hints,
@@ -2264,6 +2265,9 @@ class RobotExtendBaseProfile(RobotBaseProfile):
2264
2265
  class RobotProfile(RobotExtendBaseProfile):
2265
2266
  """Robot Framework configuration profile."""
2266
2267
 
2268
+ def __hash__(self) -> int:
2269
+ return id(self)
2270
+
2267
2271
  description: Optional[str] = field(description="Description of the profile.")
2268
2272
 
2269
2273
  detached: Optional[bool] = field(
@@ -2291,6 +2295,9 @@ class RobotProfile(RobotExtendBaseProfile):
2291
2295
  """
2292
2296
  )
2293
2297
 
2298
+ def is_enabled(self) -> bool:
2299
+ return self.enabled is None or bool(self.enabled)
2300
+
2294
2301
  hidden: Union[bool, Condition, None] = field(
2295
2302
  description="""\
2296
2303
  The profile should be hidden.
@@ -2349,13 +2356,13 @@ class RobotConfig(RobotExtendBaseProfile):
2349
2356
 
2350
2357
  tool: Any = field(description="Tool configurations.")
2351
2358
 
2352
- def select_profiles(
2359
+ def _select_profiles(
2353
2360
  self,
2354
2361
  *names: str,
2355
2362
  verbose_callback: Optional[Callable[[Union[str, Callable[[], Any]]], None]] = None,
2356
2363
  error_callback: Optional[Callable[[Union[str, Callable[[], Any]]], None]] = None,
2357
- ) -> Dict[str, RobotProfile]:
2358
- result: Dict[str, RobotProfile] = {}
2364
+ ) -> Dict[str, Tuple[RobotProfile, Optional[Set[Tuple[str, RobotProfile]]]]]:
2365
+ result: Dict[str, Tuple[RobotProfile, Optional[Set[Tuple[str, RobotProfile]]]]] = {}
2359
2366
 
2360
2367
  profiles = self.profiles or {}
2361
2368
 
@@ -2372,14 +2379,20 @@ class RobotConfig(RobotExtendBaseProfile):
2372
2379
 
2373
2380
  names = (*(default_profile or ()),)
2374
2381
 
2375
- def select(name: str) -> None:
2382
+ def select(name: str, parent_profiles: Optional[Set[Tuple[str, RobotProfile]]] = None) -> None:
2376
2383
  if not name:
2377
2384
  return
2378
2385
 
2379
2386
  nonlocal result
2380
2387
 
2381
2388
  if verbose_callback:
2382
- verbose_callback(f"Selecting profiles matching '{name}'.")
2389
+ if parent_profiles is not None:
2390
+ verbose_callback(
2391
+ f"Selecting profiles matching '{name}'"
2392
+ f" for parent profile '{next(f for f in parent_profiles)[0]}'."
2393
+ )
2394
+ else:
2395
+ verbose_callback(f"Selecting profiles matching '{name}'.")
2383
2396
 
2384
2397
  profile_names = [p for p in profiles.keys() if fnmatch.fnmatchcase(p, name)]
2385
2398
 
@@ -2393,13 +2406,24 @@ class RobotConfig(RobotExtendBaseProfile):
2393
2406
 
2394
2407
  for v in profile_names:
2395
2408
  p = profiles[v]
2396
- result.update({v: p})
2409
+
2397
2410
  if p.inherits:
2398
2411
  if isinstance(p.inherits, list):
2399
2412
  for i in p.inherits:
2400
- select(str(i))
2413
+ select(str(i), {(v, p)})
2414
+ else:
2415
+ select(str(p.inherits), {(v, p)})
2416
+
2417
+ if v in result:
2418
+ if parent_profiles is None:
2419
+ result[v] = (p, None)
2401
2420
  else:
2402
- select(str(p.inherits))
2421
+ parents = result[v][1]
2422
+ if parents is not None:
2423
+ parents.update(parent_profiles)
2424
+
2425
+ else:
2426
+ result.update({v: (p, parent_profiles)})
2403
2427
 
2404
2428
  for name in names:
2405
2429
  select(name)
@@ -2438,7 +2462,7 @@ class RobotConfig(RobotExtendBaseProfile):
2438
2462
  }
2439
2463
  )
2440
2464
 
2441
- selected_profiles = self.select_profiles(
2465
+ selected_profiles = self._select_profiles(
2442
2466
  *names, verbose_callback=verbose_callback, error_callback=error_callback
2443
2467
  )
2444
2468
  if verbose_callback:
@@ -2447,14 +2471,16 @@ class RobotConfig(RobotExtendBaseProfile):
2447
2471
  else:
2448
2472
  verbose_callback("No profiles selected.")
2449
2473
 
2450
- for profile_name, profile in sorted(selected_profiles.items(), key=lambda x: x[1].precedence or 0):
2474
+ for profile_name, (profile, parent_profiles) in sorted(
2475
+ selected_profiles.items(), key=lambda x: x[1][0].precedence or 0
2476
+ ):
2451
2477
  try:
2452
- if profile.enabled is not None and not bool(profile.enabled):
2478
+ if not profile.is_enabled():
2453
2479
  if verbose_callback:
2454
2480
  verbose_callback(f'Skipping profile "{profile_name}" because it\'s disabled.')
2455
2481
  continue
2456
2482
  except EvaluationError as e:
2457
- message = f'Error evaluating "enabled" condition for profile "{profile_name}": {e}'
2483
+ message = f"Error evaluating 'enabled' condition for profile '{profile_name}': {e}"
2458
2484
 
2459
2485
  if error_callback is None:
2460
2486
  raise ValueError(message) from e
@@ -2462,6 +2488,31 @@ class RobotConfig(RobotExtendBaseProfile):
2462
2488
  error_callback(message)
2463
2489
  continue
2464
2490
 
2491
+ if parent_profiles is not None:
2492
+ disabled_profiles = []
2493
+ skip = False
2494
+ for parent_profile in parent_profiles:
2495
+ try:
2496
+ if not parent_profile[1].is_enabled():
2497
+ disabled_profiles.append(parent_profile[0])
2498
+ except EvaluationError as e:
2499
+ message = f"Error evaluating 'enabled' condition for profile '{parent_profile[0]}': {e}"
2500
+
2501
+ if error_callback is None:
2502
+ raise ValueError(message) from e
2503
+
2504
+ error_callback(message)
2505
+ skip = True
2506
+ break
2507
+
2508
+ if skip or len(disabled_profiles) == len(parent_profiles):
2509
+ if verbose_callback:
2510
+ verbose_callback(
2511
+ f"Skipping profile inherited '{profile_name}' because no parent is enabled."
2512
+ f" Disabled profiles: {', '.join(disabled_profiles)}."
2513
+ )
2514
+ continue
2515
+
2465
2516
  if verbose_callback:
2466
2517
  verbose_callback(f'Using profile "{profile_name}".')
2467
2518
 
@@ -2471,7 +2522,7 @@ class RobotConfig(RobotExtendBaseProfile):
2471
2522
  for k, v in profile.env.items():
2472
2523
  os.environ[k] = str(v)
2473
2524
  if verbose_callback:
2474
- verbose_callback(lambda: f"Set environment variable `{k}` to `{v}`")
2525
+ verbose_callback(lambda: f"Set environment variable '{k}' to '{v}'")
2475
2526
 
2476
2527
  if profile.detached:
2477
2528
  result = RobotBaseProfile()
@@ -2520,4 +2571,4 @@ class RobotConfig(RobotExtendBaseProfile):
2520
2571
  if new is not None:
2521
2572
  setattr(result, f.name, new)
2522
2573
 
2523
- return result, selected_profiles, enabled_profiles
2574
+ return result, {k: v[0] for k, v in selected_profiles.items()}, enabled_profiles
@@ -155,6 +155,9 @@ class VariableMatcher:
155
155
  if isinstance(o, str):
156
156
  match = search_variable(o, "$@&%", ignore_errors=True)
157
157
  base = match.base
158
+ if base is None:
159
+ return False
160
+
158
161
  normalized = str(normalize(base))
159
162
  return self.normalized_name == normalized
160
163
 
@@ -1123,6 +1123,7 @@ class Namespace:
1123
1123
  top_level: bool = False,
1124
1124
  source: Optional[str] = None,
1125
1125
  parent_import: Optional[Import] = None,
1126
+ parent_source: Optional[str] = None,
1126
1127
  ) -> Optional[LibraryEntry]:
1127
1128
  result: Optional[LibraryEntry] = None
1128
1129
  try:
@@ -1304,6 +1305,26 @@ class Namespace:
1304
1305
  source=DIAGNOSTICS_SOURCE_NAME,
1305
1306
  code=type(e).__qualname__,
1306
1307
  )
1308
+ elif parent_import is not None:
1309
+ self.append_diagnostics(
1310
+ range=parent_import.range,
1311
+ message="Import definition contains errors.",
1312
+ severity=DiagnosticSeverity.ERROR,
1313
+ source=DIAGNOSTICS_SOURCE_NAME,
1314
+ code=Error.IMPORT_CONTAINS_ERRORS,
1315
+ related_information=(
1316
+ (
1317
+ [
1318
+ DiagnosticRelatedInformation(
1319
+ location=Location(str(Uri.from_path(parent_source)), value.range),
1320
+ message=str(e),
1321
+ ),
1322
+ ]
1323
+ )
1324
+ if parent_source
1325
+ else None
1326
+ ),
1327
+ )
1307
1328
  finally:
1308
1329
  self._reset_global_variables()
1309
1330
 
@@ -1318,6 +1339,7 @@ class Namespace:
1318
1339
  variables: Optional[Dict[str, Any]] = None,
1319
1340
  source: Optional[str] = None,
1320
1341
  parent_import: Optional[Import] = None,
1342
+ parent_source: Optional[str] = None,
1321
1343
  depth: int = 0,
1322
1344
  ) -> Optional[Dict[str, Any]]:
1323
1345
 
@@ -1335,6 +1357,7 @@ class Namespace:
1335
1357
  top_level=top_level,
1336
1358
  source=source,
1337
1359
  parent_import=parent_import,
1360
+ parent_source=parent_source if parent_source else source,
1338
1361
  )
1339
1362
 
1340
1363
  if entry is not None:
@@ -1358,6 +1381,7 @@ class Namespace:
1358
1381
  variables=variables,
1359
1382
  source=entry.library_doc.source,
1360
1383
  parent_import=imp if top_level else parent_import,
1384
+ parent_source=parent_source if top_level else source,
1361
1385
  depth=depth + 1,
1362
1386
  )
1363
1387
  except (SystemExit, KeyboardInterrupt):
@@ -1 +0,0 @@
1
- __version__ = "0.78.0"