# Buggy code
def concretize(maybe_stub):
    if isinstance(maybe_stub, StubMethodCall):
        obj = concretize(maybe_stub.obj)
        method = getattr(obj, maybe_stub.method_name)
        args = concretize(maybe_stub.args)
        kwargs = concretize(maybe_stub.kwargs)
        return method(*args, **kwargs)
    elif isinstance(maybe_stub, StubClass):
        return maybe_stub.proxy_class
    elif isinstance(maybe_stub, StubAttr):
        obj = concretize(maybe_stub.obj)
        attr_name = maybe_stub.attr_name
        attr_val = getattr(obj, attr_name)
        return concretize(attr_val)
    elif isinstance(maybe_stub, StubObject):
        if not hasattr(maybe_stub, "__stub_cache"):
            args = concretize(maybe_stub.args)
            kwargs = concretize(maybe_stub.kwargs)
            try:
                maybe_stub.__stub_cache = maybe_stub.proxy_class(*args, **kwargs)
            except Exception as e:
                print(("Error while instantiating %s" % maybe_stub.proxy_class))
                import traceback

                traceback.print_exc()
        ret = maybe_stub.__stub_cache
        return ret
    elif isinstance(maybe_stub, dict):
        # make sure that there's no hidden caveat
        ret = dict()
        for k, v in maybe_stub.items():
            ret[concretize(k)] = concretize(v)
        return ret
    elif isinstance(maybe_stub, (list, tuple)):
        return maybe_stub.__class__(list(map(concretize, maybe_stub)))
    else:
        return maybe_stub


# Traceback (TypeError)
Traceback (most recent call last):
File "/Users/jonathon/Documents/garage/garage/scripts/run_experiment.py", line 191, in <module>
run_experiment(sys.argv)
File "/Users/jonathon/Documents/garage/garage/scripts/run_experiment.py", line 146, in run_experiment
logger.log_parameters_lite(params_log_file, args)
File "/Users/jonathon/Documents/garage/garage/garage/misc/logger.py", line 372, in log_parameters_lite
json.dump(log_params, f, indent=2, sort_keys=True, cls=MyEncoder)
File "/anaconda2/envs/garage/lib/python3.6/json/__init__.py", line 179, in dump
for chunk in iterable:
File "/anaconda2/envs/garage/lib/python3.6/json/encoder.py", line 430, in _iterencode
yield from _iterencode_dict(o, _current_indent_level)
File "/anaconda2/envs/garage/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
yield from chunks
File "/anaconda2/envs/garage/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
yield from chunks
File "/anaconda2/envs/garage/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
yield from chunks
[Previous line repeated 1 more times]
File "/anaconda2/envs/garage/lib/python3.6/json/encoder.py", line 437, in _iterencode
o = _default(o)
File "/Users/jonathon/Documents/garage/garage/garage/misc/logger.py", line 352, in default
return json.JSONEncoder.default(self, o)
File "/anaconda2/envs/garage/lib/python3.6/json/encoder.py", line 180, in default
o.__class__.__name__)
TypeError: Object of type 'TimeLimit' is not JSON serializable

# Fixed code
def concretize(obj):
    if isinstance(obj, dict):
        # make sure that there's no hidden caveat
        ret = dict()
        for k, v in obj.items():
            ret[concretize(k)] = concretize(v)
        return ret
    elif isinstance(obj, (list, tuple)):
        return obj.__class__(list(map(concretize, obj)))
    else:
        return obj