def setup_json_scheduler(build_root, native): """Return a build graph and scheduler configured for BLD.json files under the given build root. :rtype :class:`pants.engine.scheduler.LocalScheduler` """ symbol_table = ExampleTable() # Register "literal" subjects required for these tasks. # TODO: Replace with `Subsystems`. address_mapper = AddressMapper(build_patterns=('BLD.json',), parser=JsonParser(symbol_table)) work_dir = os_path_join(build_root, '.pants.d') project_tree = FileSystemProjectTree(build_root) goals = { 'compile': Classpath, # TODO: to allow for running resolve alone, should split out a distinct 'IvyReport' product. 'resolve': Classpath, 'list': BuildFileAddresses, GenGoal.name(): GenGoal, 'ls': Snapshot, 'cat': FilesContent, } tasks = [ # Codegen GenGoal.rule(), gen_apache_java_thrift, gen_apache_python_thrift, gen_scrooge_scala_thrift, gen_scrooge_java_thrift, SingletonRule(Scrooge, Scrooge(Address.parse('src/scala/scrooge'))) ] + [ # scala dependency inference reify_scala_sources, select_package_address, calculate_package_search_path, SingletonRule(SourceRoots, SourceRoots(('src/java','src/scala'))), ] + [ # Remote dependency resolution ivy_resolve, select_rev, ] + [ # Compilers isolate_resources, write_name_file, javac, scalac, ] + ( create_graph_rules(address_mapper, symbol_table) ) + ( create_fs_rules() ) return LocalScheduler(work_dir, goals, tasks, project_tree, native)
def test_full_graph_for_planner_example(self): address_mapper = AddressMapper(JsonParser(TARGET_TABLE), "*.BUILD.json") rules = create_graph_rules(address_mapper) + create_fs_rules() fullgraph_str = self.create_full_graph(rules) print("---diagnostic------") print(fullgraph_str) print("/---diagnostic------") in_root_rules = False in_all_rules = False all_rules = [] root_rule_lines = [] for line in fullgraph_str.splitlines(): if line.startswith(" // root subject types:"): pass elif line.startswith(" // root entries"): in_root_rules = True elif line.startswith(" // internal entries"): in_all_rules = True elif in_all_rules: all_rules.append(line) elif in_root_rules: root_rule_lines.append(line) else: pass self.assertTrue(6 < len(all_rules)) self.assertTrue(12 < len(root_rule_lines)) # 2 lines per entry
def setUp(self): # Set up a scheduler that supports address mapping. symbol_table = TargetTable() address_mapper = AddressMapper(parser=JsonParser(symbol_table), build_patterns=('*.BUILD.json',)) rules = create_fs_rules() + create_graph_rules(address_mapper, symbol_table) # TODO handle updating the rule graph when passed unexpected root selectors. # Adding the following task allows us to get around the fact that SelectDependencies # requests are not currently supported. rules.append(TaskRule(UnhydratedStructs, [SelectDependencies(UnhydratedStruct, BuildFileAddresses, field_types=(Address,), field='addresses')], UnhydratedStructs)) project_tree = self.mk_fs_tree(os.path.join(os.path.dirname(__file__), 'examples/mapper_test')) self.build_root = project_tree.build_root self.scheduler = self.mk_scheduler(rules=rules, project_tree=project_tree) self.a_b = Address.parse('a/b') self.a_b_target = Target(name='b', dependencies=['//d:e'], configurations=['//a', Struct(embedded='yes')], type_alias='target')
def test_full_graph_for_planner_example(self): symbol_table_cls = TargetTable address_mapper = AddressMapper(symbol_table_cls, JsonParser, '*.BUILD.json') tasks = create_graph_tasks(address_mapper, symbol_table_cls) + create_fs_tasks() intrinsics = create_fs_intrinsics('Let us pretend that this is a ProjectTree!') rule_index = NodeBuilder.create(tasks, intrinsics) graphmaker = GraphMaker(rule_index, root_subject_fns={k: lambda p: Select(p) for k in (Address, # TODO, use the actual fns. PathGlobs, SingleAddress, SiblingAddresses, DescendantAddresses, AscendantAddresses )}) fullgraph = graphmaker.full_graph() print('---diagnostic------') print(fullgraph.error_message()) print('/---diagnostic------') print(fullgraph) # Assert that all of the rules specified the various task fns are present declared_rules = rule_index.all_rules() rules_remaining_in_graph_strs = set(str(r.rule) for r in fullgraph.rule_dependencies.keys()) declared_rule_strings = set(str(r) for r in declared_rules) self.assertEquals(declared_rule_strings, rules_remaining_in_graph_strs )
def setup_legacy_graph(path_ignore_patterns): """Construct and return the components necessary for LegacyBuildGraph construction. :param list path_ignore_patterns: A list of path ignore patterns for FileSystemProjectTree, usually taken from the `--pants-ignore` global option. :returns: A tuple of (scheduler, engine, symbol_table_cls, build_graph_cls). """ build_root = get_buildroot() project_tree = FileSystemProjectTree(build_root, path_ignore_patterns) symbol_table_cls = LegacySymbolTable # Register "literal" subjects required for these tasks. # TODO: Replace with `Subsystems`. address_mapper = AddressMapper(symbol_table_cls=symbol_table_cls, parser_cls=LegacyPythonCallbacksParser) # Create a Scheduler containing graph and filesystem tasks, with no installed goals. The # LegacyBuildGraph will explicitly request the products it needs. tasks = ( create_legacy_graph_tasks() + create_fs_tasks() + create_graph_tasks(address_mapper, symbol_table_cls) ) scheduler = LocalScheduler(dict(), tasks, project_tree) engine = LocalSerialEngine(scheduler, Storage.create(debug=False)) return LegacyGraphHelper(scheduler, engine, symbol_table_cls, LegacyBuildGraph)
def test_empty(self): """Test that parsing an empty BUILD file results in an empty AddressFamily.""" address_mapper = AddressMapper(JsonParser(TestTable())) af = run_rule(parse_address_family, address_mapper, Dir('/dev/null'), { (FilesContent, PathGlobs): lambda _: FilesContent([FileContent('/dev/null/BUILD', '')]) }) self.assertEquals(len(af.objects_by_name), 0)
def test_full_graph_for_planner_example(self): symbol_table = TargetTable() address_mapper = AddressMapper(JsonParser(symbol_table), '*.BUILD.json') rules = create_graph_rules(address_mapper, symbol_table) + create_fs_rules() fullgraph_str = self.create_full_graph(rules) print('---diagnostic------') print(fullgraph_str) print('/---diagnostic------') in_root_rules = False in_all_rules = False all_rules = [] root_rule_lines = [] for line in fullgraph_str.splitlines(): if line.startswith(' // root subject types:'): pass elif line.startswith(' // root entries'): in_root_rules = True elif line.startswith(' // internal entries'): in_all_rules = True elif in_all_rules: all_rules.append(line) elif in_root_rules: root_rule_lines.append(line) else: pass self.assertTrue(6 < len(all_rules)) self.assertTrue(12 < len(root_rule_lines)) # 2 lines per entry
def create(self, build_patterns=None, parser=None): address_mapper = AddressMapper(build_patterns=build_patterns, parser=parser) rules = create_fs_rules() + create_graph_rules(address_mapper) + [SingletonRule(SymbolTable, TestTable())] project_tree = self.mk_fs_tree(os.path.join(os.path.dirname(__file__), 'examples')) scheduler = self.mk_scheduler(rules=rules, project_tree=project_tree) return scheduler
def test_empty(self): """Test that parsing an empty BUILD file results in an empty AddressFamily.""" address_mapper = AddressMapper(JsonParser(TestTable())) af = run_rule(parse_address_family, address_mapper, Dir('/dev/null'), { (Snapshot, PathGlobs): lambda _: Snapshot(DirectoryDigest('abc', 10), (File('/dev/null/BUILD'),)), (FilesContent, DirectoryDigest): lambda _: FilesContent([FileContent('/dev/null/BUILD', b'')]), }) self.assertEqual(len(af.objects_by_name), 0)
def setup_legacy_graph(pants_ignore_patterns, workdir, build_root=None, native=None, symbol_table_cls=None, build_ignore_patterns=None, exclude_target_regexps=None, subproject_roots=None): """Construct and return the components necessary for LegacyBuildGraph construction. :param list pants_ignore_patterns: A list of path ignore patterns for FileSystemProjectTree, usually taken from the '--pants-ignore' global option. :param str workdir: The pants workdir. :param str build_root: A path to be used as the build root. If None, then default is used. :param Native native: An instance of the native-engine subsystem. :param SymbolTable symbol_table_cls: A SymbolTable class to use for build file parsing, or None to use the default. :param list build_ignore_patterns: A list of paths ignore patterns used when searching for BUILD files, usually taken from the '--build-ignore' global option. :param list exclude_target_regexps: A list of regular expressions for excluding targets. :param list subproject_roots: Paths that correspond with embedded build roots under the current build root. :returns: A tuple of (scheduler, engine, symbol_table_cls, build_graph_cls). """ build_root = build_root or get_buildroot() scm = get_scm() symbol_table_cls = symbol_table_cls or LegacySymbolTable project_tree = FileSystemProjectTree(build_root, pants_ignore_patterns) # Register "literal" subjects required for these tasks. # TODO: Replace with `Subsystems`. address_mapper = AddressMapper( symbol_table_cls=symbol_table_cls, parser_cls=LegacyPythonCallbacksParser, build_ignore_patterns=build_ignore_patterns, exclude_target_regexps=exclude_target_regexps, subproject_roots=subproject_roots) # Load the native backend. native = native or Native.Factory.global_instance().create() # Create a Scheduler containing graph and filesystem tasks, with no installed goals. The # LegacyBuildGraph will explicitly request the products it needs. tasks = (create_legacy_graph_tasks(symbol_table_cls) + create_fs_rules() + create_graph_rules(address_mapper, symbol_table_cls)) # TODO: Do not use the cache yet, as it incurs a high overhead. scheduler = LocalScheduler(workdir, dict(), tasks, project_tree, native) engine = LocalSerialEngine(scheduler, use_cache=False) change_calculator = EngineChangeCalculator( scheduler, engine, symbol_table_cls, scm) if scm else None return LegacyGraphHelper(scheduler, engine, symbol_table_cls, change_calculator)
def create(self, build_patterns=None, parser=None): address_mapper = AddressMapper(build_patterns=build_patterns, parser=parser) symbol_table = address_mapper.parser.symbol_table rules = create_fs_rules() + create_graph_rules(address_mapper, symbol_table) project_tree = self.mk_fs_tree(os.path.join(os.path.dirname(__file__), 'examples')) scheduler = self.mk_scheduler(rules=rules, project_tree=project_tree) return scheduler
def create(self, build_pattern=None, parser_cls=None): symbol_table_cls = TestTable address_mapper = AddressMapper(symbol_table_cls=symbol_table_cls, build_pattern=build_pattern, parser_cls=parser_cls) tasks = create_graph_tasks(address_mapper, symbol_table_cls) project_tree = self.mk_fs_tree(os.path.join(os.path.dirname(__file__), 'examples')) scheduler = self.mk_scheduler(tasks=tasks, project_tree=project_tree) return scheduler
def create(self, build_patterns=None, parser=None): address_mapper = AddressMapper(build_patterns=build_patterns, parser=parser) @rule def symbol_table_singleton() -> SymbolTable: return TEST_TABLE rules = create_fs_rules() + create_graph_rules(address_mapper) + [symbol_table_singleton] project_tree = self.mk_fs_tree(os.path.join(os.path.dirname(__file__), 'examples')) scheduler = self.mk_scheduler(rules=rules, project_tree=project_tree) return scheduler
def setup_json_scheduler(build_root, native): """Return a build graph and scheduler configured for BLD.json files under the given build root. :rtype :class:`pants.engine.scheduler.SchedulerSession` """ symbol_table = ExampleTable() # Register "literal" subjects required for these rules. address_mapper = AddressMapper(build_patterns=('BLD.json',), parser=JsonParser(symbol_table)) work_dir = os_path_join(build_root, '.pants.d') project_tree = FileSystemProjectTree(build_root) rules = [ # Codegen GenGoal.rule(), gen_apache_java_thrift, gen_apache_python_thrift, gen_scrooge_scala_thrift, gen_scrooge_java_thrift, SingletonRule(Scrooge, Scrooge(Address.parse('src/scala/scrooge'))) ] + [ # scala dependency inference reify_scala_sources, select_package_address, calculate_package_search_path, SingletonRule(SourceRoots, SourceRoots(('src/java','src/scala'))), ] + [ # Remote dependency resolution ivy_resolve, select_rev, ] + [ # Compilers isolate_resources, write_name_file, javac, scalac, ] + ( create_graph_rules(address_mapper, symbol_table) ) + ( create_fs_rules() ) scheduler = Scheduler(native, project_tree, work_dir, rules, DEFAULT_EXECUTION_OPTIONS, None, None) return scheduler.new_session()
def test_duplicated(self): """Test that matching the same Spec twice succeeds.""" address = SingleAddress('a', 'a') address_mapper = AddressMapper(JsonParser(TestTable())) snapshot = Snapshot(DirectoryDigest(str('xx'), 2), (Path('a/BUILD', File('a/BUILD')),)) address_family = AddressFamily('a', {'a': ('a/BUILD', 'this is an object!')}) bfas = run_rule(addresses_from_address_families, address_mapper, Specs([address, address]), { (Snapshot, PathGlobs): lambda _: snapshot, (AddressFamily, Dir): lambda _: address_family, }) self.assertEquals(len(bfas.dependencies), 1) self.assertEquals(bfas.dependencies[0].spec, 'a:a')
def setUp(self): # Set up a scheduler that supports address mapping. symbol_table_cls = TargetTable address_mapper = AddressMapper(symbol_table_cls=symbol_table_cls, parser_cls=JsonParser, build_patterns=('*.BUILD.json',)) tasks = create_graph_tasks(address_mapper, symbol_table_cls) project_tree = self.mk_fs_tree(os.path.join(os.path.dirname(__file__), 'examples/mapper_test')) self.build_root = project_tree.build_root self.scheduler = self.mk_scheduler(tasks=tasks, project_tree=project_tree) self.a_b = Address.parse('a/b') self.a_b_target = Target(name='b', dependencies=['//d:e'], configurations=['//a', Struct(embedded='yes')], type_alias='target')
def test_exclude_pattern_with_single_address(self): """Test that single address targets are filtered based on exclude patterns.""" spec = SingleAddress('root', 'not_me') address_mapper = AddressMapper(JsonParser(TestTable())) snapshot = Snapshot(DirectoryDigest('xx', 2), (Path('root/BUILD', File('root/BUILD')),)) address_family = AddressFamily('root', { 'not_me': ('root/BUILD', TargetAdaptor()), } ) targets = run_rule( addresses_from_address_families, address_mapper, Specs([spec], exclude_patterns=tuple(['root.*'])),{ (Snapshot, PathGlobs): lambda _: snapshot, (AddressFamily, Dir): lambda _: address_family, }) self.assertEqual(len(targets.dependencies), 0)
def setup_legacy_graph(pants_ignore_patterns, symbol_table_cls=None, build_ignore_patterns=None, exclude_target_regexps=None): """Construct and return the components necessary for LegacyBuildGraph construction. :param list pants_ignore_patterns: A list of path ignore patterns for FileSystemProjectTree, usually taken from the '--pants-ignore' global option. :param SymbolTable symbol_table_cls: A SymbolTable class to use for build file parsing, or None to use the default. :param list build_ignore_patterns: A list of paths ignore patterns used when searching for BUILD files, usually taken from the '--build-ignore' global option. :param list exclude_target_regexps: A list of regular expressions for excluding targets. :returns: A tuple of (scheduler, engine, symbol_table_cls, build_graph_cls). """ build_root = get_buildroot() scm = get_scm() project_tree = FileSystemProjectTree(build_root, pants_ignore_patterns) symbol_table_cls = symbol_table_cls or LegacySymbolTable # Register "literal" subjects required for these tasks. # TODO: Replace with `Subsystems`. address_mapper = AddressMapper( symbol_table_cls=symbol_table_cls, parser_cls=LegacyPythonCallbacksParser, build_ignore_patterns=build_ignore_patterns, exclude_target_regexps=exclude_target_regexps) # Create a Scheduler containing graph and filesystem tasks, with no installed goals. The # LegacyBuildGraph will explicitly request the products it needs. tasks = (create_legacy_graph_tasks(symbol_table_cls) + create_fs_tasks() + create_graph_tasks(address_mapper, symbol_table_cls)) scheduler = LocalScheduler(dict(), tasks, project_tree) # TODO: Do not use the cache yet, as it incurs a high overhead. engine = LocalSerialEngine(scheduler, Storage.create(), use_cache=False) change_calculator = EngineChangeCalculator(engine, scm) if scm else None return LegacyGraphHelper(scheduler, engine, symbol_table_cls, change_calculator)
def setUp(self) -> None: # Set up a scheduler that supports address mapping. address_mapper = AddressMapper(parser=JsonParser(TARGET_TABLE), build_patterns=('*.BUILD.json',)) # We add the `unhydrated_structs` rule because it is otherwise not used in the core engine. rules = [ unhydrated_structs ] + create_fs_rules() + create_graph_rules(address_mapper) project_tree = self.mk_fs_tree(os.path.join(os.path.dirname(__file__), 'examples/mapper_test')) self.build_root = project_tree.build_root self.scheduler = self.mk_scheduler(rules=rules, project_tree=project_tree) self.a_b = Address.parse('a/b') self.a_b_target = Target(address=self.a_b, dependencies=['//a/d/e'], configurations=['//a/d/e', Struct(embedded='yes')], type_alias='target')
def test_exclude_pattern(self): """Test that targets are filtered based on exclude patterns.""" spec = SiblingAddresses('root') address_mapper = AddressMapper(JsonParser(TestTable())) snapshot = Snapshot(DirectoryDigest(text_type('xx'), 2), (Path('root/BUILD', File('root/BUILD')), )) address_family = AddressFamily( 'root', { 'exclude_me': ('root/BUILD', TargetAdaptor()), 'not_me': ('root/BUILD', TargetAdaptor()), }) targets = run_rule( addresses_from_address_families, address_mapper, Specs([spec], exclude_patterns=tuple(['.exclude*'])), { (Snapshot, PathGlobs): lambda _: snapshot, (AddressFamily, Dir): lambda _: address_family, }) self.assertEquals(len(targets.dependencies), 1) self.assertEquals(targets.dependencies[0].spec, 'root:not_me')
def test_tag_filter(self): """Test that targets are filtered based on `tags`.""" spec = SiblingAddresses('root') address_mapper = AddressMapper(JsonParser(TestTable())) snapshot = Snapshot(DirectoryDigest(str('xx'), 2), (Path('root/BUILD', File('root/BUILD')),)) address_family = AddressFamily('root', {'a': ('root/BUILD', TargetAdaptor()), 'b': ('root/BUILD', TargetAdaptor(tags={'integration'})), 'c': ('root/BUILD', TargetAdaptor(tags={'not_integration'})) } ) targets = run_rule( addresses_from_address_families, address_mapper, Specs([spec], tags=['+integration']), { (Snapshot, PathGlobs): lambda _: snapshot, (AddressFamily, Dir): lambda _: address_family, }) self.assertEquals(len(targets.dependencies), 1) self.assertEquals(targets.dependencies[0].spec, 'root:b')
def test_full_graph_for_planner_example(self): symbol_table_cls = TargetTable address_mapper = AddressMapper(symbol_table_cls, JsonParser, '*.BUILD.json') project_tree = 'Let us pretend that this is a ProjectTree!' tasks = create_graph_tasks(address_mapper, symbol_table_cls) + create_fs_tasks(project_tree) rule_index = RuleIndex.create(tasks, tuple()) root_subject_types = {Address, PathGlobs, SingleAddress, SiblingAddresses, DescendantAddresses, AscendantAddresses} fullgraph_str = self.create_full_graph(root_subject_types, rule_index) print('---diagnostic------') print(fullgraph_str) print('/---diagnostic------') in_root_rules = False in_all_rules = False all_rules = [] root_rule_lines = [] for line in fullgraph_str.splitlines(): if line.startswith(' // root subject types:'): pass elif line.startswith(' // root entries'): in_root_rules = True elif line.startswith(' // internal entries'): in_all_rules = True elif in_all_rules: all_rules.append(line) elif in_root_rules: root_rule_lines.append(line) else: pass self.assertEquals(31, len(all_rules)) self.assertEquals(56, len(root_rule_lines)) # 2 lines per entry
def test_empty(self): """Test that parsing an empty BUILD file results in an empty AddressFamily.""" address_mapper = AddressMapper(JsonParser(TEST_TABLE)) af = run_rule( parse_address_family, rule_args=[address_mapper, Dir('/dev/null')], mock_gets=[ MockGet( product_type=Snapshot, subject_type=PathGlobs, mock=lambda _: Snapshot(Digest('abc', 10), ('/dev/null/BUILD', ), ()), ), MockGet( product_type=FilesContent, subject_type=Digest, mock=lambda _: FilesContent( [FileContent(path='/dev/null/BUILD', content=b'')]), ), ], ) self.assertEqual(len(af.objects_by_name), 0)
def setup_legacy_graph_extended( pants_ignore_patterns, local_store_dir, build_file_imports_behavior, options_bootstrapper, build_configuration, build_root=None, native=None, glob_match_error_behavior=None, build_ignore_patterns=None, exclude_target_regexps=None, subproject_roots=None, include_trace_on_error=True, execution_options=None, ): """Construct and return the components necessary for LegacyBuildGraph construction. :param list pants_ignore_patterns: A list of path ignore patterns for FileSystemProjectTree, usually taken from the '--pants-ignore' global option. :param local_store_dir: The directory to use for storing the engine's LMDB store in. :param build_file_imports_behavior: How to behave if a BUILD file being parsed tries to use import statements. Valid values: "allow", "warn", "error". :type build_file_imports_behavior: string :param str build_root: A path to be used as the build root. If None, then default is used. :param Native native: An instance of the native-engine subsystem. :param options_bootstrapper: A `OptionsBootstrapper` object containing bootstrap options. :type options_bootstrapper: :class:`pants.options.options_bootstrapper.OptionsBootstrapper` :param build_configuration: The `BuildConfiguration` object to get build file aliases from. :type build_configuration: :class:`pants.build_graph.build_configuration.BuildConfiguration` :param glob_match_error_behavior: How to behave if a glob specified for a target's sources or bundles does not expand to anything. :type glob_match_error_behavior: :class:`pants.option.global_options.GlobMatchErrorBehavior` :param list build_ignore_patterns: A list of paths ignore patterns used when searching for BUILD files, usually taken from the '--build-ignore' global option. :param list exclude_target_regexps: A list of regular expressions for excluding targets. :param list subproject_roots: Paths that correspond with embedded build roots under the current build root. :param bool include_trace_on_error: If True, when an error occurs, the error message will include the graph trace. :param execution_options: Option values for (remote) process execution. :type execution_options: :class:`pants.option.global_options.ExecutionOptions` :returns: A LegacyGraphScheduler. """ build_root = build_root or get_buildroot() build_configuration = build_configuration or BuildConfigInitializer.get(options_bootstrapper) bootstrap_options = options_bootstrapper.bootstrap_options.for_global_scope() build_file_aliases = build_configuration.registered_aliases() rules = build_configuration.rules() symbol_table = _legacy_symbol_table(build_file_aliases) project_tree = FileSystemProjectTree(build_root, pants_ignore_patterns) execution_options = execution_options or DEFAULT_EXECUTION_OPTIONS # Register "literal" subjects required for these rules. parser = LegacyPythonCallbacksParser( symbol_table, build_file_aliases, build_file_imports_behavior ) address_mapper = AddressMapper(parser=parser, build_ignore_patterns=build_ignore_patterns, exclude_target_regexps=exclude_target_regexps, subproject_roots=subproject_roots) @rule def glob_match_error_behavior_singleton() -> GlobMatchErrorBehavior: return glob_match_error_behavior or GlobMatchErrorBehavior.ignore @rule def build_configuration_singleton() -> BuildConfiguration: return build_configuration @rule def symbol_table_singleton() -> SymbolTable: return symbol_table @rule def union_membership_singleton() -> UnionMembership: return UnionMembership(build_configuration.union_rules()) @rule def build_root_singleton() -> BuildRoot: return BuildRoot.instance @rule async def single_build_file_address(specs: Specs) -> BuildFileAddress: build_file_addresses = await Get(BuildFileAddresses, Specs, specs) if len(build_file_addresses.dependencies) == 0: raise ResolveError("No targets were matched") if len(build_file_addresses.dependencies) > 1: potential_addresses = await Get(BuildFileAddresses, Specs, specs) targets = [bfa.to_address() for bfa in potential_addresses] output = '\n '.join(str(target) for target in targets) raise ResolveError( "Expected a single target, but was given multiple targets:\n" f"Did you mean one of:\n {output}" ) return build_file_addresses.dependencies[0] # Create a Scheduler containing graph and filesystem rules, with no installed goals. The # LegacyBuildGraph will explicitly request the products it needs. rules = ( [ RootRule(Console), glob_match_error_behavior_singleton, build_configuration_singleton, symbol_table_singleton, union_membership_singleton, build_root_singleton, single_build_file_address, ] + create_legacy_graph_tasks() + create_fs_rules() + create_interactive_runner_rules() + create_process_rules() + create_platform_rules() + create_graph_rules(address_mapper) + create_options_parsing_rules() + structs_rules() + rules ) goal_map = EngineInitializer._make_goal_map_from_rules(rules) union_rules = build_configuration.union_rules() scheduler = Scheduler( native, project_tree, local_store_dir, rules, union_rules, execution_options, include_trace_on_error=include_trace_on_error, visualize_to_dir=bootstrap_options.native_engine_visualize_to, ) return LegacyGraphScheduler(scheduler, build_file_aliases, goal_map)
def setup_legacy_graph(pants_ignore_patterns, workdir, build_file_imports_behavior, build_root=None, native=None, build_file_aliases=None, build_ignore_patterns=None, exclude_target_regexps=None, subproject_roots=None, include_trace_on_error=True): """Construct and return the components necessary for LegacyBuildGraph construction. :param list pants_ignore_patterns: A list of path ignore patterns for FileSystemProjectTree, usually taken from the '--pants-ignore' global option. :param str workdir: The pants workdir. :param build_file_imports_behavior: How to behave if a BUILD file being parsed tries to use import statements. Valid values: "allow", "warn", "error". :type build_file_imports_behavior: string :param str build_root: A path to be used as the build root. If None, then default is used. :param Native native: An instance of the native-engine subsystem. :param build_file_aliases: BuildFileAliases to register. :type build_file_aliases: :class:`pants.build_graph.build_file_aliases.BuildFileAliases` :param list build_ignore_patterns: A list of paths ignore patterns used when searching for BUILD files, usually taken from the '--build-ignore' global option. :param list exclude_target_regexps: A list of regular expressions for excluding targets. :param list subproject_roots: Paths that correspond with embedded build roots under the current build root. :param bool include_trace_on_error: If True, when an error occurs, the error message will include the graph trace. :returns: A tuple of (scheduler, engine, symbol_table, build_graph_cls). """ build_root = build_root or get_buildroot() scm = get_scm() if not build_file_aliases: _, build_config = OptionsInitializer( OptionsBootstrapper()).setup(init_logging=False) build_file_aliases = build_config.registered_aliases() symbol_table = LegacySymbolTable(build_file_aliases) project_tree = FileSystemProjectTree(build_root, pants_ignore_patterns) # Register "literal" subjects required for these tasks. parser = LegacyPythonCallbacksParser(symbol_table, build_file_aliases, build_file_imports_behavior) address_mapper = AddressMapper( parser=parser, build_ignore_patterns=build_ignore_patterns, exclude_target_regexps=exclude_target_regexps, subproject_roots=subproject_roots) # Load the native backend. native = native or Native.create() # Create a Scheduler containing graph and filesystem tasks, with no installed goals. The # LegacyBuildGraph will explicitly request the products it needs. tasks = (create_legacy_graph_tasks(symbol_table) + create_fs_rules() + create_graph_rules(address_mapper, symbol_table) + create_process_rules()) scheduler = LocalScheduler( workdir, dict(), tasks, project_tree, native, include_trace_on_error=include_trace_on_error) change_calculator = EngineChangeCalculator(scheduler, symbol_table, scm) if scm else None return LegacyGraphHelper(scheduler, symbol_table, change_calculator)
def _address_mapper(self): return AddressMapper(JsonParser(TestTable()))
def setup_json_scheduler(build_root, native): """Return a build graph and scheduler configured for BLD.json files under the given build root. :rtype :class:`pants.engine.scheduler.LocalScheduler` """ symbol_table_cls = ExampleTable # Register "literal" subjects required for these tasks. # TODO: Replace with `Subsystems`. address_mapper = AddressMapper(symbol_table_cls=symbol_table_cls, build_patterns=('BLD.json',), parser_cls=JsonParser) source_roots = SourceRoots(('src/java','src/scala')) scrooge_tool_address = Address.parse('src/scala/scrooge') goals = { 'compile': Classpath, # TODO: to allow for running resolve alone, should split out a distinct 'IvyReport' product. 'resolve': Classpath, 'list': Address, GenGoal.name(): GenGoal, 'ls': Files, 'cat': FilesContent, } tasks = [ # Codegen GenGoal.signature(), (JavaSources, [Select(ThriftSources), SelectVariant(ApacheThriftJavaConfiguration, 'thrift')], gen_apache_thrift), (PythonSources, [Select(ThriftSources), SelectVariant(ApacheThriftPythonConfiguration, 'thrift')], gen_apache_thrift), (ScalaSources, [Select(ThriftSources), SelectVariant(ScroogeScalaConfiguration, 'thrift'), SelectLiteral(scrooge_tool_address, Classpath)], gen_scrooge_thrift), (JavaSources, [Select(ThriftSources), SelectVariant(ScroogeJavaConfiguration, 'thrift'), SelectLiteral(scrooge_tool_address, Classpath)], gen_scrooge_thrift), ] + [ # scala dependency inference (ScalaSources, [Select(ScalaInferredDepsSources), SelectDependencies(Address, ImportedJVMPackages, field_types=(JVMPackageName,))], reify_scala_sources), (ImportedJVMPackages, [SelectProjection(FilesContent, PathGlobs, ('path_globs',), ScalaInferredDepsSources)], extract_scala_imports), (Address, [Select(JVMPackageName), SelectDependencies(AddressFamily, Dirs, field='stats', field_types=(Dir,))], select_package_address), (PathGlobs, [Select(JVMPackageName), SelectLiteral(source_roots, SourceRoots)], calculate_package_search_path), ] + [ # Remote dependency resolution (Classpath, [Select(Jar)], ivy_resolve), (Jar, [Select(ManagedJar), SelectVariant(ManagedResolve, 'resolve')], select_rev), ] + [ # Compilers (Classpath, [Select(ResourceSources)], isolate_resources), (Classpath, [Select(BuildPropertiesConfiguration)], write_name_file), # NB: Not sure these SelectDependencies should allow Jar, but they currently produce jars. (Classpath, [Select(JavaSources), SelectDependencies(Classpath, JavaSources, field_types=(Address, Jar))], javac), (Classpath, [Select(ScalaSources), SelectDependencies(Classpath, ScalaSources, field_types=(Address, Jar))], scalac), ] + ( create_graph_tasks(address_mapper, symbol_table_cls) ) + ( create_fs_tasks() ) project_tree = FileSystemProjectTree(build_root) return LocalScheduler(goals, tasks, project_tree, native, graph_lock=None)
def _address_mapper(self): return AddressMapper(JsonParser(TEST_TABLE))
def setup_legacy_graph_extended( pants_ignore_patterns, workdir, local_store_dir, build_file_imports_behavior, options_bootstrapper, build_configuration, build_root=None, native=None, glob_match_error_behavior=None, build_ignore_patterns=None, exclude_target_regexps=None, subproject_roots=None, include_trace_on_error=True, execution_options=None, ): """Construct and return the components necessary for LegacyBuildGraph construction. :param list pants_ignore_patterns: A list of path ignore patterns for FileSystemProjectTree, usually taken from the '--pants-ignore' global option. :param str workdir: The pants workdir. :param local_store_dir: The directory to use for storing the engine's LMDB store in. :param build_file_imports_behavior: How to behave if a BUILD file being parsed tries to use import statements. Valid values: "allow", "warn", "error". :type build_file_imports_behavior: string :param str build_root: A path to be used as the build root. If None, then default is used. :param Native native: An instance of the native-engine subsystem. :param options_bootstrapper: A `OptionsBootstrapper` object containing bootstrap options. :type options_bootstrapper: :class:`pants.options.options_bootstrapper.OptionsBootstrapper` :param build_configuration: The `BuildConfiguration` object to get build file aliases from. :type build_configuration: :class:`pants.build_graph.build_configuration.BuildConfiguration` :param glob_match_error_behavior: How to behave if a glob specified for a target's sources or bundles does not expand to anything. :type glob_match_error_behavior: :class:`pants.option.global_options.GlobMatchErrorBehavior` :param list build_ignore_patterns: A list of paths ignore patterns used when searching for BUILD files, usually taken from the '--build-ignore' global option. :param list exclude_target_regexps: A list of regular expressions for excluding targets. :param list subproject_roots: Paths that correspond with embedded build roots under the current build root. :param bool include_trace_on_error: If True, when an error occurs, the error message will include the graph trace. :param execution_options: Option values for (remote) process execution. :type execution_options: :class:`pants.option.global_options.ExecutionOptions` :returns: A LegacyGraphScheduler. """ build_root = build_root or get_buildroot() build_configuration = build_configuration or BuildConfigInitializer.get( options_bootstrapper) build_file_aliases = build_configuration.registered_aliases() rules = build_configuration.rules() console = Console() symbol_table = LegacySymbolTable(build_file_aliases) project_tree = FileSystemProjectTree(build_root, pants_ignore_patterns) execution_options = execution_options or DEFAULT_EXECUTION_OPTIONS # Register "literal" subjects required for these rules. parser = LegacyPythonCallbacksParser(symbol_table, build_file_aliases, build_file_imports_behavior) address_mapper = AddressMapper( parser=parser, build_ignore_patterns=build_ignore_patterns, exclude_target_regexps=exclude_target_regexps, subproject_roots=subproject_roots) # Load the native backend. native = native or Native.create() # Create a Scheduler containing graph and filesystem rules, with no installed goals. The # LegacyBuildGraph will explicitly request the products it needs. rules = ( [ SingletonRule.from_instance(console), SingletonRule.from_instance( GlobMatchErrorBehavior.create(glob_match_error_behavior)), SingletonRule.from_instance(build_configuration), ] + create_legacy_graph_tasks(symbol_table) + create_fs_rules() + create_process_rules() + create_graph_rules(address_mapper, symbol_table) + create_options_parsing_rules() + create_core_rules() + # TODO: This should happen automatically, but most tests (e.g. tests/python/pants_test/auth) fail if it's not here: [run_python_test] + rules) goal_map = EngineInitializer._make_goal_map_from_rules(rules) scheduler = Scheduler( native, project_tree, workdir, local_store_dir, rules, execution_options, include_trace_on_error=include_trace_on_error, ) return LegacyGraphScheduler(scheduler, symbol_table, console, goal_map)
def setup_legacy_graph_extended( pants_ignore_patterns: List[str], local_store_dir, build_file_imports_behavior: BuildFileImportsBehavior, options_bootstrapper: OptionsBootstrapper, build_configuration: BuildConfiguration, build_root: Optional[str] = None, native: Optional[Native] = None, glob_match_error_behavior: GlobMatchErrorBehavior = GlobMatchErrorBehavior.warn, build_ignore_patterns=None, exclude_target_regexps=None, subproject_roots=None, include_trace_on_error: bool = True, execution_options: Optional[ExecutionOptions] = None, ) -> LegacyGraphScheduler: """Construct and return the components necessary for LegacyBuildGraph construction. :param local_store_dir: The directory to use for storing the engine's LMDB store in. :param build_file_imports_behavior: How to behave if a BUILD file being parsed tries to use import statements. :param build_root: A path to be used as the build root. If None, then default is used. :param native: An instance of the native-engine subsystem. :param options_bootstrapper: A `OptionsBootstrapper` object containing bootstrap options. :param build_configuration: The `BuildConfiguration` object to get build file aliases from. :param glob_match_error_behavior: How to behave if a glob specified for a target's sources or bundles does not expand to anything. :param list build_ignore_patterns: A list of paths ignore patterns used when searching for BUILD files, usually taken from the '--build-ignore' global option. :param list exclude_target_regexps: A list of regular expressions for excluding targets. :param list subproject_roots: Paths that correspond with embedded build roots under the current build root. :param include_trace_on_error: If True, when an error occurs, the error message will include the graph trace. :param execution_options: Option values for (remote) process execution. """ build_root = build_root or get_buildroot() build_configuration = build_configuration or BuildConfigInitializer.get( options_bootstrapper) bootstrap_options = options_bootstrapper.bootstrap_options.for_global_scope( ) build_file_aliases = build_configuration.registered_aliases() rules = build_configuration.rules() symbol_table = _legacy_symbol_table(build_file_aliases) execution_options = execution_options or DEFAULT_EXECUTION_OPTIONS # Register "literal" subjects required for these rules. parser = LegacyPythonCallbacksParser(symbol_table, build_file_aliases, build_file_imports_behavior) address_mapper = AddressMapper( parser=parser, build_ignore_patterns=build_ignore_patterns, exclude_target_regexps=exclude_target_regexps, subproject_roots=subproject_roots, ) @rule def glob_match_error_behavior_singleton() -> GlobMatchErrorBehavior: return glob_match_error_behavior @rule def build_configuration_singleton() -> BuildConfiguration: return build_configuration @rule def symbol_table_singleton() -> SymbolTable: return symbol_table @rule def union_membership_singleton() -> UnionMembership: return UnionMembership(build_configuration.union_rules()) @rule def build_root_singleton() -> BuildRoot: return cast(BuildRoot, BuildRoot.instance) # Create a Scheduler containing graph and filesystem rules, with no installed goals. The # LegacyBuildGraph will explicitly request the products it needs. rules = ( RootRule(Console), glob_match_error_behavior_singleton, build_configuration_singleton, symbol_table_singleton, union_membership_singleton, build_root_singleton, *create_legacy_graph_tasks(), *create_fs_rules(), *create_interactive_runner_rules(), *create_process_rules(), *create_platform_rules(), *create_graph_rules(address_mapper), *create_options_parsing_rules(), *structs_rules(), *changed_rules(), *binary_tool_rules(), *binary_util_rules(), *rules, ) goal_map = EngineInitializer._make_goal_map_from_rules(rules) union_rules = build_configuration.union_rules() scheduler = Scheduler( native=native, ignore_patterns=pants_ignore_patterns, build_root=build_root, local_store_dir=local_store_dir, rules=rules, union_rules=union_rules, execution_options=execution_options, include_trace_on_error=include_trace_on_error, visualize_to_dir=bootstrap_options.native_engine_visualize_to, ) return LegacyGraphScheduler(scheduler, build_file_aliases, goal_map)