def test_line_oriented_goal() -> None: class OutputtingGoalOptions(LineOriented, GoalSubsystem): name = "dummy" class OutputtingGoal(Goal): subsystem_cls = OutputtingGoalOptions @goal_rule def output_rule(console: Console, options: OutputtingGoalOptions) -> OutputtingGoal: with options.output(console) as write_stdout: write_stdout("output...") with options.line_oriented(console) as print_stdout: print_stdout("line oriented") return OutputtingGoal(0) console = MockConsole() result: OutputtingGoal = run_rule( output_rule, rule_args=[ console, create_goal_subsystem(OutputtingGoalOptions, sep="\\n", output_file=None), ], ) assert result.exit_code == 0 assert console.stdout.getvalue() == "output...line oriented\n"
def run_lint_rule( *, config_collection_types: List[Type[LinterConfigurations]], targets: List[TargetWithOrigin], per_target_caching: bool, include_sources: bool = True, ) -> Tuple[int, str]: console = MockConsole(use_colors=False) union_membership = UnionMembership({LinterConfigurations: config_collection_types}) result: Lint = run_rule( lint, rule_args=[ console, TargetsWithOrigins(targets), create_goal_subsystem(LintOptions, per_target_caching=per_target_caching), union_membership, ], mock_gets=[ MockGet( product_type=LintResult, subject_type=LinterConfigurations, mock=lambda config_collection: config_collection.lint_result, ), MockGet( product_type=ConfigurationsWithSources, subject_type=ConfigurationsWithSourcesRequest, mock=lambda configs: ConfigurationsWithSources( configs if include_sources else () ), ), ], union_membership=union_membership, ) return result.exit_code, console.stdout.getvalue()
def run_typecheck_rule( *, request_types: List[Type[TypecheckRequest]], targets: List[TargetWithOrigin], include_sources: bool = True, ) -> Tuple[int, str]: console = MockConsole(use_colors=False) union_membership = UnionMembership({TypecheckRequest: request_types}) result: Typecheck = run_rule( typecheck, rule_args=[console, TargetsWithOrigins(targets), union_membership], mock_gets=[ MockGet( product_type=TypecheckResults, subject_type=TypecheckRequest, mock=lambda field_set_collection: field_set_collection.typecheck_results, ), MockGet( product_type=FieldSetsWithSources, subject_type=FieldSetsWithSourcesRequest, mock=lambda field_sets: FieldSetsWithSources( field_sets if include_sources else () ), ), ], union_membership=union_membership, ) assert not console.stdout.getvalue() return result.exit_code, console.stderr.getvalue()
def test_output_mixed(self): console = MockConsole(use_colors=False) target1 = self.make_build_target_address("testprojects/tests/python/pants/passes") target2 = self.make_build_target_address("testprojects/tests/python/pants/fails") def make_result(target): if target == target1: tr = TestResult(status=Status.SUCCESS, stdout='I passed\n', stderr='') elif target == target2: tr = TestResult(status=Status.FAILURE, stdout='I failed\n', stderr='') else: raise Exception("Unrecognised target") return AddressAndTestResult(target, tr) res = run_rule( fast_test, rule_args=[console, (target1, target2)], mock_gets=[ MockGet(product_type=AddressAndTestResult, subject_type=Address, mock=make_result), ], ) self.assertEqual(1, res.exit_code) self.assertEquals(console.stdout.getvalue(), dedent("""\ testprojects/tests/python/pants/passes stdout: I passed testprojects/tests/python/pants/fails stdout: I failed testprojects/tests/python/pants/passes ..... SUCCESS testprojects/tests/python/pants/fails ..... FAILURE """))
def run_goal( targets: Sequence[Target], *, target_type: Optional[List[str]] = None, address_regex: Optional[List[str]] = None, tag_regex: Optional[List[str]] = None, ) -> str: console = MockConsole(use_colors=False) run_rule( filter_targets, rule_args=[ Targets(targets), create_goal_subsystem( FilterOptions, sep="\\n", output_file=None, target_type=target_type or [], address_regex=address_regex or [], tag_regex=tag_regex or [], ), console, RegisteredTargetTypes.create({type(tgt) for tgt in targets}), ], ) assert not console.stderr.getvalue() return cast(str, console.stdout.getvalue())
def run_lint_rule( *, linters: List[Type[Linter]], targets: List[HydratedTargetWithOrigin], per_target_caching: bool, ) -> Tuple[int, str]: console = MockConsole(use_colors=False) union_membership = UnionMembership( OrderedDict({Linter: OrderedSet(linters)})) result: Lint = run_rule( lint, rule_args=[ console, HydratedTargetsWithOrigins(targets), MockOptions(per_target_caching=per_target_caching), union_membership, ], mock_gets=[ MockGet( product_type=LintResult, subject_type=Linter, mock=lambda linter: linter.lint_result, ), ], union_membership=union_membership, ) return result.exit_code, console.stdout.getvalue()
def test_failed_run(self) -> None: console = MockConsole(use_colors=False) program_text = b'#!/usr/bin/python\nraise RuntimeError("foo")' res = self.single_target_run(console=console, program_text=program_text, address_spec="some/addr") assert res.exit_code == 1
def test_output_mixed(self): console = MockConsole(use_colors=False) options = MockOptions(debug=False) runner = InteractiveRunner(self.scheduler) target1 = self.make_build_target_address( "testprojects/tests/python/pants/passes") target2 = self.make_build_target_address( "testprojects/tests/python/pants/fails") def make_result(target): if target == target1: tr = TestResult(status=Status.SUCCESS, stdout='I passed\n', stderr='') elif target == target2: tr = TestResult(status=Status.FAILURE, stdout='I failed\n', stderr='') else: raise Exception("Unrecognised target") return AddressAndTestResult(target, tr) def make_debug_request(target): request = TestDebugRequest(ipr=self.make_successful_ipr( ) if target == target1 else self.make_failure_ipr()) return AddressAndDebugRequest(target, request) res = run_rule( run_tests, rule_args=[console, options, runner, (target1, target2)], mock_gets=[ MockGet(product_type=AddressAndTestResult, subject_type=Address, mock=make_result), MockGet(product_type=AddressAndDebugRequest, subject_type=Address, mock=make_debug_request), MockGet(product_type=BuildFileAddress, subject_type=BuildFileAddresses, mock=lambda tgt: BuildFileAddress( rel_path=f'{tgt.spec_path}/BUILD', target_name=tgt.target_name, )), ], ) self.assertEqual(1, res.exit_code) self.assertEquals( console.stdout.getvalue(), dedent("""\ testprojects/tests/python/pants/passes stdout: I passed testprojects/tests/python/pants/fails stdout: I failed testprojects/tests/python/pants/passes ..... SUCCESS testprojects/tests/python/pants/fails ..... FAILURE """))
def single_target_test(self, result, expected_console_output, success=True, debug=False): console = MockConsole(use_colors=False) options = MockOptions(debug=debug) runner = InteractiveRunner(self.scheduler) addr = self.make_build_target_address("some/target") res = run_rule( run_tests, rule_args=[console, options, runner, BuildFileAddresses([addr])], mock_gets=[ MockGet( product_type=AddressAndTestResult, subject_type=Address, mock=lambda _: AddressAndTestResult(addr, result), ), MockGet(product_type=AddressAndDebugRequest, subject_type=Address, mock=lambda _: AddressAndDebugRequest( addr, TestDebugRequest(ipr=self.make_successful_ipr( ) if success else self.make_failure_ipr()))), MockGet( product_type=BuildFileAddress, subject_type=BuildFileAddresses, mock=lambda bfas: bfas.dependencies[0], ), ], ) assert console.stdout.getvalue() == expected_console_output assert (0 if success else 1) == res.exit_code
def test_outputting_goal(): class DummyGoal(Outputting): pass console = MockConsole() with DummyGoal.output(None, console) as output: pass
def run_fmt_rule(self, *, targets: List[HydratedTarget]) -> Tuple[Fmt, str]: result_digest = self.request_single_product( Digest, InputFilesContent([ FileContent(path=str(self.formatted_file), content=self.formatted_content.encode()) ])) console = MockConsole(use_colors=False) result: Fmt = run_rule( fmt, rule_args=[ console, HydratedTargets(targets), Workspace(self.scheduler), UnionMembership( union_rules={FormatTarget: [PythonTargetAdaptor]}) ], mock_gets=[ MockGet(product_type=AggregatedFmtResults, subject_type=PythonTargetAdaptor, mock=lambda adaptor: AggregatedFmtResults( (FmtResult(digest=result_digest, stdout=f"Formatted `{adaptor.name}`", stderr=""), ), combined_digest=result_digest)), MockGet(product_type=Digest, subject_type=DirectoriesToMerge, mock=lambda _: result_digest), ], ) return result, console.stdout.getvalue()
def run_goal( targets: List[MockTarget], *, show_documented: bool = False, show_provides: bool = False, provides_columns: Optional[str] = None, ) -> Tuple[str, str]: console = MockConsole(use_colors=False) run_rule( list_targets, rule_args=[ Addresses(tgt.address for tgt in targets), create_goal_subsystem( ListOptions, sep="\\n", output_file=None, documented=show_documented, provides=show_provides, provides_columns=provides_columns or "address,artifact_id", ), console, ], mock_gets=[ MockGet(product_type=Targets, subject_type=Addresses, mock=lambda _: targets) ], ) return cast(str, console.stdout.getvalue()), cast(str, console.stderr.getvalue())
def test_normal_run(self) -> None: console = MockConsole(use_colors=False) program_text = b'#!/usr/bin/python\nprint("hello")' res = self.single_target_run( console=console, program_text=program_text, address_spec="some/addr", ) assert res.exit_code == 0
def run_test_rule( self, *, test_runner: Type[TestRunner], targets: List[HydratedTargetWithOrigin], debug: bool = False, ) -> Tuple[int, str]: console = MockConsole(use_colors=False) options = MockOptions(debug=debug, run_coverage=False) interactive_runner = InteractiveRunner(self.scheduler) workspace = Workspace(self.scheduler) union_membership = UnionMembership( {TestRunner: OrderedSet([test_runner])}) def mock_coordinator_of_tests( wrapped_test_runner: WrappedTestRunner, ) -> AddressAndTestResult: runner = wrapped_test_runner.runner return AddressAndTestResult( address=runner.adaptor_with_origin.adaptor.address, test_result=runner.test_result, # type: ignore[attr-defined] ) result: Test = run_rule( run_tests, rule_args=[ console, options, interactive_runner, HydratedTargetsWithOrigins(targets), workspace, union_membership, ], mock_gets=[ MockGet( product_type=AddressAndTestResult, subject_type=WrappedTestRunner, mock=lambda wrapped_test_runner: mock_coordinator_of_tests( wrapped_test_runner), ), MockGet( product_type=TestDebugRequest, subject_type=TestRunner, mock=lambda _: TestDebugRequest(self.make_ipr()), ), MockGet( product_type=CoverageReport, subject_type=CoverageDataBatch, mock=lambda _: FilesystemCoverageReport( result_digest=EMPTY_DIRECTORY_DIGEST, directory_to_materialize_to=PurePath("mockety/mock"), report_file=None, ), ), ], union_membership=union_membership, ) return result.exit_code, console.stdout.getvalue()
def test_failed_run(self) -> None: console = MockConsole(use_colors=False) program_text = b'#!/usr/bin/python\nraise RuntimeError("foo")' res = self.single_target_run( console=console, program_text=program_text, address_spec="some/addr" ) self.assertEqual(res.exit_code, 1) self.assertEqual(console.stdout.getvalue(), "Running target: some/addr:addr\n") self.assertEqual(console.stderr.getvalue(), "some/addr:addr failed with code 1!\n")
def test_normal_run(self) -> None: console = MockConsole(use_colors=False) program_text = b'#!/usr/bin/python\nprint("hello")' res = self.single_target_run( console=console, program_text=program_text, spec='some/addr' ) self.assertEqual(res.exit_code, 0) self.assertEquals(console.stdout.getvalue(), "Running target: some/addr:addr\nsome/addr:addr ran successfully.\n") self.assertEquals(console.stderr.getvalue(), "")
def run_goal(*, union_membership: Optional[UnionMembership] = None, details_target: Optional[str] = None) -> str: console = MockConsole(use_colors=False) run_rule( list_target_types, rule_args=[ RegisteredTargetTypes.create( [FortranBinary, FortranLibrary, FortranTests]), union_membership or UnionMembership({}), MockOptions(details=details_target), console, ], ) return cast(str, console.stdout.getvalue())
def run_fmt_rule( self, *, language_target_collection_types: List[Type[LanguageFmtTargets]], targets: List[Target], result_digest: Digest, per_file_caching: bool, include_sources: bool = True, ) -> str: console = MockConsole(use_colors=False) union_membership = UnionMembership( {LanguageFmtTargets: language_target_collection_types}) result: Fmt = run_rule( fmt, rule_args=[ console, Targets(targets), create_goal_subsystem(FmtSubsystem, per_file_caching=per_file_caching, per_target_caching=False), Workspace(self.scheduler), union_membership, ], mock_gets=[ MockGet( product_type=LanguageFmtResults, subject_type=LanguageFmtTargets, mock=lambda language_targets_collection: language_targets_collection.language_fmt_results( result_digest), ), MockGet( product_type=TargetsWithSources, subject_type=TargetsWithSourcesRequest, mock=lambda tgts: TargetsWithSources( tgts if include_sources else ()), ), MockGet( product_type=Digest, subject_type=MergeDigests, mock=lambda _: result_digest, ), ], union_membership=union_membership, ) assert result.exit_code == 0 assert not console.stdout.getvalue() return cast(str, console.stderr.getvalue())
def single_target_test(self, result, expected_console_output, success=True): console = MockConsole(use_colors=False) addr = self.make_build_target_address("some/target") res = run_rule( fast_test, rule_args=[console, (addr,)], mock_gets=[ MockGet( product_type=AddressAndTestResult, subject_type=Address, mock=lambda _: AddressAndTestResult(addr, result), ), ], ) assert console.stdout.getvalue() == expected_console_output assert (0 if success else 1) == res.exit_code
def run_lint_rule( *, targets: List[HydratedTarget], mock_linter: Callable[[PythonTargetAdaptor], LintResult], ) -> Tuple[Lint, MockConsole]: console = MockConsole(use_colors=False) result: Lint = run_rule( lint, rule_args=[ console, HydratedTargets(targets), UnionMembership(union_rules={TargetWithSources: [PythonTargetAdaptor]}) ], mock_gets=[ MockGet(product_type=LintResult, subject_type=PythonTargetAdaptor, mock=mock_linter), ], ) return result, console
def single_target_test(self, result, expected_console_output, success=True, debug=False): console = MockConsole(use_colors=False) options = MockOptions(debug=debug, run_coverage=False) runner = InteractiveRunner(self.scheduler) workspace = Workspace(self.scheduler) addr = Address.parse("some/target") res = run_rule( run_tests, rule_args=[ console, options, runner, self.make_addresses_with_origins(addr), workspace ], mock_gets=[ MockGet( product_type=AddressAndTestResult, subject_type=AddressWithOrigin, mock=lambda _: AddressAndTestResult(addr, result), ), MockGet( product_type=AddressAndDebugRequest, subject_type=AddressWithOrigin, mock=lambda _: AddressAndDebugRequest( addr, TestDebugRequest(ipr=self.make_successful_ipr() if success else self.make_failure_ipr( )), ), ), MockGet( product_type=CoverageReport, subject_type=CoverageDataBatch, mock=lambda _: CoverageReport( result_digest=EMPTY_DIRECTORY_DIGEST, directory_to_materialize_to=PurePath("mockety/mock"), ), ), ], ) assert console.stdout.getvalue() == expected_console_output assert (0 if success else 1) == res.exit_code
def run_fmt_rule( *, targets: List[HydratedTarget], mock_formatter: Callable[[PythonTargetAdaptor], FmtResult], ) -> Tuple[Fmt, MockConsole]: console = MockConsole(use_colors=False) result: Fmt = run_rule( fmt, rule_args=[ console, HydratedTargets(targets), UnionMembership(union_rules={TargetWithSources: [PythonTargetAdaptor]}) ], mock_gets=[ MockGet(product_type=FmtResult, subject_type=PythonTargetAdaptor, mock=mock_formatter), MockGet(product_type=FilesContent, subject_type=Digest, mock=lambda _: FilesContent([])) ], ) return result, console
def run_lint_rule( self, *, lint_request_types: List[Type[LintRequest]], targets: List[Target], per_file_caching: bool, include_sources: bool = True, ) -> Tuple[int, str]: console = MockConsole(use_colors=False) workspace = Workspace(self.scheduler) union_membership = UnionMembership({LintRequest: lint_request_types}) result: Lint = run_rule( lint, rule_args=[ console, workspace, Targets(targets), create_goal_subsystem( LintSubsystem, per_file_caching=per_file_caching, per_target_caching=False ), union_membership, ], mock_gets=[ MockGet( product_type=LintResults, subject_type=LintRequest, mock=lambda field_set_collection: field_set_collection.lint_results, ), MockGet( product_type=FieldSetsWithSources, subject_type=FieldSetsWithSourcesRequest, mock=lambda field_sets: FieldSetsWithSources( field_sets if include_sources else () ), ), MockGet( product_type=Digest, subject_type=MergeDigests, mock=lambda _: EMPTY_DIGEST ), ], union_membership=union_membership, ) assert not console.stdout.getvalue() return result.exit_code, console.stderr.getvalue()
def run_goal(*, union_membership: Optional[UnionMembership] = None, details_target: Optional[str] = None) -> str: console = MockConsole(use_colors=False) run_rule( list_target_types, rule_args=[ RegisteredTargetTypes.create( [FortranBinary, FortranLibrary, FortranTests]), union_membership or UnionMembership({}), create_goal_subsystem(TargetTypesSubsystem, sep="\\n", output_file=None, details=details_target), console, PantsBin(name="./BNF"), ], ) return cast(str, console.stdout.getvalue())
def run_lint_rule( *, targets: List[HydratedTarget], mock_linter: Optional[Callable[[PythonTargetAdaptor], LintResult]] = None, ) -> Tuple[Lint, str]: if mock_linter is None: mock_linter = lambda target_adaptor: LintResult( exit_code=1, stdout=f"Linted the target `{target_adaptor.name}`", stderr="" ) console = MockConsole(use_colors=False) result: Lint = run_rule( lint, rule_args=[ console, HydratedTargets(targets), UnionMembership(union_rules={TargetWithSources: [PythonTargetAdaptor]}) ], mock_gets=[ MockGet(product_type=LintResult, subject_type=PythonTargetAdaptor, mock=mock_linter), ], ) return result, console.stdout.getvalue()
def test_line_oriented_goal() -> None: class OutputtingGoalOptions(LineOriented, GoalSubsystem): name = "dummy" class OutputtingGoal(Goal): subsystem_cls = OutputtingGoalOptions @goal_rule def output_rule(console: Console, options: OutputtingGoalOptions) -> OutputtingGoal: with options.output(console) as write_stdout: write_stdout("output...") with options.line_oriented(console) as print_stdout: print_stdout("line oriented") return OutputtingGoal(0) mock_console = MockConsole() # TODO: how should we mock `GoalSubsystem`s passed to `run_rule`? mock_options = Mock() mock_options.output = OutputtingGoalOptions.output mock_options.line_oriented = OutputtingGoalOptions.line_oriented result: OutputtingGoal = run_rule(output_rule, rule_args=[mock_console, mock_options]) assert result.exit_code == 0 assert mock_console.stdout.getvalue() == "output...line oriented"
def run_fmt_rule( self, *, language_formatters: List[Type[LanguageFormatters]], targets: List[HydratedTargetWithOrigin], result_digest: Digest, per_target_caching: bool, ) -> str: console = MockConsole(use_colors=False) union_membership = UnionMembership( OrderedDict({LanguageFormatters: OrderedSet(language_formatters)})) result: Fmt = run_rule( fmt, rule_args=[ console, HydratedTargetsWithOrigins(targets), MockOptions(per_target_caching=per_target_caching), Workspace(self.scheduler), union_membership, ], mock_gets=[ MockGet( product_type=LanguageFmtResults, subject_type=LanguageFormatters, mock=lambda language_formatters: language_formatters. language_fmt_results, ), MockGet( product_type=Digest, subject_type=DirectoriesToMerge, mock=lambda _: result_digest, ), ], union_membership=union_membership, ) assert result.exit_code == 0 return cast(str, console.stdout.getvalue())
def test_list_backends() -> None: # NB: Here, we assume that the code to find all the `register.py`s is valid. Instead, the focus # is on us being able to correctly extract all the relevant information from those # `register.py` files and then to format the information. all_register_pys = FilesContent([ FileContent( "src/python/pants/backend/fortran/register.py", dedent('''\ """Support for Fortran 98.""" # V1 entry-point def register_goals(): pass # This naively looks like a V2 entry-point, but it's not! def rules(x: int): pass ''').encode(), ), FileContent( "contrib/elixir/src/python/pants/contrib/elixir/register.py", dedent("""\ # V1 entry-point def register_goals(): pass # V2 entry-point def rules(): pass """).encode(), ), FileContent( "src/python/pants/core/register.py", dedent('''\ """Core V2 rules. These are always activated. """ def rules(): pass ''').encode(), ), ]) console = MockConsole(use_colors=False) run_rule( list_backends, rule_args=[ create_goal_subsystem(BackendsOptions, sep="\\n", output_file=None), global_subsystem_instance(SourceRootConfig), global_subsystem_instance(GlobalOptions), console, ], mock_gets=[ MockGet(product_type=Snapshot, subject_type=PathGlobs, mock=lambda _: EMPTY_SNAPSHOT), MockGet(product_type=FilesContent, subject_type=Digest, mock=lambda _: all_register_pys), ], ) assert console.stdout.getvalue() == dedent("""\ V1 backends ----------- To enable V1 backends, add the backend to `backend_packages.add` in your `pants.toml`, like this: [GLOBAL] backend_packages.add = ["pants.backend.python"] In the below list, all activated backends end with `*`. pants.backend.fortran Support for Fortran 98. pants.contrib.elixir <no description> V2 backends ----------- To enable V2 backends, add the backend to `backend_packages2.add` in your `pants.toml`, like this: [GLOBAL] backend_packages2.add = ["pants.backend.python"] In the below list, all activated backends end with `*`. pants.contrib.elixir <no description> pants.core* Core V2 rules. These are always activated. """)
def line_oriented(self, console: MockConsole): yield lambda msg: console.print_stdout(msg)
def run_test_rule( self, *, field_set: Type[TestFieldSet], targets: List[TargetWithOrigin], debug: bool = False, use_coverage: bool = False, include_sources: bool = True, valid_targets: bool = True, ) -> Tuple[int, str]: console = MockConsole(use_colors=False) options = create_goal_subsystem(TestOptions, debug=debug, use_coverage=use_coverage) interactive_runner = InteractiveRunner(self.scheduler) workspace = Workspace(self.scheduler) union_membership = UnionMembership({ TestFieldSet: [field_set], CoverageDataCollection: [MockCoverageDataCollection] }) def mock_find_valid_field_sets( _: TargetsToValidFieldSetsRequest, ) -> TargetsToValidFieldSets: if not valid_targets: return TargetsToValidFieldSets({}) return TargetsToValidFieldSets({ tgt_with_origin: [field_set.create(tgt_with_origin)] for tgt_with_origin in targets }) def mock_coordinator_of_tests( wrapped_field_set: WrappedTestFieldSet, ) -> AddressAndTestResult: field_set = cast(MockTestFieldSet, wrapped_field_set.field_set) return AddressAndTestResult(address=field_set.address, test_result=field_set.test_result) def mock_coverage_report_generation( coverage_data_collection: MockCoverageDataCollection, ) -> CoverageReports: addresses = ", ".join( coverage_data.address.spec for coverage_data in coverage_data_collection) console_report = ConsoleCoverageReport( f"Ran coverage on {addresses}") return CoverageReports(reports=(console_report, )) result: Test = run_rule( run_tests, rule_args=[ console, options, interactive_runner, workspace, union_membership ], mock_gets=[ MockGet( product_type=TargetsToValidFieldSets, subject_type=TargetsToValidFieldSetsRequest, mock=mock_find_valid_field_sets, ), MockGet( product_type=AddressAndTestResult, subject_type=WrappedTestFieldSet, mock=lambda wrapped_config: mock_coordinator_of_tests( wrapped_config), ), MockGet( product_type=TestDebugRequest, subject_type=TestFieldSet, mock=lambda _: TestDebugRequest( self.make_interactive_process()), ), MockGet( product_type=FieldSetsWithSources, subject_type=FieldSetsWithSourcesRequest, mock=lambda field_sets: FieldSetsWithSources( field_sets if include_sources else ()), ), MockGet( product_type=CoverageReports, subject_type=CoverageDataCollection, mock=mock_coverage_report_generation, ), ], union_membership=union_membership, ) assert not console.stdout.getvalue() return result.exit_code, console.stderr.getvalue()