Esempio n. 1
0
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)
Esempio n. 2
0
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)
Esempio n. 3
0
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)
Esempio n. 4
0
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", ))
Esempio n. 5
0
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(),
    )
Esempio n. 6
0
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,
    )
Esempio n. 7
0
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)
Esempio n. 8
0
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)