# Buggy code
def with_parameters(fn, **kwargs):
    """Wrapper for function trainables to pass arbitrary large data objects.

    This wrapper function will store all passed parameters in the Ray
    object store and retrieve them when calling the function. It can thus
    be used to pass arbitrary data, even datasets, to Tune trainable functions.

    This can also be used as an alternative to `functools.partial` to pass
    default arguments to trainables.

    Args:
        fn: function to wrap
        **kwargs: parameters to store in object store.


    .. code-block:: python

        from ray import tune

        def train(config, data=None):
            for sample in data:
                # ...
                tune.report(loss=loss)

        data = HugeDataset(download=True)

        tune.run(
            tune.with_parameters(train, data=data),
            #...
        )

    """
    prefix = f"{str(fn)}_"
    for k, v in kwargs.items():
        parameter_registry.put(prefix + k, v)

    use_checkpoint = detect_checkpoint_function(fn)

    def inner(config, checkpoint_dir=None):
        fn_kwargs = {}
        if use_checkpoint:
            default = checkpoint_dir
            sig = inspect.signature(fn)
            if "checkpoint_dir" in sig.parameters:
                default = sig.parameters["checkpoint_dir"].default or default
            fn_kwargs["checkpoint_dir"] = default

        for k in kwargs:
            fn_kwargs[k] = parameter_registry.get(prefix + k)
        fn(config, **fn_kwargs)

    # Use correct function signature if no `checkpoint_dir` parameter is set
    if not use_checkpoint:

        def _inner(config):
            inner(config, checkpoint_dir=None)

        return _inner

    return inner


# Traceback (ray.tune.error.TuneError)
Failure # 1 (occurred at 2020-09-26_16-50-01)
Traceback (most recent call last):
File "/home/karol/PycharmProjects/ray/python/ray/tune/trial_runner.py", line 518, in _process_trial
result = self.trial_executor.fetch_result(trial)
File "/home/karol/PycharmProjects/ray/python/ray/tune/ray_trial_executor.py", line 488, in fetch_result
result = ray.get(trial_future[0], timeout=DEFAULT_GET_TIMEOUT)
File "/home/karol/PycharmProjects/ray/python/ray/worker.py", line 1438, in get
raise value.as_instanceof_cause()
ray.exceptions.RayTaskError(TuneError): �[36mray::ImplicitFunc.train()�[39m (pid=25150, ip=141.12.239.114)
File "python/ray/_raylet.pyx", line 484, in ray._raylet.execute_task
File "python/ray/_raylet.pyx", line 438, in ray._raylet.execute_task.function_executor
File "/home/karol/PycharmProjects/ray/python/ray/tune/trainable.py", line 336, in train
result = self.step()
File "/home/karol/PycharmProjects/ray/python/ray/tune/function_runner.py", line 346, in step
self._report_thread_runner_error(block=True)
File "/home/karol/PycharmProjects/ray/python/ray/tune/function_runner.py", line 464, in _report_thread_runner_error
raise TuneError(("Trial raised an exception. Traceback:\n{}"
ray.tune.error.TuneError: Trial raised an exception. Traceback:
�[36mray::ImplicitFunc.train()�[39m (pid=25150, ip=141.12.239.114)
File "/home/karol/PycharmProjects/ray/python/ray/tune/function_runner.py", line 233, in run
self._entrypoint()
File "/home/karol/PycharmProjects/ray/python/ray/tune/function_runner.py", line 295, in entrypoint
return self._trainable_func(self.config, self._status_reporter,
File "/home/karol/PycharmProjects/ray/python/ray/tune/function_runner.py", line 527, in _trainable_func
output = fn()
File "/home/karol/PycharmProjects/ray/python/ray/tune/function_runner.py", line 595, in _inner
inner(config, checkpoint_dir=None)
File "/home/karol/PycharmProjects/ray/python/ray/tune/function_runner.py", line 589, in inner
fn(config, **fn_kwargs)
TypeError: __init__() got multiple values for argument 'arch'

# Fixed code
def with_parameters(fn, **kwargs):
    """Wrapper for function trainables to pass arbitrary large data objects.

    This wrapper function will store all passed parameters in the Ray
    object store and retrieve them when calling the function. It can thus
    be used to pass arbitrary data, even datasets, to Tune trainable functions.

    This can also be used as an alternative to `functools.partial` to pass
    default arguments to trainables.

    Args:
        fn: function to wrap
        **kwargs: parameters to store in object store.


    .. code-block:: python

        from ray import tune

        def train(config, data=None):
            for sample in data:
                # ...
                tune.report(loss=loss)

        data = HugeDataset(download=True)

        tune.run(
            tune.with_parameters(train, data=data),
            #...
        )

    """
    if not callable(fn):
        raise ValueError(
            "`tune.with_parameters()` only works with the function API. "
            "If you want to pass parameters to Trainable _classes_, consider "
            "passing them via the `config` parameter."
        )

    prefix = f"{str(fn)}_"
    for k, v in kwargs.items():
        parameter_registry.put(prefix + k, v)

    use_checkpoint = detect_checkpoint_function(fn)

    def inner(config, checkpoint_dir=None):
        fn_kwargs = {}
        if use_checkpoint:
            default = checkpoint_dir
            sig = inspect.signature(fn)
            if "checkpoint_dir" in sig.parameters:
                default = sig.parameters["checkpoint_dir"].default or default
            fn_kwargs["checkpoint_dir"] = default

        for k in kwargs:
            fn_kwargs[k] = parameter_registry.get(prefix + k)
        fn(config, **fn_kwargs)

    # Use correct function signature if no `checkpoint_dir` parameter is set
    if not use_checkpoint:

        def _inner(config):
            inner(config, checkpoint_dir=None)

        return _inner

    return inner