# Buggy code
def build(
    self,
    requirements,  # type: Iterable[InstallRequirement]
    session,  # type: PipSession
    autobuilding=False,  # type: bool
):
    # type: (...) -> List[InstallRequirement]
    """Build wheels.

    :param unpack: If True, replace the sdist we built from with the
        newly built wheel, in preparation for installation.
    :return: True if all the wheels built correctly.
    """
    # TODO: This check fails if --no-cache-dir is set. And yet we
    #       might be able to build into the ephemeral cache, surely?
    building_is_possible = self._wheel_dir or (
        autobuilding and self.wheel_cache.cache_dir
    )
    assert building_is_possible

    buildset = []
    format_control = self.finder.format_control
    for req in requirements:
        if req.constraint:
            continue
        if req.is_wheel:
            if not autobuilding:
                logger.info(
                    "Skipping %s, due to already being wheel.",
                    req.name,
                )
        elif autobuilding and req.editable:
            pass
        elif autobuilding and not req.source_dir:
            pass
        elif autobuilding and req.link and not req.link.is_artifact:
            # VCS checkout. Build wheel just for this run.
            buildset.append((req, True))
        else:
            ephem_cache = False
            if autobuilding:
                link = req.link
                base, ext = link.splitext()
                if not _contains_egg_info(base):
                    # E.g. local directory. Build wheel just for this run.
                    ephem_cache = True
                if "binary" not in format_control.get_allowed_formats(
                    canonicalize_name(req.name)
                ):
                    logger.info(
                        "Skipping bdist_wheel for %s, due to binaries "
                        "being disabled for it.",
                        req.name,
                    )
                    continue
            buildset.append((req, ephem_cache))

    if not buildset:
        return []

    # TODO by @pradyunsg
    # Should break up this method into 2 separate methods.

    # Build the wheels.
    logger.info(
        "Building wheels for collected packages: %s",
        ", ".join([req.name for (req, _) in buildset]),
    )
    _cache = self.wheel_cache  # shorter name
    with indent_log():
        build_success, build_failure = [], []
        for req, ephem in buildset:
            python_tag = None
            if autobuilding:
                python_tag = pep425tags.implementation_tag
                if ephem:
                    output_dir = _cache.get_ephem_path_for_link(req.link)
                else:
                    output_dir = _cache.get_path_for_link(req.link)
                try:
                    ensure_dir(output_dir)
                except OSError as e:
                    logger.warning("Building wheel for %s failed: %s", req.name, e)
                    build_failure.append(req)
                    continue
            else:
                output_dir = self._wheel_dir
            wheel_file = self._build_one(
                req,
                output_dir,
                python_tag=python_tag,
            )
            if wheel_file:
                build_success.append(req)
                if autobuilding:
                    # XXX: This is mildly duplicative with prepare_files,
                    # but not close enough to pull out to a single common
                    # method.
                    # The code below assumes temporary source dirs -
                    # prevent it doing bad things.
                    if req.source_dir and not os.path.exists(
                        os.path.join(req.source_dir, PIP_DELETE_MARKER_FILENAME)
                    ):
                        raise AssertionError("bad source dir - missing marker")
                    # Delete the source we built the wheel from
                    req.remove_temporary_source()
                    # set the build directory again - name is known from
                    # the work prepare_files did.
                    req.source_dir = req.build_location(self.preparer.build_dir)
                    # Update the link for this.
                    req.link = Link(path_to_url(wheel_file))
                    assert req.link.is_wheel
                    # extract the wheel into the dir
                    unpack_url(
                        req.link,
                        req.source_dir,
                        None,
                        False,
                        session=session,
                    )
            else:
                build_failure.append(req)

    # notify success/failure
    if build_success:
        logger.info(
            "Successfully built %s",
            " ".join([req.name for req in build_success]),
        )
    if build_failure:
        logger.info(
            "Failed to build %s",
            " ".join([req.name for req in build_failure]),
        )
    # Return a list of requirements that failed to build
    return build_failure


# Traceback (AssertionError)
Exception:
Traceback (most recent call last):
File "/Users/scotts/.virtualenvs/python3/lib/python3.6/site-packages/pip/_internal/cli/base_command.py", line 176, in main
status = self.run(options, args)
File "/Users/scotts/.virtualenvs/python3/lib/python3.6/site-packages/pip/_internal/commands/install.py", line 346, in run
session=session, autobuilding=True
File "/Users/scotts/.virtualenvs/python3/lib/python3.6/site-packages/pip/_internal/wheel.py", line 848, in build
assert building_is_possible
AssertionError

# Fixed code
def build(
    self,
    requirements,  # type: Iterable[InstallRequirement]
    session,  # type: PipSession
    autobuilding=False,  # type: bool
):
    # type: (...) -> List[InstallRequirement]
    """Build wheels.

    :param unpack: If True, replace the sdist we built from with the
        newly built wheel, in preparation for installation.
    :return: True if all the wheels built correctly.
    """

    buildset = []
    format_control = self.finder.format_control
    for req in requirements:
        if req.constraint:
            continue
        if req.is_wheel:
            if not autobuilding:
                logger.info(
                    "Skipping %s, due to already being wheel.",
                    req.name,
                )
        elif autobuilding and req.editable:
            pass
        elif autobuilding and not req.source_dir:
            pass
        elif autobuilding and req.link and not req.link.is_artifact:
            # VCS checkout. Build wheel just for this run.
            buildset.append((req, True))
        else:
            ephem_cache = False
            if autobuilding:
                link = req.link
                base, ext = link.splitext()
                if not _contains_egg_info(base):
                    # E.g. local directory. Build wheel just for this run.
                    ephem_cache = True
                if "binary" not in format_control.get_allowed_formats(
                    canonicalize_name(req.name)
                ):
                    logger.info(
                        "Skipping bdist_wheel for %s, due to binaries "
                        "being disabled for it.",
                        req.name,
                    )
                    continue
            buildset.append((req, ephem_cache))

    if not buildset:
        return []

    # Is any wheel build not using the ephemeral cache?
    if any(not ephem_cache for _, ephem_cache in buildset):
        have_directory_for_build = self._wheel_dir or (
            autobuilding and self.wheel_cache.cache_dir
        )
        assert have_directory_for_build

    # TODO by @pradyunsg
    # Should break up this method into 2 separate methods.

    # Build the wheels.
    logger.info(
        "Building wheels for collected packages: %s",
        ", ".join([req.name for (req, _) in buildset]),
    )
    _cache = self.wheel_cache  # shorter name
    with indent_log():
        build_success, build_failure = [], []
        for req, ephem in buildset:
            python_tag = None
            if autobuilding:
                python_tag = pep425tags.implementation_tag
                if ephem:
                    output_dir = _cache.get_ephem_path_for_link(req.link)
                else:
                    output_dir = _cache.get_path_for_link(req.link)
                try:
                    ensure_dir(output_dir)
                except OSError as e:
                    logger.warning("Building wheel for %s failed: %s", req.name, e)
                    build_failure.append(req)
                    continue
            else:
                output_dir = self._wheel_dir
            wheel_file = self._build_one(
                req,
                output_dir,
                python_tag=python_tag,
            )
            if wheel_file:
                build_success.append(req)
                if autobuilding:
                    # XXX: This is mildly duplicative with prepare_files,
                    # but not close enough to pull out to a single common
                    # method.
                    # The code below assumes temporary source dirs -
                    # prevent it doing bad things.
                    if req.source_dir and not os.path.exists(
                        os.path.join(req.source_dir, PIP_DELETE_MARKER_FILENAME)
                    ):
                        raise AssertionError("bad source dir - missing marker")
                    # Delete the source we built the wheel from
                    req.remove_temporary_source()
                    # set the build directory again - name is known from
                    # the work prepare_files did.
                    req.source_dir = req.build_location(self.preparer.build_dir)
                    # Update the link for this.
                    req.link = Link(path_to_url(wheel_file))
                    assert req.link.is_wheel
                    # extract the wheel into the dir
                    unpack_url(
                        req.link,
                        req.source_dir,
                        None,
                        False,
                        session=session,
                    )
            else:
                build_failure.append(req)

    # notify success/failure
    if build_success:
        logger.info(
            "Successfully built %s",
            " ".join([req.name for req in build_success]),
        )
    if build_failure:
        logger.info(
            "Failed to build %s",
            " ".join([req.name for req in build_failure]),
        )
    # Return a list of requirements that failed to build
    return build_failure