# Buggy code
def run(self, config, instance=None, cutoff=None, seed=12345, instance_specific="0"):
    """
    runs target algorithm <self.ta> with configuration <config> on
    instance <instance> with instance specifics <specifics>
    for at most <cutoff> seconds and random seed <seed>

    Parameters
    ----------
        config : dictionary (or similar)
            dictionary param -> value
        instance : string
            problem instance
        cutoff : double
            runtime cutoff
        seed : int
            random seed
        instance_specific: str
            instance specific information (e.g., domain file or solution)
    Returns
    -------
        status: enum of StatusType (int)
            {SUCCESS, TIMEOUT, CRASHED, ABORT}
        cost: float
            cost/regret/quality/runtime (float) (None, if not returned by TA)
        runtime: float
            runtime (None if not returned by TA)
        additional_info: dict
            all further additional run information
    """

    if instance is None:
        instance = "0"
    if cutoff is None:
        cutoff = 99999999999999.0

    # TOOD: maybe replace fixed instance specific and cutoff_length (0) to
    # other value
    cmd = []
    cmd.extend(self.ta)
    cmd.extend([instance, instance_specific, str(cutoff), "0", str(seed)])
    for p in config:
        if not config[p] is None:
            cmd.extend(["-" + str(p), str(config[p])])

    self.logger.debug("Calling: %s" % (" ".join(cmd)))
    p = Popen(cmd, shell=False, stdout=PIPE, stderr=PIPE, universal_newlines=True)
    stdout_, stderr_ = p.communicate()

    self.logger.debug("Stdout: %s" % (stdout_))
    self.logger.debug("Stderr: %s" % (stderr_))

    status = "CRASHED"
    quality = 1234567890
    runtime = 1234567890
    additional_info = {}
    for line in stdout_.split("\n"):
        if (
            line.startswith("Result of this algorithm run:")
            or line.startswith("Result for ParamILS")
            or line.startswith("Result for SMAC")
        ):
            fields = line.split(":")[1].split(",")
            fields = list(map(lambda x: x.strip(" "), fields))
            if len(fields) == 5:
                status, runtime, runlength, quality, seed = fields
                additional_info = {}
            else:
                status, runtime, runlength, quality, seed, additional_info = fields
                additional_info = {"additional_info": additional_info}

            runtime = min(float(runtime), cutoff)
            quality = float(quality)
            seed = int(seed)

    if status in ["SAT", "UNSAT", "SUCCESS"]:
        status = StatusType.SUCCESS
    elif status in ["TIMEOUT"]:
        status = StatusType.TIMEOUT
    elif status in ["CRASHED"]:
        status = StatusType.CRASHED
    elif status in ["ABORT"]:
        status = StatusType.ABORT
        self.logger.error("Target algorithm returned ABORT -- Exit!")
        sys.exit(43)
    elif status in ["MEMOUT"]:
        status = StatusType.MEMOUT

    if status in [StatusType.CRASHED, StatusType.ABORT]:
        self.logger.warn("Target algorithm crashed. Last 5 lines of stdout and stderr")
        self.logger.warn("\n".join(stdout_.split("\n")[-5:]))
        self.logger.warn("\n".join(stderr_.split("\n")[-5:]))

    if self.run_obj == "runtime":
        if status != StatusType.SUCCESS:
            cost = runtime * self.par_factor
        else:
            cost = runtime
    else:
        cost = quality

    return status, cost, float(runtime), additional_info


# Traceback (AttributeError)
Traceback (most recent call last):
File "/home/lindauer/git/SMAC3/scripts/smac", line 20, in <module>
smac.main_cli()
File "/home/lindauer/git/SMAC3/smac/smac_cli.py", line 47, in main_cli
smbo.run(max_iters=args_.max_iterations)
File "/home/lindauer/git/SMAC3/smac/smbo/smbo.py", line 282, in run
self.incumbent = self.run_initial_design()
File "/home/lindauer/git/SMAC3/smac/smbo/smbo.py", line 239, in run_initial_design
instance_specific=self.scenario.instance_specific.get(rand_inst, "0"))
File "/home/lindauer/git/SMAC3/smac/tae/execute_ta_run.py", line 103, in start
if self._supports_memory_limit is True:
AttributeError: 'ExecuteTARunOld' object has no attribute '_supports_memory_limit'

# Fixed code
def run(self, config, instance=None, cutoff=None, seed=12345, instance_specific="0"):
    """
    runs target algorithm <self.ta> with configuration <config> on
    instance <instance> with instance specifics <specifics>
    for at most <cutoff> seconds and random seed <seed>

    Parameters
    ----------
        config : dictionary (or similar)
            dictionary param -> value
        instance : string
            problem instance
        cutoff : double
            runtime cutoff
        seed : int
            random seed
        instance_specific: str
            instance specific information (e.g., domain file or solution)
    Returns
    -------
        status: enum of StatusType (int)
            {SUCCESS, TIMEOUT, CRASHED, ABORT}
        cost: float
            cost/regret/quality/runtime (float) (None, if not returned by TA)
        runtime: float
            runtime (None if not returned by TA)
        additional_info: dict
            all further additional run information
    """

    if instance is None:
        instance = "0"
    if cutoff is None:
        cutoff = 99999999999999.0

    # TOOD: maybe replace fixed instance specific and cutoff_length (0) to
    # other value
    cmd = []
    cmd.extend(self.ta)
    cmd.extend([instance, instance_specific, str(cutoff), "0", str(seed)])
    for p in config:
        if not config[p] is None:
            cmd.extend(["-" + str(p), str(config[p])])

    self.logger.debug("Calling: %s" % (" ".join(cmd)))
    p = Popen(cmd, shell=False, stdout=PIPE, stderr=PIPE, universal_newlines=True)
    stdout_, stderr_ = p.communicate()

    self.logger.debug("Stdout: %s" % (stdout_))
    self.logger.debug("Stderr: %s" % (stderr_))

    status = "CRASHED"
    quality = 1234567890
    runtime = 1234567890
    additional_info = {}
    for line in stdout_.split("\n"):
        if (
            line.startswith("Result of this algorithm run:")
            or line.startswith("Result for ParamILS")
            or line.startswith("Result for SMAC")
        ):
            fields = line.split(":")[1].split(",")
            fields = list(map(lambda x: x.strip(" "), fields))
            if len(fields) == 5:
                status, runtime, runlength, quality, seed = fields
                additional_info = {}
            else:
                status, runtime, runlength, quality, seed, additional_info = fields
                additional_info = {"additional_info": additional_info}

            runtime = min(float(runtime), cutoff)
            quality = float(quality)
            seed = int(seed)

    if status in ["SAT", "UNSAT", "SUCCESS"]:
        status = StatusType.SUCCESS
    elif status in ["TIMEOUT"]:
        status = StatusType.TIMEOUT
    elif status in ["CRASHED"]:
        status = StatusType.CRASHED
    elif status in ["ABORT"]:
        status = StatusType.ABORT
        self.logger.error("Target algorithm returned ABORT -- Exit!")
        sys.exit(43)
    elif status in ["MEMOUT"]:
        status = StatusType.MEMOUT

    if status in [StatusType.CRASHED, StatusType.ABORT]:
        self.logger.warn("Target algorithm crashed. Last 5 lines of stdout and stderr")
        self.logger.warn("\n".join(stdout_.split("\n")[-5:]))
        self.logger.warn("\n".join(stderr_.split("\n")[-5:]))

    if self.run_obj == "runtime":
        cost = runtime
    else:
        cost = quality

    return status, cost, float(runtime), additional_info