def mk_scheduler( self, rules=None, union_rules=None, project_tree=None, work_dir=None, include_trace_on_error=True, should_report_workunits=False, execution_options=None, ): """Creates a SchedulerSession for a Scheduler with the given Rules installed.""" rules = rules or [] work_dir = work_dir or self._create_work_dir() project_tree = project_tree or self.mk_fs_tree(work_dir=work_dir) local_store_dir = os.path.realpath(safe_mkdtemp()) if execution_options is not None: eo = asdict(DEFAULT_EXECUTION_OPTIONS) eo.update(execution_options) execution_options = ExecutionOptions(**eo) scheduler = Scheduler( native=self._native, ignore_patterns=project_tree.ignore_patterns, use_gitignore=False, build_root=project_tree.build_root, local_store_dir=local_store_dir, rules=rules, union_rules=union_rules, execution_options=execution_options or DEFAULT_EXECUTION_OPTIONS, include_trace_on_error=include_trace_on_error, ) return scheduler.new_session( zipkin_trace_v2=False, build_id="buildid_for_test", should_report_workunits=should_report_workunits, )
def mk_scheduler( self, rules, include_trace_on_error: bool = True, ) -> SchedulerSession: """Creates a SchedulerSession for a Scheduler with the given Rules installed.""" work_dir = self._create_work_dir() build_root = os.path.join(work_dir, "build_root") os.makedirs(build_root) local_store_dir = os.path.realpath(safe_mkdtemp()) local_execution_root_dir = os.path.realpath(safe_mkdtemp()) named_caches_dir = os.path.realpath(safe_mkdtemp()) scheduler = Scheduler( native=self._native, ignore_patterns=[], use_gitignore=False, build_root=build_root, local_store_dir=local_store_dir, local_execution_root_dir=local_execution_root_dir, named_caches_dir=named_caches_dir, ca_certs_path=None, rules=rules, union_membership=UnionMembership({}), executor=self._executor, execution_options=DEFAULT_EXECUTION_OPTIONS, include_trace_on_error=include_trace_on_error, ) return scheduler.new_session(build_id="buildid_for_test", )
def mk_scheduler( self, tmp_path: Path, rules, include_trace_on_error: bool = True, max_workunit_verbosity: LogLevel = LogLevel.DEBUG, ) -> SchedulerSession: """Creates a SchedulerSession for a Scheduler with the given Rules installed.""" build_root = tmp_path / "build_root" build_root.mkdir(parents=True, exist_ok=True) local_execution_root_dir = os.path.realpath(safe_mkdtemp()) named_caches_dir = os.path.realpath(safe_mkdtemp()) scheduler = Scheduler( ignore_patterns=[], use_gitignore=False, build_root=build_root.as_posix(), local_execution_root_dir=local_execution_root_dir, named_caches_dir=named_caches_dir, ca_certs_path=None, rules=rules, union_membership=UnionMembership({}), executor=self._executor, execution_options=DEFAULT_EXECUTION_OPTIONS, local_store_options=DEFAULT_LOCAL_STORE_OPTIONS, include_trace_on_error=include_trace_on_error, ) return scheduler.new_session( build_id="buildid_for_test", max_workunit_level=max_workunit_verbosity, )
def _set_new_session(self, scheduler: Scheduler) -> None: self.scheduler = scheduler.new_session( build_id="buildid_for_test", session_values=SessionValues({ OptionsBootstrapper: self.options_bootstrapper, CompleteEnvironment: self.environment, **self.extra_session_values, }), max_workunit_level=self.max_workunit_verbosity, )
def mk_scheduler( self, rules=None, project_tree=None, work_dir=None, include_trace_on_error=True, execution_options=None, ca_certs_path=None, ) -> SchedulerSession: """Creates a SchedulerSession for a Scheduler with the given Rules installed.""" rules = rules or [] work_dir = work_dir or self._create_work_dir() project_tree = project_tree or self.mk_fs_tree(work_dir=work_dir) local_store_dir = os.path.realpath(safe_mkdtemp()) local_execution_root_dir = os.path.realpath(safe_mkdtemp()) named_caches_dir = os.path.realpath(safe_mkdtemp()) if execution_options is not None: eo = asdict(DEFAULT_EXECUTION_OPTIONS) eo.update(execution_options) execution_options = ExecutionOptions(**eo) scheduler = Scheduler( native=self._native, ignore_patterns=project_tree.ignore_patterns, use_gitignore=False, build_root=project_tree.build_root, local_store_dir=local_store_dir, local_execution_root_dir=local_execution_root_dir, named_caches_dir=named_caches_dir, ca_certs_path=ca_certs_path, rules=rules, union_membership=UnionMembership({}), executor=self._executor, execution_options=execution_options or DEFAULT_EXECUTION_OPTIONS, include_trace_on_error=include_trace_on_error, ) return scheduler.new_session(build_id="buildid_for_test", )
def create_scheduler(rules, union_rules=None, validate=True, native=None): """Create a Scheduler.""" native = native or init_native() tree = FileSystemProjectTree(os.getcwd()) return Scheduler( native=native, ignore_patterns=tree.ignore_patterns, use_gitignore=False, build_root=tree.build_root, local_store_dir="./.pants.d", rules=rules, union_rules=union_rules, execution_options=DEFAULT_EXECUTION_OPTIONS, validate=validate, )
def create_scheduler(rules, union_rules=None, validate=True, native=None): """Create a Scheduler.""" native = native or init_native() return Scheduler( native=native, ignore_patterns=[], use_gitignore=False, build_root=str(Path.cwd()), local_store_dir="./.pants.d", local_execution_root_dir="./.pants.d", rules=rules, union_rules=union_rules, execution_options=DEFAULT_EXECUTION_OPTIONS, validate=validate, )
def create_scheduler(rules, validate=True, native=None): """Create a Scheduler.""" native = native or Native() return Scheduler( native=native, ignore_patterns=[], use_gitignore=False, build_root=str(Path.cwd()), local_store_dir="./.pants.d/lmdb_store", local_execution_root_dir="./.pants.d", named_caches_dir="./.pants.d/named_caches", rules=rules, union_membership=UnionMembership({}), execution_options=DEFAULT_EXECUTION_OPTIONS, validate=validate, )
def create_scheduler(rules, validate=True): """Create a Scheduler.""" return Scheduler( ignore_patterns=[], use_gitignore=False, build_root=str(Path.cwd()), local_execution_root_dir=".", named_caches_dir="./.pants.d/named_caches", ca_certs_path=None, rules=rules, union_membership=UnionMembership({}), executor=_EXECUTOR, execution_options=DEFAULT_EXECUTION_OPTIONS, local_store_options=DEFAULT_LOCAL_STORE_OPTIONS, validate_reachability=validate, )
def __init__( self, scheduler: Scheduler, period_secs=10, lease_extension_interval_secs=(30 * 60), gc_interval_secs=(4 * 60 * 60), ): super().__init__() self._scheduler_session = scheduler.new_session( build_id="store_gc_service_session") self._logger = logging.getLogger(__name__) self._period_secs = period_secs self._lease_extension_interval_secs = lease_extension_interval_secs self._gc_interval_secs = gc_interval_secs self._set_next_gc() self._set_next_lease_extension()
def __init__( self, watchman: Watchman, scheduler: Scheduler, build_root: str, ): """ :param watchman: The Watchman instance as provided by the WatchmanLauncher subsystem. :param session: A SchedulerSession to invalidate for. :param build_root: The current build root. """ super().__init__() self._logger = logging.getLogger(__name__) self._watchman = watchman self._build_root = os.path.realpath(build_root) self._watchman_is_running = threading.Event() self._scheduler_session = scheduler.new_session( zipkin_trace_v2=False, build_id="fs_event_service_session" ) self._handler = Watchman.EventHandler( name=self.PANTS_ALL_FILES_SUBSCRIPTION_NAME, metadata=dict( fields=["name"], # Request events for all file types. # NB: Touching a file invalidates its parent directory due to: # https://github.com/facebook/watchman/issues/305 # ...but if we were to skip watching directories, we'd still have to invalidate # the parents of any changed files, and we wouldn't see creation/deletion of # empty directories. expression=[ "allof", # All of the below rules must be true to match. ["not", ["dirname", "dist", self.ZERO_DEPTH]], # Exclude the ./dist dir. # N.B. 'wholename' ensures we match against the absolute ('x/y/z') vs base path ('z'). [ "not", ["pcre", r"^\..*", "wholename"], ], # Exclude files in hidden dirs (.pants.d etc). ["not", ["match", "*.pyc"]] # Exclude .pyc files. # TODO(kwlzn): Make exclusions here optionable. # Related: https://github.com/pantsbuild/pants/issues/2956 ], ), # NB: We stream events from Watchman in `self.run`, so we don't need a callback. callback=lambda: None, )
def __init__( self, scheduler: Scheduler, period_secs: float = 10, lease_extension_interval_secs: float = (float(LOCAL_STORE_LEASE_TIME_SECS) / 100), gc_interval_secs: float = (1 * 60 * 60), local_store_options: LocalStoreOptions = DEFAULT_LOCAL_STORE_OPTIONS, ): super().__init__() self._scheduler_session = scheduler.new_session(build_id="store_gc_service_session") self._logger = logging.getLogger(__name__) self._period_secs = period_secs self._lease_extension_interval_secs = lease_extension_interval_secs self._gc_interval_secs = gc_interval_secs self._target_size_bytes = local_store_options.target_total_size_bytes() self._set_next_gc() self._set_next_lease_extension()
def setup_legacy_graph_extended( pants_ignore_patterns: List[str], use_gitignore: bool, local_store_dir: str, local_execution_root_dir: str, named_caches_dir: str, build_file_prelude_globs: Tuple[str, ...], options_bootstrapper: OptionsBootstrapper, build_configuration: BuildConfiguration, execution_options: ExecutionOptions, 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, ) -> 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 local_execution_root_dir: The directory to use for local execution sandboxes. :param named_caches_dir: The base directory for named cache storage. :param build_file_prelude_globs: Globs to match files to be prepended to all BUILD files. :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() registered_target_types = RegisteredTargetTypes.create( build_configuration.target_types()) symbol_table = _legacy_symbol_table(build_file_aliases, registered_target_types) execution_options = execution_options or DEFAULT_EXECUTION_OPTIONS # Register "literal" subjects required for these rules. parser = LegacyPythonCallbacksParser(symbol_table, build_file_aliases) address_mapper = AddressMapper( parser=parser, prelude_glob_patterns=build_file_prelude_globs, 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 registered_target_types_singleton() -> RegisteredTargetTypes: return registered_target_types @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, registered_target_types_singleton, union_membership_singleton, build_root_singleton, *interactive_runner.rules(), *graph.rules(), *options_parsing.rules(), *process.rules(), *target.rules(), *create_legacy_graph_tasks(), *create_fs_rules(), *create_platform_rules(), *create_graph_rules(address_mapper), *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, use_gitignore=use_gitignore, build_root=build_root, local_store_dir=local_store_dir, local_execution_root_dir=local_execution_root_dir, named_caches_dir=named_caches_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)
def setup_graph_extended( build_configuration: BuildConfiguration, execution_options: ExecutionOptions, native: Native, *, executor: PyExecutor, pants_ignore_patterns: List[str], use_gitignore: bool, local_store_dir: str, local_execution_root_dir: str, named_caches_dir: str, ca_certs_path: Optional[str] = None, build_root: Optional[str] = None, include_trace_on_error: bool = True, native_engine_visualize_to: Optional[str] = None, ) -> GraphScheduler: build_root = build_root or get_buildroot() rules = build_configuration.rules union_membership = UnionMembership.from_rules( build_configuration.union_rules) registered_target_types = RegisteredTargetTypes.create( build_configuration.target_types) execution_options = execution_options or DEFAULT_EXECUTION_OPTIONS @rule def parser_singleton() -> Parser: return Parser( target_type_aliases=registered_target_types.aliases, object_aliases=build_configuration.registered_aliases, ) @rule def build_configuration_singleton() -> BuildConfiguration: return build_configuration @rule def registered_target_types_singleton() -> RegisteredTargetTypes: return registered_target_types @rule def union_membership_singleton() -> UnionMembership: return union_membership @rule def build_root_singleton() -> BuildRoot: return cast(BuildRoot, BuildRoot.instance) # Create a Scheduler containing graph and filesystem rules, with no installed goals. rules = FrozenOrderedSet(( *collect_rules(locals()), *build_files.rules(), *fs.rules(), *environment.rules(), *desktop.rules(), *graph.rules(), *options_parsing.rules(), *process.rules(), *platform.rules(), *changed_rules(), *streaming_workunit_handler_rules(), *specs_calculator.rules(), *rules, )) goal_map = EngineInitializer._make_goal_map_from_rules(rules) rules = FrozenOrderedSet(( *rules, # Install queries for each Goal. *(QueryRule(goal_type, GraphSession.goal_param_types) for goal_type in goal_map.values()), QueryRule(Snapshot, [PathGlobs]), # Used by the SchedulerService. )) def ensure_absolute_path(v: str) -> str: return Path(v).resolve().as_posix() def ensure_optional_absolute_path(v: Optional[str]) -> Optional[str]: if v is None: return None return ensure_absolute_path(v) scheduler = Scheduler( native=native, ignore_patterns=pants_ignore_patterns, use_gitignore=use_gitignore, build_root=build_root, local_store_dir=ensure_absolute_path(local_store_dir), local_execution_root_dir=ensure_absolute_path( local_execution_root_dir), named_caches_dir=ensure_absolute_path(named_caches_dir), ca_certs_path=ensure_optional_absolute_path(ca_certs_path), rules=rules, union_membership=union_membership, executor=executor, execution_options=execution_options, include_trace_on_error=include_trace_on_error, visualize_to_dir=native_engine_visualize_to, ) return GraphScheduler(scheduler, goal_map)
def setup_graph_extended( options_bootstrapper: OptionsBootstrapper, build_configuration: BuildConfiguration, execution_options: ExecutionOptions, native: Native, *, pants_ignore_patterns: List[str], use_gitignore: bool, local_store_dir: str, local_execution_root_dir: str, named_caches_dir: str, build_root: Optional[str] = None, include_trace_on_error: bool = True, ) -> GraphScheduler: build_root = build_root or get_buildroot() build_configuration = build_configuration or BuildConfigInitializer.get( options_bootstrapper) rules = build_configuration.rules union_membership = UnionMembership.from_rules( build_configuration.union_rules) registered_target_types = RegisteredTargetTypes.create( build_configuration.target_types) bootstrap_options = options_bootstrapper.bootstrap_options.for_global_scope( ) execution_options = execution_options or DEFAULT_EXECUTION_OPTIONS @rule def parser_singleton() -> Parser: return Parser( target_type_aliases=registered_target_types.aliases, object_aliases=build_configuration.registered_aliases, ) @rule def build_configuration_singleton() -> BuildConfiguration: return build_configuration @rule def registered_target_types_singleton() -> RegisteredTargetTypes: return registered_target_types @rule def union_membership_singleton() -> UnionMembership: return union_membership @rule def build_root_singleton() -> BuildRoot: return cast(BuildRoot, BuildRoot.instance) # Create a Scheduler containing graph and filesystem rules, with no installed goals. rules = FrozenOrderedSet(( *collect_rules(locals()), RootRule(Console), *build_files.rules(), *fs.rules(), *graph.rules(), *uuid.rules(), *options_parsing.rules(), *process.rules(), *create_platform_rules(), *changed_rules(), *rules, )) goal_map = EngineInitializer._make_goal_map_from_rules(rules) def ensure_absolute_path(v: str) -> str: return Path(v).resolve().as_posix() scheduler = Scheduler( native=native, ignore_patterns=pants_ignore_patterns, use_gitignore=use_gitignore, build_root=build_root, local_store_dir=ensure_absolute_path(local_store_dir), local_execution_root_dir=ensure_absolute_path( local_execution_root_dir), named_caches_dir=ensure_absolute_path(named_caches_dir), rules=rules, union_membership=union_membership, execution_options=execution_options, include_trace_on_error=include_trace_on_error, visualize_to_dir=bootstrap_options.native_engine_visualize_to, ) return GraphScheduler(scheduler, goal_map)
def setup_graph_extended( build_configuration: BuildConfiguration, execution_options: ExecutionOptions, *, executor: PyExecutor, pants_ignore_patterns: list[str], use_gitignore: bool, local_store_options: LocalStoreOptions, local_execution_root_dir: str, named_caches_dir: str, use_deprecated_python_macros: bool, ca_certs_path: str | None = None, build_root: str | None = None, include_trace_on_error: bool = True, engine_visualize_to: str | None = None, watch_filesystem: bool = True, ) -> GraphScheduler: build_root_path = build_root or get_buildroot() rules = build_configuration.rules union_membership: UnionMembership registered_target_types = RegisteredTargetTypes.create( build_configuration.target_types) execution_options = execution_options or DEFAULT_EXECUTION_OPTIONS @rule def parser_singleton() -> Parser: return Parser( build_root=build_root_path, target_type_aliases=registered_target_types.aliases, object_aliases=build_configuration.registered_aliases, use_deprecated_python_macros=use_deprecated_python_macros, ) @rule def build_configuration_singleton() -> BuildConfiguration: return build_configuration @rule def registered_target_types_singleton() -> RegisteredTargetTypes: return registered_target_types @rule def union_membership_singleton() -> UnionMembership: return union_membership @rule def build_root_singleton() -> BuildRoot: return cast(BuildRoot, BuildRoot.instance) # Create a Scheduler containing graph and filesystem rules, with no installed goals. rules = FrozenOrderedSet(( *collect_rules(locals()), *build_files.rules(), *fs.rules(), *environment.rules(), *desktop.rules(), *graph.rules(), *options_parsing.rules(), *process.rules(), *system_binaries.rules(), *platform.rules(), *changed_rules(), *streaming_workunit_handler_rules(), *specs_calculator.rules(), *rules, )) goal_map = EngineInitializer._make_goal_map_from_rules(rules) union_membership = UnionMembership.from_rules(( *build_configuration.union_rules, *(r for r in rules if isinstance(r, UnionRule)), )) rules = FrozenOrderedSet(( *rules, # Install queries for each Goal. *(QueryRule(goal_type, GraphSession.goal_param_types) for goal_type in goal_map.values()), # Install queries for each request/response pair used by the BSP support. # Note: These are necessary because the BSP support is a built-in goal that makes # synchronous requests into the engine. *(QueryRule(impl.response_type, (impl.request_type, Workspace)) for impl in union_membership.get(BSPHandlerMapping)), QueryRule(Snapshot, [PathGlobs]), # Used by the SchedulerService. )) def ensure_absolute_path(v: str) -> str: return Path(v).resolve().as_posix() def ensure_optional_absolute_path(v: str | None) -> str | None: if v is None: return None return ensure_absolute_path(v) scheduler = Scheduler( ignore_patterns=pants_ignore_patterns, use_gitignore=use_gitignore, build_root=build_root_path, local_execution_root_dir=ensure_absolute_path( local_execution_root_dir), named_caches_dir=ensure_absolute_path(named_caches_dir), ca_certs_path=ensure_optional_absolute_path(ca_certs_path), rules=rules, union_membership=union_membership, executor=executor, execution_options=execution_options, local_store_options=local_store_options, include_trace_on_error=include_trace_on_error, visualize_to_dir=engine_visualize_to, watch_filesystem=watch_filesystem, ) return GraphScheduler(scheduler, goal_map)
def setup_legacy_graph_extended( options_bootstrapper: OptionsBootstrapper, build_configuration: BuildConfiguration, execution_options: ExecutionOptions, *, pants_ignore_patterns: List[str], use_gitignore: bool, local_store_dir: str, local_execution_root_dir: str, named_caches_dir: str, build_root: Optional[str] = None, native: Optional[Native] = None, glob_match_error_behavior: GlobMatchErrorBehavior = GlobMatchErrorBehavior.warn, build_patterns: Optional[Iterable[str]] = None, build_file_prelude_globs: Optional[Iterable[str]] = None, build_ignore_patterns: Optional[Iterable[str]] = None, tags: Optional[Iterable[str]] = None, exclude_target_regexps: Optional[Iterable[str]] = None, subproject_roots: Optional[Iterable[str]] = None, include_trace_on_error: bool = True, ) -> LegacyGraphScheduler: """Construct and return the components necessary for LegacyBuildGraph construction.""" 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( ) execution_options = execution_options or DEFAULT_EXECUTION_OPTIONS build_file_aliases = build_configuration.registered_aliases rules = build_configuration.rules union_membership = UnionMembership.from_rules( build_configuration.union_rules) registered_target_types = RegisteredTargetTypes.create( build_configuration.target_types) parser = Parser(target_type_aliases=registered_target_types.aliases, object_aliases=build_file_aliases) address_mapper = AddressMapper( parser=parser, prelude_glob_patterns=build_file_prelude_globs, build_patterns=build_patterns, build_ignore_patterns=build_ignore_patterns, tags=tags, exclude_target_regexps=exclude_target_regexps, subproject_roots=subproject_roots, ) @rule def address_mapper_singleton() -> AddressMapper: return address_mapper @rule def glob_match_error_behavior_singleton() -> GlobMatchErrorBehavior: return glob_match_error_behavior @rule def build_configuration_singleton() -> BuildConfiguration: return build_configuration @rule def registered_target_types_singleton() -> RegisteredTargetTypes: return registered_target_types @rule def union_membership_singleton() -> UnionMembership: return union_membership @rule def build_root_singleton() -> BuildRoot: return cast(BuildRoot, BuildRoot.instance) # Create a Scheduler containing graph and filesystem rules, with no installed goals. rules = FrozenOrderedSet(( *collect_rules(locals()), RootRule(Console), *build_files.rules(), *fs.rules(), *graph.rules(), *uuid.rules(), *options_parsing.rules(), *process.rules(), *create_platform_rules(), *changed_rules(), *rules, )) goal_map = EngineInitializer._make_goal_map_from_rules(rules) def ensure_absolute_path(v: str) -> str: return Path(v).resolve().as_posix() scheduler = Scheduler( native=native, ignore_patterns=pants_ignore_patterns, use_gitignore=use_gitignore, build_root=build_root, local_store_dir=ensure_absolute_path(local_store_dir), local_execution_root_dir=ensure_absolute_path( local_execution_root_dir), named_caches_dir=ensure_absolute_path(named_caches_dir), rules=rules, union_membership=union_membership, 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)