<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 pull=True, build_context: Optional[Path]=None):
 """ A proxy for commonly built images, returns them from the local system if they exist, tries to pull them if pull isn't disabled, otherwise builds them by the definition in ``dockerfile``. :param name: Name of the image :param tag: Image tag :param dockerfile: Dockerfile text or a callable (no arguments) that produces Dockerfile text :param pull: If the image is not present locally, allow pulling from registry (default is ``True``) :param build_context: A path to a folder. If it's provided, docker will build the image in the context of this folder. (eg. if ``ADD`` is needed) """

        if self.image_exists(name, tag):
            logger.info("Image %s:%s exists", name, tag)
            return

        elif pull:
            logger.info("Trying to pull image %s:%s", name, tag)

            try:
                self.client.images.pull(name, tag=tag)
                logger.info("The image %s:%s was pulled from registry", name, tag)
                return
            except docker.errors.APIError:
                logger.info("The image %s:%s can't be pulled, building locally.", name, tag)

        if callable(dockerfile):
            dockerfile = dockerfile()

        try:
            if build_context is None:
                fileobj = BytesIO(bytes(dockerfile, "utf-8"))  # required by the docker library

                self.client.images.build(
                    fileobj=fileobj,
                    tag=f"{name}:{tag}"
                )
            else:
                dockerfile_file = build_context / "dockerfile"
                dockerfile_file.write_text(dockerfile)

                self.client.images.build(
                    path=str(build_context.resolve()),
                    dockerfile=dockerfile_file.name,
                    tag=f"{name}:{tag}"
                )

                dockerfile_file.unlink()
        except docker.errors.BuildError as e:
            for line in e.build_log:
                if isinstance(line, dict) and line.get("errorDetail") and line["errorDetail"].get("code") in {124, 143}:
                    raise BuildTimeoutError(f"Installing of requirements timeouted after "
                                            f"{self.requirements_timeout} seconds.")

            logger.exception(e)

            raise BuildError("Building docker image failed, see extra info for details.", extra_info={
                "build_log": e.build_log
            })