robotcode-runner 0.93.1__tar.gz → 0.95.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.93.1
3
+ Version: 0.95.0
4
4
  Summary: RobotCode runner 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.93.1
29
- Requires-Dist: robotcode-plugin==0.93.1
30
- Requires-Dist: robotcode-robot==0.93.1
31
- Requires-Dist: robotcode==0.93.1
28
+ Requires-Dist: robotcode-modifiers==0.95.0
29
+ Requires-Dist: robotcode-plugin==0.95.0
30
+ Requires-Dist: robotcode-robot==0.95.0
31
+ Requires-Dist: robotcode==0.95.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.93.1",
32
- "robotcode-modifiers==0.93.1",
33
- "robotcode-plugin==0.93.1",
34
- "robotcode==0.93.1",
31
+ "robotcode-robot==0.95.0",
32
+ "robotcode-modifiers==0.95.0",
33
+ "robotcode-plugin==0.95.0",
34
+ "robotcode==0.95.0",
35
35
  ]
36
36
 
37
37
  [project.entry-points.robotcode]
@@ -0,0 +1 @@
1
+ __version__ = "0.95.0"
@@ -216,6 +216,7 @@ class TestItem:
216
216
  range: Optional[Range] = None
217
217
  tags: Optional[List[str]] = None
218
218
  error: Optional[str] = None
219
+ rpa: Optional[bool] = None
219
220
 
220
221
 
221
222
  @dataclass
@@ -228,7 +229,9 @@ class ResultItem:
228
229
  class Statistics:
229
230
  suites: int = 0
230
231
  suites_with_tests: int = 0
232
+ suites_with_tasks: int = 0
231
233
  tests: int = 0
234
+ tasks: int = 0
232
235
 
233
236
 
234
237
  def get_rel_source(source: Optional[str]) -> Optional[str]:
@@ -254,7 +257,7 @@ class Collector(SuiteVisitor):
254
257
  )
255
258
  self._current = self.all
256
259
  self.suites: List[TestItem] = []
257
- self.tests: List[TestItem] = []
260
+ self.test_and_tasks: List[TestItem] = []
258
261
  self.tags: Dict[str, List[TestItem]] = defaultdict(list)
259
262
  self.normalized_tags: Dict[str, List[TestItem]] = defaultdict(list)
260
263
  self.statistics = Statistics()
@@ -294,6 +297,7 @@ class Collector(SuiteVisitor):
294
297
  ),
295
298
  children=[],
296
299
  error=suite.error_message if isinstance(suite, ErroneousTestSuite) else None,
300
+ rpa=suite.rpa,
297
301
  )
298
302
  except ValueError as e:
299
303
  raise ValueError(f"Error while parsing suite {suite.source}: {e}") from e
@@ -313,7 +317,10 @@ class Collector(SuiteVisitor):
313
317
 
314
318
  self.statistics.suites += 1
315
319
  if suite.tests:
316
- self.statistics.suites_with_tests += 1
320
+ if suite.rpa:
321
+ self.statistics.suites_with_tasks += 1
322
+ else:
323
+ self.statistics.suites_with_tests += 1
317
324
 
318
325
  def end_suite(self, _suite: TestSuite) -> None:
319
326
  self._collected.pop()
@@ -332,7 +339,7 @@ class Collector(SuiteVisitor):
332
339
  try:
333
340
  absolute_path = normalized_path(Path(test.source)) if test.source is not None else None
334
341
  item = TestItem(
335
- type="test",
342
+ type="task" if self._current.rpa else "test",
336
343
  id=f"{absolute_path or ''};{test.longname};{test.lineno}",
337
344
  name=test.name,
338
345
  longname=test.longname,
@@ -344,6 +351,7 @@ class Collector(SuiteVisitor):
344
351
  end=Position(line=test.lineno - 1, character=0),
345
352
  ),
346
353
  tags=list(set(normalize(str(t), ignore="_") for t in test.tags)) if test.tags else None,
354
+ rpa=self._current.rpa,
347
355
  )
348
356
  except ValueError as e:
349
357
  raise ValueError(f"Error while parsing suite {test.source}: {e}") from e
@@ -352,10 +360,12 @@ class Collector(SuiteVisitor):
352
360
  self.tags[str(tag)].append(item)
353
361
  self.normalized_tags[normalize(str(tag), ignore="_")].append(item)
354
362
 
355
- self.tests.append(item)
363
+ self.test_and_tasks.append(item)
356
364
  self._current.children.append(item)
357
-
358
- self.statistics.tests += 1
365
+ if self._current.rpa:
366
+ self.statistics.tasks += 1
367
+ else:
368
+ self.statistics.tests += 1
359
369
 
360
370
 
361
371
  @click.group(invoke_without_command=False)
@@ -543,6 +553,28 @@ def handle_options(
543
553
  raise UnknownError("Unexpected error happened.")
544
554
 
545
555
 
556
+ def print_statistics(app: Application, suite: TestSuite, collector: Collector) -> None:
557
+ def print() -> Iterable[str]:
558
+ yield click.style("Statistics:", underline=True, fg="blue")
559
+ yield os.linesep
560
+ yield click.style(" - Suites: ", underline=True, bold=True, fg="blue")
561
+ yield f"{collector.statistics.suites}{os.linesep}"
562
+ if collector.statistics.suites_with_tests:
563
+ yield click.style(" - Suites with tests: ", underline=True, bold=True, fg="blue")
564
+ yield f"{collector.statistics.suites_with_tests}{os.linesep}"
565
+ if collector.statistics.suites_with_tasks:
566
+ yield click.style(" - Suites with tasks: ", underline=True, bold=True, fg="blue")
567
+ yield f"{collector.statistics.suites_with_tasks}{os.linesep}"
568
+ if collector.statistics.tests:
569
+ yield click.style(" - Tests: ", underline=True, bold=True, fg="blue")
570
+ yield f"{collector.statistics.tests}{os.linesep}"
571
+ if collector.statistics.tasks:
572
+ yield click.style(" - Tasks: ", underline=True, bold=True, fg="blue")
573
+ yield f"{collector.statistics.tasks}{os.linesep}"
574
+
575
+ app.echo_via_pager(print())
576
+
577
+
546
578
  @discover.command(
547
579
  context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
548
580
  add_help_option=True,
@@ -551,7 +583,7 @@ def handle_options(
551
583
  @click.option(
552
584
  "--tags / --no-tags",
553
585
  "show_tags",
554
- default=False,
586
+ default=True,
555
587
  show_default=True,
556
588
  help="Show the tags that are present.",
557
589
  )
@@ -591,48 +623,70 @@ def all(
591
623
 
592
624
  if collector.all.children:
593
625
  if app.config.output_format is None or app.config.output_format == OutputFormat.TEXT:
594
- tests_or_tasks = "Task" if suite.rpa else "Test"
595
626
 
596
627
  def print(item: TestItem, indent: int = 0) -> Iterable[str]:
597
- type = click.style(
598
- item.type.capitalize() if item.type == "suite" else tests_or_tasks.capitalize(),
599
- fg="green",
600
- )
601
-
602
- if item.type == "test":
628
+ if item.type in ["test", "task"]:
603
629
  yield " "
604
- yield type
605
- yield click.style(f": {item.longname}", bold=True)
630
+ yield click.style(f"{item.type.capitalize()}: ", fg="blue")
631
+ yield click.style(item.longname, bold=True)
606
632
  yield click.style(
607
633
  f" ({item.source if full_paths else item.rel_source}"
608
634
  f":{item.range.start.line + 1 if item.range is not None else 1}){os.linesep}"
609
635
  )
610
636
  if show_tags and item.tags:
611
- yield click.style(" Tags:", bold=True, fg="green")
637
+ yield click.style(" Tags:", bold=True, fg="yellow")
612
638
  yield f" {', '. join(normalize(str(tag), ignore='_') for tag in sorted(item.tags))}{os.linesep}"
613
639
  else:
614
- yield type
615
- yield f": {item.longname}"
640
+ yield click.style(f"{item.type.capitalize()}: ", fg="green")
641
+ yield click.style(item.longname, bold=True)
616
642
  yield click.style(f" ({item.source if full_paths else item.rel_source}){os.linesep}")
617
643
  for child in item.children or []:
618
644
  yield from print(child, indent + 2)
619
645
 
620
- if indent == 0:
621
- yield os.linesep
622
-
623
- yield click.style("Suites: ", underline=True, bold=True, fg="blue")
624
- yield f"{collector.statistics.suites}{os.linesep}"
625
- yield click.style(f"Suites with {tests_or_tasks}: ", underline=True, bold=True, fg="blue")
626
- yield f"{collector.statistics.suites_with_tests}{os.linesep}"
627
- yield click.style(f"{tests_or_tasks}: ", underline=True, bold=True, fg="blue")
628
- yield f"{collector.statistics.tests}{os.linesep}"
629
-
630
646
  app.echo_via_pager(print(collector.all.children[0]))
647
+ print_statistics(app, suite, collector)
631
648
 
632
649
  else:
633
650
  app.print_data(ResultItem([collector.all], diagnostics), remove_defaults=True)
634
651
 
635
652
 
653
+ def _test_or_tasks(
654
+ selected_type: str,
655
+ app: Application,
656
+ full_paths: bool,
657
+ show_tags: bool,
658
+ by_longname: Tuple[str, ...],
659
+ exclude_by_longname: Tuple[str, ...],
660
+ robot_options_and_args: Tuple[str, ...],
661
+ ) -> None:
662
+ suite, collector, diagnostics = handle_options(app, by_longname, exclude_by_longname, robot_options_and_args)
663
+
664
+ if collector.all.children:
665
+ if app.config.output_format is None or app.config.output_format == OutputFormat.TEXT:
666
+
667
+ def print(items: List[TestItem]) -> Iterable[str]:
668
+ for item in items:
669
+ if item.type != selected_type:
670
+ continue
671
+
672
+ yield click.style(f"{item.type.capitalize()}: ", fg="blue")
673
+ yield click.style(item.longname, bold=True)
674
+ yield click.style(
675
+ f" ({item.source if full_paths else item.rel_source}"
676
+ f":{item.range.start.line + 1 if item.range is not None else 1}){os.linesep}"
677
+ )
678
+ if show_tags and item.tags:
679
+ yield click.style(" Tags:", bold=True, fg="yellow")
680
+ yield f" {', '. join(normalize(str(tag), ignore='_') for tag in sorted(item.tags))}{os.linesep}"
681
+
682
+ if collector.test_and_tasks:
683
+ app.echo_via_pager(print(collector.test_and_tasks))
684
+ print_statistics(app, suite, collector)
685
+
686
+ else:
687
+ app.print_data(ResultItem(collector.test_and_tasks, diagnostics), remove_defaults=True)
688
+
689
+
636
690
  @discover.command(
637
691
  context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
638
692
  add_help_option=True,
@@ -677,34 +731,53 @@ def tests(
677
731
  ```
678
732
  """
679
733
 
680
- suite, collector, diagnostics = handle_options(app, by_longname, exclude_by_longname, robot_options_and_args)
681
-
682
- if collector.all.children:
683
- if app.config.output_format is None or app.config.output_format == OutputFormat.TEXT:
734
+ _test_or_tasks("test", app, full_paths, show_tags, by_longname, exclude_by_longname, robot_options_and_args)
684
735
 
685
- tests_or_tasks = "Task" if suite.rpa else "Test"
686
736
 
687
- def print(items: List[TestItem]) -> Iterable[str]:
688
- for item in items:
689
- type = click.style(
690
- item.type.capitalize() if item.type == "suite" else tests_or_tasks.capitalize(),
691
- fg="blue",
692
- )
693
- yield type
694
- yield click.style(f": {item.longname}", bold=True)
695
- yield click.style(
696
- f" ({item.source if full_paths else item.rel_source}"
697
- f":{item.range.start.line + 1 if item.range is not None else 1}){os.linesep}"
698
- )
699
- if show_tags and item.tags:
700
- yield click.style(" Tags:", bold=True, fg="green")
701
- yield f" {', '. join(normalize(str(tag), ignore='_') for tag in sorted(item.tags))}{os.linesep}"
737
+ @discover.command(
738
+ context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
739
+ add_help_option=True,
740
+ epilog="Use `-- --help` to see `robot` help.",
741
+ )
742
+ @click.option(
743
+ "--tags / --no-tags",
744
+ "show_tags",
745
+ default=False,
746
+ show_default=True,
747
+ help="Show the tags that are present.",
748
+ )
749
+ @click.option(
750
+ "--full-paths / --no-full-paths",
751
+ "full_paths",
752
+ default=False,
753
+ show_default=True,
754
+ help="Show full paths instead of releative.",
755
+ )
756
+ @add_options(*ROBOT_OPTIONS)
757
+ @pass_application
758
+ def tasks(
759
+ app: Application,
760
+ full_paths: bool,
761
+ show_tags: bool,
762
+ by_longname: Tuple[str, ...],
763
+ exclude_by_longname: Tuple[str, ...],
764
+ robot_options_and_args: Tuple[str, ...],
765
+ ) -> None:
766
+ """\
767
+ Discover tasks with the selected configuration, profiles, options and
768
+ arguments.
702
769
 
703
- if collector.tests:
704
- app.echo_via_pager(print(collector.tests))
770
+ You can use all known `robot` arguments to filter for example by tags or to use pre-run-modifier.
705
771
 
706
- else:
707
- app.print_data(ResultItem(collector.tests, diagnostics), remove_defaults=True)
772
+ \b
773
+ Examples:
774
+ ```
775
+ robotcode discover tasks
776
+ robotcode --profile regression discover tasks
777
+ robotcode --profile regression discover tasks --include regression --exclude wipANDnotready
778
+ ```
779
+ """
780
+ _test_or_tasks("task", app, full_paths, show_tags, by_longname, exclude_by_longname, robot_options_and_args)
708
781
 
709
782
 
710
783
  @discover.command(
@@ -743,7 +816,7 @@ def suites(
743
816
  ```
744
817
  """
745
818
 
746
- _suite, collector, diagnostics = handle_options(app, by_longname, exclude_by_longname, robot_options_and_args)
819
+ suite, collector, diagnostics = handle_options(app, by_longname, exclude_by_longname, robot_options_and_args)
747
820
 
748
821
  if collector.all.children:
749
822
  if app.config.output_format is None or app.config.output_format == OutputFormat.TEXT:
@@ -760,6 +833,8 @@ def suites(
760
833
  if collector.suites:
761
834
  app.echo_via_pager(print(collector.suites))
762
835
 
836
+ print_statistics(app, suite, collector)
837
+
763
838
  else:
764
839
  app.print_data(ResultItem(collector.suites, diagnostics), remove_defaults=True)
765
840
 
@@ -788,6 +863,13 @@ class TagsResult:
788
863
  show_default=True,
789
864
  help="Show tests where the tag is present.",
790
865
  )
866
+ @click.option(
867
+ "--tasks / --no-tasks",
868
+ "show_tasks",
869
+ default=False,
870
+ show_default=True,
871
+ help="Show tasks where the tag is present.",
872
+ )
791
873
  @click.option(
792
874
  "--full-paths / --no-full-paths",
793
875
  "full_paths",
@@ -801,6 +883,7 @@ def tags(
801
883
  app: Application,
802
884
  normalized: bool,
803
885
  show_tests: bool,
886
+ show_tasks: bool,
804
887
  full_paths: bool,
805
888
  by_longname: Tuple[str, ...],
806
889
  exclude_by_longname: Tuple[str, ...],
@@ -822,7 +905,7 @@ def tags(
822
905
  ```
823
906
  """
824
907
 
825
- _suite, collector, _diagnostics = handle_options(app, by_longname, exclude_by_longname, robot_options_and_args)
908
+ suite, collector, _diagnostics = handle_options(app, by_longname, exclude_by_longname, robot_options_and_args)
826
909
 
827
910
  if collector.all.children:
828
911
  if app.config.output_format is None or app.config.output_format == OutputFormat.TEXT:
@@ -832,11 +915,17 @@ def tags(
832
915
  yield click.style(
833
916
  f"{tag}{os.linesep}",
834
917
  bold=show_tests,
835
- fg="green" if show_tests else None,
918
+ fg="yellow" if show_tests else None,
836
919
  )
837
- if show_tests:
920
+ if show_tests or show_tasks:
838
921
  for t in items:
839
- yield click.style(f" {t.longname}", bold=True) + click.style(
922
+ if show_tests != show_tasks:
923
+ if show_tests and t.type != "test":
924
+ continue
925
+ if show_tasks and t.type != "task":
926
+ continue
927
+ yield click.style(f" {t.type.capitalize()}: ", fg="blue")
928
+ yield click.style(t.longname, bold=True) + click.style(
840
929
  f" ({t.source if full_paths else t.rel_source}"
841
930
  f":{t.range.start.line + 1 if t.range is not None else 1}){os.linesep}"
842
931
  )
@@ -844,6 +933,8 @@ def tags(
844
933
  if collector.normalized_tags:
845
934
  app.echo_via_pager(print(collector.normalized_tags if normalized else collector.tags))
846
935
 
936
+ print_statistics(app, suite, collector)
937
+
847
938
  else:
848
939
  app.print_data(TagsResult(collector.normalized_tags), remove_defaults=True)
849
940
 
@@ -1 +0,0 @@
1
- __version__ = "0.93.1"