# Path: Popen_noblock.py
# ON_POSIX = 'posix' in sys.builtin_module_names
# def enqueue_output(out, queue):
#     def __init__(self, *args, **kwargs):
# class Popen_async(object):
# 
# Path: memoize.py
# def memoize(f):
#     """ Memoization decorator for a function taking one or more arguments. """
#     class memodict(dict):
#         def __getitem__(self, *key, **kwkey):
#             return dict.__getitem__(self, (tuple(key), tuple((k, kwkey[k]) for k in sorted(kwkey.keys()))))
# 
#         def __missing__(self, key):
#             args, kwargs = key
#             self[key] = ret = f(*args, **dict(kwargs))
#             return ret
# 
#     return memodict().__getitem__
# 
# Path: file_util.py
# def clean_v_file(file_name):
#     clean_extra_coq_files(file_name, extra_exts=('.v',))
# 
# Path: util.py
# def re_escape(*args, **kwargs):
#     ret = re.escape(*args, **kwargs)
#     for ch in ':"':
#         ret = ret.replace('\\' + ch, ch)
#     return ret
# 
# Path: custom_arguments.py
# LOG_ALWAYS=None
# 
# Path: coq_version.py
# def group_coq_args(args, coqc_help, topname=None, is_coq_makefile=False):
#     bindings, unrecognized_bindings = group_coq_args_split_recognized(args, coqc_help, topname=topname, is_coq_makefile=is_coq_makefile)
#     return bindings + [tuple([v]) for v in unrecognized_bindings]
# 
# def get_coqc_help(coqc_prog, **kwargs):
#     kwargs['log']('Running command: "%s"' % '" "'.join([coqc_prog, "-q", "--help"]), level=2)
#     return get_coqc_help_helper(coqc_prog)


import os, sys, tempfile, subprocess, re, time, math, glob, threading, shutil, traceback
import util
from Popen_noblock import Popen_async, Empty
from memoize import memoize
from file_util import clean_v_file
from util import re_escape
from custom_arguments import LOG_ALWAYS
from coq_version import group_coq_args, get_coqc_help
def timeout_Popen_communicate(log, *args, **kwargs):
    ret = { 'value' : ('', ''), 'returncode': None }
    timeout = kwargs.get('timeout')
    del kwargs['timeout']
    input_val = kwargs.get('input')
    if input_val is not None: input_val = input_val.encode('utf-8')
    del kwargs['input']
    p = subprocess.Popen(*args, **kwargs)

    def target():
        ret['value'] = tuple(map(util.s, p.communicate(input=input_val)))
        ret['returncode'] = p.returncode

    thread = threading.Thread(target=target)
    thread.start()

    thread.join(timeout)
    if not thread.is_alive():
        return (ret['value'], ret['returncode'])

    p.terminate()
    thread.join()
    return (tuple(map((lambda s: (s if s else '') + TIMEOUT_POSTFIX), ret['value'])), ret['returncode'])


def memory_robust_timeout_Popen_communicate(log, *args, **kwargs):
    while True:
        try:
            return timeout_Popen_communicate(log, *args, **kwargs)
        except OSError as e:

# Path: Popen_noblock.py
# ON_POSIX = 'posix' in sys.builtin_module_names
# def enqueue_output(out, queue):
#     def __init__(self, *args, **kwargs):
# class Popen_async(object):
# 
# Path: memoize.py
# def memoize(f):
#     """ Memoization decorator for a function taking one or more arguments. """
#     class memodict(dict):
#         def __getitem__(self, *key, **kwkey):
#             return dict.__getitem__(self, (tuple(key), tuple((k, kwkey[k]) for k in sorted(kwkey.keys()))))
# 
#         def __missing__(self, key):
#             args, kwargs = key
#             self[key] = ret = f(*args, **dict(kwargs))
#             return ret
# 
#     return memodict().__getitem__
# 
# Path: file_util.py
# def clean_v_file(file_name):
#     clean_extra_coq_files(file_name, extra_exts=('.v',))
# 
# Path: util.py
# def re_escape(*args, **kwargs):
#     ret = re.escape(*args, **kwargs)
#     for ch in ':"':
#         ret = ret.replace('\\' + ch, ch)
#     return ret
# 
# Path: custom_arguments.py
# LOG_ALWAYS=None
# 
# Path: coq_version.py
# def group_coq_args(args, coqc_help, topname=None, is_coq_makefile=False):
#     bindings, unrecognized_bindings = group_coq_args_split_recognized(args, coqc_help, topname=topname, is_coq_makefile=is_coq_makefile)
#     return bindings + [tuple([v]) for v in unrecognized_bindings]
# 
# def get_coqc_help(coqc_prog, **kwargs):
#     kwargs['log']('Running command: "%s"' % '" "'.join([coqc_prog, "-q", "--help"]), level=2)
#     return get_coqc_help_helper(coqc_prog)


# Path: diagnose_error.py
import os, sys, tempfile, subprocess, re, time, math, glob, threading, shutil, traceback
import util
from Popen_noblock import Popen_async, Empty
from memoize import memoize
from file_util import clean_v_file
from util import re_escape
from custom_arguments import LOG_ALWAYS
from coq_version import group_coq_args, get_coqc_help

def timeout_Popen_communicate(log, *args, **kwargs):
    ret = { 'value' : ('', ''), 'returncode': None }
    timeout = kwargs.get('timeout')
    del kwargs['timeout']
    input_val = kwargs.get('input')
    if input_val is not None: input_val = input_val.encode('utf-8')
    del kwargs['input']
    p = subprocess.Popen(*args, **kwargs)

    def target():
        ret['value'] = tuple(map(util.s, p.communicate(input=input_val)))
        ret['returncode'] = p.returncode

    thread = threading.Thread(target=target)
    thread.start()

    thread.join(timeout)
    if not thread.is_alive():
        return (ret['value'], ret['returncode'])

    p.terminate()
    thread.join()
    return (tuple(map((lambda s: (s if s else '') + TIMEOUT_POSTFIX), ret['value'])), ret['returncode'])


def memory_robust_timeout_Popen_communicate(log, *args, **kwargs):
    while True:
        try:
            return timeout_Popen_communicate(log, *args, **kwargs)
        except OSError as e:

            log('Warning: subprocess.Popen%s%s failed with %s\nTrying again in 10s' % (repr(tuple(args)), repr(kwargs), repr(e)), force_stdout=True, level=LOG_ALWAYS)