def call_apply_bpe(workspace_dir: str, input_fname: str, output_fname: str, model_fname: str):
    """
    Call BPE apply script.

    :param workspace_dir: Workspace directory where subword-nmt is checked out.
    :param input_fname: Path of tokenized input file, plain text or gzipped.
    :param output_fname: Path of byte-pair encoded output file, gzipped.
    :param model_fname: Path of BPE model file (codes).
    """
    apply_bpe_fname = os.path.join(workspace_dir, DIR_THIRD_PARTY, SUBWORD_NMT_DEST, "apply_bpe.py")
    with bin_open(input_fname) as inp, gzip.open(output_fname, "wb") as out:
        apply_bpe = subprocess.Popen([sys.executable, apply_bpe_fname, "-c", model_fname],
                                     stdin=subprocess.PIPE,
                                     stdout=subprocess.PIPE)
        apply_bpe_thread = threading.Thread(target=copy_out, args=(apply_bpe.stdout, out, True))
        apply_bpe_thread.start()
        for line in inp:
            # Use an empty line placeholder to avoid blank line duplication
            # issues with BPE script
            if not line.strip():
                line = PLACEHOLDER + b"\n"
            apply_bpe.stdin.write(line)
        apply_bpe.stdin.close()
        apply_bpe_thread.join()
        apply_bpe.wait()
Call BPE apply script.

    :param workspace_dir: Workspace directory where subword-nmt is checked out.
    :param input_fname: Path of tokenized input file, plain text or gzipped.
    :param output_fname: Path of byte-pair encoded output file, gzipped.
    :param model_fname: Path of BPE model file (codes).