async def setup_black(setup_request: SetupRequest, black: Black, python_setup: PythonSetup) -> Setup: # Black requires 3.6+ but uses the typed-ast library to work with 2.7, 3.4, 3.5, 3.6, and 3.7. # However, typed-ast does not understand 3.8+, so instead we must run Black with Python 3.8+ # when relevant. We only do this if if <3.8 can't be used, as we don't want a loose requirement # like `>=3.6` to result in requiring Python 3.8, which would error if 3.8 is not installed on # the machine. all_interpreter_constraints = InterpreterConstraints.create_from_compatibility_fields( (field_set.interpreter_constraints for field_set in setup_request.request.field_sets), python_setup, ) tool_interpreter_constraints = (all_interpreter_constraints if ( black.options.is_default("interpreter_constraints") and all_interpreter_constraints.requires_python38_or_newer( python_setup.interpreter_universe)) else black.interpreter_constraints) black_pex_get = Get( VenvPex, PexRequest, black.to_pex_request( interpreter_constraints=tool_interpreter_constraints), ) source_files_get = Get( SourceFiles, SourceFilesRequest(field_set.source for field_set in setup_request.request.field_sets), ) source_files, black_pex = await MultiGet(source_files_get, black_pex_get) source_files_snapshot = ( source_files.snapshot if setup_request.request.prior_formatter_result is None else setup_request.request.prior_formatter_result) config_files = await Get(ConfigFiles, ConfigFilesRequest, black.config_request(source_files_snapshot.dirs)) input_digest = await Get( Digest, MergeDigests( (source_files_snapshot.digest, config_files.snapshot.digest))) process = await Get( Process, VenvPexProcess( black_pex, argv=generate_argv(source_files, black, check_only=setup_request.check_only), input_digest=input_digest, output_files=source_files_snapshot.files, concurrency_available=len(setup_request.request.field_sets), description= f"Run Black on {pluralize(len(setup_request.request.field_sets), 'file')}.", level=LogLevel.DEBUG, ), ) return Setup(process, original_snapshot=source_files_snapshot)
async def setup_black(wrapped_target: FormattablePythonTarget, black: Black) -> BlackSetup: config_path: Optional[str] = black.get_options().config config_snapshot = await Get(Snapshot, PathGlobs(include=(config_path,))) resolved_requirements_pex = await Get( Pex, CreatePex( output_filename="black.pex", requirements=PexRequirements(requirements=tuple(black.get_requirement_specs())), interpreter_constraints=PexInterpreterConstraints( constraint_set=tuple(black.default_interpreter_constraints) ), entry_point=black.get_entry_point(), ) ) sources_digest = wrapped_target.target.sources.snapshot.directory_digest merged_input_files = await Get( Digest, DirectoriesToMerge( directories=( sources_digest, resolved_requirements_pex.directory_digest, config_snapshot.directory_digest, ) ), ) return BlackSetup(config_path, resolved_requirements_pex, merged_input_files)
async def setup( request: SetupRequest, black: Black, python_setup: PythonSetup, subprocess_encoding_environment: SubprocessEncodingEnvironment, ) -> Setup: adaptors_with_origins = request.formatter.adaptors_with_origins requirements_pex = await Get[Pex](PexRequest( output_filename="black.pex", requirements=PexRequirements(black.get_requirement_specs()), interpreter_constraints=PexInterpreterConstraints( black.default_interpreter_constraints), entry_point=black.get_entry_point(), )) config_path: Optional[str] = black.options.config config_snapshot = await Get[Snapshot](PathGlobs( globs=tuple([config_path] if config_path else []), glob_match_error_behavior=GlobMatchErrorBehavior.error, description_of_origin="the option `--black-config`", )) if request.formatter.prior_formatter_result is None: all_source_files = await Get[SourceFiles](LegacyAllSourceFilesRequest( adaptor_with_origin.adaptor for adaptor_with_origin in adaptors_with_origins)) all_source_files_snapshot = all_source_files.snapshot else: all_source_files_snapshot = request.formatter.prior_formatter_result specified_source_files = await Get[SourceFiles]( LegacySpecifiedSourceFilesRequest(adaptors_with_origins)) merged_input_files = await Get[Digest](DirectoriesToMerge(directories=( all_source_files_snapshot.directory_digest, requirements_pex.directory_digest, config_snapshot.directory_digest, )), ) address_references = ", ".join( sorted(adaptor_with_origin.adaptor.address.reference() for adaptor_with_origin in adaptors_with_origins)) process_request = requirements_pex.create_execute_request( python_setup=python_setup, subprocess_encoding_environment=subprocess_encoding_environment, pex_path="./black.pex", pex_args=generate_args( specified_source_files=specified_source_files, black=black, check_only=request.check_only, ), input_files=merged_input_files, output_files=all_source_files_snapshot.files, description=f"Run black for {address_references}", ) return Setup(process_request)
async def format_build_file_with_black(request: FormatWithBlackRequest, black: Black) -> RewrittenBuildFile: black_ics = await _find_python_interpreter_constraints_from_lockfile(black) black_pex_get = Get( VenvPex, PexRequest, black.to_pex_request(interpreter_constraints=black_ics)) build_file_digest_get = Get(Digest, CreateDigest([request.to_file_content()])) config_files_get = Get( ConfigFiles, ConfigFilesRequest, black.config_request(recursive_dirname(request.path))) black_pex, build_file_digest, config_files = await MultiGet( black_pex_get, build_file_digest_get, config_files_get) input_digest = await Get( Digest, MergeDigests( (build_file_digest, config_files.snapshot.digest))) argv = [] if black.config: argv.extend(["--config", black.config]) argv.extend(black.args) argv.append(request.path) black_result = await Get( ProcessResult, VenvPexProcess( black_pex, argv=argv, input_digest=input_digest, output_files=(request.path, ), description=f"Run Black on {request.path}.", level=LogLevel.DEBUG, ), ) if black_result.output_digest == build_file_digest: return RewrittenBuildFile(request.path, request.lines, change_descriptions=()) result_contents = await Get(DigestContents, Digest, black_result.output_digest) assert len(result_contents) == 1 result_lines = tuple( result_contents[0].content.decode("utf-8").splitlines()) return RewrittenBuildFile(request.path, result_lines, change_descriptions=("Format with Black", ))
async def setup_black(black: Black) -> BlackSetup: config_path: Optional[str] = black.get_options().config config_snapshot = await Get[Snapshot](PathGlobs(include=(config_path, ))) requirements_pex = await Get[Pex](CreatePex( output_filename="black.pex", requirements=PexRequirements( requirements=tuple(black.get_requirement_specs())), interpreter_constraints=PexInterpreterConstraints( constraint_set=tuple(black.default_interpreter_constraints)), entry_point=black.get_entry_point(), )) return BlackSetup( requirements_pex=requirements_pex, config_snapshot=config_snapshot, passthrough_args=black.get_args(), )
async def setup_black(black: Black) -> BlackSetup: config_path: Optional[str] = black.options.config config_snapshot = await Get[Snapshot](PathGlobs( globs=tuple([config_path] if config_path else []), glob_match_error_behavior=GlobMatchErrorBehavior.error, description_of_origin="the option `--black-config`", )) requirements_pex = await Get[Pex](CreatePex( output_filename="black.pex", requirements=PexRequirements( requirements=tuple(black.get_requirement_specs())), interpreter_constraints=PexInterpreterConstraints( constraint_set=tuple(black.default_interpreter_constraints)), entry_point=black.get_entry_point(), )) return BlackSetup( requirements_pex=requirements_pex, config_snapshot=config_snapshot, passthrough_args=tuple(black.options.args), skip=black.options.skip, )
async def setup( request: SetupRequest, black: Black, python_setup: PythonSetup, subprocess_encoding_environment: SubprocessEncodingEnvironment, ) -> Setup: requirements_pex_request = Get[Pex](PexRequest( output_filename="black.pex", requirements=PexRequirements(black.get_requirement_specs()), interpreter_constraints=PexInterpreterConstraints( black.default_interpreter_constraints), entry_point=black.get_entry_point(), )) config_path: Optional[str] = black.options.config config_snapshot_request = Get[Snapshot](PathGlobs( globs=tuple([config_path] if config_path else []), glob_match_error_behavior=GlobMatchErrorBehavior.error, description_of_origin="the option `--black-config`", )) all_source_files_request = Get[SourceFiles](AllSourceFilesRequest( field_set.sources for field_set in request.field_sets)) specified_source_files_request = Get[SourceFiles]( SpecifiedSourceFilesRequest((field_set.sources, field_set.origin) for field_set in request.field_sets)) requests: List[Get] = [ requirements_pex_request, config_snapshot_request, specified_source_files_request, ] if request.field_sets.prior_formatter_result is None: requests.append(all_source_files_request) requirements_pex, config_snapshot, specified_source_files, *rest = cast( Union[Tuple[Pex, Snapshot, SourceFiles], Tuple[Pex, Snapshot, SourceFiles, SourceFiles]], await MultiGet(requests), ) all_source_files_snapshot = (request.field_sets.prior_formatter_result if request.field_sets.prior_formatter_result else rest[0].snapshot) input_digest = await Get[Digest](MergeDigests( (all_source_files_snapshot.digest, requirements_pex.digest, config_snapshot.digest))) address_references = ", ".join( sorted(field_set.address.reference() for field_set in request.field_sets)) process = requirements_pex.create_process( python_setup=python_setup, subprocess_encoding_environment=subprocess_encoding_environment, pex_path="./black.pex", pex_args=generate_args( specified_source_files=specified_source_files, black=black, check_only=request.check_only, ), input_digest=input_digest, output_files=all_source_files_snapshot.files, description= (f"Run Black on {pluralize(len(request.field_sets), 'target')}: {address_references}." ), ) return Setup(process, original_digest=all_source_files_snapshot.digest)
async def black_fmt(request: BlackRequest, black: Black, python_setup: PythonSetup) -> FmtResult: if black.skip: return FmtResult.skip(formatter_name=request.name) # Black requires 3.6+ but uses the typed-ast library to work with 2.7, 3.4, 3.5, 3.6, and 3.7. # However, typed-ast does not understand 3.8+, so instead we must run Black with Python 3.8+ # when relevant. We only do this if if <3.8 can't be used, as we don't want a loose requirement # like `>=3.6` to result in requiring Python 3.8, which would error if 3.8 is not installed on # the machine. tool_interpreter_constraints = black.interpreter_constraints if black.options.is_default("interpreter_constraints"): try: # Don't compute this unless we have to, since it might fail. all_interpreter_constraints = InterpreterConstraints.create_from_compatibility_fields( (field_set.interpreter_constraints for field_set in request.field_sets), python_setup, ) except ValueError: raise ValueError( softwrap( """ Could not compute an interpreter to run Black on, due to conflicting requirements in the repo. Please set `[black].interpreter_constraints` explicitly in pants.toml to a suitable interpreter. """ ) ) if all_interpreter_constraints.requires_python38_or_newer( python_setup.interpreter_universe ): tool_interpreter_constraints = all_interpreter_constraints black_pex_get = Get( VenvPex, PexRequest, black.to_pex_request(interpreter_constraints=tool_interpreter_constraints), ) config_files_get = Get( ConfigFiles, ConfigFilesRequest, black.config_request(request.snapshot.dirs) ) black_pex, config_files = await MultiGet(black_pex_get, config_files_get) input_digest = await Get( Digest, MergeDigests((request.snapshot.digest, config_files.snapshot.digest)) ) result = await Get( ProcessResult, VenvPexProcess( black_pex, argv=( *(("--config", black.config) if black.config else ()), "-W", "{pants_concurrency}", *black.args, *request.snapshot.files, ), input_digest=input_digest, output_files=request.snapshot.files, concurrency_available=len(request.field_sets), description=f"Run Black on {pluralize(len(request.field_sets), 'file')}.", level=LogLevel.DEBUG, ), ) output_snapshot = await Get(Snapshot, Digest, result.output_digest) return FmtResult.create(request, result, output_snapshot, strip_chroot_path=True)