# Buggy code
def __init__(self, config=None, logger_creator=None):
    """Initialize an Trainable.

    Sets up logging and points ``self.logdir`` to a directory in which
    training outputs should be placed.

    Subclasses should prefer defining ``_setup()`` instead of overriding
    ``__init__()`` directly.

    Args:
        config (dict): Trainable-specific configuration data. By default
            will be saved as ``self.config``.
        logger_creator (func): Function that creates a ray.tune.Logger
            object. If unspecified, a default logger is created.
    """

    self._experiment_id = uuid.uuid4().hex
    self.config = config or {}
    trial_info = self.config.pop(TRIAL_INFO, None)

    if logger_creator:
        self._result_logger = logger_creator(self.config)
        self._logdir = self._result_logger.logdir
    else:
        logdir_prefix = datetime.today().strftime("%Y-%m-%d_%H-%M-%S")
        ray.utils.try_to_create_directory(DEFAULT_RESULTS_DIR)
        self._logdir = tempfile.mkdtemp(prefix=logdir_prefix, dir=DEFAULT_RESULTS_DIR)
        self._result_logger = UnifiedLogger(self.config, self._logdir, loggers=None)

    self._iteration = 0
    self._time_total = 0.0
    self._timesteps_total = None
    self._episodes_total = None
    self._time_since_restore = 0.0
    self._timesteps_since_restore = 0
    self._iterations_since_restore = 0
    self._restored = False
    self._trial_info = trial_info

    start_time = time.time()
    self._setup(copy.deepcopy(self.config))
    setup_time = time.time() - start_time
    if setup_time > SETUP_TIME_THRESHOLD:
        logger.info(
            "_setup took {:.3f} seconds. If your trainable is "
            "slow to initialize, consider setting "
            "reuse_actors=True to reduce actor creation "
            "overheads.".format(setup_time)
        )
    self._local_ip = ray.services.get_node_ip_address()
    log_sys_usage = self.config.get("log_sys_usage", False)
    self._monitor = UtilMonitor(start=log_sys_usage)


# Traceback (NotImplementedError)
$ python ./tests/tune_done_test.py
2020-03-22 12:17:21,455 INFO resource_spec.py:212 -- Starting Ray with 10.3 GiB memory available for workers and up to 5.17 GiB for objects. You can adjust these settings with ray.init(memory=<bytes>, object_store_memory=<bytes>).
2020-03-22 12:17:21,746 INFO services.py:1078 -- View the Ray dashboard at localhost:8265
== Status ==
Memory usage on this node: 17.8/32.0 GiB
Using FIFO scheduling algorithm.
Resources requested: 1/16 CPUs, 0/0 GPUs, 0.0/10.3 GiB heap, 0.0/3.56 GiB objects
Result logdir: /Users/hartikainen/ray_results/done-test
Number of trials: 1 (1 RUNNING)
+---------------------------+----------+-------+-------+
| Trial name                | status   | loc   | a/b   |
|---------------------------+----------+-------+-------|
| MyTrainableClass_14fda478 | RUNNING  |       |       |
+---------------------------+----------+-------+-------+


Result for MyTrainableClass_14fda478:
date: 2020-03-22_12-17-23
done: false
episode_reward_mean: 1
experiment_id: 3549c7334c884d3abc309232da4f6679
experiment_tag: '0_b={''d'': ''4''}'
hostname: catz-48fe.stcatz.ox.ac.uk
iterations_since_restore: 1
node_ip: 129.67.48.254
pid: 73820
time_since_restore: 3.0994415283203125e-06
time_this_iter_s: 3.0994415283203125e-06
time_total_s: 3.0994415283203125e-06
timestamp: 1584879443
timesteps_since_restore: 0
training_iteration: 1
trial_id: 14fda478
what:
'1': '2'
'3': 4
'5':
'6': 4

Result for MyTrainableClass_14fda478:
date: 2020-03-22_12-17-23
done: true
episode_reward_mean: 3
experiment_id: 3549c7334c884d3abc309232da4f6679
experiment_tag: '0_b={''d'': ''4''}'
hostname: catz-48fe.stcatz.ox.ac.uk
iterations_since_restore: 3
node_ip: 129.67.48.254
pid: 73820
time_since_restore: 9.775161743164062e-06
time_this_iter_s: 2.86102294921875e-06
time_total_s: 9.775161743164062e-06
timestamp: 1584879443
timesteps_since_restore: 0
training_iteration: 3
trial_id: 14fda478
what:
'1': '2'
'3': 4
'5':
'6': 4

2020-03-22 12:17:23,204 ERROR trial_runner.py:513 -- Trial MyTrainableClass_14fda478: Error processing event.
Traceback (most recent call last):
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/trial_runner.py", line 511, in _process_trial
self._execute_action(trial, decision)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/trial_runner.py", line 595, in _execute_action
self.trial_executor.stop_trial(trial)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/ray_trial_executor.py", line 263, in stop_trial
trial, error=error, error_msg=error_msg, stop_logger=stop_logger)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/ray_trial_executor.py", line 204, in _stop_trial
trial.close_logger()
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/trial.py", line 315, in close_logger
self.result_logger.close()
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/logger.py", line 305, in close
_logger.close()
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/logger.py", line 233, in close
self._try_log_hparams(self.last_result)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/logger.py", line 244, in _try_log_hparams
hparam_dict=scrubbed_params, metric_dict=result)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/tensorboardX/summary.py", line 102, in hparams
v = make_np(v)[0]
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/tensorboardX/x2num.py", line 34, in make_np
'Got {}, but expected numpy array or torch tensor.'.format(type(x)))
NotImplementedError: Got <class 'dict'>, but expected numpy array or torch tensor.
Traceback (most recent call last):
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/trial_runner.py", line 511, in _process_trial
self._execute_action(trial, decision)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/trial_runner.py", line 595, in _execute_action
self.trial_executor.stop_trial(trial)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/ray_trial_executor.py", line 263, in stop_trial
trial, error=error, error_msg=error_msg, stop_logger=stop_logger)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/ray_trial_executor.py", line 204, in _stop_trial
trial.close_logger()
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/trial.py", line 315, in close_logger
self.result_logger.close()
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/logger.py", line 305, in close
_logger.close()
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/logger.py", line 233, in close
self._try_log_hparams(self.last_result)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/logger.py", line 244, in _try_log_hparams
hparam_dict=scrubbed_params, metric_dict=result)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/tensorboardX/summary.py", line 102, in hparams
v = make_np(v)[0]
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/tensorboardX/x2num.py", line 34, in make_np
'Got {}, but expected numpy array or torch tensor.'.format(type(x)))
NotImplementedError: Got <class 'dict'>, but expected numpy array or torch tensor.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "./tests/tune_done_test.py", line 24, in <module>
'b': tune.sample_from(lambda spec: spec['config']['b']['c']),
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/tune.py", line 324, in run
runner.step()
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/trial_runner.py", line 335, in step
self._process_events()  # blocking
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/trial_runner.py", line 444, in _process_events
self._process_trial(trial)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/trial_runner.py", line 514, in _process_trial
self._process_trial_failure(trial, traceback.format_exc())
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/trial_runner.py", line 580, in _process_trial_failure
trial, error=True, error_msg=error_msg)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/ray_trial_executor.py", line 263, in stop_trial
trial, error=error, error_msg=error_msg, stop_logger=stop_logger)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/ray_trial_executor.py", line 204, in _stop_trial
trial.close_logger()
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/trial.py", line 315, in close_logger
self.result_logger.close()
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/logger.py", line 305, in close
_logger.close()
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/logger.py", line 233, in close
self._try_log_hparams(self.last_result)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/ray/tune/logger.py", line 244, in _try_log_hparams
hparam_dict=scrubbed_params, metric_dict=result)
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/tensorboardX/summary.py", line 102, in hparams
v = make_np(v)[0]
File "/Users/hartikainen/conda/envs/softlearning-tf2/lib/python3.7/site-packages/tensorboardX/x2num.py", line 34, in make_np
'Got {}, but expected numpy array or torch tensor.'.format(type(x)))
NotImplementedError: Got <class 'dict'>, but expected numpy array or torch tensor.

# Fixed code
def __init__(self, config=None, logger_creator=None):
    """Initialize an Trainable.

    Sets up logging and points ``self.logdir`` to a directory in which
    training outputs should be placed.

    Subclasses should prefer defining ``_setup()`` instead of overriding
    ``__init__()`` directly.

    Args:
        config (dict): Trainable-specific configuration data. By default
            will be saved as ``self.config``.
        logger_creator (func): Function that creates a ray.tune.Logger
            object. If unspecified, a default logger is created.
    """

    self._experiment_id = uuid.uuid4().hex
    self.config = config or {}
    trial_info = self.config.pop(TRIAL_INFO, None)

    if logger_creator:
        self._result_logger = logger_creator(self.config)
        self._logdir = self._result_logger.logdir
    else:
        logdir_prefix = datetime.today().strftime("%Y-%m-%d_%H-%M-%S")
        ray.utils.try_to_create_directory(DEFAULT_RESULTS_DIR)
        self._logdir = tempfile.mkdtemp(prefix=logdir_prefix, dir=DEFAULT_RESULTS_DIR)
        self._result_logger = UnifiedLogger(self.config, self._logdir, loggers=None)

    self._iteration = 0
    self._time_total = 0.0
    self._timesteps_total = None
    self._episodes_total = None
    self._time_since_restore = 0.0
    self._timesteps_since_restore = 0
    self._iterations_since_restore = 0
    self._restored = False
    self._trial_info = trial_info

    start_time = time.time()
    self._setup(copy.deepcopy(self.config))
    setup_time = time.time() - start_time
    if setup_time > SETUP_TIME_THRESHOLD:
        logger.info(
            "_setup took {:.3f} seconds. If your trainable is "
            "slow to initialize, consider setting "
            "reuse_actors=True to reduce actor creation "
            "overheads.".format(setup_time)
        )
    self._local_ip = self.get_current_ip()
    log_sys_usage = self.config.get("log_sys_usage", False)
    self._monitor = UtilMonitor(start=log_sys_usage)